first commit
This commit is contained in:
1
wp-content/plugins/revslider/js/dropdownchecklist/ui.dropdownchecklist-1.4-min.js
vendored
Normal file
1
wp-content/plugins/revslider/js/dropdownchecklist/ui.dropdownchecklist-1.4-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,917 @@
|
||||
;(function($) {
|
||||
/*
|
||||
* ui.dropdownchecklist
|
||||
*
|
||||
* Copyright (c) 2008-2010 Adrian Tosca, Copyright (c) 2010-2011 Ittrium LLC
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt) OR GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
*/
|
||||
// The dropdown check list jQuery plugin transforms a regular select html element into a dropdown check list.
|
||||
$.widget("ui.dropdownchecklist", {
|
||||
// Some globlals
|
||||
// $.ui.dropdownchecklist.gLastOpened - keeps track of last opened dropdowncheck list so we can close it
|
||||
// $.ui.dropdownchecklist.gIDCounter - simple counter to provide a unique ID as needed
|
||||
version: function() {
|
||||
alert('DropDownCheckList v1.4');
|
||||
},
|
||||
// Creates the drop container that keeps the items and appends it to the document
|
||||
_appendDropContainer: function( controlItem ) {
|
||||
var wrapper = $("<div/>");
|
||||
// the container is wrapped in a div
|
||||
wrapper.addClass("ui-dropdownchecklist ui-dropdownchecklist-dropcontainer-wrapper");
|
||||
wrapper.addClass("ui-widget");
|
||||
// assign an id
|
||||
wrapper.attr("id",controlItem.attr("id") + '-ddw');
|
||||
// initially positioned way off screen to prevent it from displaying
|
||||
// NOTE absolute position to enable width/height calculation
|
||||
wrapper.css({ position: 'absolute', left: "-33000px", top: "-33000px" });
|
||||
|
||||
var container = $("<div/>"); // the actual container
|
||||
container.addClass("ui-dropdownchecklist-dropcontainer ui-widget-content");
|
||||
container.css("overflow-y", "auto");
|
||||
wrapper.append(container);
|
||||
|
||||
// insert the dropdown after the master control to try to keep the tab order intact
|
||||
// if you just add it to the end, tabbing out of the drop down takes focus off the page
|
||||
// @todo 22Sept2010 - check if size calculation is thrown off if the parent of the
|
||||
// selector is hidden. We may need to add it to the end of the document here,
|
||||
// calculate the size, and then move it back into proper position???
|
||||
//$(document.body).append(wrapper);
|
||||
wrapper.insertAfter(controlItem);
|
||||
|
||||
// flag that tells if the drop container is shown or not
|
||||
wrapper.isOpen = false;
|
||||
return wrapper;
|
||||
},
|
||||
// Look for browser standard 'open' on a closed selector
|
||||
_isDropDownKeyShortcut: function(e,keycode) {
|
||||
return e.altKey && ($.ui.keyCode.DOWN == keycode);// Alt + Down Arrow
|
||||
},
|
||||
// Look for key that will tell us to close the open dropdown
|
||||
_isDropDownCloseKey: function(e,keycode) {
|
||||
return ($.ui.keyCode.ESCAPE == keycode) || ($.ui.keyCode.ENTER == keycode);
|
||||
},
|
||||
// Handler to change the active focus based on a keystroke, moving some count of
|
||||
// items from the element that has the current focus
|
||||
_keyFocusChange: function(target,delta,limitToItems) {
|
||||
// Find item with current focus
|
||||
var focusables = $(":focusable");
|
||||
var index = focusables.index(target);
|
||||
if ( index >= 0 ) {
|
||||
index += delta;
|
||||
if ( limitToItems ) {
|
||||
// Bound change to list of input elements
|
||||
var allCheckboxes = this.dropWrapper.find("input:not([disabled])");
|
||||
var firstIndex = focusables.index(allCheckboxes.get(0));
|
||||
var lastIndex = focusables.index(allCheckboxes.get(allCheckboxes.length-1));
|
||||
if ( index < firstIndex ) {
|
||||
index = lastIndex;
|
||||
} else if ( index > lastIndex ) {
|
||||
index = firstIndex;
|
||||
}
|
||||
}
|
||||
focusables.get(index).focus();
|
||||
}
|
||||
},
|
||||
// Look for navigation, open, close (wired to keyup)
|
||||
_handleKeyboard: function(e) {
|
||||
var self = this;
|
||||
var keyCode = (e.keyCode || e.which);
|
||||
if (!self.dropWrapper.isOpen && self._isDropDownKeyShortcut(e, keyCode)) {
|
||||
// Key command to open the dropdown
|
||||
e.stopImmediatePropagation();
|
||||
self._toggleDropContainer(true);
|
||||
} else if (self.dropWrapper.isOpen && self._isDropDownCloseKey(e, keyCode)) {
|
||||
// Key command to close the dropdown (but we retain focus in the control)
|
||||
e.stopImmediatePropagation();
|
||||
self._toggleDropContainer(false);
|
||||
self.controlSelector.focus();
|
||||
} else if (self.dropWrapper.isOpen
|
||||
&& (e.target.type == 'checkbox')
|
||||
&& ((keyCode == $.ui.keyCode.DOWN) || (keyCode == $.ui.keyCode.UP)) ) {
|
||||
// Up/Down to cycle throught the open items
|
||||
e.stopImmediatePropagation();
|
||||
self._keyFocusChange(e.target, (keyCode == $.ui.keyCode.DOWN) ? 1 : -1, true);
|
||||
} else if (self.dropWrapper.isOpen && (keyCode == $.ui.keyCode.TAB) ) {
|
||||
// I wanted to adjust normal 'tab' processing here, but research indicates
|
||||
// that TAB key processing is NOT a cancelable event. You have to use a timer
|
||||
// hack to pull the focus back to where you want it after browser tab
|
||||
// processing completes. Not going to work for us.
|
||||
//e.stopImmediatePropagation();
|
||||
//self._keyFocusChange(e.target, (e.shiftKey) ? -1 : 1, true);
|
||||
}
|
||||
},
|
||||
// Look for change of focus
|
||||
_handleFocus: function(e,focusIn,forDropdown) {
|
||||
var self = this;
|
||||
if (forDropdown && !self.dropWrapper.isOpen) {
|
||||
// if the focus changes when the control is NOT open, mark it to show where the focus is/is not
|
||||
e.stopImmediatePropagation();
|
||||
if (focusIn) {
|
||||
self.controlSelector.addClass("ui-state-hover");
|
||||
if ($.ui.dropdownchecklist.gLastOpened != null) {
|
||||
$.ui.dropdownchecklist.gLastOpened._toggleDropContainer( false );
|
||||
}
|
||||
} else {
|
||||
self.controlSelector.removeClass("ui-state-hover");
|
||||
}
|
||||
} else if (!forDropdown && !focusIn) {
|
||||
// The dropdown is open, and an item (NOT the dropdown) has just lost the focus.
|
||||
// we really need a reliable method to see who has the focus as we process the blur,
|
||||
// but that mechanism does not seem to exist. Instead we rely on a delay before
|
||||
// posting the blur, with a focus event cancelling it before the delay expires.
|
||||
if ( e != null ) { e.stopImmediatePropagation(); }
|
||||
self.controlSelector.removeClass("ui-state-hover");
|
||||
self._toggleDropContainer( false );
|
||||
}
|
||||
},
|
||||
// Clear the pending change of focus, which keeps us 'in' the control
|
||||
_cancelBlur: function(e) {
|
||||
var self = this;
|
||||
if (self.blurringItem != null) {
|
||||
clearTimeout(self.blurringItem);
|
||||
self.blurringItem = null;
|
||||
}
|
||||
},
|
||||
// Creates the control that will replace the source select and appends it to the document
|
||||
// The control resembles a regular select with single selection
|
||||
_appendControl: function() {
|
||||
var self = this, sourceSelect = this.sourceSelect, options = this.options;
|
||||
|
||||
// the control is wrapped in a basic container
|
||||
// inline-block at this level seems to give us better size control
|
||||
var wrapper = $("<span/>");
|
||||
wrapper.addClass("ui-dropdownchecklist ui-dropdownchecklist-selector-wrapper ui-widget");
|
||||
wrapper.css( { display: "inline-block", cursor: "default", overflow: "hidden" } );
|
||||
|
||||
// assign an ID
|
||||
var baseID = sourceSelect.attr("id");
|
||||
if ((baseID == null) || (baseID == "")) {
|
||||
baseID = "ddcl-" + $.ui.dropdownchecklist.gIDCounter++;
|
||||
} else {
|
||||
baseID = "ddcl-" + baseID;
|
||||
}
|
||||
wrapper.attr("id",baseID);
|
||||
|
||||
// the actual control which you can style
|
||||
// inline-block needed to enable 'width' but has interesting problems cross browser
|
||||
var control = $("<span/>");
|
||||
control.addClass("ui-dropdownchecklist-selector ui-state-default");
|
||||
control.css( { display: "inline-block", overflow: "hidden", 'white-space': 'nowrap'} );
|
||||
// Setting a tab index means we are interested in the tab sequence
|
||||
var tabIndex = sourceSelect.attr("tabIndex");
|
||||
if ( tabIndex == null ) {
|
||||
tabIndex = 0;
|
||||
} else {
|
||||
tabIndex = parseInt(tabIndex);
|
||||
if ( tabIndex < 0 ) {
|
||||
tabIndex = 0;
|
||||
}
|
||||
}
|
||||
control.attr("tabIndex", tabIndex);
|
||||
control.keyup(function(e) {self._handleKeyboard(e);});
|
||||
control.focus(function(e) {self._handleFocus(e,true,true);});
|
||||
control.blur(function(e) {self._handleFocus(e,false,true);});
|
||||
wrapper.append(control);
|
||||
|
||||
// the optional icon (which is inherently a block) which we can float
|
||||
if (options.icon != null) {
|
||||
var iconPlacement = (options.icon.placement == null) ? "left" : options.icon.placement;
|
||||
var anIcon = $("<div/>");
|
||||
anIcon.addClass("ui-icon");
|
||||
anIcon.addClass( (options.icon.toOpen != null) ? options.icon.toOpen : "ui-icon-triangle-1-e");
|
||||
anIcon.css({ 'float': iconPlacement });
|
||||
control.append(anIcon);
|
||||
}
|
||||
// the text container keeps the control text that is built from the selected (checked) items
|
||||
// inline-block needed to prevent long text from wrapping to next line when icon is active
|
||||
var textContainer = $("<span/>");
|
||||
textContainer.addClass("ui-dropdownchecklist-text");
|
||||
textContainer.css( { display: "inline-block", 'white-space': "nowrap", overflow: "hidden" } );
|
||||
control.append(textContainer);
|
||||
|
||||
// add the hover styles to the control
|
||||
wrapper.hover(
|
||||
function() {
|
||||
if (!self.disabled) {
|
||||
control.addClass("ui-state-hover");
|
||||
}
|
||||
}
|
||||
, function() {
|
||||
if (!self.disabled) {
|
||||
control.removeClass("ui-state-hover");
|
||||
}
|
||||
}
|
||||
);
|
||||
// clicking on the control toggles the drop container
|
||||
wrapper.click(function(event) {
|
||||
if (!self.disabled) {
|
||||
event.stopImmediatePropagation();
|
||||
self._toggleDropContainer( !self.dropWrapper.isOpen );
|
||||
}
|
||||
});
|
||||
wrapper.insertAfter(sourceSelect);
|
||||
|
||||
// Watch for a window resize and adjust the control if open
|
||||
$(window).resize(function() {
|
||||
if (!self.disabled && self.dropWrapper.isOpen) {
|
||||
// Reopen yourself to get the position right
|
||||
self._toggleDropContainer(true);
|
||||
}
|
||||
});
|
||||
return wrapper;
|
||||
},
|
||||
// Creates a drop item that coresponds to an option element in the source select
|
||||
_createDropItem: function(index, tabIndex, value, text, optCss, checked, disabled, indent) {
|
||||
var self = this, options = this.options, sourceSelect = this.sourceSelect, controlWrapper = this.controlWrapper;
|
||||
// the item contains a div that contains a checkbox input and a lable for the text
|
||||
// the div
|
||||
var item = $("<div/>");
|
||||
item.addClass("ui-dropdownchecklist-item");
|
||||
item.css({'white-space': "nowrap"});
|
||||
var checkedString = checked ? ' checked="checked"' : '';
|
||||
var classString = disabled ? ' class="inactive"' : ' class="active"';
|
||||
|
||||
// generated id must be a bit unique to keep from colliding
|
||||
var idBase = controlWrapper.attr("id");
|
||||
var id = idBase + '-i' + index;
|
||||
var checkBox;
|
||||
|
||||
// all items start out disabled to keep them out of the tab order
|
||||
if (self.isMultiple) { // the checkbox
|
||||
checkBox = $('<input disabled type="checkbox" id="' + id + '"' + checkedString + classString + ' tabindex="' + tabIndex + '" />');
|
||||
} else { // the radiobutton
|
||||
checkBox = $('<input disabled type="radio" id="' + id + '" name="' + idBase + '"' + checkedString + classString + ' tabindex="' + tabIndex + '" />');
|
||||
}
|
||||
checkBox = checkBox.attr("index", index).val(value);
|
||||
item.append(checkBox);
|
||||
|
||||
// the text
|
||||
var label = $("<label for=" + id + "/>");
|
||||
label.addClass("ui-dropdownchecklist-text");
|
||||
if ( optCss != null ) label.attr('style',optCss);
|
||||
label.css({ cursor: "default" });
|
||||
label.html(text);
|
||||
if (indent) {
|
||||
item.addClass("ui-dropdownchecklist-indent");
|
||||
}
|
||||
item.addClass("ui-state-default");
|
||||
if (disabled) {
|
||||
item.addClass("ui-state-disabled");
|
||||
}
|
||||
label.click(function(e) {e.stopImmediatePropagation();});
|
||||
item.append(label);
|
||||
|
||||
// active items display themselves with hover
|
||||
item.hover(
|
||||
function(e) {
|
||||
var anItem = $(this);
|
||||
if (!anItem.hasClass("ui-state-disabled")) { anItem.addClass("ui-state-hover"); }
|
||||
}
|
||||
, function(e) {
|
||||
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,sourceSelect.get(0));
|
||||
} catch (ex) {
|
||||
// reject the change on any error
|
||||
aCheckBox.prop("checked",!aCheckBox.prop("checked"));
|
||||
self._syncSelected(aCheckBox);
|
||||
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
|
||||
// event to the current item with focus when the user
|
||||
// clicks in the scroll bar. So if you have a scrollable
|
||||
// dropdown with focus on an item, clicking in the scroll
|
||||
// will close the drop down.
|
||||
// I have no solution for blur processing at this time.
|
||||
/*********
|
||||
var timerFunction = function(){
|
||||
// I had a hell of a time getting setTimeout to fire this, do not try to
|
||||
// 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.prop("checked");
|
||||
aCheckBox.prop("checked", !checked);
|
||||
|
||||
var callback = self.options.onItemClick;
|
||||
if ($.isFunction(callback)) try {
|
||||
callback.call(self,aCheckBox,sourceSelect.get(0));
|
||||
} catch (ex) {
|
||||
// reject the change on any error
|
||||
aCheckBox.prop("checked",checked);
|
||||
self._syncSelected(aCheckBox);
|
||||
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) {
|
||||
var anItem = $(this);
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
item.keyup(function(e) {self._handleKeyboard(e);});
|
||||
return item;
|
||||
},
|
||||
_createGroupItem: function(text,disabled) {
|
||||
var self = this;
|
||||
var group = $("<div />");
|
||||
group.addClass("ui-dropdownchecklist-group ui-widget-header");
|
||||
if (disabled) {
|
||||
group.addClass("ui-state-disabled");
|
||||
}
|
||||
group.css({'white-space': "nowrap"});
|
||||
|
||||
var label = $("<span/>");
|
||||
label.addClass("ui-dropdownchecklist-text");
|
||||
label.css( { cursor: "default" });
|
||||
label.text(text);
|
||||
group.append(label);
|
||||
|
||||
// anything interesting when you click the group???
|
||||
group.click(function(e) {
|
||||
var aGroup= $(this);
|
||||
e.stopImmediatePropagation();
|
||||
// retain the focus even if no action is taken
|
||||
aGroup.focus();
|
||||
self._cancelBlur();
|
||||
});
|
||||
// do not let the focus wander around
|
||||
group.focus(function(e) {
|
||||
var aGroup = $(this);
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
return group;
|
||||
},
|
||||
_createCloseItem: function(text) {
|
||||
var self = this;
|
||||
var closeItem = $("<div />");
|
||||
closeItem.addClass("ui-state-default ui-dropdownchecklist-close ui-dropdownchecklist-item");
|
||||
closeItem.css({'white-space': 'nowrap', 'text-align': 'right'});
|
||||
|
||||
var label = $("<span/>");
|
||||
label.addClass("ui-dropdownchecklist-text");
|
||||
label.css( { cursor: "default" });
|
||||
label.html(text);
|
||||
closeItem.append(label);
|
||||
|
||||
// close the control on click
|
||||
closeItem.click(function(e) {
|
||||
var aGroup= $(this);
|
||||
e.stopImmediatePropagation();
|
||||
// retain the focus even if no action is taken
|
||||
aGroup.focus();
|
||||
self._toggleDropContainer( false );
|
||||
});
|
||||
closeItem.hover(
|
||||
function(e) { $(this).addClass("ui-state-hover"); }
|
||||
, function(e) { $(this).removeClass("ui-state-hover"); }
|
||||
);
|
||||
// do not let the focus wander around
|
||||
closeItem.focus(function(e) {
|
||||
var aGroup = $(this);
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
return closeItem;
|
||||
},
|
||||
// Creates the drop items and appends them to the drop container
|
||||
// Also calculates the size needed by the drop container and returns it
|
||||
_appendItems: function() {
|
||||
var self = this, config = this.options, sourceSelect = this.sourceSelect, dropWrapper = this.dropWrapper;
|
||||
var dropContainerDiv = dropWrapper.find(".ui-dropdownchecklist-dropcontainer");
|
||||
sourceSelect.children().each(function(index) { // when the select has groups
|
||||
var opt = $(this);
|
||||
if (opt.is("option")) {
|
||||
self._appendOption(opt, dropContainerDiv, index, false, false);
|
||||
} else if (opt.is("optgroup")) {
|
||||
var disabled = opt.prop("disabled");
|
||||
var text = opt.attr("label");
|
||||
if (text != "") {
|
||||
var group = self._createGroupItem(text,disabled);
|
||||
dropContainerDiv.append(group);
|
||||
}
|
||||
self._appendOptions(opt, dropContainerDiv, index, true, disabled);
|
||||
}
|
||||
});
|
||||
if ( config.explicitClose != null ) {
|
||||
var closeItem = self._createCloseItem(config.explicitClose);
|
||||
dropContainerDiv.append(closeItem);
|
||||
}
|
||||
var divWidth = dropContainerDiv.outerWidth();
|
||||
var divHeight = dropContainerDiv.outerHeight();
|
||||
return { width: divWidth, height: divHeight };
|
||||
},
|
||||
_appendOptions: function(parent, container, parentIndex, indent, forceDisabled) {
|
||||
var self = this;
|
||||
parent.children("option").each(function(index) {
|
||||
var option = $(this);
|
||||
var childIndex = (parentIndex + "." + index);
|
||||
self._appendOption(option, container, childIndex, indent, forceDisabled);
|
||||
});
|
||||
},
|
||||
_appendOption: function(option, container, index, indent, forceDisabled) {
|
||||
var self = this;
|
||||
// Note that the browsers destroy any html structure within the OPTION
|
||||
var text = option.html();
|
||||
if ( (text != null) && (text != '') ) {
|
||||
var value = option.val();
|
||||
var optCss = option.attr('style');
|
||||
var selected = option.prop("selected");
|
||||
var disabled = (forceDisabled || option.prop("disabled"));
|
||||
// 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 == 'exclusive') {
|
||||
if ((senderCheckbox == null) && $(selectOptions[0]).prop("selected") ) {
|
||||
// Initialization call with first item active
|
||||
allCheckboxes.prop("checked", false);
|
||||
$(allCheckboxes[0]).prop("checked", true);
|
||||
} else if ((senderCheckbox != null) && (senderCheckbox.attr("index") == 0)) {
|
||||
// Action on the first, so all other checkboxes NOT active
|
||||
var firstIsActive = senderCheckbox.prop("checked");
|
||||
allCheckboxes.prop("checked", false);
|
||||
$(allCheckboxes[0]).prop("checked", firstIsActive);
|
||||
} 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).prop("checked");
|
||||
if (!checked) { allChecked = false; }
|
||||
} else {
|
||||
firstCheckbox = $(this);
|
||||
}
|
||||
});
|
||||
if ( firstCheckbox != null ) {
|
||||
if ( allChecked ) {
|
||||
// when all are checked, only the first left checked
|
||||
allCheckboxes.prop("checked", false);
|
||||
}
|
||||
firstCheckbox.prop("checked", allChecked );
|
||||
}
|
||||
}
|
||||
} else if (options.firstItemChecksAll) {
|
||||
if ((senderCheckbox == null) && $(selectOptions[0]).prop("selected") ) {
|
||||
// Initialization call with first item active so force all to be active
|
||||
allCheckboxes.prop("checked", true);
|
||||
} else if ((senderCheckbox != null) && (senderCheckbox.attr("index") == 0)) {
|
||||
// Check all checkboxes if the first one is 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).prop("checked");
|
||||
if (!checked) { allChecked = false; }
|
||||
} else {
|
||||
firstCheckbox = $(this);
|
||||
}
|
||||
});
|
||||
if ( firstCheckbox != null ) {
|
||||
firstCheckbox.prop("checked", allChecked );
|
||||
}
|
||||
}
|
||||
}
|
||||
// do the actual synch with the source select
|
||||
var empties = 0;
|
||||
allCheckboxes = dropWrapper.find("input");
|
||||
allCheckboxes.each(function(index) {
|
||||
var anOption = $(selectOptions[index + empties]);
|
||||
var optionText = anOption.html();
|
||||
if ( (optionText == null) || (optionText == '') ) {
|
||||
empties += 1;
|
||||
anOption = $(selectOptions[index + empties]);
|
||||
}
|
||||
anOption.prop("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
|
||||
_updateControlText: function() {
|
||||
var self = this, sourceSelect = this.sourceSelect, options = this.options, controlWrapper = this.controlWrapper;
|
||||
var firstOption = sourceSelect.find("option:first");
|
||||
var selectOptions = sourceSelect.find("option");
|
||||
var text = self._formatText(selectOptions, options.firstItemChecksAll, firstOption);
|
||||
var controlLabel = controlWrapper.find(".ui-dropdownchecklist-text");
|
||||
controlLabel.html(text);
|
||||
// the attribute needs naked text, not html
|
||||
controlLabel.attr("title", controlLabel.text());
|
||||
},
|
||||
// Formats the text that is shown in the control
|
||||
_formatText: function(selectOptions, firstItemChecksAll, firstOption) {
|
||||
var text;
|
||||
if ( $.isFunction(this.options.textFormatFunction) ) {
|
||||
// let the callback do the formatting, but do not allow it to fail
|
||||
try {
|
||||
text = this.options.textFormatFunction(selectOptions);
|
||||
} catch(ex) {
|
||||
alert( 'textFormatFunction failed: ' + ex );
|
||||
}
|
||||
} else if (firstItemChecksAll && (firstOption != null) && firstOption.prop("selected")) {
|
||||
// just set the text from the first item
|
||||
text = firstOption.html();
|
||||
} else {
|
||||
// concatenate the text from the checked items
|
||||
text = "";
|
||||
selectOptions.each(function() {
|
||||
if ($(this).prop("selected")) {
|
||||
if ( text != "" ) { text += ", "; }
|
||||
/* NOTE use of .html versus .text, which can screw up ampersands for IE */
|
||||
var optCss = $(this).attr('style');
|
||||
var tempspan = $('<span/>');
|
||||
tempspan.html( $(this).html() );
|
||||
if ( optCss == null ) {
|
||||
text += tempspan.html();
|
||||
} else {
|
||||
tempspan.attr('style',optCss);
|
||||
text += $("<span/>").append(tempspan).html();
|
||||
}
|
||||
}
|
||||
});
|
||||
if ( text == "" ) {
|
||||
text = (this.options.emptyText != null) ? this.options.emptyText : " ";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
},
|
||||
// Shows and hides the drop container
|
||||
_toggleDropContainer: function( makeOpen ) {
|
||||
var self = this;
|
||||
// hides the last shown drop container
|
||||
var hide = function(instance) {
|
||||
if ((instance != null) && instance.dropWrapper.isOpen ){
|
||||
instance.dropWrapper.isOpen = false;
|
||||
$.ui.dropdownchecklist.gLastOpened = null;
|
||||
|
||||
var config = instance.options;
|
||||
instance.dropWrapper.css({
|
||||
top: "-33000px",
|
||||
left: "-33000px"
|
||||
});
|
||||
var aControl = instance.controlSelector;
|
||||
aControl.removeClass("ui-state-active");
|
||||
aControl.removeClass("ui-state-hover");
|
||||
|
||||
var anIcon = instance.controlWrapper.find(".ui-icon");
|
||||
if ( anIcon.length > 0 ) {
|
||||
anIcon.removeClass( (config.icon.toClose != null) ? config.icon.toClose : "ui-icon-triangle-1-s");
|
||||
anIcon.addClass( (config.icon.toOpen != null) ? config.icon.toOpen : "ui-icon-triangle-1-e");
|
||||
}
|
||||
$(document).unbind("click", hide);
|
||||
|
||||
// keep the items out of the tab order by disabling them
|
||||
instance.dropWrapper.find("input.active").prop("disabled",true);
|
||||
|
||||
// the following blur just does not fire??? because it is hidden??? because it does not have focus???
|
||||
//instance.sourceSelect.trigger("blur");
|
||||
//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;
|
||||
/**** 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.position().top + instance.controlWrapper.outerHeight() + "px"
|
||||
, left: instance.controlWrapper.position().left + "px"
|
||||
});
|
||||
} else if (config.positionHow == 'relative') {
|
||||
/** Scrolls with the parent but does NOT float above subsequent content */
|
||||
instance.dropWrapper.css({
|
||||
position: 'relative'
|
||||
, top: "0px"
|
||||
, left: "0px"
|
||||
});
|
||||
}
|
||||
var zIndex = 0;
|
||||
if (config.zIndex == null) {
|
||||
var ancestorsZIndexes = instance.controlWrapper.parents().map(
|
||||
function() {
|
||||
var zIndex = $(this).css("z-index");
|
||||
return isNaN(zIndex) ? 0 : zIndex; }
|
||||
).get();
|
||||
var parentZIndex = Math.max.apply(Math, ancestorsZIndexes);
|
||||
if ( parentZIndex >= 0) zIndex = parentZIndex+1;
|
||||
} else {
|
||||
/* Explicit set from the optins */
|
||||
zIndex = parseInt(config.zIndex);
|
||||
}
|
||||
if (zIndex > 0) {
|
||||
instance.dropWrapper.css( { 'z-index': zIndex } );
|
||||
}
|
||||
|
||||
var aControl = instance.controlSelector;
|
||||
aControl.addClass("ui-state-active");
|
||||
aControl.removeClass("ui-state-hover");
|
||||
|
||||
var anIcon = instance.controlWrapper.find(".ui-icon");
|
||||
if ( anIcon.length > 0 ) {
|
||||
anIcon.removeClass( (config.icon.toOpen != null) ? config.icon.toOpen : "ui-icon-triangle-1-e");
|
||||
anIcon.addClass( (config.icon.toClose != null) ? config.icon.toClose : "ui-icon-triangle-1-s");
|
||||
}
|
||||
$(document).bind("click", function(e) {hide(instance);} );
|
||||
|
||||
// insert the items back into the tab order by enabling all active ones
|
||||
var activeItems = instance.dropWrapper.find("input.active");
|
||||
activeItems.prop("disabled",false);
|
||||
|
||||
// we want the focus on the first active input item
|
||||
var firstActiveItem = activeItems.get(0);
|
||||
if ( firstActiveItem != null ) {
|
||||
firstActiveItem.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
if ( makeOpen ) {
|
||||
hide($.ui.dropdownchecklist.gLastOpened);
|
||||
show(self);
|
||||
} else {
|
||||
hide(self);
|
||||
}
|
||||
},
|
||||
// Set the size of the control and of the drop container
|
||||
_setSize: function(dropCalculatedSize) {
|
||||
var options = this.options, dropWrapper = this.dropWrapper, controlWrapper = this.controlWrapper;
|
||||
|
||||
// use the width from config options if set, otherwise set the same width as the drop container
|
||||
var controlWidth = dropCalculatedSize.width;
|
||||
if (options.width != null) {
|
||||
controlWidth = parseInt(options.width);
|
||||
} else if (options.minWidth != null) {
|
||||
var minWidth = parseInt(options.minWidth);
|
||||
// if the width is too small (usually when there are no items) set a minimum width
|
||||
if (controlWidth < minWidth) {
|
||||
controlWidth = minWidth;
|
||||
}
|
||||
}
|
||||
var control = this.controlSelector;
|
||||
control.css({ width: controlWidth + "px" });
|
||||
|
||||
// if we size the text, then Firefox places icons to the right properly
|
||||
// and we do not wrap on long lines
|
||||
var controlText = control.find(".ui-dropdownchecklist-text");
|
||||
var controlIcon = control.find(".ui-icon");
|
||||
if ( controlIcon != null ) {
|
||||
// Must be an inner/outer/border problem, but IE6 needs an extra bit of space,
|
||||
// otherwise you can get text pushed down into a second line when icons are active
|
||||
controlWidth -= (controlIcon.outerWidth() + 4);
|
||||
controlText.css( { width: controlWidth + "px" } );
|
||||
}
|
||||
// Account for padding, borders, etc
|
||||
controlWidth = controlWrapper.outerWidth();
|
||||
|
||||
// the drop container height can be set from options
|
||||
var maxDropHeight = (options.maxDropHeight != null)
|
||||
? parseInt(options.maxDropHeight)
|
||||
: -1;
|
||||
var dropHeight = ((maxDropHeight > 0) && (dropCalculatedSize.height > maxDropHeight))
|
||||
? maxDropHeight
|
||||
: dropCalculatedSize.height;
|
||||
// ensure the drop container is not less than the control width (would be ugly)
|
||||
var dropWidth = dropCalculatedSize.width < controlWidth ? controlWidth : dropCalculatedSize.width;
|
||||
|
||||
$(dropWrapper).css({
|
||||
height: dropHeight + "px",
|
||||
width: dropWidth + "px"
|
||||
});
|
||||
dropWrapper.find(".ui-dropdownchecklist-dropcontainer").css({
|
||||
height: dropHeight + "px"
|
||||
});
|
||||
},
|
||||
// Initializes the plugin
|
||||
_init: function() {
|
||||
var self = this, options = this.options;
|
||||
if ( $.ui.dropdownchecklist.gIDCounter == null) {
|
||||
$.ui.dropdownchecklist.gIDCounter = 1;
|
||||
}
|
||||
// item blurring relies on a cancelable timer
|
||||
self.blurringItem = null;
|
||||
|
||||
// sourceSelect is the select on which the plugin is applied
|
||||
var sourceSelect = self.element;
|
||||
self.initialDisplay = sourceSelect.css("display");
|
||||
sourceSelect.css("display", "none");
|
||||
self.initialMultiple = sourceSelect.prop("multiple");
|
||||
self.isMultiple = self.initialMultiple;
|
||||
if (options.forceMultiple != null) { self.isMultiple = options.forceMultiple; }
|
||||
sourceSelect.prop("multiple", true);
|
||||
self.sourceSelect = sourceSelect;
|
||||
|
||||
// append the control that resembles a single selection select
|
||||
var controlWrapper = self._appendControl();
|
||||
self.controlWrapper = controlWrapper;
|
||||
self.controlSelector = controlWrapper.find(".ui-dropdownchecklist-selector");
|
||||
|
||||
// create the drop container where the items are shown
|
||||
var dropWrapper = self._appendDropContainer(controlWrapper);
|
||||
self.dropWrapper = dropWrapper;
|
||||
|
||||
// append the items from the source select element
|
||||
var dropCalculatedSize = self._appendItems();
|
||||
|
||||
// updates the text shown in the control
|
||||
self._updateControlText(controlWrapper, dropWrapper, sourceSelect);
|
||||
|
||||
// set the sizes of control and drop container
|
||||
self._setSize(dropCalculatedSize);
|
||||
|
||||
// look for possible auto-check needed on first item
|
||||
if ( options.firstItemChecksAll ) {
|
||||
self._syncSelected(null);
|
||||
}
|
||||
// BGIFrame for IE6
|
||||
if (options.bgiframe && typeof self.dropWrapper.bgiframe == "function") {
|
||||
self.dropWrapper.bgiframe();
|
||||
}
|
||||
// listen for change events on the source select element
|
||||
// ensure we avoid processing internally triggered changes
|
||||
self.sourceSelect.change(function(event, eventName) {
|
||||
if (eventName != 'ddcl_internal') {
|
||||
self._sourceSelectChangeHandler(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
// Refresh the disable and check state from the underlying control
|
||||
_refreshOption: function(item,disabled,selected) {
|
||||
var aParent = item.parent();
|
||||
// account for enabled/disabled
|
||||
if ( disabled ) {
|
||||
item.prop("disabled",true);
|
||||
item.removeClass("active");
|
||||
item.addClass("inactive");
|
||||
aParent.addClass("ui-state-disabled");
|
||||
} else {
|
||||
item.prop("disabled",false);
|
||||
item.removeClass("inactive");
|
||||
item.addClass("active");
|
||||
aParent.removeClass("ui-state-disabled");
|
||||
}
|
||||
// adjust the checkbox state
|
||||
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;
|
||||
|
||||
var allCheckBoxes = dropWrapper.find("input");
|
||||
var allGroups = dropWrapper.find(".ui-dropdownchecklist-group");
|
||||
|
||||
var groupCount = 0;
|
||||
var optionCount = 0;
|
||||
sourceSelect.children().each(function(index) {
|
||||
var opt = $(this);
|
||||
var disabled = opt.prop("disabled");
|
||||
if (opt.is("option")) {
|
||||
var selected = opt.prop("selected");
|
||||
var anItem = $(allCheckBoxes[optionCount]);
|
||||
self._refreshOption(anItem, disabled, selected);
|
||||
optionCount += 1;
|
||||
} else if (opt.is("optgroup")) {
|
||||
var text = opt.attr("label");
|
||||
if (text != "") {
|
||||
var aGroup = $(allGroups[groupCount]);
|
||||
self._refreshGroup(aGroup, disabled);
|
||||
groupCount += 1;
|
||||
}
|
||||
opt.children("option").each(function() {
|
||||
var subopt = $(this);
|
||||
var subdisabled = (disabled || subopt.prop("disabled"));
|
||||
var selected = subopt.prop("selected");
|
||||
var subItem = $(allCheckBoxes[optionCount]);
|
||||
self._refreshOption(subItem, subdisabled, selected );
|
||||
optionCount += 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
// sync will handle firstItemChecksAll and updateControlText
|
||||
self._syncSelected(null);
|
||||
},
|
||||
// External command to enable the ddcl control
|
||||
enable: function() {
|
||||
this.controlSelector.removeClass("ui-state-disabled");
|
||||
this.disabled = false;
|
||||
},
|
||||
// External command to disable the ddcl control
|
||||
disable: function() {
|
||||
this.controlSelector.addClass("ui-state-disabled");
|
||||
this.disabled = true;
|
||||
},
|
||||
// External command to destroy all traces of the ddcl control
|
||||
destroy: function() {
|
||||
$.Widget.prototype.destroy.apply(this, arguments);
|
||||
this.sourceSelect.css("display", this.initialDisplay);
|
||||
this.sourceSelect.prop("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'
|
||||
, bgiframe: false
|
||||
, explicitClose: null
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
@ -0,0 +1,49 @@
|
||||
|
||||
.ui-dropdownchecklist {
|
||||
font-size: medium;
|
||||
color: black;
|
||||
}
|
||||
.ui-dropdownchecklist-selector {
|
||||
height: 20px;
|
||||
border: 1px solid #ddd;
|
||||
background: #fff;
|
||||
}
|
||||
.ui-state-hover, .ui-state-active {
|
||||
border-color: #5794bf;
|
||||
}
|
||||
.ui-dropdownchecklist-dropcontainer {
|
||||
background-color: #fff;
|
||||
border: 1px solid #999;
|
||||
}
|
||||
.ui-dropdownchecklist-item {
|
||||
}
|
||||
.ui-state-hover {
|
||||
background-color: #39f;
|
||||
}
|
||||
.ui-state-disabled label {
|
||||
color: #ccc;
|
||||
}
|
||||
.ui-dropdownchecklist-group {
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
.ui-dropdownchecklist-indent {
|
||||
padding-left: 7px;
|
||||
}
|
||||
/* Font size of 0 on the -selector and an explicit medium on -text required to eliminate
|
||||
descender problems within the containers and still have a valid size for the text */
|
||||
.ui-dropdownchecklist-selector-wrapper {
|
||||
vertical-align: middle;
|
||||
font-size: 0px;
|
||||
}
|
||||
.ui-dropdownchecklist-selector {
|
||||
padding: 1px 2px 2px 2px;
|
||||
font-size: 0px;
|
||||
}
|
||||
.ui-dropdownchecklist-text {
|
||||
font-size: medium;
|
||||
/* line-height: 20px; */
|
||||
}
|
||||
.ui-dropdownchecklist-group {
|
||||
padding: 1px 2px 2px 2px;
|
||||
}
|
Reference in New Issue
Block a user