diff options
Diffstat (limited to 'includes/js/dojox/form/DropDownSelect.js')
-rw-r--r-- | includes/js/dojox/form/DropDownSelect.js | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/includes/js/dojox/form/DropDownSelect.js b/includes/js/dojox/form/DropDownSelect.js new file mode 100644 index 0000000..94d26d1 --- /dev/null +++ b/includes/js/dojox/form/DropDownSelect.js @@ -0,0 +1,267 @@ +if(!dojo._hasResource["dojox.form.DropDownSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.form.DropDownSelect"] = true; +dojo.provide("dojox.form.DropDownSelect"); + +dojo.require("dijit.form.Button"); +dojo.require("dijit.Menu"); + +dojo.require("dojo.data.ItemFileWriteStore"); + +dojo.declare("dojox.form.DropDownSelect", dijit.form.DropDownButton, { + // summary: + // This is a "Styleable" select box - it is basically a DropDownButton which + // can take as its input a <select>. + + baseClass: "dojoxDropDownSelect", + + /*===== + dojox.form.__SelectOption = function(){ + // value: String + // The value of the option. Setting to empty (or missing) will + // place a separator at that location + // label: String + // The label for our option. It can contain html tags. + this.value = value; + this.label = label; + } + =====*/ + + // options: dojox.form.__SelectOption[] + // our set of options + options: null, + + // emptyLabel: string + // What to display in an "empty" dropdown + emptyLabel: "", + + // _isPopulated: boolean + // Whether or not we have been populated + _isPopulated: false, + + _addMenuItem: function(/* dojox.form.__SelectOption */ option){ + // summary: + // For the given option, add a menu item to our dropdown + // If the option doesn't have a value, then a separator is added + // in that place. + var menu = this.dropDown; + + if(!option.value){ + // We are a separator (no label set for it) + menu.addChild(new dijit.MenuSeparator()); + }else{ + // Just a regular menu option + var click = dojo.hitch(this, "setAttribute","value",option); + var mi = new dijit.MenuItem({ + id: this.id + "_item_" + option.value, + label: option.label, + onClick: click + }); + menu.addChild(mi); + + } + }, + + _resetButtonState: function(){ + // summary: + // Resets the menu and the length attribute of the button - and + // ensures that the label is appropriately set. + var len = this.options.length; + + // reset the menu to make it "populatable on the next click + var dropDown = this.dropDown; + dojo.forEach(dropDown.getChildren(), function(child){ + child.destroyRecursive(); + }); + this._isPopulated = false; + + // Set our length attribute and our value + this.setAttribute("readOnly", (len === 1)); + this.setAttribute("disabled", (len === 0)); + this.setAttribute("value", this.value); + }, + + _updateSelectedState: function(){ + // summary: + // Sets the "selected" class on the item for styling purposes + var val = this.value; + if(val){ + var testId = this.id + "_item_" + val; + dojo.forEach(this.dropDown.getChildren(), function(child){ + dojo[child.id === testId ? "addClass" : "removeClass"](child.domNode, + this.baseClass + "SelectedOption"); + }, this); + } + }, + + addOption: function(/* dojox.form.__SelectOption or string, optional */ value, /* string? */ label){ + // summary: + // Adds an option to the end of the select. If value is empty or + // missing, a separator is created instead. + + this.options.push(value.value ? value : { value:value, label:label }); + }, + + removeOption: function(/* string, dojox.form.__SelectOption or number */ valueOrIdx){ + // summary: + // Removes the given option + this.options = dojo.filter(this.options, function(node, idx){ + return !((typeof valueOrIdx === "number" && idx === valueOrIdx) || + (typeof valueOrIdx === "string" && node.value === valueOrIdx) || + (valueOrIdx.value && node.value === valueOrIdx.value)); + }); + }, + + setOptionLabel: function(/*string*/ value, /*string*/ label){ + dojo.forEach(this.options, function(node){ + if(node.value === value){ + node.label = label; + } + }); + }, + + destroy: function(){ + // summary: + // Clear out an outstanding hack handle + if(this._labelHackHandle){ + clearTimeout(this._labelHackHandle); + } + this.inherited(arguments); + }, + + setLabel: function(/* string */ content){ + // summary: + // Wraps our label in a div - that way, our rich text can work + // correctly. + + content = '<div class=" ' + this.baseClass + 'Label">' + + content + + '</div>'; + // Because FF2 has a problem with layout, we need to delay this + // call for it. + if(this._labelHackHandle){ + clearTimeout(this._labelHackHandle); + } + if(dojo.isFF === 2){ + this._labelHackHandle = setTimeout(dojo.hitch(this, function(){ + this._labelHackHandle = null; + dijit.form.DropDownButton.prototype.setLabel.call(this, content); + }), 0); + }else{ + this.inherited(arguments); + } + }, + + setAttribute: function(/*string*/ attr, /* anything */ value){ + // summary: sometime we get called to set our value - we need to + // make sure and route those requests through _setValue() + // instead. + if(attr === "value"){ + // If a string is passed, then we set our value from looking it up. + if(typeof value === "string"){ + value = dojo.filter(this.options, function(node){ + return node.value === value; + })[0]; + } + + // If we don't have a value, try to show the first item + if(!value){ + value = this.options[0] || { value: "", label: "" }; + } + this.value = value.value; + if(this._started){ + this.setLabel(value.label || this.emptyLabel || " "); + } + this._handleOnChange(value.value); + value = this.value; + }else{ + this.inherited(arguments); + } + }, + + _fillContent: function(){ + // summary: + // Loads our options and sets up our dropdown correctly. We + // don't want any content, so we don't call any inherit chain + // function. + var opts = this.options; + if(!opts){ + opts = this.options = this.srcNodeRef ? dojo.query(">", + this.srcNodeRef).map(function(node){ + if(node.getAttribute("type") === "separator"){ + return { value: "", label: "" }; + } + return { value: node.getAttribute("value"), + label: String(node.innerHTML) }; + }, this) : []; + } + + // Set the value to be the first, or the selected index + if(opts.length && !this.value){ + var si = this.srcNodeRef.selectedIndex; + this.value = opts[si != -1 ? si : 0].value; + } + + // Create the dropDown widget + this.dropDown = new dijit.Menu(); + }, + + postCreate: function(){ + // summary: sets up our event handling that we need for functioning + // as a select + + this.inherited(arguments); + + // Make our event connections for updating state + var fx = function(){ + dojo[this._opened ? "addClass" : "removeClass"](this.focusNode, + this.baseClass + "ButtonOpened"); + }; + this.connect(this, "_openDropDown", fx); + this.connect(this, "_closeDropDown", fx); + this.connect(this, "onChange", "_updateSelectedState"); + this.connect(this, "addOption", "_resetButtonState"); + this.connect(this, "removeOption", "_resetButtonState"); + this.connect(this, "setOptionLabel", "_resetButtonState"); + }, + + startup: function(){ + // summary: + // FF2 has layout problems if the reset call isn't done on a + // slight delay + this.inherited(arguments); + if(dojo.isFF === 2){ + setTimeout(dojo.hitch(this, this._resetButtonState), 0); + }else{ + this._resetButtonState(); + } + }, + + _populate: function(/* function */ callback){ + // summary: + // populates the menu (and does the callback, if passed) + + var dropDown = this.dropDown; + + // Add each menu item + dojo.forEach(this.options, this._addMenuItem, this); + + // Update states + this._updateSelectedState(); + dojo.addClass(this.dropDown.domNode, this.baseClass + "Menu"); + this._isPopulated = true; + if(callback){ callback.call(this); } + }, + + _toggleDropDown: function(){ + // summary: Overrides DropDownButton's toggle function to make sure + // that the values are correctly populated. + var dropDown = this.dropDown; + if(dropDown && !dropDown.isShowingNow && !this._isPopulated){ + this._populate(dojox.form.DropDownSelect.superclass._toggleDropDown); + }else{ + this.inherited(arguments); + } + } +}); + +} |