21c7a2872bd9d08f29623b78f5a63eca040c1ead chmalee Thu Oct 17 12:34:21 2024 -0700 Fix position of dropdownchecklists and make them correctly determine when the options have been selected or not, refs #34647 diff --git src/hg/js/ui.dropdownchecklist.js src/hg/js/ui.dropdownchecklist.js index 2496fd8..bcceb3e 100644 --- src/hg/js/ui.dropdownchecklist.js +++ src/hg/js/ui.dropdownchecklist.js @@ -281,31 +281,31 @@ var anItem = $(this); anItem.removeClass("ui-state-hover"); } ); // clicking on the checkbox synchronizes the source select checkBox.click(function(e) { var aCheckBox = $(this); e.stopImmediatePropagation(); if (aCheckBox.hasClass("active") ) { // Active checkboxes take active action var callback = self.options.onItemClick; if ($.isFunction(callback)) try { callback.call(self,aCheckBox); } catch (ex) { // reject the change on any error - aCheckBox.attr("checked",!aCheckBox.attr("checked")); + aCheckBox.prop("checked",!aCheckBox.prop("checked")); return; } self._syncSelected(aCheckBox); self.sourceSelect.trigger("change", 'ddcl_internal'); if (!self.isMultiple && options.closeRadioOnClick) { self._toggleDropContainer(false); } } }); // we are interested in the focus leaving the check box // but we need to detect the focus leaving one check box but // entering another. There is no reliable way to detect who // received the focus on a blur, so post the blur in the future, // knowing we will cancel it if we capture the focus in a timely manner // 23Sept2010 - unfortunately, IE 7+ and Chrome like to post a blur @@ -320,39 +320,39 @@ // define it within the blur function try { self._handleFocus(null,false,false); } catch(ex){ alert('timer failed: '+ex);} }; checkBox.blur(function(e) { self.blurringItem = setTimeout( timerFunction, 200 ); }); checkBox.focus(function(e) {self._cancelBlur();}); **********/ // check/uncheck the item on clicks on the entire item div item.click(function(e) { var anItem = $(this); e.stopImmediatePropagation(); if (!anItem.hasClass("ui-state-disabled") ) { // check/uncheck the underlying control var aCheckBox = anItem.find("input"); - var checked = aCheckBox.attr("checked"); - aCheckBox.attr("checked", !checked); + var checked = aCheckBox.prop("checked"); + aCheckBox.prop("checked", !checked); var callback = self.options.onItemClick; if ($.isFunction(callback)) try { callback.call(self,aCheckBox); } catch (ex) { // reject the change on any error - aCheckBox.attr("checked",checked); + aCheckBox.prop("checked",checked); return; } self._syncSelected(aCheckBox); self.sourceSelect.trigger("change", 'ddcl_internal'); if (!checked && !self.isMultiple && options.closeRadioOnClick) { self._toggleDropContainer(false); } } else { // retain the focus even if disabled anItem.focus(); self._cancelBlur(); } }); // do not let the focus wander around item.focus(function(e) { @@ -469,55 +469,55 @@ // Use the same tab index as the selector replacement var tabIndex = self.controlSelector.attr("tabindex"); var item = self._createDropItem(index, tabIndex, value, text, optCss, selected, disabled, indent); container.append(item); }, // Synchronizes the items checked and the source select // When firstItemChecksAll option is active also synchronizes the checked items // senderCheckbox parameters is the checkbox input that generated the synchronization _syncSelected: function(senderCheckbox) { var self = this, options = this.options, sourceSelect = this.sourceSelect, dropWrapper = this.dropWrapper; var selectOptions = sourceSelect.get(0).options; var allCheckboxes = dropWrapper.find("input.active"); if (options.firstItemChecksAll) { if ((senderCheckbox == null) && $(selectOptions[0]).attr("selected") ) { // Initialization call with first item active so force all to be active - allCheckboxes.attr("checked", true); + allCheckboxes.prop("checked", true); } else if ((senderCheckbox != null) && (senderCheckbox.attr("index") == 0)) { // Check all checkboxes if the first one is checked - allCheckboxes.attr("checked", senderCheckbox.attr("checked")); + allCheckboxes.prop("checked", senderCheckbox.prop("checked")); } else { // check the first checkbox if all the other checkboxes are checked var allChecked = true; var firstCheckbox = null; allCheckboxes.each(function(index) { if (index > 0) { - var checked = $(this).attr("checked"); + var checked = $(this).prop("checked"); if (!checked) { allChecked = false; } } else { firstCheckbox = $(this); } }); if ( firstCheckbox != null ) { - firstCheckbox.attr("checked", allChecked ); + firstCheckbox.prop("checked", allChecked ); } } } // do the actual synch with the source select allCheckboxes = dropWrapper.find("input"); allCheckboxes.each(function(index) { - $(selectOptions[index]).attr("selected", $(this).attr("checked")); + $(selectOptions[index]).attr("selected", $(this).prop("checked")); }); // update the text shown in the control self._updateControlText(); // Ensure the focus stays pointing where the user is working if ( senderCheckbox != null) { senderCheckbox.focus(); } }, _sourceSelectChangeHandler: function(event) { var self = this, dropWrapper = this.dropWrapper; dropWrapper.find("input").val(self.sourceSelect.val()); // update the text shown in the control self._updateControlText(); }, // Updates the text shown in the control depending on the checked (selected) items @@ -601,30 +601,31 @@ //instance.sourceSelect.triggerHandler("blur"); if($.isFunction(config.onComplete)) { try { config.onComplete.call(instance,instance.sourceSelect.get(0)); } catch(ex) { alert( 'callback failed: ' + ex ); }} } }; // shows the given drop container instance var show = function(instance) { if ( !instance.dropWrapper.isOpen ) { instance.dropWrapper.isOpen = true; $.ui.dropdownchecklist.gLastOpened = instance; var config = instance.options; + config.positionHow = $.ui.dropdownchecklist.defaults.positionHow; /**** Issue127 (and the like) to correct positioning when parent element is relative **** This positioning only worked with simple, non-relative parent position instance.dropWrapper.css({ top: instance.controlWrapper.offset().top + instance.controlWrapper.outerHeight() + "px", left: instance.controlWrapper.offset().left + "px" }); ****/ if ((config.positionHow == null) || (config.positionHow == 'absolute')) { /** Floats above subsequent content, but does NOT scroll */ instance.dropWrapper.css({ position: 'absolute' , top: instance.controlWrapper.offset().top + instance.controlWrapper.outerHeight() + "px" , left: instance.controlWrapper.offset().left + "px" }); } else if (config.positionHow == 'relative') { @@ -790,31 +791,31 @@ _refreshOption: function(item,disabled,selected) { var aParent = item.parent(); // account for enabled/disabled if ( disabled ) { item.attr("disabled","disabled"); item.removeClass("active"); item.addClass("inactive"); aParent.addClass("ui-state-disabled"); } else { item.removeAttr("disabled"); item.removeClass("inactive"); item.addClass("active"); aParent.removeClass("ui-state-disabled"); } // adjust the checkbox state - item.attr("checked",selected); + item.prop("checked",selected); }, _refreshGroup: function(group,disabled) { if ( disabled ) { group.addClass("ui-state-disabled"); } else { group.removeClass("ui-state-disabled"); } }, // External command to explicitly close the dropdown close: function() { this._toggleDropContainer(false); }, // External command to refresh the ddcl from the underlying selector refresh: function() { var self = this, sourceSelect = this.sourceSelect, dropWrapper = this.dropWrapper; @@ -867,22 +868,22 @@ $.Widget.prototype.destroy.apply(this, arguments); this.sourceSelect.css("display", this.initialDisplay); this.sourceSelect.attr("multiple", this.initialMultiple); this.controlWrapper.unbind().remove(); this.dropWrapper.remove(); } }); $.extend($.ui.dropdownchecklist, { defaults: { width: null , maxDropHeight: null , firstItemChecksAll: false , closeRadioOnClick: false , minWidth: 50 - , positionHow: 'absolute' + , positionHow: 'relative' , bgiframe: false , explicitClose: null } }); })(jQuery);