diff --git a/packages/jquery/plugins/jquery.select2.selectAll.js b/packages/jquery/plugins/jquery.select2.selectAll.js new file mode 100644 index 000000000..f53f0c684 --- /dev/null +++ b/packages/jquery/plugins/jquery.select2.selectAll.js @@ -0,0 +1,92 @@ +/** + * jquery.select2.selectAll.js + * + * A Select2 extension that adds "Select All" and "Unselect All" functionality to Select2 dropdowns. + * + * @description + * This extension creates a custom adapter for Select2 that adds "Select All" and "Unselect All" + * buttons to the dropdown of multi-select Select2 instances. These buttons allow users to quickly + * select or unselect all options in the dropdown. + * + * @usage + * 1. Include this file after loading jQuery and Select2. + * 2. Initialize Select2 with the custom adapter: + * $('#your-select-element').select2({ + * dropdownAdapter: $.fn.select2.amd.require('select2/selectAllAdapter') + * }); + * + * @dependencies + * - jQuery (https://jquery.com) + * - Select2 (https://select2.org) + * + * @source + * This script is based on the code from: + * https://jsfiddle.net/beaver71/tjvjytp3/ + * Modified and packaged as a reusable extension. + * The original code was written for Select2 version 4.0.5. When adapting it for the latest version + * (4.1.0-rc.0), some modifications were necessary due to changes in Select2's internal structure + * and API. The custom adapter code has been updated to be compatible with version 4.1.0-rc.0, + * addressing issues that arose from differences in how Select2 handles custom adapters in the + * newer version. These changes ensure that the "Select All" and "Unselect All" functionality + * works correctly with the latest Select2 release while maintaining backwards compatibility + * where possible. + */ + +(function ($) { + 'use strict'; + + $.fn.select2.amd.define('select2/selectAllAdapter', [ + 'select2/utils', + 'select2/dropdown', + 'select2/dropdown/attachBody' + ], function (Utils, Dropdown, AttachBody) { + + function SelectAll() { } + SelectAll.prototype.render = function (decorated) { + var self = this, + $rendered = decorated.call(this), + $selectAll = $( + '' + ), + $unselectAll = $( + '' + ), + $btnContainer = $('
').append($selectAll).append($unselectAll); + if (!this.$element.prop("multiple")) { + // This isn't a multi-select, don't add the buttons + return $rendered; + } + $rendered.find('.select2-dropdown').prepend($btnContainer); + $selectAll.on('click', function (e) { + e.preventDefault(); + var $options = self.$element.find('option'); + var values = []; + + $options.each(function() { + if (!this.disabled) { + values.push(this.value); + } + }); + + self.$element.val(values); + self.$element.trigger('change'); + self.trigger('close'); + }); + $unselectAll.on('click', function (e) { + e.preventDefault(); + self.$element.val([]); + self.$element.trigger('change'); + self.trigger('close'); + }); + return $rendered; + }; + + return Utils.Decorate( + Utils.Decorate( + Dropdown, + AttachBody + ), + SelectAll + ); + }); +})(jQuery); \ No newline at end of file diff --git a/templates/CRM/common/jquery.files.tpl b/templates/CRM/common/jquery.files.tpl index 784cea274..958fe3e03 100644 --- a/templates/CRM/common/jquery.files.tpl +++ b/templates/CRM/common/jquery.files.tpl @@ -71,6 +71,7 @@ packages/jquery/plugins/jquery.chosen.js packages/jquery/css/jquery.chosen.css packages/jquery/plugins/jquery.select2.js +packages/jquery/plugins/jquery.select2.selectAll.js packages/jquery/css/jquery.select2.css packages/jquery/plugins/jquery.modal.min.js diff --git a/templates/CRM/common/select2.tpl b/templates/CRM/common/select2.tpl index 20300a307..cde9bf2cd 100644 --- a/templates/CRM/common/select2.tpl +++ b/templates/CRM/common/select2.tpl @@ -1,14 +1,25 @@ {if !$nowrapper}