summaryrefslogtreecommitdiff
path: root/includes/js/dojox/form
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojox/form')
-rw-r--r--includes/js/dojox/form/CheckedMultiSelect.js223
-rw-r--r--includes/js/dojox/form/DropDownSelect.js267
-rw-r--r--includes/js/dojox/form/PasswordValidator.js280
-rw-r--r--includes/js/dojox/form/README39
-rw-r--r--includes/js/dojox/form/nls/PasswordValidator.js1
-rw-r--r--includes/js/dojox/form/resources/CheckedMultiSelect.css65
-rw-r--r--includes/js/dojox/form/resources/CheckedMultiSelect.css.commented.css99
-rw-r--r--includes/js/dojox/form/resources/CheckedMultiSelect.html4
-rw-r--r--includes/js/dojox/form/resources/DropDownSelect.css137
-rw-r--r--includes/js/dojox/form/resources/DropDownSelect.css.commented.css209
-rw-r--r--includes/js/dojox/form/resources/PasswordValidator.html3
-rw-r--r--includes/js/dojox/form/resources/_CheckedMultiSelectItem.html4
-rw-r--r--includes/js/dojox/form/tests/test_CheckedMultiSelect.html91
-rw-r--r--includes/js/dojox/form/tests/test_DropDownSelect.html128
-rw-r--r--includes/js/dojox/form/tests/test_PasswordValidator.html216
15 files changed, 1766 insertions, 0 deletions
diff --git a/includes/js/dojox/form/CheckedMultiSelect.js b/includes/js/dojox/form/CheckedMultiSelect.js
new file mode 100644
index 0000000..eb80c72
--- /dev/null
+++ b/includes/js/dojox/form/CheckedMultiSelect.js
@@ -0,0 +1,223 @@
+if(!dojo._hasResource["dojox.form.CheckedMultiSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.form.CheckedMultiSelect"] = true;
+dojo.provide("dojox.form.CheckedMultiSelect");
+
+dojo.require("dijit.form.MultiSelect");
+dojo.require("dijit.form.CheckBox");
+
+dojo.declare("dojox.form._CheckedMultiSelectItem",
+ [dijit._Widget, dijit._Templated],
+ {
+ // summary:
+ // The individual items for a CheckedMultiSelect
+
+ widgetsInTemplate: true,
+ templateString:"<div class=\"dijitReset ${baseClass}\"\n\t><input class=\"${baseClass}Box\" dojoType=\"dijit.form.CheckBox\" dojoAttachPoint=\"checkBox\" dojoAttachEvent=\"_onClick:_changeBox\" type=\"checkbox\" \n\t><div class=\"dijitInline ${baseClass}Label\" dojoAttachPoint=\"labelNode\" dojoAttachEvent=\"onmousedown:_onMouse,onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick\">${option.innerHTML}</div\n></div>\n",
+
+ baseClass: "dojoxMultiSelectItem",
+
+ // option: Element
+ // The option that is associated with this item
+ option: null,
+ parent: null,
+
+ // disabled: boolean
+ // Whether or not this widget is disabled
+ disabled: false,
+
+ _changeBox: function(){
+ // summary:
+ // Called to force the select to match the state of the check box
+ // (only on click of the checkbox)
+ this.option.selected = this.checkBox.getValue() && true;
+
+ // fire the parent's change
+ this.parent._onChange();
+
+ // refocus the parent
+ this.parent.focus();
+ },
+
+ _labelClick: function(){
+ // summary:
+ // Called when the label portion is clicked
+ dojo.stopEvent(e);
+ if(this.disabled){
+ return;
+ }
+ var cb = this.checkBox;
+ cb.setValue(!cb.getValue());
+ this._changeBox();
+ },
+
+ _onMouse: function(e){
+ // summary:
+ // Sets the hover state depending on mouse state (passes through
+ // to the check box)
+ this.checkBox._onMouse(e);
+ },
+
+ _onClick: function(e){
+ // summary:
+ // Sets the click state (passes through to the check box)
+ this.checkBox._onClick(e);
+ },
+
+ _updateBox: function(){
+ // summary:
+ // Called to force the box to match the state of the select
+ this.checkBox.setValue(this.option.selected);
+ },
+
+ setAttribute: function(attr, value){
+ // summary:
+ // Disables (or enables) all the children as well
+ this.inherited(arguments);
+ switch(attr){
+ case "disabled":
+ this.checkBox.setAttribute(attr, value);
+ break;
+ default:
+ break;
+ }
+ }
+});
+
+dojo.declare("dojox.form.CheckedMultiSelect", dijit.form.MultiSelect, {
+ // summary:
+ // Extends the core dijit MultiSelect to provide a "checkbox" selector
+
+ templateString: "",
+ templateString:"<div class=\"dijit dijitReset dijitInline\" dojoAttachEvent=\"onmousedown:_mouseDown,onclick:focus\"\n\t><select class=\"${baseClass}Select\" multiple=\"true\" dojoAttachPoint=\"containerNode,focusNode\" dojoAttachEvent=\"onchange: _onChange\"></select\n\t><div dojoAttachPoint=\"wrapperDiv\"></div\n></div>\n",
+
+ baseClass: "dojoxMultiSelect",
+
+ // children: dojox.form._CheckedMultiSelectItem[]
+ // Array of all our children (for updating them)
+ children: [],
+
+ /*=====
+ 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,
+
+ _mouseDown: function(e){
+ // summary:
+ // Cancels the mousedown event to prevent others from stealing
+ // focus
+ dojo.stopEvent(e);
+ },
+
+ _updateChildren: function(){
+ // summary:
+ // Called to update the checked states of my children to match me
+ dojo.forEach(this.children,function(child){
+ child._updateBox();
+ });
+ },
+
+ _addChild: function(/*Element*/ option){
+ // summary:
+ // Adds and returns a child for the given option.
+ var item = new dojox.form._CheckedMultiSelectItem({
+ option: option,
+ parent: this
+ });
+ this.wrapperDiv.appendChild(item.domNode);
+ return item;
+ },
+
+ _loadChildren: function(){
+ // summary:
+ // Reloads the children to match our box.
+
+ // Destroy any existing children before loading them again
+ dojo.forEach(this.children, function(child){
+ child.destroyRecursive();
+ });
+ this.children = dojo.query("option", this.domNode).map(function(child){
+ return this._addChild(child);
+ }, this);
+ this.options = dojo.map(this.children, function(child){
+ var opt = child.option;
+ return { value:opt.value, label: opt.text };
+ });
+ // Update the statuses of the children
+ this._updateChildren();
+ },
+
+ addOption: function(/* dojox.form.__SelectOption or string, optional */ value, /* string? */ label){
+ // summary: Adds the given option to the select
+
+ var o = new Option("","");
+ o.value = value.value || value;
+ o.innerHTML = value.label || label;
+ this.containerNode.appendChild(o);
+ },
+
+ removeOption: function(/*String*/ optionId){
+ dojo.query("option[value=" + optionId + "]", this.domNode).forEach(function(node){
+ node.parentNode.removeChild(node);
+ }, this);
+ },
+
+ setOptionLabel: function(/*string*/ optionId, /*string*/ label){
+ dojo.query("option[value=" + optionId + "]", this.domNode).forEach(function(node){
+ node.innerHTML = label;
+ });
+ },
+
+ addSelected: function(select){
+ this.inherited(arguments);
+
+ // Reload my children and the children of the guy pointing to me
+ if(select._loadChildren){
+ select._loadChildren();
+ }
+ this._loadChildren();
+ },
+
+ setAttribute: function(attr, value){
+ // summary:
+ // Disable (or enable) all the children as well
+ this.inherited(arguments);
+ switch(attr){
+ case "disabled":
+ dojo.forEach(this.children, function(node){
+ if(node && node.setAttribute){
+ node.setAttribute(attr, value);
+ }
+ });
+ break;
+ default:
+ break;
+ }
+ },
+
+ startup: function(){
+ if(this._started){ return; }
+ this.inherited(arguments);
+
+ // Load children and make connections
+ this._loadChildren();
+ this.connect(this, "setValue", "_updateChildren");
+ this.connect(this, "invertSelection", "_updateChildren");
+ this.connect(this, "addOption", "_loadChildren");
+ this.connect(this, "removeOption", "_loadChildren");
+ this.connect(this, "setOptionLabel", "_loadChildren");
+ this._started = true;
+ }
+});
+
+}
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 || "&nbsp;");
+ }
+ 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);
+ }
+ }
+});
+
+}
diff --git a/includes/js/dojox/form/PasswordValidator.js b/includes/js/dojox/form/PasswordValidator.js
new file mode 100644
index 0000000..e147ddf
--- /dev/null
+++ b/includes/js/dojox/form/PasswordValidator.js
@@ -0,0 +1,280 @@
+if(!dojo._hasResource["dojox.form.PasswordValidator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.form.PasswordValidator"] = true;
+dojo.provide("dojox.form.PasswordValidator");
+
+dojo.require("dijit.form._FormWidget");
+dojo.require("dijit.form.ValidationTextBox");
+
+dojo.requireLocalization("dojox.form", "PasswordValidator", null, "ROOT");
+
+dojo.declare("dojox.form._ChildTextBox", dijit.form.ValidationTextBox, {
+ // summary:
+ // A class that is shared between all our children - extends
+ // ValidationTextBox and provides some shared functionality
+ //
+ // containerWidget: widget
+ // Our parent (the PasswordValidator)
+ containerWidget: null,
+
+ // type: string
+ // Don't override this - we are all "password" types
+ type: "password",
+
+ reset: function(){
+ // summary:
+ // Force-set to empty string (we don't save passwords EVER)...and
+ // since _OldPWBox overrides setValue to check for empty string,
+ // call our parent class directly (not this.inherited())
+ dijit.form.ValidationTextBox.prototype.setValue.call(this, "", true);
+ this._hasBeenBlurred = false;
+ }
+});
+
+
+
+dojo.declare("dojox.form._OldPWBox", dojox.form._ChildTextBox, {
+ // summary:
+ // A class representing our "old password" box.
+ //
+ // _isPWValid: boolean
+ // Whether or not the password is valid
+ _isPWValid: false,
+
+ setValue: function(/* anything */ newVal, /* boolean? */ priority){
+ // summary:
+ // Updates _isPWValid if this isn't our initial update by calling
+ // our PasswordValidator's pwCheck function
+ if(newVal === ""){
+ newVal = dojox.form._OldPWBox.superclass.getValue.call(this);
+ }
+ if(priority !== null){
+ // Priority is passed in as null, explicitly when this is an
+ // update (not initially set). We want to check our password now.
+ this._isPWValid = this.containerWidget.pwCheck(newVal);
+ }
+ this.inherited("setValue", arguments);
+ },
+
+ isValid: function(/* boolean */ isFocused){
+ // Take into account the isPWValid setting
+ return this.inherited("isValid", arguments) && this._isPWValid;
+ },
+
+ _update: function(/* event */ e){
+ // Only call validate() if we've been blurred or else we get popups
+ // too early.
+ if(this._hasBeenBlurred){ this.validate(true); }
+ this._onMouse(e);
+ },
+
+ getValue: function(){
+ // summary:
+ // Only returns a value if our container widget is valid. This
+ // is to prevent exposure of "oldPW" too early.
+ if(this.containerWidget.isValid()){
+ return this.inherited("getValue", arguments);
+ }else{
+ return "";
+ }
+ }
+});
+
+
+dojo.declare("dojox.form._NewPWBox", dojox.form._ChildTextBox, {
+ // summary:
+ // A class representing our new password textbox
+
+ // required: boolean
+ // Whether or not this widget is required (default: true)
+ required: true,
+
+ onChange: function(){
+ // summary:
+ // Validates our verify box - to make sure that a change to me is
+ // reflected there
+ this.containerWidget._inputWidgets[2].validate(false);
+ this.inherited(arguments);
+ }
+});
+
+dojo.declare("dojox.form._VerifyPWBox", dojox.form._ChildTextBox, {
+ // summary:
+ // A class representing our verify textbox
+
+ isValid: function(isFocused){
+ // summary:
+ // Validates that we match the "real" password
+ return this.inherited("isValid", arguments) &&
+ (this.getValue() == this.containerWidget._inputWidgets[1].getValue());
+ }
+});
+
+dojo.declare("dojox.form.PasswordValidator", dijit.form._FormValueWidget, {
+ // summary:
+ // A password validation widget that simplifies the "old/new/verify"
+ // style of requesting passwords. You will probably want to override
+ // this class and implement your own pwCheck function.
+ //
+ // required: boolean
+ // Whether or not it is required for form submission
+ required: true,
+
+ // inputWidgets: TextBox[]
+ // An array of text boxes that are our components
+ _inputWidgets: null,
+
+ // oldName: string?
+ // The name to send our old password as (when form is posted)
+ oldName: "",
+
+ templateString:"<div dojoAttachPoint=\"containerNode\">\n\t<input type=\"hidden\" name=\"${name}\" value=\"\" dojoAttachPoint=\"focusNode\" />\n</div>\n",
+
+ _hasBeenBlurred: false,
+
+ isValid: function(/* boolean */ isFocused){
+ // summary: we are valid if ALL our children are valid
+ return dojo.every(this._inputWidgets, function(i){
+ if(i && i._setStateClass){ i._setStateClass(); }
+ return (!i || i.isValid());
+ });
+ },
+
+ validate: function(/* boolean */ isFocused){
+ // summary: Validating this widget validates all our children
+ return dojo.every(dojo.map(this._inputWidgets, function(i){
+ if(i && i.validate){
+ i._hasBeenBlurred = (i._hasBeenBlurred || this._hasBeenBlurred);
+ return i.validate();
+ }
+ return true;
+ }, this), "return item;");
+ },
+
+ reset: function(){
+ // summary: Resetting this widget resets all our children
+ this._hasBeenBlurred = false;
+ dojo.forEach(this._inputWidgets, function(i){
+ if(i && i.reset){ i.reset(); }
+ }, this);
+ },
+
+ _createSubWidgets: function(){
+ // summary:
+ // Turns the inputs inside this widget into "real" validation
+ // widgets - and sets up the needed connections.
+ var widgets = this._inputWidgets,
+ msg = dojo.i18n.getLocalization("dojox.form", "PasswordValidator",
+ this.lang);
+ dojo.forEach(widgets, function(i, idx){
+ if(i){
+ var p = {containerWidget: this}, c;
+ if(idx === 0){
+ p.name = this.oldName;
+ p.invalidMessage = msg.badPasswordMessage;
+ c = dojox.form._OldPWBox;
+ }else if(idx === 1){
+ p.required = this.required;
+ c = dojox.form._NewPWBox;
+ }else if(idx === 2){
+ p.invalidMessage = msg.nomatchMessage;
+ c = dojox.form._VerifyPWBox;
+ }
+ widgets[idx] = new c(p, i);
+ }
+ }, this);
+ },
+
+ pwCheck: function(/* string */ password){
+ // summary:
+ // Overridable function for validation of the old password box.
+ //
+ // This function is called and passed the old password. Return
+ // true if it's OK to continue, and false if it is not.
+ //
+ // IMPORTANT SECURITY NOTE: Do NOT EVER EVER EVER check this in
+ // HTML or JavaScript!!!
+ //
+ // You will probably want to override this function to callback
+ // to a server to verify the password (the callback will need to
+ // be syncronous) - and it's probably a good idea to validate
+ // it again on form submission before actually doing
+ // anything destructive - that's why the "oldName" value
+ // is available.
+ //
+ // And don't just fetch the password from the server
+ // either :) Send the test password (probably hashed, for
+ // security) and return from the server a status instead.
+ //
+ // Again - DON'T BE INSECURE!!! Security is left as an exercise
+ // for the reader :)
+ return false;
+ },
+
+ postCreate: function(){
+ // summary:
+ // Sets up the correct widgets. You *MUST* specify one child
+ // text box (a simple HTML <input> element) with pwType="new"
+ // *and* one child text box with pwType="verify". You *MAY*
+ // specify a third child text box with pwType="old" in order to
+ // prompt the user to enter in their old password before the
+ // widget returns that it is valid.
+
+ this.inherited(arguments);
+
+ // Turn my inputs into the correct stuff....
+ var widgets = this._inputWidgets = [];
+ dojo.forEach(["old","new","verify"], function(i){
+ widgets.push(dojo.query("input[pwType=" + i + "]",
+ this.containerNode)[0]);
+ }, this);
+ if (!widgets[1] || !widgets[2]){
+ throw new Error("Need at least pwType=\"new\" and pwType=\"verify\"");
+ }
+ if (this.oldName && !widgets[0]){
+ throw new Error("Need to specify pwType=\"old\" if using oldName");
+ }
+ this._createSubWidgets();
+ },
+
+ setAttribute: function(/* string */ attr, /* anything */ value){
+ this.inherited(arguments);
+
+ // Disabling (or enabling) the container disables (or enables) all
+ // the subwidgets as well - same for requiring
+ switch(attr){
+ case "disabled":
+ case "required":
+ dojo.forEach(this._inputWidgets, function(i){
+ if(i && i.setAttribute){ i.setAttribute(attr, value);}
+ });
+ break;
+ default:
+ break;
+ }
+ },
+
+ getValue: function(){
+ // summary: overridden to return an empty string if we aren't valid.
+ if (this.isValid()){
+ return this._inputWidgets[1].getValue();
+ }else{
+ return "";
+ }
+ },
+
+ focus: function(){
+ // summary:
+ // places focus on the first invalid input widget - if all
+ // input widgets are valid, the first widget is focused.
+ var f = false;
+ dojo.forEach(this._inputWidgets, function(i){
+ if(i && !i.isValid() && !f){
+ i.focus();
+ f = true;
+ }
+ });
+ if(!f){ this._inputWidgets[1].focus(); }
+ }
+});
+
+}
diff --git a/includes/js/dojox/form/README b/includes/js/dojox/form/README
new file mode 100644
index 0000000..3fc4f7c
--- /dev/null
+++ b/includes/js/dojox/form/README
@@ -0,0 +1,39 @@
+-------------------------------------------------------------------------------
+dojox.form Collection
+-------------------------------------------------------------------------------
+Version 1.0
+Release date: 02/26/2008
+-------------------------------------------------------------------------------
+Project state:
+experimental
+-------------------------------------------------------------------------------
+Credits
+ Nathan Toone (nathan)
+
+-------------------------------------------------------------------------------
+Project description
+
+ This is a collection of additional widgets that can be used in forms.
+-------------------------------------------------------------------------------
+Dependencies:
+
+ Depends on dojo core and dijit
+-------------------------------------------------------------------------------
+Documentation
+
+-------------------------------------------------------------------------------
+Installation instructions
+
+ Install into /dojox/form
+-------------------------------------------------------------------------------
+Additional Notes (Brief widget list):
+
+ * CheckedMultiSelect - an extension to dijit.form.MultiSelect which
+ uses check boxes instead of ctrl-click
+
+ * PasswordValidator - a widget which simplifies the common "old/new/verify"
+ mechanism of specifying passwords
+
+ * DropDownSelect - an extension to dijit.form.DropDownButton which is
+ meant to mirror the html <select> drop down
+
diff --git a/includes/js/dojox/form/nls/PasswordValidator.js b/includes/js/dojox/form/nls/PasswordValidator.js
new file mode 100644
index 0000000..4887d27
--- /dev/null
+++ b/includes/js/dojox/form/nls/PasswordValidator.js
@@ -0,0 +1 @@
+({"badPasswordMessage":"Invalid Password.","nomatchMessage":"Passwords do not match."}) \ No newline at end of file
diff --git a/includes/js/dojox/form/resources/CheckedMultiSelect.css b/includes/js/dojox/form/resources/CheckedMultiSelect.css
new file mode 100644
index 0000000..1953b1e
--- /dev/null
+++ b/includes/js/dojox/form/resources/CheckedMultiSelect.css
@@ -0,0 +1,65 @@
+
+.dojoxMultiSelectSelect { display: none; }
+.dojoxMultiSelect {
+ border: solid black 1px;
+ margin: 1px 0;
+ overflow: scroll;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ height: 100px;
+}
+.dj_ie .dojoxMultiSelect,
+.dj_safari .dojoxMultiSelect {
+
+ padding-right: 15px;
+}
+.dojoxMultiSelectItem {
+ white-space: nowrap;
+ padding:.1em .2em;
+ cursor:default;
+}
+.dojoxMultiSelectDisabled * {
+ color:gray !important;
+}
+.dojoxMultiSelectItemLabel {
+ margin-left: .2em;
+}
+.tundra .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+.tundra .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/tundra/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #b3b3b3;
+ line-height: normal;
+}
+.tundra .dojoxMultiSelectFocused {
+
+ border-color:#406b9b;
+}
+.soria .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+.soria .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/soria/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/soria/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #8ba0bd;
+ line-height: normal;
+}
+.soria .dojoxMultiSelectFocused {
+
+ border-color:#406b9b;
+}
+.nihilo .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+.nihilo .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/nihilo/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/nihilo/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #d3d3d3;
+ line-height: normal;
+}
+.nihilo .dojoxMultiSelectFocused {
+
+ border-color:#b3b3b3;
+}
diff --git a/includes/js/dojox/form/resources/CheckedMultiSelect.css.commented.css b/includes/js/dojox/form/resources/CheckedMultiSelect.css.commented.css
new file mode 100644
index 0000000..32cd0b5
--- /dev/null
+++ b/includes/js/dojox/form/resources/CheckedMultiSelect.css.commented.css
@@ -0,0 +1,99 @@
+/*
+**----------------------------------------------------------------------------
+** CheckedMultiSelect
+**----------------------------------------------------------------------------
+*/
+.dojoxMultiSelectSelect { display: none; }
+
+.dojoxMultiSelect {
+ border: solid black 1px;
+ margin: 1px 0;
+ overflow: scroll;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ height: 100px;
+}
+
+.dj_ie .dojoxMultiSelect,
+.dj_safari .dojoxMultiSelect {
+ /* So that the scroll bar doesn't cover stuff up */
+ padding-right: 15px;
+}
+
+.dojoxMultiSelectItem {
+ white-space: nowrap;
+ padding:.1em .2em;
+ cursor:default;
+}
+
+.dojoxMultiSelectDisabled * {
+ color:gray !important;
+}
+
+.dojoxMultiSelectItemLabel {
+ margin-left: .2em;
+}
+
+/*
+**----------------------------------------------------------------------------
+** Tundra theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
+.tundra .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+
+.tundra .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/tundra/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #b3b3b3;
+ line-height: normal;
+}
+
+.tundra .dojoxMultiSelectFocused {
+ /* input field when focused (ie: typing affects it) */
+ border-color:#406b9b;
+}
+
+/*
+**----------------------------------------------------------------------------
+** Soria theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
+.soria .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+
+.soria .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/soria/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/soria/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #8ba0bd;
+ line-height: normal;
+}
+
+.soria .dojoxMultiSelectFocused {
+ /* input field when focused (ie: typing affects it) */
+ border-color:#406b9b;
+}
+
+/*
+**----------------------------------------------------------------------------
+** Nihilo theme (make look similar to text box)
+**----------------------------------------------------------------------------
+*/
+.nihilo .dojoxMultiSelect {
+ margin: 0em 0.1em;
+}
+
+.nihilo .dojoxMultiSelect {
+ background:#fff url("../../../dijit/themes/nihilo/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/nihilo/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #d3d3d3;
+ line-height: normal;
+}
+
+.nihilo .dojoxMultiSelectFocused {
+ /* input field when focused (ie: typing affects it) */
+ border-color:#b3b3b3;
+}
+
diff --git a/includes/js/dojox/form/resources/CheckedMultiSelect.html b/includes/js/dojox/form/resources/CheckedMultiSelect.html
new file mode 100644
index 0000000..256aad7
--- /dev/null
+++ b/includes/js/dojox/form/resources/CheckedMultiSelect.html
@@ -0,0 +1,4 @@
+<div class="dijit dijitReset dijitInline" dojoAttachEvent="onmousedown:_mouseDown,onclick:focus"
+ ><select class="${baseClass}Select" multiple="true" dojoAttachPoint="containerNode,focusNode" dojoAttachEvent="onchange: _onChange"></select
+ ><div dojoAttachPoint="wrapperDiv"></div
+></div> \ No newline at end of file
diff --git a/includes/js/dojox/form/resources/DropDownSelect.css b/includes/js/dojox/form/resources/DropDownSelect.css
new file mode 100644
index 0000000..cbd1971
--- /dev/null
+++ b/includes/js/dojox/form/resources/DropDownSelect.css
@@ -0,0 +1,137 @@
+
+.dojoxDropDownSelect {
+ margin: 0.2em;
+}
+.dijit_a11y .dojoxDropDownSelectDisabled .dijitButtonNode {
+ border-style: dotted !important;
+ border-color: #999 !important;
+ color:#999 !important;
+}
+.dojoxDropDownSelect .dijitButtonNode {
+ padding: 0px;
+}
+.dijitButtonNode .dojoxDropDownSelectLabel *
+{
+ vertical-align: baseline;
+}
+.dojoxDropDownSelectSelectedOption * {
+ font-weight: bold;
+}
+.dojoxDropDownSelectDisabled .dijitArrowButtonInner,
+.dojoxDropDownSelectReadOnly .dijitArrowButtonInner {
+ display: none;
+}
+.dojoxDropDownSelectMenu .dijitMenuItemIcon {
+ width: 1px;
+}
+.tundra .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.tundra .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+.tundra .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.tundra .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+.tundra .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/tundra/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #b3b3b3;
+ line-height: normal;
+}
+.tundra .dojoxDropDownSelectDisabled .dijitButtonNode {
+
+ border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
+
+ background:#e4e4e4 url("../../../dijit/themes/tundra/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60;
+}
+.dj_ie .tundra .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50);
+}
+.tundra .dojoxDropDownSelectHover .dijitButtonNode,
+.tundra .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+
+
+ border-color:#a5beda;
+ border-bottom-color:#5c7590;
+ border-right-color:#5c7590;
+ color:#000;
+ background:#fcfdff url("../../../dijit/themes/tundra/images/buttonHover.png") repeat-x bottom;
+}
+.tundra .dojoxDropDownSelectActive .dijitButtonNode {
+
+ border-color:#366dba;
+ background: #ededed url("../../../dijit/themes/tundra/images/buttonActive.png") bottom repeat-x;
+}
+.soria .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.soria .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+.soria .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/soria/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/soria/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #8ba0bd;
+ line-height: normal;
+}
+.soria .dojoxDropDownSelectDisabled .dijitButtonNode {
+
+ border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
+
+ background:#c3d3e5 url("../../../dijit/themes/soria/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60;
+}
+.dj_ie .soria .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50);
+}
+.soria .dojoxDropDownSelectHover .dijitButtonNode,
+.soria .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+
+
+ color:#000;
+ background:#acc5e2 url("../../../dijit/themes/soria/images/buttonHover.png") repeat-x top left;
+}
+.soria .dojoxDropDownSelectActive .dijitButtonNode {
+
+ border-color:#657c9c;
+ background: #91b4e5 url("../../../dijit/themes/soria/images/buttonActive.png") top left repeat-x;
+}
+.nihilo .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.nihilo .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+.nihilo .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/nihilo/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/nihilo/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #d3d3d3;
+ line-height: normal;
+}
+.nihilo .dojoxDropDownSelectDisabled .dijitButtonNode {
+
+ border-color: #dedede;
+
+ background:#fafafa url("../../../dijit/themes/nihilo/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60;
+}
+.dj_ie .nihilo .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50);
+}
+.nihilo .dojoxDropDownSelectHover .dijitButtonNode,
+.nihilo .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+
+
+ color:#000;
+ background:#fcfcfc url("../../../dijit/themes/nihilo/images/buttonHover.png") repeat-x top left;
+}
+.nihilo .dojoxDropDownSelectActive .dijitButtonNode {
+
+ border-color:#dedede;
+ background: #f5f5f5 url("../../../dijit/themes/nihilo/images/buttonActive.png") top left repeat-x;
+}
diff --git a/includes/js/dojox/form/resources/DropDownSelect.css.commented.css b/includes/js/dojox/form/resources/DropDownSelect.css.commented.css
new file mode 100644
index 0000000..a0a0636
--- /dev/null
+++ b/includes/js/dojox/form/resources/DropDownSelect.css.commented.css
@@ -0,0 +1,209 @@
+/*
+**----------------------------------------------------------------------------
+** DropDownSelect
+**----------------------------------------------------------------------------
+*/
+/* Mirror dijitDropDownButton a bit */
+.dojoxDropDownSelect {
+ margin: 0.2em;
+}
+.dijit_a11y .dojoxDropDownSelectDisabled .dijitButtonNode {
+ border-style: dotted !important;
+ border-color: #999 !important;
+ color:#999 !important;
+}
+
+/* And remove the padding - so it looks a "bit" more like a text box */
+.dojoxDropDownSelect .dijitButtonNode {
+ padding: 0px;
+}
+
+/* Fix the baseline of our label (for multi-size font elements) */
+.dijitButtonNode .dojoxDropDownSelectLabel *
+{
+ vertical-align: baseline;
+}
+
+/* Styling for the currently-selected option (rich text can mess this up) */
+.dojoxDropDownSelectSelectedOption * {
+ font-weight: bold;
+}
+
+/* And remove the arrow when we are read-only or disabled (1 or 0 options) */
+.dojoxDropDownSelectDisabled .dijitArrowButtonInner,
+.dojoxDropDownSelectReadOnly .dijitArrowButtonInner {
+ display: none;
+}
+
+/* And hide (at least, mostly) the menuItemIcon column */
+.dojoxDropDownSelectMenu .dijitMenuItemIcon {
+ width: 1px;
+}
+
+/*
+**----------------------------------------------------------------------------
+** Common stylings
+**----------------------------------------------------------------------------
+*/
+/* Cursor States */
+.tundra .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.tundra .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+
+
+/*
+**----------------------------------------------------------------------------
+** Tundra stylings
+**----------------------------------------------------------------------------
+*/
+/* Cursor States */
+.tundra .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.tundra .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+
+/* Make unselected "look" more like a text box and less like a button */
+.tundra .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/tundra/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/tundra/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #b3b3b3;
+ line-height: normal;
+}
+
+/* Mirror DropDownButton */
+.tundra .dojoxDropDownSelectDisabled .dijitButtonNode {
+ /* disabled state - inner */
+ border-color: #d5d5d5 #bdbdbd #bdbdbd #d5d5d5;
+ /*color:#b4b4b4;*/
+ background:#e4e4e4 url("../../../dijit/themes/tundra/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60; /* Safari, Opera and Mozilla */
+}
+
+.dj_ie .tundra .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50); /* IE */
+}
+
+.tundra .dojoxDropDownSelectHover .dijitButtonNode,
+.tundra .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+ /* hover and opened state - inner */
+ /* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
+ border-color:#a5beda;
+ border-bottom-color:#5c7590;
+ border-right-color:#5c7590;
+ color:#000;
+ background:#fcfdff url("../../../dijit/themes/tundra/images/buttonHover.png") repeat-x bottom;
+}
+
+.tundra .dojoxDropDownSelectActive .dijitButtonNode {
+ /* active state - inner (for when you are pressing a normal button, or
+ * when a toggle button is in a depressed state
+ */
+ border-color:#366dba;
+ background: #ededed url("../../../dijit/themes/tundra/images/buttonActive.png") bottom repeat-x;
+}
+
+
+/*
+**----------------------------------------------------------------------------
+** Soria stylings
+**----------------------------------------------------------------------------
+*/
+/* Cursor States */
+.soria .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.soria .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+
+/* Make unselected "look" more like a text box and less like a button */
+.soria .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/soria/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/soria/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #8ba0bd;
+ line-height: normal;
+}
+
+/* Mirror DropDownButton */
+.soria .dojoxDropDownSelectDisabled .dijitButtonNode {
+ /* disabled state - inner */
+ border-color: #b9bbdd #b9bbdd #b9bbdd #b9bbdd;
+ /*color:#b4b4b4;*/
+ background:#c3d3e5 url("../../../dijit/themes/soria/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60; /* Safari, Opera and Mozilla */
+}
+
+.dj_ie .soria .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50); /* IE */
+}
+
+.soria .dojoxDropDownSelectHover .dijitButtonNode,
+.soria .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+ /* hover state - inner */
+ /* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
+ color:#000;
+ background:#acc5e2 url("../../../dijit/themes/soria/images/buttonHover.png") repeat-x top left;
+}
+
+.soria .dojoxDropDownSelectActive .dijitButtonNode {
+ /* active state - inner (for when you are pressing a normal button, or
+ * when a toggle button is in a depressed state
+ */
+ border-color:#657c9c;
+ background: #91b4e5 url("../../../dijit/themes/soria/images/buttonActive.png") top left repeat-x;
+}
+
+/*
+**----------------------------------------------------------------------------
+** Nihilo stylings
+**----------------------------------------------------------------------------
+*/
+/* Cursor States */
+.nihilo .dojoxDropDownSelectDisabled * {
+ cursor: not-allowed !important;
+}
+.nihilo .dojoxDropDownSelectReadOnly * {
+ cursor: default !important;
+}
+
+/* Make unselected "look" more like a text box and less like a button */
+.nihilo .dojoxDropDownSelect .dijitButtonNode {
+ background:#fff url("../../../dijit/themes/nihilo/images/validationInputBg.png") repeat-x top left;
+ #background:#fff url('../../../dijit/themes/nihilo/images/validationInputBg.gif') repeat-x top left;
+ border:1px solid #d3d3d3;
+ line-height: normal;
+}
+
+/* Mirror DropDownButton */
+.nihilo .dojoxDropDownSelectDisabled .dijitButtonNode {
+ /* disabled state - inner */
+ border-color: #dedede;
+ /*color:#b4b4b4;*/
+ background:#fafafa url("../../../dijit/themes/nihilo/images/buttonDisabled.png") top repeat-x;
+ opacity: 0.60; /* Safari, Opera and Mozilla */
+}
+
+.dj_ie .nihilo .dojoxDropDownSelectDisabled .dijitButtonNode * {
+ filter: gray() alpha(opacity=50); /* IE */
+}
+
+.nihilo .dojoxDropDownSelectHover .dijitButtonNode,
+.nihilo .dojoxDropDownSelect .dojoxDropDownSelectButtonOpened {
+ /* hover state - inner */
+ /* TODO: change from Hover to Selected so that button is still highlighted while drop down is being used */
+ color:#000;
+ background:#fcfcfc url("../../../dijit/themes/nihilo/images/buttonHover.png") repeat-x top left;
+}
+
+.nihilo .dojoxDropDownSelectActive .dijitButtonNode {
+ /* active state - inner (for when you are pressing a normal button, or
+ * when a toggle button is in a depressed state
+ */
+ border-color:#dedede;
+ background: #f5f5f5 url("../../../dijit/themes/nihilo/images/buttonActive.png") top left repeat-x;
+}
diff --git a/includes/js/dojox/form/resources/PasswordValidator.html b/includes/js/dojox/form/resources/PasswordValidator.html
new file mode 100644
index 0000000..80a55ae
--- /dev/null
+++ b/includes/js/dojox/form/resources/PasswordValidator.html
@@ -0,0 +1,3 @@
+<div dojoAttachPoint="containerNode">
+ <input type="hidden" name="${name}" value="" dojoAttachPoint="focusNode" />
+</div> \ No newline at end of file
diff --git a/includes/js/dojox/form/resources/_CheckedMultiSelectItem.html b/includes/js/dojox/form/resources/_CheckedMultiSelectItem.html
new file mode 100644
index 0000000..d9ec863
--- /dev/null
+++ b/includes/js/dojox/form/resources/_CheckedMultiSelectItem.html
@@ -0,0 +1,4 @@
+<div class="dijitReset ${baseClass}"
+ ><input class="${baseClass}Box" dojoType="dijit.form.CheckBox" dojoAttachPoint="checkBox" dojoAttachEvent="_onClick:_changeBox" type="checkbox"
+ ><div class="dijitInline ${baseClass}Label" dojoAttachPoint="labelNode" dojoAttachEvent="onmousedown:_onMouse,onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick">${option.innerHTML}</div
+></div>
diff --git a/includes/js/dojox/form/tests/test_CheckedMultiSelect.html b/includes/js/dojox/form/tests/test_CheckedMultiSelect.html
new file mode 100644
index 0000000..b8729d2
--- /dev/null
+++ b/includes/js/dojox/form/tests/test_CheckedMultiSelect.html
@@ -0,0 +1,91 @@
+<html>
+ <head>
+ <script type="text/javascript"
+ src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true">
+ </script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.parser");
+ dojo.require("dojox.form.CheckedMultiSelect");
+ dojo.require("dijit.form.Button");
+ dojo.require("dijit.form.Form");
+
+ dojo.addOnLoad(function(){
+ doh.register("tests",
+ [
+ function test_setValue(t){
+ t.is(["VA","WA"], form.getValues().ms1);
+ form.setValues({ms1: ["TN","CA"]});
+ t.is(["TN","CA"], form.getValues().ms1);
+ ms1.invertSelection();
+ t.is(["VA","WA","FL"], form.getValues().ms1);
+ },
+ function test_addSelected(t){
+ ms1.addSelected(ms2);
+ t.is([], form.getValues().ms2);
+ ms1.invertSelection();
+ t.is(["TN","CA"], form.getValues().ms1);
+ },
+ ]
+ );
+ doh.run();
+ dojo.connect(ms1, "onChange", function(val){
+ console.log("First Select Changed to " + val);
+ });
+ });
+ </script>
+ <style>
+ @import url(../../../dojo/resources/dojo.css);
+ @import url(../../../dijit/themes/tundra/tundra.css);
+ @import url(../resources/CheckedMultiSelect.css);
+ @import url(../../../dijit/tests/css/dijitTests.css);
+ </style>
+ </head>
+ <body class="tundra">
+ <h1 class="testTitle">Test: dojox.form.CheckedMultiSelect</h1>
+ <h2>Automated test</h2>
+ <form dojoType="dijit.form.Form" jsId="form">
+ <select jsId="ms1" multiple="true" name="ms1" dojoType="dojox.form.CheckedMultiSelect">
+ <option value="TN">Tennessee</option>
+ <option value="VA" selected="selected">Virginia</option>
+ <option value="WA" selected="selected">Washington</option>
+ <option value="FL">Florida</option>
+ <option value="CA">California</option>
+ </select>
+ <hr>
+ <select jsId="ms2" multiple="true" name="ms2" dojoType="dojox.form.CheckedMultiSelect">
+ <option value="UT">Utah</option>
+ <option value="TX" selected="selected">Texas</option>
+ <option value="GA" selected="selected">Georgia</option>
+ <option value="ID">Idaho</option>
+ <option value="WY">Wyoming</option>
+ <option value="OR">Oregon</option>
+ <option value="PA">Pennsylvania</option>
+ </select>
+ <hr>
+ <select jsId="ms3" multiple="true" name="ms3" dojoType="dojox.form.CheckedMultiSelect">
+ </select>
+ <hr>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ console.dir(form.getValues());
+ </script>
+ Get Values
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ var idx = dojo.query("option", ms3.domNode).length;
+ ms3.addOption(idx + "", "Option " + (idx + 1));
+ </script>
+ Add Option
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ ms3.setAttribute("disabled", !ms3.disabled);
+ </script>
+ Toggle Disabled
+ </button>
+ </form>
+ </body>
+</html>
diff --git a/includes/js/dojox/form/tests/test_DropDownSelect.html b/includes/js/dojox/form/tests/test_DropDownSelect.html
new file mode 100644
index 0000000..4487e54
--- /dev/null
+++ b/includes/js/dojox/form/tests/test_DropDownSelect.html
@@ -0,0 +1,128 @@
+<html>
+ <head>
+ <script type="text/javascript"
+ src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true">
+ </script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.parser");
+ dojo.require("dojox.form.DropDownSelect");
+ dojo.require("dijit.form.Button");
+ dojo.require("dijit.form.Form");
+
+ var numOptions = 0;
+ var numChanges = 0;
+
+ dojo.addOnLoad(function(){
+ dojo.connect(s1, "onChange", function(val){
+ console.log("First Select Changed to " + val);
+ numChanges++;
+ });
+ doh.register("tests",
+ [
+ function test_setValue(t){
+ t.is({s1:"VA", s2:"CA", s3:"AL", s4: "AK", s5: "move", s6:"", s7:"NY"}, form.getValues());
+ s1.setAttribute("value", "WA");
+ t.is("WA", s1.value);
+ s1.setAttribute("value", "UT");
+ t.is("TN", s1.value);
+ t.is(2, numChanges);
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <style>
+ @import url(../../../dojo/resources/dojo.css);
+ @import url(../../../dijit/themes/tundra/tundra.css);
+ @import url(../resources/DropDownSelect.css);
+ @import url(../../../dijit/tests/css/dijitTests.css);
+ </style>
+ <style>
+ .ark { text-decoration: underline; }
+ </style>
+ </head>
+ <body class="tundra">
+ <h1 class="testTitle">Test: dojox.form.DropDownSelect</h1>
+ <h2>Automated test</h2>
+ <form dojoType="dijit.form.Form" jsId="form">
+ <h4 class="testSubtitle">Setting Defaults</h4>
+ <select jsId="s1" name="s1" dojoType="dojox.form.DropDownSelect">
+ <option value="TN">Tennessee</option>
+ <option value="VA" selected="selected">Virginia</option>
+ <option value="WA">Washington</option>
+ <option value="FL">Florida</option>
+ <option value="CA">California</option>
+ </select>
+ <select jsId="s2" name="s2" value="CA" dojoType="dojox.form.DropDownSelect">
+ <option value="AL">Alabama</option>
+ <option value="AK">Alaska</option>
+ <option value="AZ">Arizona</option>
+ <option value="AR">Arkansas</option>
+ <option value="CA">California</option>
+ </select>
+ <select jsId="s3" name="s3" dojoType="dojox.form.DropDownSelect">
+ <option value="AL">Alabama</option>
+ <option value="AK">Alaska</option>
+ <option type="separator"></option>
+ <option value="AZ">Arizona</option>
+ <option value="AR">Arkansas</option>
+ <option type="separator"></option>
+ <option value="CA">California</option>
+ </select>
+ <hr>
+ <h4 class="testSubtitle">Rich Text (Need to use divs and spans - since browsers hack selects to pieces)</h4>
+ <div jsId="s4" name="s4" value="AK" dojoType="dojox.form.DropDownSelect">
+ <span value="AL"><b>Alabama</b></span>
+ <span value="AK"><font color="red">A</font><font color="orange">l</font><font color="yellow">a</font><font color="green">s</font><font color="blue">k</font><font color="purple">a</font></span>
+ <span value="AZ"><i>Arizona</i></span>
+ <span value="AR"><span class="ark">Arkansas</span></span>
+ <span value="CA"><span style="font-size:25%">C</span><span style="font-size:50%">a</span><span style="font-size:75%">l</span><span style="font-size:90%">i</span><span style="font-size:100%">f</span><span style="font-size:125%">o</span><span style="font-size:133%">r</span><span style="font-size:150%">n</span><span style="font-size:175%">i</span><span style="font-size:200%">a</span></span>
+ <span value="NM">New<br>&nbsp;&nbsp;Mexico</span>
+ </div>
+ <div jsId="s5" name="s5" value="move" dojoType="dojox.form.DropDownSelect">
+ <span value="copy"><img style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndCopy.png" /> Copy</span>
+ <span value="move"><img style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndMove.png" /> Move</span>
+ <span value="nocopy"><img style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndNoCopy.png" /> No Copy</span>
+ <span value="nomove"><img style="vertical-align: middle;margin-top: 1px;margin-bottom:1px;" src="../../../dijit/themes/tundra/images/dndNoMove.png" /> No Move</span>
+ </div>
+ <hr>
+ <h4 class="testSubtitle">Empty</h4>
+ <select jsId="s6" name="s6" dojoType="dojox.form.DropDownSelect">
+ </select>
+ <hr>
+ <h4 class="testSubtitle">Single Item</h4>
+ <select jsId="s7" name="s7" dojoType="dojox.form.DropDownSelect">
+ <option value="NY">New York</option>
+ </select>
+ <hr>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ console.dir(form.getValues());
+ </script>
+ Get Values
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ numOptions++;
+ s6.addOption(numOptions + "", "Option " + numOptions);
+ </script>
+ Add Option
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ s6.removeOption(0);
+ </script>
+ Remove Top Option
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ s4.setAttribute("disabled", !s4.disabled);
+ </script>
+ Toggle Disabled
+ </button>
+ </form>
+ </body>
+</html>
diff --git a/includes/js/dojox/form/tests/test_PasswordValidator.html b/includes/js/dojox/form/tests/test_PasswordValidator.html
new file mode 100644
index 0000000..e3b1e63
--- /dev/null
+++ b/includes/js/dojox/form/tests/test_PasswordValidator.html
@@ -0,0 +1,216 @@
+<html>
+ <head>
+ <script type="text/javascript"
+ src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true">
+ </script>
+ <script type="text/javascript">
+ dojo.require("doh.runner");
+ dojo.require("dojo.parser");
+ dojo.require("dojox.form.PasswordValidator");
+ dojo.require("dijit.form.Button");
+ dojo.require("dijit.form.Form");
+
+ dojo.addOnLoad(function(){
+ doh.register("tests",
+ [
+ function test_setDisabled(t){
+ valid1.setAttribute("disabled", true);
+ t.t(dojo.every(dojo.query("[widgetId]",
+ valid1.domNode).map(function(i){
+ return dijit.byNode(i);
+ }), function(i){return i.disabled;}));
+ valid1.setAttribute("disabled", false);
+ t.t(dojo.every(dojo.query("[widgetId]",
+ valid1.domNode).map(function(i){
+ return dijit.byNode(i);
+ }), function(i){return !i.disabled;}));
+ },
+ function test_isValid(t){
+ t.f(form1.isValid());
+ dijit.byId("nv1").setValue("test");
+ dijit.byId("vv1").setValue("Test");
+ t.f(form1.isValid());
+ dijit.byId("vv1").setValue("test");
+ t.t(form1.isValid());
+ t.t(form6.isValid());
+ t.is({password: ""}, form6.getValues());
+ dijit.byId("nv6").setValue("test");
+ t.f(form6.isValid());
+ t.is({password: ""}, form6.getValues());
+ dijit.byId("vv6").setValue("test");
+ t.t(form6.isValid());
+ t.is({password: "test"}, form6.getValues());
+ },
+ function test_getValue(t){
+ dijit.byId("nv1").setValue("test");
+ dijit.byId("vv1").setValue("Test");
+ t.is({password: ""}, form1.getValues());
+ dijit.byId("vv1").setValue("test123");
+ dijit.byId("nv1").setValue("test123");
+ t.is({password: "test123"}, form1.getValues());
+ },
+ function test_oldPW(t){
+ dijit.byId("nv2").setValue("test");
+ dijit.byId("vv2").setValue("test");
+ t.f(form2.isValid());
+ dijit.byId("ov2").setValue("oldpw4");
+ t.f(form2.isValid());
+ dijit.byId("ov2").setValue("oldpw2");
+ t.t(form2.isValid());
+ },
+ function test_getOldValue(t){
+ t.is({password: "test"}, form2.getValues());
+ dijit.byId("nv3").setValue("test");
+ dijit.byId("vv3").setValue("test");
+ dijit.byId("ov3").setValue("oldpw4");
+ t.is({password: "", oldPassword: ""}, form3.getValues());
+ dijit.byId("ov3").setValue("oldpw3");
+ dijit.byId("vv3").setValue("Test");
+ t.is({password: "", oldPassword: ""}, form3.getValues());
+ dijit.byId("vv3").setValue("test");
+ t.is({password: "test", oldPassword: "oldpw3"}, form3.getValues());
+ },
+ function test_getValuesInTable(t){
+ dijit.byId("nv4").setValue("test");
+ dijit.byId("vv4").setValue("test");
+ dijit.byId("ov4").setValue("oldpw4");
+ t.is({password: "test"}, form4.getValues());
+ dijit.byId("nv5").setValue("test");
+ dijit.byId("vv5").setValue("test");
+ dijit.byId("ov5").setValue("oldpw5");
+ t.is({password: "test", oldPassword: "oldpw5"}, form5.getValues());
+ }
+ ]
+ );
+ doh.run();
+ });
+ </script>
+ <link rel="stylesheet" type="text/css" href="../../../dijit/themes/tundra/tundra.css">
+ <link rel="stylesheet" type="text/css" href="../../../dijit/tests/css/dijitTests.css">
+ </head>
+ <body class="tundra">
+ <h1 class="testTitle">Test: dojox.form.PasswordValidator</h1>
+ <h2>Automated test</h2>
+ <h4 class="testSubtitle">No old password</h4>
+ <form dojoType="dijit.form.Form" jsId="form1">
+ <div dojoType="dojox.form.PasswordValidator" jsId="valid1" name="password">
+ <label>Password: <input type="password" id="nv1" pwType="new" /></label><br>
+ <label>Validate: <input type="password" id="vv1" pwType="verify" /></label><br>
+ </div>
+ </form>
+ <hr>
+ <h4 class="testSubtitle">Old password (hard-coded to "oldpw2") - not passed to getValues</h4>
+ <form dojoType="dijit.form.Form" jsId="form2">
+ <div dojoType="dojox.form.PasswordValidator" jsId="valid2" name="password">
+ <script type="dojo/method" event="pwCheck" args="password">
+ /*
+ NOTE: Do NOT EVER EVER EVER do this sort of a check!!!
+
+ This is only as an example. You will probably want to
+ override the pwCheck function to callback to a server to
+ verify the password (the callback will need to be
+ syncronous) - and it's probably a good idea to validate
+ it again on form submission before actually doing
+ anything destructive - that's why the "oldName" value
+ is there.
+
+ And don't just fetch the password from the server
+ either :) Send the test password (probably hashed, for
+ security) and return from the server a status instead.
+
+ Again - DON'T DO THIS - it is HORRIBLY INSECURE!!!!
+
+ Security is left as an exercise to the reader :)
+ */
+ return password === "oldpw2";
+ </script>
+ <label>Old Password: <input type="password" id="ov2" pwType="old" /></label><br>
+ <label>Password: <input type="password" id="nv2" pwType="new" /></label><br>
+ <label>Validate: <input type="password" id="vv2" pwType="verify" /></label><br>
+ </div>
+ </form>
+ <hr>
+ <h4 class="testSubtitle">Old password (hard-coded to "oldpw3") - passed to getValues</h4>
+ <form dojoType="dijit.form.Form" jsId="form3">
+ <div dojoType="dojox.form.PasswordValidator" jsId="valid3" name="password" oldName="oldPassword">
+ <script type="dojo/method" event="pwCheck" args="password">
+ console.log("Checking " + password);
+ return password === "oldpw3";
+ </script>
+ <label>Old Password: <input type="password" id="ov3" pwType="old" /></label><br>
+ <label>Password: <input type="password" id="nv3" pwType="new" /></label><br>
+ <label>Validate: <input type="password" id="vv3" pwType="verify" /></label><br>
+ </div>
+ </form>
+ <hr>
+ <h4 class="testSubtitle">In Table, Old password (hard-coded to "oldpw4") - not passed to getValues</h4>
+ <form dojoType="dijit.form.Form" jsId="form4">
+ <div dojoType="dojox.form.PasswordValidator" jsId="valid4" name="password">
+ <script type="dojo/method" event="pwCheck" args="password">
+ return password === "oldpw4";
+ </script>
+ <table>
+ <tr>
+ <td><label for="ov4">Old Password:</label></td>
+ <td><input type="password" id="ov4" pwType="old" /></td>
+ </tr>
+ <tr>
+ <td><label for="nv4">Password:</label></td>
+ <td><input type="password" id="nv4" pwType="new" /></td>
+ </tr>
+ <tr>
+ <td><label for="vv4">Validate:</label></td>
+ <td><input type="password" id="vv4" pwType="verify" /></td>
+ </tr>
+ </table>
+ </div>
+ </form>
+ <hr>
+ <h4 class="testSubtitle">In Table, Old password (hard-coded to "oldpw5") - passed to getValues</h4>
+ <form dojoType="dijit.form.Form" jsId="form5">
+ <div dojoType="dojox.form.PasswordValidator" jsId="valid5" name="password" oldName="oldPassword">
+ <script type="dojo/method" event="pwCheck" args="password">
+ return password === "oldpw5";
+ </script>
+ <table>
+ <tr>
+ <td><label for="ov5">Old Password:</label></td>
+ <td><input type="password" id="ov5" pwType="old" /></td>
+ </tr>
+ <tr>
+ <td><label for="nv5">Password:</label></td>
+ <td><input type="password" id="nv5" pwType="new" /></td>
+ </tr>
+ <tr>
+ <td><label for="vv5">Validate:</label></td>
+ <td><input type="password" id="vv5" pwType="verify" /></td>
+ </tr>
+ </table>
+ </div>
+ </form>
+ <hr>
+ <h4 class="testSubtitle">No old password, not required</h4>
+ <form dojoType="dijit.form.Form" jsId="form6">
+ <div dojoType="dojox.form.PasswordValidator" required="false" jsId="valid6" name="password">
+ <label>Password: <input type="password" id="nv6" pwType="new" /></label><br>
+ <label>Validate: <input type="password" id="vv6" pwType="verify" /></label><br>
+ </div>
+ </form>
+ <hr>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ dojo.forEach([form1, form2, form3, form4, form5, form6], function(i){
+ console.dir(i.getValues());
+ });
+ </script>
+ Get Values
+ </button>
+ <button dojoType="dijit.form.Button">
+ <script type="dojo/method" event="onClick">
+ valid5.setAttribute("disabled", !valid5.disabled);
+ </script>
+ Toggle Disabled
+ </button>
+ </body>
+</html>