From 5f5eac9bc25f4620d5653bc646beb384f5745e9b Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Wed, 7 Feb 2018 21:55:48 -0800 Subject: [PATCH 1/2] Eliminate replacement _toggleChecked code in multiselect.filter.js Replaces the separate _toggleChecked function code in multiselect.filter.js with instead using a parameter that changes the context for _toggleChecked in multiselect.js . Also, a few housekeeping updates. Note: The events.js file that I pulled has tabs in it. What I am pushing back has spaces instead. (consider this fair warning lol) --- src/jquery.multiselect.filter.js | 50 +-- src/jquery.multiselect.js | 33 +- tests/unit/events.js | 632 +++++++++++++++---------------- tests/unit/filter.js | 2 +- 4 files changed, 348 insertions(+), 369 deletions(-) diff --git a/src/jquery.multiselect.filter.js b/src/jquery.multiselect.filter.js index d709284..8cd641d 100644 --- a/src/jquery.multiselect.filter.js +++ b/src/jquery.multiselect.filter.js @@ -71,11 +71,11 @@ else if(e.which === 27) { $element.multiselect('close'); e.preventDefault(); - } + } else if(e.which === 9 && e.shiftKey) { $element.multiselect('close'); e.preventDefault(); - } + } else if(e.altKey) { switch(e.which) { case 82: @@ -100,7 +100,7 @@ // automatically reset the widget on close? if (this.options.autoReset) $element.on('multiselectclose', $.proxy(this._reset, this)); - + // rebuild cache when multiselect is updated $element.on('multiselectrefresh', $.proxy(function() { this.updateCache(); @@ -113,47 +113,19 @@ .prependTo(this.$header); // reference to the actual inputs - this.$inputs = this.instance.$menu.find('input[type="checkbox"], input[type="radio"]'); + this.$inputs = this.instance.$inputs; // 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 - this.instance._toggleChecked = function(flag, group) { - var self = this; - var $element = this.element; - var $inputs = (group && group.length) ? group : this.$inputs; - - // do not include hidden elems if the menu isn't open. - var selector = self._isOpen ? ':disabled, :hidden' : ':disabled'; - - $inputs = $inputs - .not(selector) - .each(this._toggleState('checked', flag)); - - // update text - this.update(); - - // gather an array of the values that actually changed - var values = {}; - var inputCount = $inputs.length; - for (var x = 0; x < inputCount; x++) { - values[ $inputs.get(x).value ] = true; - } - - // select option tags - $element.find('option').filter(function() { - if(!this.disabled && values[this.value]) { - self._toggleState('selected', flag).call(this); - } - }); - - // trigger the change event on the select - if(inputCount) - $element.trigger('change'); - + // Change the normal _toggleChecked fxn behavior so that when checkAll/uncheckAll + // is fired, only the currently displayed filtered inputs are checked + var $instance = this.instance; + $instance._oldToggleChecked = $instance._toggleChecked; + $instance._toggleChecked = function(flag, group, filteredInputs) { + $instance._oldToggleChecked(flag, group, true); }; + }, // thx for the logic here ben alman diff --git a/src/jquery.multiselect.js b/src/jquery.multiselect.js index 29dfb60..c389bad 100644 --- a/src/jquery.multiselect.js +++ b/src/jquery.multiselect.js @@ -68,7 +68,7 @@ * 3. If still do not have a valid DOM element to append to, then append to the document body. * * NOTE: this.element and this.document are jQuery objects per the jQuery UI widget API. - * @returns {object} jQuery object to append to or document body. + * @returns {object} jQuery object for the DOM element to append to. */ _getAppendEl: function() { var elem = this.options.appendTo; // jQuery object or selector, DOM element or null. @@ -80,7 +80,7 @@ elem = this.element.closest(".ui-front, dialog"); } if (!elem.length) { - elem = document.body; // Position at end of body. Note that this returns a DOM element. + elem = $(document.body); // Position at end of body. Note that this returns a DOM element. } return elem; }, @@ -169,7 +169,7 @@ var $checkboxes = (this.$checkboxes = $( document.createElement('ul') ) ) .addClass('ui-multiselect-checkboxes ui-helper-reset' + (/\bmenu\b/i.test(wrapText) ? '' : ' ui-multiselect-nowrap')); - // This is the menu that will hold all the options. + // This is the menu container that will hold all the options added via refresh(). var $menu = (this.$menu = $( document.createElement('div') ) ) .addClass('ui-multiselect-menu ui-widget ui-widget-content ui-corner-all' + (elSelect.multiple ? '' : ' ui-multiselect-single ') @@ -177,8 +177,7 @@ .append($header, $checkboxes); $button.insertAfter($element); - // This is an empty menu at this point. - $menu.appendTo( this._getAppendEl() ); + this._getAppendEl().append($menu); this._bindEvents(); @@ -731,7 +730,7 @@ /** * Converts dimensions specified in options to pixel values. * Determines if specified value is a minimum, maximum or exact value. - * The value can be a number or a string with px, pts, ems, or % units. + * The value can be a number or a string with px, pts, ems, in, cm, mm, or % units. * Number/Numeric string treated as pixel measurements * - 30 * - '30' @@ -936,7 +935,7 @@ /** * Calculate accurate outerWidth(false) using getBoundingClientRect() * Note that this presumes that the element is visible in the layout. - * @param {node} DOM node or jQuery equivalent get width for. + * @param {node} DOM node or jQuery equivalent to get width for. * @returns {float} Decimal floating point value for the width. */ _getBCRWidth: function(elem) { @@ -950,7 +949,7 @@ /** * Calculate accurate outerHeight(false) using getBoundingClientRect() * Note that this presumes that the element is visible in the layout. - * @param {node} DOM node or jQuery equivalent get height for. + * @param {node} DOM node or jQuery equivalent to get height for. * @returns {float} Decimal floating point value for the height. */ _getBCRHeight: function(elem) { @@ -964,7 +963,7 @@ /** * Calculate jQuery width correction factor to fix floating point round-off errors. * Note that this presumes that the element is visible in the layout. - * @param {node} DOM node or jQuery equivalent get width for. + * @param {node} DOM node or jQuery equivalent to get width for. * @returns {float} Correction value for the width--typically a decimal < 1.0 */ _jqWidthFix: function(elem) { @@ -979,7 +978,7 @@ /** * Calculate jQuery height correction factor to fix floating point round-off errors. * Note that this presumes that the element is visible in the layout. - * @param {node} DOM node or jQuery equivalent get height for. + * @param {node} DOM node or jQuery equivalent to get height for. * @returns {float} Correction value for the height--typically a decimal < 1.0 */ _jqHeightFix: function(elem) { @@ -1090,12 +1089,21 @@ * Potentially scoped down to visible elements from filteredInputs * @param {string} flag checked property to set * @param {object} group option group that was clicked, if any - * @param {array} filteredInputs visible elements with the filter applied + * @param {boolean} filteredInputs does not toggle hidden inputs if filtering. */ _toggleChecked: function(flag, group, filteredInputs) { var self = this; var $element = self.element; - var $inputs = (group && group.length) ? group : (filteredInputs || self.$inputs); + var $inputs = (group && group.length) ? group : self.$inputs; + + if (filteredInputs) { + // Do not include hidden inputs if the menu isn't open. + $inputs = $inputs.not( self._isOpen ? ':disabled, :hidden' : ':disabled' ); + } + else { + // If not filtering, then the underlying select is cleared out each time. + $element[0].selectedIndex = -1; + } // toggle state on inputs $inputs.each(self._toggleState('checked', flag)); @@ -1113,7 +1121,6 @@ }); // toggle state on original option tags - $element[0].selectedIndex = -1; $element.find('option') .each( function() { if (!this.disabled && values[this.value]) { diff --git a/tests/unit/events.js b/tests/unit/events.js index 20f4576..154cb51 100644 --- a/tests/unit/events.js +++ b/tests/unit/events.js @@ -1,337 +1,337 @@ (function($){ - QUnit.module("events"); - - QUnit.test("multiselectopen", function(assert){ - // inject widget - el = $("").appendTo(body); - el.multiselect({ - open: function(e,ui){ - assert.ok( true, 'option: multiselect("open") fires open callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectopen', 'option: event type in callback'); - assert.equal(menu().css("display"), 'block', 'menu display css property assert.equal block'); - assert.propEqual(ui, {}, 'option: ui hash in callback'); - } - }) - .bind("multiselectopen", function(e,ui){ - assert.ok(true, 'event: multiselect("open") fires multiselectopen event'); - assert.equal(this, el[0], 'event: context of event'); - assert.propEqual(ui, {}, 'event: ui hash'); - }); - - // now try to open it.. - el.multiselect("open"); - - // make sure the width of the menu and button are equivalent - assert.equal( button().outerWidth(), menu().outerWidth(), 'button and menu widths are equivalent'); - - // close - el.multiselect("close"); - - // make sure a click event on the button opens the menu as well. - button().trigger("click"); - el.multiselect("close"); - - // make sure a click event on a span inside the button opens the menu as well. - button().find("span:first").trigger("click"); - - // reset for next test - el.multiselect("destroy").remove(); - - // now try returning false prevent opening - el = $("") - .appendTo(body) - .multiselect() - .bind("multiselectbeforeopen", function(){ - assert.ok( true, "event: binding multiselectbeforeopen to return false (prevent from opening)" ); - return false; - }) - .multiselect("open"); - - assert.ok( !el.multiselect("isOpen"), "multiselect is not open after multiselect('open')" ); - el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectclose", function(assert){ - // inject widget - el = $("").appendTo(body); - el.multiselect({ - close: function(e,ui){ - assert.ok( true, 'option: multiselect("close") fires close callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectclose', 'option: event type in callback'); - assert.equal(menu().css("display"), 'none', 'menu display css property assert.equal none'); - assert.propEqual(ui, {}, 'option: ui hash'); - } - }) - .bind("multiselectclose", function(e,ui){ - assert.ok(true, 'multiselect("close") fires multiselectclose event'); - assert.equal(this, el[0], 'event: context of event'); - assert.propEqual(ui, {}, 'event: ui hash'); - }) - .multiselect("open") - .multiselect("close") - .multiselect("open"); - - // make sure a click event on the button closes the menu as well. - button().click(); - el.multiselect("open"); - - // make sure a click event on a span inside the button closes the menu as well. - button().find("span:first").click(); - - // make sure that the menu is actually closed. see issue #68 - assert.ok( el.multiselect('isOpen') === false, 'menu is indeed closed' ); - - el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectbeforeclose", function(assert){ - // inject widget - el = $("").appendTo(body); - el.multiselect({ - beforeclose: function(e,ui){ - assert.ok( true, 'option: multiselect("beforeclose") fires close callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectbeforeclose', 'option: event type in callback'); - assert.propEqual(ui, {}, 'option: ui hash'); - } - }) - .bind("multiselectbeforeclose", function(e,ui){ - assert.ok(true, 'multiselect("beforeclose") fires multiselectclose event'); - assert.equal(this, el[0], 'event: context of event'); - assert.propEqual(ui, {}, 'event: ui hash'); - }) - .multiselect("open") - .multiselect("close"); - - el.multiselect("destroy").remove(); - - // test 'return false' functionality - el = $("").appendTo(body); - el.multiselect({ - beforeclose: function(){ - return false; - } - }); - - el.multiselect('open').multiselect('close'); - assert.ok( menu().is(':visible') && el.multiselect("isOpen"), "returning false inside callback prevents menu from closing" ); - el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectclick with multiple widgets", function(assert) { - var first = $("").appendTo(body).multiselect(); - var second = $("").appendTo(body).multiselect(); - assert.equal($('.ui-multiselect').length, 2, "two mutliselects are on the page"); - first.multiselect("refresh"); - second.multiselect("refresh"); - var $label = $(second.multiselect("getLabels")[0]); - var $wrongInput = $(first.multiselect("getLabels")[0]).find("input"); - $label.click(); - assert.equal($label.find("input").prop("checked"), true, "the input for that label should be checked"); - assert.equal($wrongInput.prop("checked"), false, "the input for the corresponding label on the first widget should not be checked"); - first.multiselect("destroy").remove(); - second.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectclick", function(assert){ - var times = 0; - - // inject widget - el = $("") - .appendTo(body); - - el.multiselect({ - click: function(e,ui){ - assert.ok(true, 'option: triggering the click event on the second checkbox fires the click callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectclick', 'option: event type in callback'); - assert.equal(ui.value, "2", "option: ui.value assert.equal"); - assert.equal(ui.text, "Option 2", "option: ui.text assert.equal"); - - if(times === 0) { + QUnit.module("events"); + + QUnit.test("multiselectopen", function(assert){ + // inject widget + el = $("").appendTo(body); + el.multiselect({ + open: function(e,ui){ + assert.ok( true, 'option: multiselect("open") fires open callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectopen', 'option: event type in callback'); + assert.equal(menu().css("display"), 'block', 'menu display css property assert.equal block'); + assert.propEqual(ui, {}, 'option: ui hash in callback'); + } + }) + .on("multiselectopen", function(e,ui){ + assert.ok(true, 'event: multiselect("open") fires multiselectopen event'); + assert.equal(this, el[0], 'event: context of event'); + assert.propEqual(ui, {}, 'event: ui hash'); + }); + + // now try to open it.. + el.multiselect("open"); + + // make sure the width of the menu and button are equivalent + assert.equal( button().outerWidth(), menu().outerWidth(), 'button and menu widths are equivalent'); + + // close + el.multiselect("close"); + + // make sure a click event on the button opens the menu as well. + button().trigger("click"); + el.multiselect("close"); + + // make sure a click event on a span inside the button opens the menu as well. + button().find("span:first").trigger("click"); + + // reset for next test + el.multiselect("destroy").remove(); + + // now try returning false prevent opening + el = $("") + .appendTo(body) + .multiselect() + .on("multiselectbeforeopen", function(){ + assert.ok( true, "event: binding multiselectbeforeopen to return false (prevent from opening)" ); + return false; + }) + .multiselect("open"); + + assert.ok( !el.multiselect("isOpen"), "multiselect is not open after multiselect('open')" ); + el.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectclose", function(assert){ + // inject widget + el = $("").appendTo(body); + el.multiselect({ + close: function(e,ui){ + assert.ok( true, 'option: multiselect("close") fires close callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectclose', 'option: event type in callback'); + assert.equal(menu().css("display"), 'none', 'menu display css property assert.equal none'); + assert.propEqual(ui, {}, 'option: ui hash'); + } + }) + .on("multiselectclose", function(e,ui){ + assert.ok(true, 'multiselect("close") fires multiselectclose event'); + assert.equal(this, el[0], 'event: context of event'); + assert.propEqual(ui, {}, 'event: ui hash'); + }) + .multiselect("open") + .multiselect("close") + .multiselect("open"); + + // make sure a click event on the button closes the menu as well. + button().click(); + el.multiselect("open"); + + // make sure a click event on a span inside the button closes the menu as well. + button().find("span:first").click(); + + // make sure that the menu is actually closed. see issue #68 + assert.ok( el.multiselect('isOpen') === false, 'menu is indeed closed' ); + + el.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectbeforeclose", function(assert){ + // inject widget + el = $("").appendTo(body); + el.multiselect({ + beforeclose: function(e,ui){ + assert.ok( true, 'option: multiselect("beforeclose") fires close callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectbeforeclose', 'option: event type in callback'); + assert.propEqual(ui, {}, 'option: ui hash'); + } + }) + .on("multiselectbeforeclose", function(e,ui){ + assert.ok(true, 'multiselect("beforeclose") fires multiselectclose event'); + assert.equal(this, el[0], 'event: context of event'); + assert.propEqual(ui, {}, 'event: ui hash'); + }) + .multiselect("open") + .multiselect("close"); + + el.multiselect("destroy").remove(); + + // test 'return false' functionality + el = $("").appendTo(body); + el.multiselect({ + beforeclose: function(){ + return false; + } + }); + + el.multiselect('open').multiselect('close'); + assert.ok( menu().is(':visible') && el.multiselect("isOpen"), "returning false inside callback prevents menu from closing" ); + el.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectclick with multiple widgets", function(assert) { + var first = $("").appendTo(body).multiselect(); + var second = $("").appendTo(body).multiselect(); + assert.equal($('.ui-multiselect').length, 2, "two mutliselects are on the page"); + first.multiselect("refresh"); + second.multiselect("refresh"); + var $label = $(second.multiselect("getLabels")[0]); + var $wrongInput = $(first.multiselect("getLabels")[0]).find("input"); + $label.click(); + assert.equal($label.find("input").prop("checked"), true, "the input for that label should be checked"); + assert.equal($wrongInput.prop("checked"), false, "the input for the corresponding label on the first widget should not be checked"); + first.multiselect("destroy").remove(); + second.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectclick", function(assert){ + var times = 0; + + // inject widget + el = $("") + .appendTo(body); + + el.multiselect({ + click: function(e,ui){ + assert.ok(true, 'option: triggering the click event on the second checkbox fires the click callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectclick', 'option: event type in callback'); + assert.equal(ui.value, "2", "option: ui.value assert.equal"); + assert.equal(ui.text, "Option 2", "option: ui.text assert.equal"); + + if(times === 0) { assert.equal(ui.checked, true, "option: ui.checked assert.equal"); - } else if(times === 1) { + } else if(times === 1) { assert.equal(ui.checked, false, "option: ui.checked assert.equal"); - } - } - }) - .bind("multiselectclick", function(e,ui){ - assert.ok(true, 'event: triggering the click event on the second checkbox triggers multiselectclick'); - assert.equal(this, el[0], 'event: context of event'); - assert.equal(ui.value, "2", "event: ui.value assert.equal"); - assert.equal(ui.text, "Option 2", "event: ui.text assert.equal"); + } + } + }) + .on("multiselectclick", function(e,ui){ + assert.ok(true, 'event: triggering the click event on the second checkbox triggers multiselectclick'); + assert.equal(this, el[0], 'event: context of event'); + assert.equal(ui.value, "2", "event: ui.value assert.equal"); + assert.equal(ui.text, "Option 2", "event: ui.text assert.equal"); if(times === 0) { assert.equal(ui.checked, true, "option: ui.checked assert.equal"); } else if(times === 1) { assert.equal(ui.checked, false, "option: ui.checked assert.equal"); } - }) - .bind("change", function(e){ - if(++times === 1){ - assert.equal(el.val().join(), "2", "event: select element val() within the change event is correct" ); - } else { - assert.equal(el.val(), null, "event: select element val() within the change event is correct" ); - } - - assert.ok(true, "event: the select's change event fires"); - }) - .multiselect("open"); - - // trigger a click event on the input - var lastInput = menu().find("input").last(); - lastInput[0].click(); - - // trigger once more. - lastInput[0].click(); - - // make sure it has focus - assert.equal(true, lastInput.is(":focus"), "The input has focus"); - - // make sure menu isn't closed automatically - assert.equal( true, el.multiselect('isOpen'), 'menu stays open' ); - - el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectcheckall", function(assert){ - // inject widget - el = $('').appendTo(body); - - el.multiselect({ - checkAll: function(e,ui){ - assert.ok( true, 'option: multiselect("checkAll") fires checkall callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectcheckall', 'option: event type in callback'); - assert.propEqual(ui, {}, 'option: ui hash in callback'); - } - }) - .bind("multiselectcheckall", function(e,ui){ - assert.ok( true, 'event: multiselect("checkall") fires multiselectcheckall event' ); - assert.equal(this, el[0], 'event: context of event'); - assert.propEqual(ui, {}, 'event: ui hash'); - }) - .bind("change", function(){ - assert.ok(true, "event: the select's change event fires"); - assert.equal( el.val().join(), "1,2", "event: select element val() within the change event is correct" ); - }) - .multiselect("open") - .multiselect("checkAll"); - - assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); - - el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectuncheckall", function(assert){ - // inject widget - el = $('').appendTo(body); - - el.multiselect({ - uncheckAll: function(e,ui){ - assert.ok( true, 'option: multiselect("uncheckAll") fires uncheckall callback' ); - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectuncheckall', 'option: event type in callback'); - assert.propEqual(ui, {}, 'option: ui hash in callback'); - } - }) - .bind("multiselectuncheckall", function(e,ui){ - assert.ok( true, 'event: multiselect("uncheckall") fires multiselectuncheckall event' ); - assert.equal(this, el[0], 'event: context of event'); - assert.propEqual(ui, {}, 'event: ui hash'); - }) - .bind("change", function(){ - assert.ok(true, "event: the select's change event fires"); - assert.equal( el.val(), null, "event: select element val() within the change event is correct" ); - }) - .multiselect("open") - .multiselect("uncheckAll"); - - assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); - - el.multiselect("destroy").remove(); - }); - - - QUnit.test("multiselectbeforeoptgrouptoggle", function(assert){ - // inject widget - el = $('') + }) + .on("change", function(e){ + if(++times === 1){ + assert.equal(el.val().join(), "2", "event: select element val() within the change event is correct" ); + } else { + assert.equal(el.val(), null, "event: select element val() within the change event is correct" ); + } + + assert.ok(true, "event: the select's change event fires"); + }) + .multiselect("open"); + + // trigger a click event on the input + var lastInput = menu().find("input").last(); + lastInput[0].click(); + + // trigger once more. + lastInput[0].click(); + + // make sure it has focus + assert.equal(true, lastInput.is(":focus"), "The input has focus"); + + // make sure menu isn't closed automatically + assert.equal( true, el.multiselect('isOpen'), 'menu stays open' ); + + el.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectcheckall", function(assert){ + // inject widget + el = $('').appendTo(body); + + el.multiselect({ + checkAll: function(e,ui){ + assert.ok( true, 'option: multiselect("checkAll") fires checkall callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectcheckall', 'option: event type in callback'); + assert.propEqual(ui, {}, 'option: ui hash in callback'); + } + }) + .on("multiselectcheckall", function(e,ui){ + assert.ok( true, 'event: multiselect("checkall") fires multiselectcheckall event' ); + assert.equal(this, el[0], 'event: context of event'); + assert.propEqual(ui, {}, 'event: ui hash'); + }) + .on("change", function(){ + assert.ok(true, "event: the select's change event fires"); + assert.equal( el.val().join(), "1,2", "event: select element val() within the change event is correct" ); + }) + .multiselect("open") + .multiselect("checkAll"); + + assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); + + el.multiselect("destroy").remove(); + }); + + QUnit.test("multiselectuncheckall", function(assert){ + // inject widget + el = $('').appendTo(body); + + el.multiselect({ + uncheckAll: function(e,ui){ + assert.ok( true, 'option: multiselect("uncheckAll") fires uncheckall callback' ); + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectuncheckall', 'option: event type in callback'); + assert.propEqual(ui, {}, 'option: ui hash in callback'); + } + }) + .on("multiselectuncheckall", function(e,ui){ + assert.ok( true, 'event: multiselect("uncheckall") fires multiselectuncheckall event' ); + assert.equal(this, el[0], 'event: context of event'); + assert.propEqual(ui, {}, 'event: ui hash'); + }) + .on("change", function(){ + assert.ok(true, "event: the select's change event fires"); + assert.equal( el.val(), null, "event: select element val() within the change event is correct" ); + }) + .multiselect("open") + .multiselect("uncheckAll"); + + assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); + + el.multiselect("destroy").remove(); + }); + + + QUnit.test("multiselectbeforeoptgrouptoggle", function(assert){ + // inject widget + el = $('') .appendTo(body); - el.bind("change", function(){ - assert.ok(true, "the select's change event fires"); - }) - .multiselect({ - beforeoptgrouptoggle: function(e,ui){ - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectbeforeoptgrouptoggle', 'option: event type in callback'); - assert.equal(ui.label, "Set One", 'option: ui.label assert.equal'); - assert.equal(ui.inputs.length, 2, 'option: number of inputs in the ui.inputs key'); - } - }) - .bind("multiselectbeforeoptgrouptoggle", function(e,ui){ - assert.ok( true, 'option: multiselect("uncheckall") fires multiselectuncheckall event' ); - assert.equal(this, el[0], 'event: context of event'); - assert.equal(ui.label, "Set One", 'event: ui.label assert.equal'); - assert.equal(ui.inputs.length, 2, 'event: number of inputs in the ui.inputs key'); - }) - .multiselect("open"); - - menu().find(".ui-multiselect-optgroup a").click(); - - el.multiselect("destroy").remove(); - el = el.clone(); - - // test return false preventing checkboxes from activating - el.bind("change", function(){ - assert.ok( true ); // should not fire - }).multiselect({ - beforeoptgrouptoggle: function(){ - return false; - }, - // if this fires the expected count will be off. just a redundant way of checking that return false worked + el.on("change", function(){ + assert.ok(true, "the select's change event fires"); + }) + .multiselect({ + beforeoptgrouptoggle: function(e,ui){ + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectbeforeoptgrouptoggle', 'option: event type in callback'); + assert.equal(ui.label, "Set One", 'option: ui.label assert.equal'); + assert.equal(ui.inputs.length, 2, 'option: number of inputs in the ui.inputs key'); + } + }) + .on("multiselectbeforeoptgrouptoggle", function(e,ui){ + assert.ok( true, 'option: multiselect("uncheckall") fires multiselectuncheckall event' ); + assert.equal(this, el[0], 'event: context of event'); + assert.equal(ui.label, "Set One", 'event: ui.label assert.equal'); + assert.equal(ui.inputs.length, 2, 'event: number of inputs in the ui.inputs key'); + }) + .multiselect("open"); + + menu().find(".ui-multiselect-optgroup a").click(); + + el.multiselect("destroy").remove(); + el = el.clone(); + + // test return false preventing checkboxes from activating + el.on("change", function(){ + assert.ok( true ); // should not fire + }).multiselect({ + beforeoptgrouptoggle: function(){ + return false; + }, + // if this fires the expected count will be off. just a redundant way of checking that return false worked optgrouptoggle: function(){ assert.ok( true ); } - }).appendTo( body ); + }).appendTo( body ); var label = menu().find("li.ui-multiselect-optgroup-label a").click(); assert.equal( menu().find(":input:checked").length, 0, "when returning false inside the optgrouptoggle handler, no checkboxes are checked" ); el.multiselect("destroy").remove(); - }); - - QUnit.test("multiselectoptgrouptoggle", function(assert){ - // inject widget - el = $('').appendTo(body); - - el.multiselect({ - optgrouptoggle: function(e,ui){ - assert.equal(this, el[0], "option: context of callback"); - assert.equal(e.type, 'multiselectoptgrouptoggle', 'option: event type in callback'); - assert.equal(ui.label, "Set One", 'option: ui.label assert.equal'); - assert.equal(ui.inputs.length, 2, 'option: number of inputs in the ui.inputs key'); - assert.equal(ui.checked, true, 'option: ui.checked assert.equal true'); - } - }) - .bind("multiselectoptgrouptoggle", function(e,ui){ - assert.ok( true, 'option: multiselect("uncheckall") fires multiselectuncheckall event' ); - assert.equal(this, el[0], 'event: context of event'); - assert.equal(ui.label, "Set One", 'event: ui.label assert.equal'); - assert.equal(ui.inputs.length, 2, 'event: number of inputs in the ui.inputs key'); - assert.equal(ui.checked, true, 'event: ui.checked assert.equal true'); - }) - .multiselect("open"); - - // trigger native click event on optgroup - menu().find(".ui-multiselect-optgroup a").click(); - assert.equal(menu().find(":input:checked").length, 2, "both checkboxes are actually checked" ); - - assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); - - el.multiselect("destroy").remove(); - }); + }); + + QUnit.test("multiselectoptgrouptoggle", function(assert){ + // inject widget + el = $('').appendTo(body); + + el.multiselect({ + optgrouptoggle: function(e,ui){ + assert.equal(this, el[0], "option: context of callback"); + assert.equal(e.type, 'multiselectoptgrouptoggle', 'option: event type in callback'); + assert.equal(ui.label, "Set One", 'option: ui.label assert.equal'); + assert.equal(ui.inputs.length, 2, 'option: number of inputs in the ui.inputs key'); + assert.equal(ui.checked, true, 'option: ui.checked assert.equal true'); + } + }) + .on("multiselectoptgrouptoggle", function(e,ui){ + assert.ok( true, 'option: multiselect("uncheckall") fires multiselectuncheckall event' ); + assert.equal(this, el[0], 'event: context of event'); + assert.equal(ui.label, "Set One", 'event: ui.label assert.equal'); + assert.equal(ui.inputs.length, 2, 'event: number of inputs in the ui.inputs key'); + assert.equal(ui.checked, true, 'event: ui.checked assert.equal true'); + }) + .multiselect("open"); + + // trigger native click event on optgroup + menu().find(".ui-multiselect-optgroup a").click(); + assert.equal(menu().find(":input:checked").length, 2, "both checkboxes are actually checked" ); + + assert.equal(menu().find("input").first().is(":focus"), true, "The first input has focus"); + + el.multiselect("destroy").remove(); + }); })(jQuery); diff --git a/tests/unit/filter.js b/tests/unit/filter.js index 1615bfe..0e363b7 100644 --- a/tests/unit/filter.js +++ b/tests/unit/filter.js @@ -41,7 +41,7 @@ '' + '' + '' + - ''); + ''); el.appendTo(document.body); el.multiselect(); From 3747d58bc67b6b152acd5446270d620a252acb45 Mon Sep 17 00:00:00 2001 From: Steve James <4stevejames@gmail.com> Date: Thu, 8 Feb 2018 10:59:32 -0800 Subject: [PATCH 2/2] Remove filteredInputs parameter --- src/jquery.multiselect.filter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jquery.multiselect.filter.js b/src/jquery.multiselect.filter.js index 8cd641d..c91ddf5 100644 --- a/src/jquery.multiselect.filter.js +++ b/src/jquery.multiselect.filter.js @@ -122,7 +122,7 @@ // is fired, only the currently displayed filtered inputs are checked var $instance = this.instance; $instance._oldToggleChecked = $instance._toggleChecked; - $instance._toggleChecked = function(flag, group, filteredInputs) { + $instance._toggleChecked = function(flag, group) { $instance._oldToggleChecked(flag, group, true); };