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);