From a474e1626309f74bf5df23ab03d0c7596f8042ab Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 13:55:45 -0800 Subject: [PATCH 1/9] $variable and more comments Mostly changing to $naming scheme for jQuery objects and adding more comments. --- src/jquery.multiselect.js | 419 +++++++++++++++++++------------------- 1 file changed, 204 insertions(+), 215 deletions(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index 7bd32d5..ddaeaf7 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -1,11 +1,11 @@ /* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */ /* - * jQuery MultiSelect UI Widget 2.0.1 + * jQuery MultiSelect UI Widget 3.0.0 * Copyright (c) 2012 Eric Hynds * * Depends: - * - jQuery 1.4.2+ - * - jQuery UI 1.11 widget factory + * - jQuery 1.7+ (http://api.jquery.com/) + * - jQuery UI 1.11 widget factory (http://api.jqueryui.com/jQuery.widget/) * * Optional: * - jQuery UI effects @@ -25,59 +25,59 @@ // default options options: { - header: true, - height: 175, - minWidth: 225, - classes: '', - openIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be used here instead of the default jQuery UI icons. - closeIcon: '', - checkAllIcon: '', - uncheckAllIcon: '', - flipAllIcon: '', - checkAllText: 'Check all', // If blank or null, link not shown. - uncheckAllText: 'Uncheck all', // If blank or null, link not shown. - flipAllText: 'Flip all', // If blank or null, link not shown. - showCheckAll: true, - showUncheckAll: true, - showFlipAll: false, - noneSelectedText: 'Select options', - selectedText: '# selected', - selectedList: 0, - show: null, - hide: null, - autoOpen: false, - position: {}, - appendTo: null, - menuWidth:null, - selectedListSeparator: ', ', - disableInputsOnToggle: true, - groupColumns: false + header: true, // (true | false) If true, the header is shown. + height: 175, // (int) Sets the height of the menu. + minWidth: 225, // (int) Sets the minimum width of the menu. + classes: '', // Classes that you can provide to be applied to the elements making up the widget. + openIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + closeIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + checkAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + uncheckAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + flipAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + checkAllText: 'Check all', // (str | blank | null) If blank or null, link not shown. + uncheckAllText: 'Uncheck all', // (str | blank | null) If blank or null, link not shown. + flipAllText: 'Flip all', // (str | blank | null) If blank or null, link not shown. + showCheckAll: true, // (true | false) Show or hide the Check All link without blanking the text. + showUncheckAll: true, // (true | false) Show or hide the Uncheck All link without blanking the text. + showFlipAll: false, // (true | false) Show or hide the Flip All link without blanking the text. + noneSelectedText: 'Select options', // (str) The text to show in the button where nothing is selected. + selectedText: '# of # selected', // (str) A "template" that indicates how to show the count of selections in the button. The "#'s" are replaced by the selection count & option count. + selectedList: 0, // (int) The actual list selections will be shown in the button when the count of selections is <= than this number. + show: null, // (array) An array containing menu opening effects. + hide: null, // (array) An array containing menu closing effects. + autoOpen: false, // (true | false) If true, then the menu will be opening immediately after initialization. + position: {}, // (object) A jQuery UI position object that constrains how the pop-up menu is positioned. + appendTo: null, // (jQuery | DOM element | selector str) If provided, this specifies what element to append the widget to in the DOM. + menuWidth:null, // (int | null) If a number is provided, sets the menu width. + selectedListSeparator: ', ', // (str) This allows customization of the list separator. Use ',
' to make the button grow vertically showing 1 selection per line. + disableInputsOnToggle: true, // (true | false) + groupColumns: false // (true | false) }, // This method determines which element to append the menu to // Uses the element provided in the options first, then looks for ui-front / dialog // Otherwise appends to the body _getAppendEl: function() { - var element = this.options.appendTo; - if(element) { - element = element.jquery || element.nodeType ? $(element) : this.document.find(element).eq(0); + var elem = this.options.appendTo; // jQuery object, DOM element, OR selector str. + if(elem) { + elem = elem.jquery || elem.nodeType ? $(elem) : this.document.find(elem).eq(0); // Note that the find handles the selector case. } - if(!element || !element[0]) { - element = this.element.closest(".ui-front, dialog"); + if(!elem || !elem[0]) { + elem = this.element.closest(".ui-front, dialog"); } - if(!element.length) { - element = this.document[0].body; + if(!elem.length) { + elem = this.document[0].body; // Position at end of body. } - return element; + return elem; }, // Performs the initial creation of the widget _create: function() { - var el = this.element; + var $el = this.element.hide(); // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ var o = this.options; this.speed = $.fx.speeds._default; // default speed for effects - this._isOpen = false; // assume no + this._isOpen = false; // assume no this.inputIdCounter = 0; // create a unique namespace for events that the widget @@ -87,30 +87,31 @@ // bump unique ID after assigning it to the widget instance this.multiselectID = multiselectID++; - // The button that opens the widget menu - var button = (this.button = $('')) + // The button that opens the widget menu. + // The ui-multiselect-open span is necessary below to simplify dynamically changing the open icon. + var $button = (this.$button = $('')) .addClass('ui-multiselect ui-widget ui-state-default ui-corner-all ' + o.classes) - .attr({ 'title':el.attr('title'), 'tabIndex':el.attr('tabIndex'), 'id': el.attr('id') ? el.attr('id') + '_ms' : null }) + .attr({ title: $el.attr('title'), tabIndex: $el.attr('tabIndex'), id: $el.attr('id') ? $el.attr('id') + '_ms' : null }) .prop('aria-haspopup', true) - .insertAfter(el); + .insertAfter($el); - this.buttonlabel = $('') + this.$buttonlabel = $('') .html(o.noneSelectedText) - .appendTo(button); + .appendTo($button); // This is the menu that will hold all the options - this.menu = $('
') + var $menu = (this.$menu = $('
')) .addClass('ui-multiselect-menu ui-widget ui-widget-content ui-corner-all ' + o.classes) .appendTo(this._getAppendEl()); // Menu header to hold controls for the menu - this.header = $('
') + var $header = (this.$header = $('
')) .addClass('ui-widget-header ui-corner-all ui-multiselect-header ui-helper-clearfix') - .appendTo(this.menu); + .appendTo($menu); // Header controls, will contain the check all/uncheck all buttons // Depending on how the options are set, this may be empty or simply plain text - this.headerLinkContainer = $('
    ') + this.$headerLinkContainer = $('
      ') .addClass('ui-helper-reset') .html(function() { if(o.header === true) { @@ -132,12 +133,12 @@ } }) .append('
    • ' + o.closeIcon + '
    • ') - .appendTo(this.header); + .appendTo($header); // Holds the actual check boxes for inputs - var checkboxContainer = (this.checkboxContainer = $('
        ')) + this.$checkboxContainer = $('
          ') .addClass('ui-multiselect-checkboxes ui-helper-reset') - .appendTo(this.menu); + .appendTo($menu); // perform event bindings this._bindEvents(); @@ -146,26 +147,28 @@ this.refresh(true); // If this is a single select widget, add the appropriate class - if(!el[0].multiple) { - this.menu.addClass('ui-multiselect-single'); + if(!$el[0].multiple) { + $menu.addClass('ui-multiselect-single'); } - el.hide(); }, // https://api.jqueryui.com/jquery.widget/#method-_init _init: function() { + var $element = this.element; + var $headerLinks = this.$headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip'); + if(this.options.header === false) { - this.header.hide(); + this.$header.hide(); } - if(!!this.element[0].multiple) { - this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip').show(); + if(!!$element[0].multiple) { // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ + $headerLinks.show(); } else { - this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip').hide(); + $headerLinks.hide(); } if(this.options.autoOpen) { this.open(); } - if(this.element.is(':disabled')) { + if(!!$element[0].disabled) { this.disable(); } }, @@ -180,17 +183,16 @@ * */ _makeOption: function(option) { - var title = option.title ? option.title : null; - var value = option.value; - var el = this.element; - var id = el.attr('id') || this.multiselectID; // unique ID for the label & option tags + var title = option.title || null; + var $element = this.element; // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ + var id = $element[0].id || this.multiselectID; // unique ID for the label & option tags var inputID = 'ui-multiselect-' + this.multiselectID + '-' + (option.id || id + '-option-' + this.inputIdCounter++); var isDisabled = option.disabled; var isSelected = option.selected; var labelClasses = [ 'ui-corner-all' ]; var liClasses = []; var o = this.options; - var isMultiple = !!el[0].multiple; // Pick up the select type from the underlying element + var isMultiple = !!$element[0].multiple; // Pick up the select type from the underlying element if(isDisabled) { liClasses.push('ui-multiselect-disabled'); @@ -211,7 +213,7 @@ var $input = $("").attr({ "name": "multiselect_" + id, "type": isMultiple ? "checkbox" : "radio", - "value": value, + "value": option.value, "title": title, "id": inputID, "checked": isSelected ? "checked" : null, @@ -231,9 +233,9 @@ // Builds a menu item for each option in the underlying select // Option groups are built here as well - _buildOptionList: function(element, $appendTo) { + _buildOptionList: function($element, $appendTo) { var self = this; - element.children().each(function() { + $element.children().each(function() { var $this = $(this); if(this.tagName === 'OPTGROUP') { var $optionGroup = $("
            ").addClass('ui-multiselect-optgroup ' + this.className).appendTo($appendTo); @@ -252,32 +254,30 @@ // Refreshes the widget to pick up changes to the underlying select // Rebuilds the menu, sets button width refresh: function(init) { - var self = this; - var el = this.element; - var o = this.options; - var menu = this.menu; - var checkboxContainer = this.checkboxContainer; - var html = ""; + var $el = this.element; // "element" is a jQuery object representing the underlying select + var $menu = this.$menu; + var $headerLinks = this.$headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip'); var $dropdown = $("
              ").addClass('ui-multiselect-checkboxes ui-helper-reset'); + this.inputIdCounter = 0; // update header link container visibility if needed if (this.options.header) { - if(!!el[0].multiple) { - this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip').show(); + if(!!$el[0].multiple) { + $headerLinks.show(); } else { - this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip').hide(); + $headerLinks.hide(); } } - this._buildOptionList(el, $dropdown); + this._buildOptionList($el, $dropdown); - this.menu.find(".ui-multiselect-checkboxes").remove(); - this.menu.append($dropdown); + this.$menu.find(".ui-multiselect-checkboxes").remove(); + this.$menu.append($dropdown); // cache some more useful elements - this.labels = menu.find('label'); - this.inputs = this.labels.children('input'); + this.$labels = $menu.find('label'); + this.$inputs = this.$labels.children('input'); this._setButtonWidth(); @@ -292,7 +292,7 @@ // updates the button text. call refresh() to rebuild update: function(isDefault) { var o = this.options; - var $inputs = this.inputs; + var $inputs = this.$inputs; var $checked = $inputs.filter(':checked'); var numChecked = $checked.length; var value; @@ -311,7 +311,7 @@ this._setButtonValue(value); if(isDefault) { - this.button[0].defaultValue = value; + this.$button[0].defaultValue = value; } }, @@ -319,61 +319,58 @@ // this exists as a separate method so that the developer // can easily override it. _setButtonValue: function(value) { - this.buttonlabel.text(value); + this.$buttonlabel.text(value); }, _bindButtonEvents: function() { var self = this; - var button = this.button; + var $button = this.$button; function clickHandler() { self[ self._isOpen ? 'close' : 'open' ](); return false; } - // webkit doesn't like it when you click on the span :( - button - .find('span') - .bind('click.multiselect', clickHandler); - - // button events - button.bind({ - click: clickHandler, - keypress: function(e) { - switch(e.which) { - case 27: // esc - case 38: // up - case 37: // left - self.close(); - break; - case 39: // right - case 40: // down - self.open(); - break; - } - }, - mouseenter: function() { - if(!button.hasClass('ui-state-disabled')) { - $(this).addClass('ui-state-hover'); - } - }, - mouseleave: function() { - $(this).removeClass('ui-state-hover'); - }, - focus: function() { - if(!button.hasClass('ui-state-disabled')) { - $(this).addClass('ui-state-focus'); - } - }, - blur: function() { - $(this).removeClass('ui-state-focus'); - } - }); + $button // button events + .on({ + click: clickHandler, + keypress: function(e) { + switch(e.which) { + case 27: // esc + case 38: // up + case 37: // left + self.close(); + break; + case 39: // right + case 40: // down + self.open(); + break; + } + }, + mouseenter: function() { + if(!$button.hasClass('ui-state-disabled')) { + $button.addClass('ui-state-hover'); + } + }, + mouseleave: function() { + $button.removeClass('ui-state-hover'); + }, + focus: function() { + if(!$button.hasClass('ui-state-disabled')) { + $button.addClass('ui-state-focus'); + } + }, + blur: function() { + $button.removeClass('ui-state-focus'); + } + }) + .find('span') // webkit doesn't like it when you click on the span :( + .on('click.multiselect', clickHandler); }, _bindMenuEvents: function() { var self = this; // optgroup label toggle support - this.menu.on('click.multiselect', '.ui-multiselect-optgroup a', function(e) { + this.$menu.on('click.multiselect', '.ui-multiselect-optgroup a', function(e) { e.preventDefault(); var $this = $(this); @@ -400,7 +397,7 @@ }) .on('mouseenter.multiselect', 'label', function() { if(!$(this).hasClass('ui-state-disabled')) { - self.labels.removeClass('ui-state-hover'); + self.$labels.removeClass('ui-state-hover'); $(this).addClass('ui-state-hover').find('input').focus(); } }) @@ -415,8 +412,8 @@ switch(e.which) { case 9: // tab if(e.shiftKey) { - self.menu.find(".ui-state-hover").removeClass("ui-state-hover"); - self.header.find("li").last().find("a").focus(); + self.$menu.find(".ui-state-hover").removeClass("ui-state-hover"); + self.$header.find("li").last().find("a").focus(); } else { self.close(); } @@ -451,7 +448,7 @@ var val = this.value; var optionText = $this.parent().find("span").text(); var checked = this.checked; - var tags = self.element.find('option'); + var $tags = self.element.find('option'); var isMultiple = !!self.element[0].multiple; // bail if this input is disabled or the event is cancelled @@ -468,7 +465,7 @@ $this.prop('aria-selected', checked); // change state on the original option tags - tags.each(function() { + $tags.each(function() { if(this.value === val) { this.selected = checked; } else if(!isMultiple) { @@ -478,7 +475,7 @@ // some additional single select-specific logic if(!isMultiple) { - self.labels.removeClass('ui-state-active'); + self.$labels.removeClass('ui-state-active'); $this.closest('label').toggleClass('ui-state-active', checked); // close menu @@ -497,7 +494,7 @@ _bindHeaderEvents: function() { var self = this; // header links - this.header.on('click.multiselect', 'a', function(e) { + this.$header.on('click.multiselect', 'a', function(e) { var $this = $(this); if($this.hasClass('ui-multiselect-close')) { self.close(); @@ -516,7 +513,7 @@ break; case 9: var $target = $(e.target); - if((e.shiftKey && !$target.parent().prev().length && !self.header.find(".ui-multiselect-filter").length) || (!$target.parent().next().length && !self.labels.length && !e.shiftKey)) { + if((e.shiftKey && !$target.parent().prev().length && !self.$header.find(".ui-multiselect-filter").length) || (!$target.parent().next().length && !self.$labels.length && !e.shiftKey)) { self.close(); e.preventDefault(); } @@ -534,14 +531,14 @@ this._bindHeaderEvents(); // close each widget when clicking on any other element/anywhere else on the page - $doc.bind('mousedown.' + self._namespaceID, function(event) { + $doc.on('mousedown.' + self._namespaceID, function(event) { var target = event.target; if(self._isOpen && - target !== self.button[0] && - target !== self.menu[0] && - !$.contains(self.menu[0], target) && - !$.contains(self.button[0], target) + target !== self.$button[0] && + target !== self.$menu[0] && + !$.contains(self.$menu[0], target) && + !$.contains(self.$button[0], target) ) { self.close(); } @@ -569,7 +566,7 @@ var lastChar = minVal[ minVal.length -1 ]; width = minVal.match(/\d+/); if(lastChar === '%') { - width = this.element.parent().outerWidth() * (width/100); + width = this.element.parent().outerWidth() * (width/100); // element is a jQuery object } else { width = parseInt(minVal, 10); } @@ -580,40 +577,40 @@ // set button width _setButtonWidth: function() { - var width = this.element.outerWidth(); + var width = this.element.outerWidth(); // element is a jQuery object var minVal = this._getMinWidth(); if(width < minVal) { width = minVal; } // set widths - this.button.outerWidth(width); + this.$button.outerWidth(width); }, // set menu width _setMenuWidth: function() { - var m = this.menu; - var width = (this.button.outerWidth() <= 0) ? this._getMinWidth() : this.button.outerWidth(); + var m = this.$menu; + var width = (this.$button.outerWidth() <= 0) ? this._getMinWidth() : this.$button.outerWidth(); m.outerWidth(this.options.menuWidth || width); }, // Sets the height of the menu // Will set a scroll bar if the menu height exceeds that of the height in options _setMenuHeight: function() { - var headerHeight = this.menu.children(".ui-multiselect-header:visible").outerHeight(true); + var headerHeight = this.$menu.children(".ui-multiselect-header:visible").outerHeight(true); var ulHeight = 0; - this.menu.find(".ui-multiselect-checkboxes li, .ui-multiselect-checkboxes a").each(function(idx, li) { + this.$menu.find(".ui-multiselect-checkboxes li, .ui-multiselect-checkboxes a").each(function(idx, li) { ulHeight += $(li).outerHeight(true); }); if(ulHeight > this.options.height) { - this.menu.children(".ui-multiselect-checkboxes").css("overflow", "auto"); + this.$menu.children(".ui-multiselect-checkboxes").css("overflow", "auto"); ulHeight = this.options.height; } else { - this.menu.children(".ui-multiselect-checkboxes").css("overflow", "hidden"); + this.$menu.children(".ui-multiselect-checkboxes").css("overflow", "hidden"); } - this.menu.children(".ui-multiselect-checkboxes").height(ulHeight); - this.menu.height(ulHeight + headerHeight); + this.$menu.children(".ui-multiselect-checkboxes").height(ulHeight); + this.$menu.height(ulHeight + headerHeight); }, // Resizes the menu, called every time the menu is opened @@ -636,10 +633,10 @@ // if at the first/last element if(!$next.length) { - var $container = this.menu.find('ul').last(); + var $container = this.$menu.find('ul').last(); // move to the first/last - this.menu.find('label:visible')[ moveToLast ? 'last' : 'first' ]().trigger('mouseover'); + this.$menu.find('label:visible')[ moveToLast ? 'last' : 'first' ]().trigger('mouseover'); // set scroll position $container.scrollTop(moveToLast ? $container.height() : 0); @@ -671,8 +668,9 @@ // Toggles checked state on either an option group or all inputs _toggleChecked: function(flag, group) { - var $inputs = (group && group.length) ? group : this.inputs; + var $inputs = (group && group.length) ? group : this.$inputs; var self = this; + var $el = this.element; // element is a jQuery object // toggle state on inputs $inputs.each(this._toggleState('checked', flag)); @@ -690,8 +688,8 @@ }); // toggle state on original option tags - this.element.selectedIndex = -1; - this.element + $el.selectedIndex = -1; + $el .find('option') .each(function() { if(!this.disabled && values[this.value]) { @@ -701,16 +699,16 @@ // trigger the change event on the select if($inputs.length) { - this.element.trigger("change"); + $el.trigger("change"); } }, // Toggle disable state on the widget and underlying select _toggleDisabled: function(flag) { - this.button.prop({ 'disabled':flag, 'aria-disabled':flag })[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled'); + this.$button.prop({ 'disabled':flag, 'aria-disabled':flag })[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled'); if(this.options.disableInputsOnToggle) { - var checkboxes = this.menu.find(".ui-multiselect-checkboxes").get(0); + var checkboxes = this.$menu.find(".ui-multiselect-checkboxes").get(0); var matchedInputs = []; var key = "ech-multiselect-disabled"; var i = 0; @@ -746,18 +744,18 @@ // open the menu open: function(e) { var self = this; - var button = this.button; - var menu = this.menu; + var $button = this.$button; + var $menu = this.$menu; var speed = this.speed; var o = this.options; var args = []; // bail if the multiselectopen event returns false, this widget is disabled, or is already open - if(this._trigger('beforeopen') === false || button.hasClass('ui-state-disabled') || this._isOpen) { + if(this._trigger('beforeopen') === false || $button.hasClass('ui-state-disabled') || this._isOpen) { return; } - var $container = menu.find('.ui-multiselect-checkboxes'); + var $container = $menu.find('.ui-multiselect-checkboxes'); var effect = o.show; // figure out opening effects/speeds @@ -776,7 +774,7 @@ $container.scrollTop(0); // show the menu, maybe with a speed/effect combo - $.fn.show.apply(menu, args); + $.fn.show.apply($menu, args); this._resizeMenu(); // positon @@ -784,17 +782,16 @@ // select the first not disabled option or the filter input if available - var filter = this.header.find(".ui-multiselect-filter"); + var filter = this.$header.find(".ui-multiselect-filter"); if(filter.length) { filter.first().find('input').trigger('focus'); - } else if(this.labels.length){ - this.labels.filter(':not(.ui-state-disabled)').eq(0).trigger('mouseover').trigger('mouseenter').find('input').trigger('focus'); + } else if(this.$labels.length){ + this.$labels.filter(':not(.ui-state-disabled)').eq(0).trigger('mouseover').trigger('mouseenter').find('input').trigger('focus'); } else { - this.header.find('a').first().trigger('focus'); + this.$header.find('a').first().trigger('focus'); } - - button.addClass('ui-state-active'); + $button.addClass('ui-state-active'); this._isOpen = true; this._trigger('open'); }, @@ -810,7 +807,7 @@ var speed = this.speed; var args = []; - // figure out opening effects/speeds + // figure out closing effects/speeds if($.isArray(o.hide)) { effect = o.hide[0]; speed = o.hide[1] || this.speed; @@ -820,11 +817,11 @@ args = [ effect, speed ]; } - $.fn.hide.apply(this.menu, args); - this.button.removeClass('ui-state-active').trigger('blur').trigger('mouseleave'); + $.fn.hide.apply(this.$menu, args); + this.$button.removeClass('ui-state-active').trigger('blur').trigger('mouseleave'); this._isOpen = false; this._trigger('close'); - this.button.trigger('focus'); + this.$button.trigger('focus'); }, enable: function() { @@ -842,7 +839,7 @@ uncheckAll: function() { this._toggleChecked(false); - if ( !this.element[0].multiple ) + if ( !this.element[0].multiple ) // element is a jQuery object this.element[0].selectedIndex = -1; // Forces the underlying single-select to have no options selected. this._trigger('uncheckAll'); }, @@ -853,11 +850,11 @@ }, getChecked: function() { - return this.menu.find('input').filter(':checked'); + return this.$menu.find('input').filter(':checked'); }, getUnchecked: function() { - return this.menu.find('input').not(':checked'); + return this.$menu.find('input').not(':checked'); }, destroy: function() { @@ -865,11 +862,11 @@ $.Widget.prototype.destroy.call(this); // unbind events - $doc.unbind(this._namespaceID); - $(this.element[0].form).unbind(this._namespaceID); + $doc.off(this._namespaceID); + $(this.element[0].form).off(this._namespaceID); // element is a jQuery object - this.button.remove(); - this.menu.remove(); + this.$button.remove(); + this.$menu.remove(); this.element.show(); return this; @@ -880,19 +877,19 @@ }, widget: function() { - return this.menu; + return this.$menu; }, getButton: function() { - return this.button; + return this.$button; }, getMenu: function() { - return this.menu; + return this.$menu; }, getLabels: function() { - return this.labels; + return this.$labels; }, /* @@ -908,16 +905,16 @@ this.element.children("OPTGROUP").filter(function() { return $(this).prop("label") === groupLabel; }).append($option); - this.menu.find(".ui-multiselect-optgroup").filter(function() { + this.$menu.find(".ui-multiselect-optgroup").filter(function() { return $(this).find("a").text() === groupLabel; }).append(this._makeOption(optionNode)); } else { this.element.append($option); - this.menu.find(".ui-multiselect-checkboxes").append(this._makeOption(optionNode)); + this.$menu.find(".ui-multiselect-checkboxes").append(this._makeOption(optionNode)); } //update cached elements - this.labels = this.menu.find('label'); - this.inputs = this.labels.children('input'); + this.$labels = this.$menu.find('label'); + this.$inputs = this.$labels.children('input'); }, removeOption: function(value) { @@ -925,18 +922,18 @@ return; } this.element.find("option[value=" + value + "]").remove(); - this.labels.find("input[value=" + value + "]").parents("li").remove(); + this.$labels.find("input[value=" + value + "]").parents("li").remove(); //update cached elements - this.labels = this.menu.find('label'); - this.inputs = this.labels.children('input'); + this.$labels = this.$menu.find('label'); + this.$inputs = this.$labels.children('input'); }, position: function() { var pos = { my: "top", at: "bottom", - of: this.button + of: this.$button }; if(!$.isEmptyObject(this.options.position)) { pos.my = this.options.position.my || pos.my; @@ -944,50 +941,42 @@ pos.of = this.options.position.of || pos.of; } if($.ui && $.ui.position) { - this.menu.position(pos); + this.$menu.position(pos); } else { - pos = this.button.position(); - pos.top += this.button.outerHeight(false); - this.menu.offset(pos); + pos = this.$button.position(); + pos.top += this.$button.outerHeight(false); + this.$menu.offset(pos); } }, // react to option changes after initialization _setOption: function(key, value) { - var menu = this.menu; + var $menu = this.$menu; switch(key) { case 'header': if(typeof value === 'boolean') { - this.header[value ? 'show' : 'hide'](); + this.$header[value ? 'show' : 'hide'](); } else if(typeof value === 'string') { - this.headerLinkContainer.children("li:not(:last-child)").remove(); - this.headerLinkContainer.prepend("
            • " + value + "
            • "); + this.$headerLinkContainer.children("li:not(:last-child)").remove(); + this.$headerLinkContainer.prepend("
            • " + value + "
            • "); } break; case 'checkAllText': - menu.find('a.ui-multiselect-all span').eq(-1).text(value); // eq(-1) finds the last span - break; case 'uncheckAllText': - menu.find('a.ui-multiselect-none span').eq(-1).text(value); - break; case 'flipAllText': - menu.find('a.ui-multiselect-flip span').eq(-1).text(value); + $menu.find('a.ui-multiselect-' + {checkAllText: 'all', uncheckAllText: 'none', flipAllText: 'flip'}[key] + ' span').eq(-1).text(value); // eq(-1) finds the last span break; case 'checkAllIcon': - menu.find('a.ui-multiselect-all span').eq(0).replaceWith(value); - break; case 'uncheckAllIcon': - menu.find('a.ui-multiselect-none span').eq(0).replaceWith(value); - break; case 'flipAllIcon': - menu.find('a.ui-multiselect-flip span').eq(0).replaceWith(value); + $menu.find('a.ui-multiselect-' + {checkAllIcon: 'all', uncheckAllIcon: 'none', flipAllIcon: 'flip'}[key] + ' span').eq(0).replaceWith(value); // eq(0) finds the first span break; case 'openIcon': - menu.find('span.ui-multiselect-open').html(value); + $menu.find('span.ui-multiselect-open').html(value); break; case 'closeIcon': - menu.find('a.ui-multiselect-close').html(value); + $menu.find('a.ui-multiselect-close').html(value); break; case 'height': this.options[key] = value; @@ -1006,13 +995,13 @@ this.update(); break; case 'classes': - menu.add(this.button).removeClass(this.options.classes).addClass(value); + $menu.add(this.$button).removeClass(this.options.classes).addClass(value); break; case 'multiple': var el_0 = this.element[0]; if (!!el_0.multiple != value) { - menu.toggleClass('ui-multiselect-multiple', value); - menu.toggleClass('ui-multiselect-single', !value); + $menu.toggleClass('ui-multiselect-multiple', value); + $menu.toggleClass('ui-multiselect-single', !value); el_0.multiple = value; this.uncheckAll(); this.refresh(); From 5d0f625ec143b13ddeaaa419bae2653915a8ef60 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 13:59:13 -0800 Subject: [PATCH 2/9] $variable naming and ditch bind bind() is deprecated. Use on() instead. --- src/jquery.multiselect.filter.js | 65 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/jquery.multiselect.filter.js b/src/jquery.multiselect.filter.js index 435920d..9c873d6 100644 --- a/src/jquery.multiselect.filter.js +++ b/src/jquery.multiselect.filter.js @@ -1,11 +1,12 @@ /* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */ /* - * jQuery MultiSelect UI Widget Filtering Plugin 2.0.0 + * jQuery MultiSelect UI Widget Filtering Plugin 3.0.0 * Copyright (c) 2012 Eric Hynds * * http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/ * * Depends: + * - jQuery 1.7+ * - jQuery UI MultiSelect widget * * Dual licensed under the MIT and GPL licenses: @@ -48,30 +49,30 @@ _create: function() { var opts = this.options; - var elem = $(this.element); + var $elem = this.element; // get the multiselect instance - this.instance = elem.multiselect('instance'); + this.instance = $elem.multiselect('instance'); // store header; add filter class so the close/check all/uncheck all links can be positioned correctly - this.header = this.instance.menu.find('.ui-multiselect-header').addClass('ui-multiselect-hasfilter'); + this.$header = this.instance.$menu.find('.ui-multiselect-header').addClass('ui-multiselect-hasfilter'); - // wrapper elem - this.input = $("").attr({ + // wrapper $elem + this.$input = $("").attr({ placeholder: opts.placeholder, type: "search" }).css({ width: (/\d/.test(opts.width) ? opts.width + 'px' : null) - }).bind({ + }).on({ keydown: function(e) { // prevent the enter key from submitting the form / closing the widget if(e.which === 13) { e.preventDefault(); } else if(e.which === 27) { - elem.multiselect('close'); + $elem.multiselect('close'); e.preventDefault(); } else if(e.which === 9 && e.shiftKey) { - elem.multiselect('close'); + $elem.multiselect('close'); e.preventDefault(); } else if(e.altKey) { switch(e.which) { @@ -80,13 +81,13 @@ $(this).val('').trigger('input', ''); break; case 65: - elem.multiselect('checkAll'); + $elem.multiselect('checkAll'); break; case 85: - elem.multiselect('uncheckAll'); + $elem.multiselect('uncheckAll'); break; case 76: - elem.multiselect('instance').labels.first().trigger("mouseenter"); + $elem.multiselect('instance').$labels.first().trigger("mouseenter"); break; } } @@ -96,25 +97,25 @@ }); // automatically reset the widget on close? if(this.options.autoReset) { - elem.bind('multiselectclose', $.proxy(this._reset, this)); + $elem.on('multiselectclose', $.proxy(this._reset, this)); } // rebuild cache when multiselect is updated - elem.bind('multiselectrefresh', $.proxy(function() { + $elem.on('multiselectrefresh', $.proxy(function() { this.updateCache(); this._handler(); }, this)); - this.wrapper = $("
              ").addClass("ui-multiselect-filter").text(opts.label).append(this.input).prependTo(this.header); + this.$wrapper = $("
              ").addClass("ui-multiselect-filter").text(opts.label).append(this.$input).prependTo(this.$header); // reference to the actual inputs - this.inputs = this.instance.menu.find('input[type="checkbox"], input[type="radio"]'); + this.$inputs = this.instance.$menu.find('input[type="checkbox"], input[type="radio"]'); // cache input values for searching this.updateCache(); // rewrite internal _toggleChecked fn so that when checkAll/uncheckAll is fired, - // only the currently filtered elements are checked + // only the currently filtered $elements are checked this.instance._toggleChecked = function(flag, group) { - var $inputs = (group && group.length) ? group : this.labels.find('input'); + var $inputs = (group && group.length) ? group : this.$labels.find('input'); var _self = this; // do not include hidden elems if the menu isn't open. @@ -149,11 +150,11 @@ // thx for the logic here ben alman _handler: function(e) { - var term = $.trim(this.input[0].value.toLowerCase()), + var term = $.trim(this.$input[0].value.toLowerCase()), // speed up lookups - rows = this.rows, inputs = this.inputs, cache = this.cache; - var $groups = this.instance.menu.find(".ui-multiselect-optgroup"); + rows = this.rows, $inputs = this.$inputs, $cache = this.$cache; + var $groups = this.instance.$menu.find(".ui-multiselect-optgroup"); $groups.show(); if(!term) { rows.show(); @@ -162,10 +163,10 @@ var regex = new RegExp(term.replace(rEscape, "\\$&"), 'gi'); - this._trigger("filter", e, $.map(cache, function(v, i) { + this._trigger("filter", e, $.map($cache, function(v, i) { if(v.search(regex) !== -1) { rows.eq(i).show(); - return inputs.get(i); + return $inputs.get(i); } return null; @@ -183,36 +184,36 @@ }, _reset: function() { - this.input.val('').trigger('input', ''); + this.$input.val('').trigger('input', ''); }, updateCache: function() { // each list item - this.rows = this.instance.labels.parent(); + this.rows = this.instance.$labels.parent(); // cache - this.cache = this.element.children().map(function() { - var elem = $(this); + this.$cache = this.element.children().map(function() { + var $elem = $(this); // account for optgroups if(this.tagName.toLowerCase() === "optgroup") { - elem = elem.children(); + $elem = $elem.children(); } - return elem.map(function() { + return $elem.map(function() { return this.innerHTML.toLowerCase(); }).get(); }).get(); }, widget: function() { - return this.wrapper; + return this.$wrapper; }, destroy: function() { $.Widget.prototype.destroy.call(this); - this.input.val('').trigger("keyup"); - this.wrapper.remove(); + this.$input.val('').trigger("keyup"); + this.$wrapper.remove(); } }); From e8921e8564c7f2b570a4c54ceff39461055b6b90 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 14:12:35 -0800 Subject: [PATCH 3/9] Update limited selectedList/checkAll test Changed the default selectedText to be "# of # selected" so that developers will be aware that this form is available. (It always has been available..) --- tests/unit/options.js | 592 +++++++++++++++++++++--------------------- 1 file changed, 296 insertions(+), 296 deletions(-) diff --git a/tests/unit/options.js b/tests/unit/options.js index 3388170..5ca530a 100644 --- a/tests/unit/options.js +++ b/tests/unit/options.js @@ -1,182 +1,182 @@ (function($){ - module("options"); + module("options"); - test("noneSelectedText", function(){ - expect(7); - var text; + test("noneSelectedText", function(){ + expect(7); + var text; - el = $("select").multiselect({ - noneSelectedText: 'None Selected' - }); + el = $("select").multiselect({ + noneSelectedText: 'None Selected' + }); - // read from widget - text = el.multiselect("option", "noneSelectedText"); + // read from widget + text = el.multiselect("option", "noneSelectedText"); - equals( button().text(), text, 'on init, button reads "None Selected"'); - el.multiselect("checkAll"); - ok( button().text() !== text, 'after checkAll, button no longer reads "None Selected"'); - el.multiselect("uncheckAll"); - equals( button().text(), text, 'after uncheckAll, button text restored to "None Selected"'); + equals( button().text(), text, 'on init, button reads "None Selected"'); + el.multiselect("checkAll"); + ok( button().text() !== text, 'after checkAll, button no longer reads "None Selected"'); + el.multiselect("uncheckAll"); + equals( button().text(), text, 'after uncheckAll, button text restored to "None Selected"'); - // change the option value - el.multiselect("option", "noneSelectedText", "No Checkboxes Checked"); - equals( el.multiselect("option", "noneSelectedText"), "No Checkboxes Checked", "new noneSelectedText value set correctly"); + // change the option value + el.multiselect("option", "noneSelectedText", "No Checkboxes Checked"); + equals( el.multiselect("option", "noneSelectedText"), "No Checkboxes Checked", "new noneSelectedText value set correctly"); - // read updated value from widget - text = el.multiselect("option", "noneSelectedText"); + // read updated value from widget + text = el.multiselect("option", "noneSelectedText"); - // test against the new value - equals( button().text(), text, 'after changing the option value, button now reads "No Checkboxes Checked"'); - el.multiselect("checkAll"); - ok( button().text() !== text, 'after checkAll, button no longer reads "No Checkboxes Checked"'); - el.multiselect("uncheckAll"); - equals( button().text(), text, 'after uncheckAll, button text restored to "No Checkboxes Checked"'); + // test against the new value + equals( button().text(), text, 'after changing the option value, button now reads "No Checkboxes Checked"'); + el.multiselect("checkAll"); + ok( button().text() !== text, 'after checkAll, button no longer reads "No Checkboxes Checked"'); + el.multiselect("uncheckAll"); + equals( button().text(), text, 'after uncheckAll, button text restored to "No Checkboxes Checked"'); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); - test("selectedText", function(){ - expect(3); - var numOptions = $("select option").length; + test("selectedText", function(){ + expect(3); + var numOptions = $("select option").length; - el = $("select").multiselect({ - selectedText: '# of # selected' - }); + el = $("select").multiselect({ + selectedText: '# of # selected' + }); - el.multiselect("checkAll"); - equals( button().text(), numOptions+' of '+numOptions+' selected', 'after checkAll, button reflects the total number of checked boxes'); + el.multiselect("checkAll"); + equals( button().text(), numOptions+' of '+numOptions+' selected', 'after checkAll, button reflects the total number of checked boxes'); - // change option value - el.multiselect("option", "selectedText", function( numChecked ){ - return numChecked + ' options selected'; - }); + // change option value + el.multiselect("option", "selectedText", function( numChecked ){ + return numChecked + ' options selected'; + }); - equals( button().text(), numOptions+' options selected', 'after changing the option to a function value, button reflects the new text'); + equals( button().text(), numOptions+' options selected', 'after changing the option to a function value, button reflects the new text'); - // uncheck all - el.multiselect("uncheckAll"); - equals( button().text(), el.multiselect("option","noneSelectedText"), 'after unchecking all, button text now reflects noneSelectedText option value'); + // uncheck all + el.multiselect("uncheckAll"); + equals( button().text(), el.multiselect("option","noneSelectedText"), 'after unchecking all, button text now reflects noneSelectedText option value'); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); - test("selectedList", function(){ - expect(2); + test("selectedList", function(){ + expect(2); - var html = ''; + var html = ''; - el = $(html).appendTo("body").multiselect({ - selectedList: 3 - }); + el = $(html).appendTo("body").multiselect({ + selectedList: 3 + }); - el.multiselect("checkAll"); - equals( button().text(), 'foo "with quotes", bar, baz', 'after checkAll, button text is a list of all options in the select'); - el.multiselect("destroy").remove(); + el.multiselect("checkAll"); + equals( button().text(), 'foo "with quotes", bar, baz', 'after checkAll, button text is a list of all options in the select'); + el.multiselect("destroy").remove(); - el = $(html).appendTo("body").multiselect({ - selectedList: 2 - }); + el = $(html).appendTo("body").multiselect({ + selectedList: 2 + }); - el.multiselect("checkAll"); - equals( button().text(), '3 selected', 'after checkAll with a limited selectedList value, button value displays number of checked'); - el.multiselect("destroy").remove(); - }); + el.multiselect("checkAll"); + equals( button().text(), '3 of 3 selected', 'after checkAll with a limited selectedList value, button value displays number of checked'); + el.multiselect("destroy").remove(); + }); - function asyncSelectedList( useTrigger, message ){ - expect(1); - stop(); + function asyncSelectedList( useTrigger, message ){ + expect(1); + stop(); - var html = '', - checkboxes; + var html = '', + checkboxes; - el = $(html).appendTo(body).multiselect({ - selectedList: 2 - }); + el = $(html).appendTo(body).multiselect({ + selectedList: 2 + }); - checkboxes = el.multiselect("widget").find(":checkbox"); + checkboxes = el.multiselect("widget").find(":checkbox"); - if( useTrigger ){ - checkboxes.eq(0).trigger('click'); - checkboxes.eq(1).trigger('click'); - } else { - checkboxes.eq(0)[0].click(); - checkboxes.eq(1)[0].click(); - } + if( useTrigger ){ + checkboxes.eq(0).trigger('click'); + checkboxes.eq(1).trigger('click'); + } else { + checkboxes.eq(0)[0].click(); + checkboxes.eq(1)[0].click(); + } - setTimeout(function(){ - equals( button().text(), 'foo, bar', message); - el.multiselect("destroy").remove(); - start(); - }, 10); - } + setTimeout(function(){ + equals( button().text(), 'foo, bar', message); + el.multiselect("destroy").remove(); + start(); + }, 10); + } - test("selectedList - manual trigger - jQuery", function(){ - asyncSelectedList( true, 'manually checking items with trigger()' ); - }); + test("selectedList - manual trigger - jQuery", function(){ + asyncSelectedList( true, 'manually checking items with trigger()' ); + }); - test("selectedList - manual trigger - native", function(){ - asyncSelectedList( false, 'manually checking items with element.click()' ); - }); + test("selectedList - manual trigger - native", function(){ + asyncSelectedList( false, 'manually checking items with element.click()' ); + }); - test("selectedList - encoding", function() { - expect(1); + test("selectedList - encoding", function() { + expect(1); - el = $('') - .appendTo("body") - .multiselect({ selectedList: 1 }); + el = $('') + .appendTo("body") + .multiselect({ selectedList: 1 }); - equals(button().text(), 'A&E'); - el.multiselect("destroy").remove(); - }); + equals(button().text(), 'A&E'); + el.multiselect("destroy").remove(); + }); - test("height", function(){ - expect(2); + test("height", function(){ + expect(2); - var height = 100; + var height = 100; - el = $("select").multiselect({ height: height }).multiselect("open"); - equals( height, menu().find("ul.ui-multiselect-checkboxes").height(), 'height after opening property set to '+ height ); + el = $("select").multiselect({ height: height }).multiselect("open"); + equals( height, menu().find("ul.ui-multiselect-checkboxes").height(), 'height after opening property set to '+ height ); - // change height and re-test - height = 300; - el.multiselect("option", "height", height); - equals( height, menu().find(".ui-multiselect-checkboxes").height(), 'changing value through api to '+ height ); + // change height and re-test + height = 300; + el.multiselect("option", "height", height); + equals( height, menu().find(".ui-multiselect-checkboxes").height(), 'changing value through api to '+ height ); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); - test("minWidth", function(){ - expect(5); + test("minWidth", function(){ + expect(5); - var minWidth = 321; + var minWidth = 321; - el = $("select").multiselect({ minWidth:minWidth }).multiselect("open"); - equals( minWidth, button().outerWidth(), 'outerWidth of button is ' + minWidth ); + el = $("select").multiselect({ minWidth:minWidth }).multiselect("open"); + equals( minWidth, button().outerWidth(), 'outerWidth of button is ' + minWidth ); - // change height and re-test - minWidth = 351; - el.multiselect("option", "minWidth", minWidth); - equals( minWidth, button().outerWidth(), 'changing value through api to '+minWidth); + // change height and re-test + minWidth = 351; + el.multiselect("option", "minWidth", minWidth); + equals( minWidth, button().outerWidth(), 'changing value through api to '+minWidth); - // change height to something that should fail. - minWidth = 10; - el.multiselect("option", "minWidth", minWidth); - var outerWidth = button().outerWidth(); - ok( minWidth !== outerWidth, 'changing value through api to '+minWidth+' (too small), outerWidth is actually ' + outerWidth); + // change height to something that should fail. + minWidth = 10; + el.multiselect("option", "minWidth", minWidth); + var outerWidth = button().outerWidth(); + ok( minWidth !== outerWidth, 'changing value through api to '+minWidth+' (too small), outerWidth is actually ' + outerWidth); - minWidth = "50%"; - el.multiselect("option", "minWidth", minWidth); - outerWidth = Math.floor(button().outerWidth()); - var halfParent = Math.floor(el.parent().outerWidth()/2); - ok(outerWidth === halfParent, 'changing value to 50%'); + minWidth = "50%"; + el.multiselect("option", "minWidth", minWidth); + outerWidth = Math.floor(button().outerWidth()); + var halfParent = Math.floor(el.parent().outerWidth()/2); + ok(outerWidth === halfParent, 'changing value to 50%'); - minWidth = "351px"; - el.multiselect("option", "minWidth", minWidth); - equals( 351, button().outerWidth(), 'minWidth supports strings suffixed with px as well as integer px values'); + minWidth = "351px"; + el.multiselect("option", "minWidth", minWidth); + equals( 351, button().outerWidth(), 'minWidth supports strings suffixed with px as well as integer px values'); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); test("menuWidth", function(){ expect(2); @@ -194,193 +194,193 @@ el.multiselect("destroy"); }); - test("checkAllText", function(){ - expect(2); - var text = "foo"; + test("checkAllText", function(){ + expect(2); + var text = "foo"; - el = $("select").multiselect({ checkAllText:text, showCheckAll:true }); - equals( text, menu().find(".ui-multiselect-all").text(), 'check all link reads '+text ); + el = $("select").multiselect({ checkAllText:text, showCheckAll:true }); + equals( text, menu().find(".ui-multiselect-all").text(), 'check all link reads '+text ); - // set through option - text = "bar"; - el.multiselect("option","checkAllText","bar"); - equals( text, menu().find(".ui-multiselect-all").text(), 'check all link reads '+text ); + // set through option + text = "bar"; + el.multiselect("option","checkAllText","bar"); + equals( text, menu().find(".ui-multiselect-all").text(), 'check all link reads '+text ); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); - test("uncheckAllText", function(){ - expect(2); - var text = "foo"; + test("uncheckAllText", function(){ + expect(2); + var text = "foo"; - el = $("select").multiselect({ uncheckAllText:text, showUncheckAll:true }); - equals( text, menu().find(".ui-multiselect-none").text(), 'check all link reads '+text ); + el = $("select").multiselect({ uncheckAllText:text, showUncheckAll:true }); + equals( text, menu().find(".ui-multiselect-none").text(), 'check all link reads '+text ); - // set through option - text = "bar"; - el.multiselect("option","uncheckAllText","bar"); - equals( text, menu().find(".ui-multiselect-none").text(), 'changing value through api to '+text ); + // set through option + text = "bar"; + el.multiselect("option","uncheckAllText","bar"); + equals( text, menu().find(".ui-multiselect-none").text(), 'changing value through api to '+text ); - el.multiselect("destroy"); - }); + el.multiselect("destroy"); + }); - test("flipAllText", function(){ - expect(2); - var text = "foo"; + test("flipAllText", function(){ + expect(2); + var text = "foo"; - el = $("select").multiselect({ flipAllText:text, showFlipAll:true }); - equals( text, menu().find(".ui-multiselect-flip").text(), 'flip all link reads '+text ); + el = $("select").multiselect({ flipAllText:text, showFlipAll:true }); + equals( text, menu().find(".ui-multiselect-flip").text(), 'flip all link reads '+text ); - // set through option - text = "bar"; - el.multiselect("option","flipAllText","bar"); - equals( text, menu().find(".ui-multiselect-flip").text(), 'changing value through api to '+text ); + // set through option + text = "bar"; + el.multiselect("option","flipAllText","bar"); + equals( text, menu().find(".ui-multiselect-flip").text(), 'changing value through api to '+text ); - el.multiselect("destroy"); - }); - - test("autoOpen", function(){ - expect(2); + el.multiselect("destroy"); + }); - el = $("select").multiselect({ autoOpen:false }); + test("autoOpen", function(){ + expect(2); - ok( menu().is(":hidden"), 'menu is hidden with autoOpen off'); - el.multiselect("destroy"); + el = $("select").multiselect({ autoOpen:false }); - el = $("select").multiselect({ autoOpen:true }); - ok( menu().is(":visible"), 'menu is visible with autoOpen on'); - el.multiselect("destroy"); + ok( menu().is(":hidden"), 'menu is hidden with autoOpen off'); + el.multiselect("destroy"); - // no built in support for change on the fly; not testing it. - }); + el = $("select").multiselect({ autoOpen:true }); + ok( menu().is(":visible"), 'menu is visible with autoOpen on'); + el.multiselect("destroy"); - test("multiple (false - single select)", function(){ - expect(10); + // no built in support for change on the fly; not testing it. + }); - $("select").removeAttr("multiple"); - el = $("select").multiselect({ multiple:false }); + test("multiple (false - single select)", function(){ + expect(10); - // get some references - var $menu = menu(), $header = header(); + $("select").removeAttr("multiple"); + el = $("select").multiselect({ multiple:false }); - ok( $header.find('a.ui-multiselect-all').is(':hidden'), 'select all link is hidden' ); - ok( $header.find('a.ui-multiselect-none').is(':hidden'), 'select none link is hidden' ); - ok( $header.find('a.ui-multiselect-close').css('display') !== 'hidden', 'close link is visible' ); - ok( !$menu.find(":checkbox").length, 'no checkboxes are present'); - ok( $menu.find(":radio").length > 0, 'but radio boxes are'); + // get some references + var $menu = menu(), $header = header(); - // simulate click on ALL radios - var radios = $menu.find(":radio").trigger("click"); + ok( $header.find('a.ui-multiselect-all').is(':hidden'), 'select all link is hidden' ); + ok( $header.find('a.ui-multiselect-none').is(':hidden'), 'select none link is hidden' ); + ok( $header.find('a.ui-multiselect-close').css('display') !== 'hidden', 'close link is visible' ); + ok( !$menu.find(":checkbox").length, 'no checkboxes are present'); + ok( $menu.find(":radio").length > 0, 'but radio boxes are'); - // at the end of that, only one radio should be checked and the menu closed - equals( radios.filter(":checked").length, 1, 'After checking all radios, only one is actually checked'); - equals( false, el.multiselect('isOpen'), 'Menu is closed' ); + // simulate click on ALL radios + var radios = $menu.find(":radio").trigger("click"); - // uncheck boxes... should only be one - radios.filter(":checked").trigger("click"); + // at the end of that, only one radio should be checked and the menu closed + equals( radios.filter(":checked").length, 1, 'After checking all radios, only one is actually checked'); + equals( false, el.multiselect('isOpen'), 'Menu is closed' ); - // method calls - el.multiselect("checkAll"); - equals( $menu.find("input:radio:checked").length, 1, 'After checkAll method call only one is actually checked'); - - el.multiselect("uncheckAll"); - equals( $menu.find("input:radio:checked").length, 0, 'After uncheckAll method nothing is checked'); - - // check/uncheck all links - equals( $menu.find(".ui-multiselect-all, ui-multiselect-none").filter(":visible").length, 0, "Check/uncheck all links don't exist"); - - el.multiselect("destroy"); - $("select").attr("multiple","multiple"); - }); - - test("multiple (changing dynamically)", function(){ - expect(6); - - el = $('') - .appendTo("body") - .multiselect(); - - el.multiselect("option", "multiple", false); - equals(el[0].multiple, false, "When changing a multiple select to a single select, the select element no longer has the multiple property"); - equals(menu().hasClass("ui-multiselect-single"), true, "...and the menu now has the single select class"); - equals(menu().find('input[type="radio"]').length, 1, "...and the checkbox is now a radio button"); - - el.multiselect("option", "multiple", true); - equals(el[0].multiple, true, "When changing a single select to a multiple select, the select element has the multiple property"); - equals(menu().hasClass("ui-multiselect-single"), false, "...and the menu doesn't have the single select class"); - equals(menu().find('input[type="checkbox"]').length, 1, "...and the radio button is now a checkbox"); - - el.multiselect("destroy").remove(); - }); - - test("classes", function(){ - expect(6); - - var classname = 'foo'; - - el = $("select").multiselect({ classes:classname }); - var $button = button(), $widget = menu(); - - equals( $widget.hasClass(classname), true, 'menu has the class ' + classname); - equals( $button.hasClass(classname), true, 'button has the class ' + classname); - - // change it up - var newclass = 'bar'; - el.multiselect("option", "classes", newclass); - equals( $widget.hasClass(newclass), true, 'menu has the new class ' + newclass); - equals( $button.hasClass(newclass), true, 'button has the new class ' + newclass); - equals( $button.hasClass(classname), false, 'menu no longer has the class ' + classname); - equals( $button.hasClass(classname), false, 'button no longer has the class ' + classname); - el.multiselect("destroy"); - }); - - test("header", function(){ - expect(7); - - function countLinks(){ - return header().find("a").length; - } - - // default - el = $("select").multiselect({ autoOpen:true }); - ok(header().is(':visible'), "default config: header is visible" ); - el.multiselect("option", "header", false); - ok(header().is(':hidden'), "after changing header option on default config: header is no longer visible" ); - - // test for all links within the default header - equals(countLinks(), 3, "number of links in the default header config"); - - el.multiselect("destroy"); - - // create again, this time header false - el = $("select").multiselect({ header:false, autoOpen:true }); - ok(header().is(':hidden'), "init with header false: header is not visible" ); - el.multiselect("option", "header", true); - ok(header().is(':visible'), "after changing header option: header is visible" ); - - el.multiselect("destroy"); - - // create again, this time custom header - el = $("select").multiselect({ header:"hai guyz", autoOpen:true }); - equals(header().text(), "hai guyz", "header equals custom text"); - equals(countLinks(), 1, "number of links in the custom header config (should be close button)"); - - el.multiselect("destroy"); - }); - test("openIcon", function(){ - expect(1); - var icon = ''; - el = $("select").multiselect({ openIcon:icon }); - equals(button().find(".ui-multiselect-open").find(".ui-icon-search").length, 1); - el.multiselect("destroy"); - }); - test("closeIcon", function(){ - expect(1); - var icon = ''; - el = $("select").multiselect({ autoOpen:true, closeIcon:icon }); - equals(menu().find(".ui-multiselect-close").find(".ui-icon-search").length, 1); - el.multiselect("destroy"); - }); + // uncheck boxes... should only be one + radios.filter(":checked").trigger("click"); + + // method calls + el.multiselect("checkAll"); + equals( $menu.find("input:radio:checked").length, 1, 'After checkAll method call only one is actually checked'); + + el.multiselect("uncheckAll"); + equals( $menu.find("input:radio:checked").length, 0, 'After uncheckAll method nothing is checked'); + + // check/uncheck all links + equals( $menu.find(".ui-multiselect-all, ui-multiselect-none").filter(":visible").length, 0, "Check/uncheck all links don't exist"); + + el.multiselect("destroy"); + $("select").attr("multiple","multiple"); + }); + + test("multiple (changing dynamically)", function(){ + expect(6); + + el = $('') + .appendTo("body") + .multiselect(); + + el.multiselect("option", "multiple", false); + equals(el[0].multiple, false, "When changing a multiple select to a single select, the select element no longer has the multiple property"); + equals(menu().hasClass("ui-multiselect-single"), true, "...and the menu now has the single select class"); + equals(menu().find('input[type="radio"]').length, 1, "...and the checkbox is now a radio button"); + + el.multiselect("option", "multiple", true); + equals(el[0].multiple, true, "When changing a single select to a multiple select, the select element has the multiple property"); + equals(menu().hasClass("ui-multiselect-single"), false, "...and the menu doesn't have the single select class"); + equals(menu().find('input[type="checkbox"]').length, 1, "...and the radio button is now a checkbox"); + + el.multiselect("destroy").remove(); + }); + + test("classes", function(){ + expect(6); + + var classname = 'foo'; + + el = $("select").multiselect({ classes:classname }); + var $button = button(), $widget = menu(); + + equals( $widget.hasClass(classname), true, 'menu has the class ' + classname); + equals( $button.hasClass(classname), true, 'button has the class ' + classname); + + // change it up + var newclass = 'bar'; + el.multiselect("option", "classes", newclass); + equals( $widget.hasClass(newclass), true, 'menu has the new class ' + newclass); + equals( $button.hasClass(newclass), true, 'button has the new class ' + newclass); + equals( $button.hasClass(classname), false, 'menu no longer has the class ' + classname); + equals( $button.hasClass(classname), false, 'button no longer has the class ' + classname); + el.multiselect("destroy"); + }); + + test("header", function(){ + expect(7); + + function countLinks(){ + return header().find("a").length; + } + + // default + el = $("select").multiselect({ autoOpen:true }); + ok(header().is(':visible'), "default config: header is visible" ); + el.multiselect("option", "header", false); + ok(header().is(':hidden'), "after changing header option on default config: header is no longer visible" ); + + // test for all links within the default header + equals(countLinks(), 3, "number of links in the default header config"); + + el.multiselect("destroy"); + + // create again, this time header false + el = $("select").multiselect({ header:false, autoOpen:true }); + ok(header().is(':hidden'), "init with header false: header is not visible" ); + el.multiselect("option", "header", true); + ok(header().is(':visible'), "after changing header option: header is visible" ); + + el.multiselect("destroy"); + + // create again, this time custom header + el = $("select").multiselect({ header:"hai guyz", autoOpen:true }); + equals(header().text(), "hai guyz", "header equals custom text"); + equals(countLinks(), 1, "number of links in the custom header config (should be close button)"); + + el.multiselect("destroy"); + }); + test("openIcon", function(){ + expect(1); + var icon = ''; + el = $("select").multiselect({ openIcon:icon }); + equals(button().find(".ui-multiselect-open").find(".ui-icon-search").length, 1); + el.multiselect("destroy"); + }); + test("closeIcon", function(){ + expect(1); + var icon = ''; + el = $("select").multiselect({ autoOpen:true, closeIcon:icon }); + equals(menu().find(".ui-multiselect-close").find(".ui-icon-search").length, 1); + el.multiselect("destroy"); + }); test("selectedListSeparator", function(){ expect(3); el = $("select").multiselect({ selectedListSeparator: "
              ", selectedList: 15 }); From b3b16e551e752d4bfa4fd3c762e9b3dbfae750e6 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 14:15:55 -0800 Subject: [PATCH 4/9] $variable naming --- tests/unit/methods.js | 394 +++++++++++++++++++++--------------------- 1 file changed, 197 insertions(+), 197 deletions(-) diff --git a/tests/unit/methods.js b/tests/unit/methods.js index 784761f..675cbaa 100644 --- a/tests/unit/methods.js +++ b/tests/unit/methods.js @@ -1,203 +1,203 @@ (function($){ - module("methods"); - - test("open", function(){ - expect(2); - - el = $("select").multiselect().multiselect("open"); - ok( el.multiselect("isOpen"), "isOpen parameter true" ); - equals( menu().css("display"), "block", "Test display CSS property" ); - el.multiselect("destroy"); - }); - - test("close", function(){ - expect(2); - - el = $("select").multiselect().multiselect("open").multiselect("close"); - ok( !el.multiselect("isOpen"), "isOpen parameter false" ); - equals( menu().css("display"), "none", "Test display CSS property" ); - el.multiselect("destroy"); - }); - - test("enable", function(){ - expect(2); - - el = $("select").multiselect().multiselect("disable").multiselect("enable"); - ok( button().is(":disabled") === false, "Button is enabled" ); - ok( el.is(":disabled") === false, "Original select is enabled" ); - el.multiselect("destroy"); - }); - - test("disable", function(){ - expect(2); - - // clone this one so the original is not affected - el = $("select").clone(true).appendTo(body).multiselect().multiselect("disable"); - ok( button().is(":disabled"), 'Button is disabled'); - ok( el.is(":disabled"), 'Original select is disabled'); - el.multiselect("destroy").remove(); - }); - - test("enabling w/ pre-disabled tags (#216)", function(){ - expect(5); - - el = $('') + .appendTo(document.body) + .multiselect(); + + var boxes = menu().find("input"); + var disabled = boxes.first(); + var enabled = boxes.last(); + var key = "ech-multiselect-disabled"; + + equals(disabled.is(":disabled"), true, "The first option is disabled"); + el.multiselect("disable"); + equals(disabled.attr(key), undefined, "After disabling the widget, the pre-disabled option is not flagged to re-enable"); + equals(enabled.attr(key), "true", "and the enabled option is flagged to be re-enable"); + el.multiselect("enable"); + equals(disabled.is(":disabled"), true, "After enabling, the first option is still disabled"); + equals(disabled.attr(key), undefined, "and the option no longer has the stored data flag"); + el.multiselect("destroy").remove(); + }); + + test("widget", function(){ + expect(1); + + el = $("select").multiselect(); + ok( menu().is("div.ui-multiselect-menu"), 'Widget is the menu element'); + el.multiselect("destroy"); + }); + + test("getButton", function(){ + expect(1); + + el = $("select").multiselect(); + var button = el.multiselect("getButton"); + ok( button.is("button.ui-multiselect"), 'Button is the button element'); + el.multiselect("destroy"); + }); + + test("getMenu", function(){ + expect(1); + el = $("select").multiselect(); + var menu = el.multiselect("getMenu"); + ok( menu.is(".ui-multiselect-menu"), 'Menu is the menu element'); + el.multiselect("destroy"); + }); + + test("getLabels", function(){ + expect(1); + el = $("select").multiselect(); + var labels = el.multiselect("getLabels"); + ok(labels.length === $(".ui-multiselect-menu label").length, 'Returns all the labels'); + el.multiselect("destroy"); + }); + + test("addOption", function() { + expect(2); + el = $("select").clone().appendTo(body).multiselect(); + var attrs = {title: "Test Title", value: "newOption"}; + el.multiselect("addOption", attrs, "Option New"); + ok(el.find("option[value=newOption]").length === 1, "The option is added to the source element"); + ok(menu().find("input[value=newOption]").length === 1, "The option is added to the menu"); + el.multiselect("destroy").remove(); + }); + + test("removeOption", function() { + expect(4); + el = $("select").clone().appendTo(body).multiselect(); + ok(el.find("option[value=1]").length === 1, "The option exists in the source element"); + ok(menu().find("input[value=1]").length === 1, "The option exists in the menu"); + el.multiselect("removeOption", "1"); + ok(el.find("option[value=1]").length === 0, "The option is removed from the source element"); + ok(menu().find("input[value=1]").length === 0, "The option is removed from the menu"); + el.multiselect("destroy").remove(); + }); + + test("checkAll", function(){ + expect(1); + + el = $("select").multiselect().multiselect("checkAll"); + var inputs = menu().find("input"); + ok( inputs.filter(":checked").length === inputs.length, 'All inputs selected on the widget?'); + el.multiselect("destroy"); + }); + + test("uncheckAll", function(){ + expect(1); + + el = $("select").multiselect().multiselect("checkAll").multiselect("uncheckAll"); + ok( menu().find("input:checked").length === 0, 'All inputs unchecked on the widget?'); + el.multiselect("destroy"); + }); + + test("isOpen", function(){ + expect(2); + + el = $("select").multiselect().multiselect("open"); + ok( el.multiselect("isOpen"), 'Testing isOpen method after calling open method'); + el = $("select").multiselect("close"); + ok( !el.multiselect("isOpen"), 'Testing isOpen method after calling close method'); + el.multiselect("destroy"); + }); + + test("destroy", function(){ + expect(2); + + el = $("select").multiselect().multiselect("destroy"); + ok( !$(".ui-multiselect").length , 'button.ui-multiselect removed from the DOM'); + ok( !el.data("multiselect") , 'no more multiselect obj attached to elem'); + }); + + test("getChecked", function(){ + expect(2); + + el = $("select").multiselect().multiselect("checkAll"); + equals( el.multiselect("getChecked").length, 9, 'number of checkboxes returned after checking all and calling getChecked'); + el.multiselect("uncheckAll"); + equals( el.multiselect("getChecked").length, 0, 'number of checkboxes returned after unchecking all and calling getChecked'); + el.multiselect("destroy"); + }); test("getUnchecked", function(){ - expect(2); - - el = $("select").multiselect().multiselect("checkAll"); - equals( el.multiselect("getUnchecked").length, 0, 'number of checkboxes returned after checking all and calling getUnchecked'); - el.multiselect("uncheckAll"); - equals( el.multiselect("getUnchecked").length, 9, 'number of checkboxes returned after unchecking all and calling getUnchecked'); - el.multiselect("destroy"); - }); - - test("refresh", function(){ - expect(6); - - el = $("select").clone().appendTo(body).multiselect(); - el.empty().html(''); - el.multiselect('refresh'); - - var checkboxes, getCheckboxes = (function hai(){ - checkboxes = menu().find('input[type="checkbox"]'); - return hai; - })(); - - equals( checkboxes.length, 2, "After clearing the select, adding 2 options, and refresh(), only 2 checkboxes exist"); - equals( checkboxes.eq(0).val(), 'foo', 'first is foo' ); - equals( checkboxes.eq(1).val(), 'bar', 'second is bar' ); - - // add one more w/ append, just for safety's sake - el.append(''); - el.multiselect('refresh'); - getCheckboxes(); - equals( checkboxes.eq(2).val(), 'baz', 'after an append() call, the third option is now baz' ); - equals($(el.multiselect("instance").inputs[0]).data().testval, 123, "the first input has the data attribute testval with value 123"); - equals($(el.multiselect("instance").inputs[2]).data().testval, "something", "the third input has the data attribute testval with value something"); - - el.multiselect("destroy").remove(); - }); - - test("position", function() { + expect(2); + + el = $("select").multiselect().multiselect("checkAll"); + equals( el.multiselect("getUnchecked").length, 0, 'number of checkboxes returned after checking all and calling getUnchecked'); + el.multiselect("uncheckAll"); + equals( el.multiselect("getUnchecked").length, 9, 'number of checkboxes returned after unchecking all and calling getUnchecked'); + el.multiselect("destroy"); + }); + + test("refresh", function(){ + expect(6); + + el = $("select").clone().appendTo(body).multiselect(); + el.empty().html(''); + el.multiselect('refresh'); + + var checkboxes, getCheckboxes = (function hai(){ + checkboxes = menu().find('input[type="checkbox"]'); + return hai; + })(); + + equals( checkboxes.length, 2, "After clearing the select, adding 2 options, and refresh(), only 2 checkboxes exist"); + equals( checkboxes.eq(0).val(), 'foo', 'first is foo' ); + equals( checkboxes.eq(1).val(), 'bar', 'second is bar' ); + + // add one more w/ append, just for safety's sake + el.append(''); + el.multiselect('refresh'); + getCheckboxes(); + equals( checkboxes.eq(2).val(), 'baz', 'after an append() call, the third option is now baz' ); + equals($(el.multiselect("instance").$inputs[0]).data().testval, 123, "the first input has the data attribute testval with value 123"); + equals($(el.multiselect("instance").$inputs[2]).data().testval, "something", "the third input has the data attribute testval with value something"); + + el.multiselect("destroy").remove(); + }); + + test("position", function() { expect(2); var left = "500px"; @@ -216,6 +216,6 @@ equals(menu().css("left"), left, "After calling position(), the menu has updated to the same left value as the button"); el.multiselect("destroy").remove(); - }); + }); })(jQuery); From 730198a6961b76f5d539b85ee866b34910ac7748 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 14:37:33 -0800 Subject: [PATCH 5/9] Fix comment alignment --- src/jquery.multiselect.js | 58 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index ddaeaf7..4f4517d 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -4,7 +4,7 @@ * Copyright (c) 2012 Eric Hynds * * Depends: - * - jQuery 1.7+ (http://api.jquery.com/) + * - jQuery 1.7+ (http://api.jquery.com/) * - jQuery UI 1.11 widget factory (http://api.jqueryui.com/jQuery.widget/) * * Optional: @@ -25,48 +25,48 @@ // default options options: { - header: true, // (true | false) If true, the header is shown. - height: 175, // (int) Sets the height of the menu. - minWidth: 225, // (int) Sets the minimum width of the menu. - classes: '', // Classes that you can provide to be applied to the elements making up the widget. + header: true, // (true | false) If true, the header is shown. + height: 175, // (int) Sets the height of the menu. + minWidth: 225, // (int) Sets the minimum width of the menu. + classes: '', // Classes that you can provide to be applied to the elements making up the widget. openIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. - closeIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. - checkAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + closeIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. + checkAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. uncheckAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. flipAllIcon: '', // Scaleable HTML Entities or Font-Awesome icons can be specified here instead of the default jQuery UI icons. - checkAllText: 'Check all', // (str | blank | null) If blank or null, link not shown. - uncheckAllText: 'Uncheck all', // (str | blank | null) If blank or null, link not shown. - flipAllText: 'Flip all', // (str | blank | null) If blank or null, link not shown. - showCheckAll: true, // (true | false) Show or hide the Check All link without blanking the text. - showUncheckAll: true, // (true | false) Show or hide the Uncheck All link without blanking the text. - showFlipAll: false, // (true | false) Show or hide the Flip All link without blanking the text. - noneSelectedText: 'Select options', // (str) The text to show in the button where nothing is selected. - selectedText: '# of # selected', // (str) A "template" that indicates how to show the count of selections in the button. The "#'s" are replaced by the selection count & option count. - selectedList: 0, // (int) The actual list selections will be shown in the button when the count of selections is <= than this number. - show: null, // (array) An array containing menu opening effects. - hide: null, // (array) An array containing menu closing effects. - autoOpen: false, // (true | false) If true, then the menu will be opening immediately after initialization. - position: {}, // (object) A jQuery UI position object that constrains how the pop-up menu is positioned. - appendTo: null, // (jQuery | DOM element | selector str) If provided, this specifies what element to append the widget to in the DOM. - menuWidth:null, // (int | null) If a number is provided, sets the menu width. - selectedListSeparator: ', ', // (str) This allows customization of the list separator. Use ',
              ' to make the button grow vertically showing 1 selection per line. - disableInputsOnToggle: true, // (true | false) - groupColumns: false // (true | false) + checkAllText: 'Check all', // (str | blank | null) If blank or null, link not shown. + uncheckAllText: 'Uncheck all', // (str | blank | null) If blank or null, link not shown. + flipAllText: 'Flip all', // (str | blank | null) If blank or null, link not shown. + showCheckAll: true, // (true | false) Show or hide the Check All link without blanking the text. + showUncheckAll: true, // (true | false) Show or hide the Uncheck All link without blanking the text. + showFlipAll: false, // (true | false) Show or hide the Flip All link without blanking the text. + noneSelectedText: 'Select options', // (str) The text to show in the button where nothing is selected. + selectedText: '# of # selected', // (str) A "template" that indicates how to show the count of selections in the button. The "#'s" are replaced by the selection count & option count. + selectedList: 0, // (int) The actual list selections will be shown in the button when the count of selections is <= than this number. + show: null, // (array) An array containing menu opening effects. + hide: null, // (array) An array containing menu closing effects. + autoOpen: false, // (true | false) If true, then the menu will be opening immediately after initialization. + position: {}, // (object) A jQuery UI position object that constrains how the pop-up menu is positioned. + appendTo: null, // (jQuery | DOM element | selector str) If provided, this specifies what element to append the widget to in the DOM. + menuWidth:null, // (int | null) If a number is provided, sets the menu width. + selectedListSeparator: ', ', // (str) This allows customization of the list separator. Use ',
              ' to make the button grow vertically showing 1 selection per line. + disableInputsOnToggle: true, // (true | false) + groupColumns: false // (true | false) }, // This method determines which element to append the menu to // Uses the element provided in the options first, then looks for ui-front / dialog // Otherwise appends to the body _getAppendEl: function() { - var elem = this.options.appendTo; // jQuery object, DOM element, OR selector str. + var elem = this.options.appendTo; // jQuery object, DOM element, OR selector str. if(elem) { - elem = elem.jquery || elem.nodeType ? $(elem) : this.document.find(elem).eq(0); // Note that the find handles the selector case. + elem = elem.jquery || elem.nodeType ? $(elem) : this.document.find(elem).eq(0); // Note that the find handles the selector case. } if(!elem || !elem[0]) { elem = this.element.closest(".ui-front, dialog"); } if(!elem.length) { - elem = this.document[0].body; // Position at end of body. + elem = this.document[0].body; // Position at end of body. } return elem; }, @@ -184,7 +184,7 @@ */ _makeOption: function(option) { var title = option.title || null; - var $element = this.element; // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ + var $element = this.element; // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ var id = $element[0].id || this.multiselectID; // unique ID for the label & option tags var inputID = 'ui-multiselect-' + this.multiselectID + '-' + (option.id || id + '-option-' + this.inputIdCounter++); var isDisabled = option.disabled; From 12eea3879e05dd0aa02e6e15a1b8b7950ce74520 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 15:00:44 -0800 Subject: [PATCH 6/9] Added comment --- src/jquery.multiselect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index 4f4517d..a415244 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -63,7 +63,7 @@ elem = elem.jquery || elem.nodeType ? $(elem) : this.document.find(elem).eq(0); // Note that the find handles the selector case. } if(!elem || !elem[0]) { - elem = this.element.closest(".ui-front, dialog"); + elem = this.element.closest(".ui-front, dialog"); // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ } if(!elem.length) { elem = this.document[0].body; // Position at end of body. From 79274babcc3c1ac55cc26b287d130bb35ed59f17 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 15:13:16 -0800 Subject: [PATCH 7/9] Consistently set var $element = this.element --- src/jquery.multiselect.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index a415244..8b951ec 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -254,7 +254,7 @@ // Refreshes the widget to pick up changes to the underlying select // Rebuilds the menu, sets button width refresh: function(init) { - var $el = this.element; // "element" is a jQuery object representing the underlying select + var $element = this.element; // "element" is a jQuery object representing the underlying select var $menu = this.$menu; var $headerLinks = this.$headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip'); var $dropdown = $("
                ").addClass('ui-multiselect-checkboxes ui-helper-reset'); @@ -263,14 +263,14 @@ // update header link container visibility if needed if (this.options.header) { - if(!!$el[0].multiple) { + if(!!$element[0].multiple) { $headerLinks.show(); } else { $headerLinks.hide(); } } - this._buildOptionList($el, $dropdown); + this._buildOptionList($element, $dropdown); this.$menu.find(".ui-multiselect-checkboxes").remove(); this.$menu.append($dropdown); @@ -448,7 +448,7 @@ var val = this.value; var optionText = $this.parent().find("span").text(); var checked = this.checked; - var $tags = self.element.find('option'); + var $tags = self.element.find('option'); // "element" is a jQuery object representing the underlying select var isMultiple = !!self.element[0].multiple; // bail if this input is disabled or the event is cancelled @@ -670,7 +670,7 @@ _toggleChecked: function(flag, group) { var $inputs = (group && group.length) ? group : this.$inputs; var self = this; - var $el = this.element; // element is a jQuery object + var $element = this.element; // element is a jQuery object // toggle state on inputs $inputs.each(this._toggleState('checked', flag)); @@ -688,8 +688,8 @@ }); // toggle state on original option tags - $el.selectedIndex = -1; - $el + $element.selectedIndex = -1; + $element .find('option') .each(function() { if(!this.disabled && values[this.value]) { @@ -699,7 +699,7 @@ // trigger the change event on the select if($inputs.length) { - $el.trigger("change"); + $element.trigger("change"); } }, From 2884af22c2ce84cd362fd81f71b2de6e9bdf1e3a Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 15:40:03 -0800 Subject: [PATCH 8/9] Relocate comment in init --- src/jquery.multiselect.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index 8b951ec..ea5a145 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -154,13 +154,13 @@ // https://api.jqueryui.com/jquery.widget/#method-_init _init: function() { - var $element = this.element; + var $element = this.element; // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ var $headerLinks = this.$headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none, .ui-multiselect-flip'); if(this.options.header === false) { this.$header.hide(); } - if(!!$element[0].multiple) { // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ + if(!!$element[0].multiple) { $headerLinks.show(); } else { $headerLinks.hide(); From a94c0a16ab00d5b3214e307e9f074953b32a24fa Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Sat, 13 Jan 2018 16:52:54 -0800 Subject: [PATCH 9/9] Use $element instead of $el --- src/jquery.multiselect.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index ea5a145..f0ba55f 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -73,7 +73,7 @@ // Performs the initial creation of the widget _create: function() { - var $el = this.element.hide(); // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ + var $element = this.element.hide(); // element is a jQuery object per http://api.jqueryui.com/jQuery.widget/ var o = this.options; this.speed = $.fx.speeds._default; // default speed for effects @@ -91,9 +91,12 @@ // The ui-multiselect-open span is necessary below to simplify dynamically changing the open icon. var $button = (this.$button = $('')) .addClass('ui-multiselect ui-widget ui-state-default ui-corner-all ' + o.classes) - .attr({ title: $el.attr('title'), tabIndex: $el.attr('tabIndex'), id: $el.attr('id') ? $el.attr('id') + '_ms' : null }) + .attr({ title: $element.attr('title'), + tabIndex: $element.attr('tabIndex'), + id: $element.attr('id') ? $element.attr('id') + '_ms' : null + }) .prop('aria-haspopup', true) - .insertAfter($el); + .insertAfter($element); this.$buttonlabel = $('') .html(o.noneSelectedText) @@ -147,7 +150,7 @@ this.refresh(true); // If this is a single select widget, add the appropriate class - if(!$el[0].multiple) { + if(!$element[0].multiple) { $menu.addClass('ui-multiselect-single'); } },