diff options
author | Andrew Dolgov <[email protected]> | 2013-04-02 20:06:16 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2013-04-02 20:06:16 +0400 |
commit | 870334be3f58507c05bfc72f3edbe5db10af4caf (patch) | |
tree | 441e1c41780eb75d422025cabea17724e2cc4a79 /lib/dojo/tt-rss-layer.js.uncompressed.js | |
parent | 7caa48fe6a3a37bd08f846f90e407ef31171f12c (diff) |
remove dojo uncompressed files
Diffstat (limited to 'lib/dojo/tt-rss-layer.js.uncompressed.js')
-rw-r--r-- | lib/dojo/tt-rss-layer.js.uncompressed.js | 34329 |
1 files changed, 0 insertions, 34329 deletions
diff --git a/lib/dojo/tt-rss-layer.js.uncompressed.js b/lib/dojo/tt-rss-layer.js.uncompressed.js deleted file mode 100644 index 8d05b4f80..000000000 --- a/lib/dojo/tt-rss-layer.js.uncompressed.js +++ /dev/null @@ -1,34329 +0,0 @@ -require({cache:{ -'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">✓</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\"> </td>\n</tr>\n", -'dijit/form/TextBox':function(){ -require({cache:{ -'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}}); -define("dijit/form/TextBox", [ - "dojo/_base/declare", // declare - "dojo/dom-construct", // domConstruct.create - "dojo/dom-style", // domStyle.getComputedStyle - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.hitch - "dojo/sniff", // has("ie") has("mozilla") - "./_FormValueWidget", - "./_TextBoxMixin", - "dojo/text!./templates/TextBox.html", - "../main" // to export dijit._setSelectionRange, remove in 2.0 -], function(declare, domConstruct, domStyle, kernel, lang, has, - _FormValueWidget, _TextBoxMixin, template, dijit){ - - // module: - // dijit/form/TextBox - - var TextBox = declare("dijit.form.TextBox", [_FormValueWidget, _TextBoxMixin], { - // summary: - // A base class for textbox form inputs - - templateString: template, - _singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" data-dojo-attach-point="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />', - - _buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events - - baseClass: "dijitTextBox", - - postMixInProperties: function(){ - var type = this.type.toLowerCase(); - if(this.templateString && this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == this.constructor.prototype.templateString)){ - this.templateString = this._singleNodeTemplate; - } - this.inherited(arguments); - }, - - postCreate: function(){ - this.inherited(arguments); - - if(has("ie") < 9){ - // IE INPUT tag fontFamily has to be set directly using STYLE - // the defer gives IE a chance to render the TextBox and to deal with font inheritance - this.defer(function(){ - try{ - var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed - if(s){ - var ff = s.fontFamily; - if(ff){ - var inputs = this.domNode.getElementsByTagName("INPUT"); - if(inputs){ - for(var i=0; i < inputs.length; i++){ - inputs[i].style.fontFamily = ff; - } - } - } - } - }catch(e){/*when used in a Dialog, and this is called before the dialog is - shown, s.fontFamily would trigger "Invalid Argument" error.*/} - }); - } - }, - - _onInput: function(e){ - this.inherited(arguments); - if(this.intermediateChanges){ // _TextBoxMixin uses onInput - // allow the key to post to the widget input box - this.defer(function(){ this._handleOnChange(this.get('value'), false); }); - } - }, - - _setPlaceHolderAttr: function(v){ - this._set("placeHolder", v); - if(!this._phspan){ - this._attachPoints.push('_phspan'); - // dijitInputField class gives placeHolder same padding as the input field - // parent node already has dijitInputField class but it doesn't affect this <span> - // since it's position: absolute. - this._phspan = domConstruct.create('span',{ onmousedown:function(e){ e.preventDefault(); }, className:'dijitPlaceHolder dijitInputField'},this.textbox,'after'); - } - this._phspan.innerHTML=""; - this._phspan.appendChild(this._phspan.ownerDocument.createTextNode(v)); - this._updatePlaceHolder(); - }, - - _updatePlaceHolder: function(){ - if(this._phspan){ - this._phspan.style.display=(this.placeHolder&&!this.focused&&!this.textbox.value)?"":"none"; - } - }, - - _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ - this.inherited(arguments); - this._updatePlaceHolder(); - }, - - getDisplayedValue: function(){ - // summary: - // Deprecated. Use get('displayedValue') instead. - // tags: - // deprecated - kernel.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use get('displayedValue') instead.", "", "2.0"); - return this.get('displayedValue'); - }, - - setDisplayedValue: function(/*String*/ value){ - // summary: - // Deprecated. Use set('displayedValue', ...) instead. - // tags: - // deprecated - kernel.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0"); - this.set('displayedValue', value); - }, - - _onBlur: function(e){ - if(this.disabled){ return; } - this.inherited(arguments); - this._updatePlaceHolder(); - - if(has("mozilla")){ - if(this.selectOnClick){ - // clear selection so that the next mouse click doesn't reselect - this.textbox.selectionStart = this.textbox.selectionEnd = undefined; - } - } - }, - - _onFocus: function(/*String*/ by){ - if(this.disabled || this.readOnly){ return; } - this.inherited(arguments); - this._updatePlaceHolder(); - } - }); - - if(has("ie")){ - TextBox.prototype._isTextSelected = function(){ - var range = this.ownerDocument.selection.createRange(); - var parent = range.parentElement(); - return parent == this.textbox && range.text.length > 0; - }; - - // Overrides definition of _setSelectionRange from _TextBoxMixin (TODO: move to _TextBoxMixin.js?) - dijit._setSelectionRange = _TextBoxMixin._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ - if(element.createTextRange){ - var r = element.createTextRange(); - r.collapse(true); - r.moveStart("character", -99999); // move to 0 - r.moveStart("character", start); // delta from 0 is the correct position - r.moveEnd("character", stop-start); - r.select(); - } - } - } - - return TextBox; -}); - -}, -'dijit/_base/scroll':function(){ -define("dijit/_base/scroll", [ - "dojo/window", // windowUtils.scrollIntoView - "../main" // export symbol to dijit -], function(windowUtils, dijit){ - // module: - // dijit/_base/scroll - - /*===== - return { - // summary: - // Back compatibility module, new code should use windowUtils directly instead of using this module. - }; - =====*/ - - dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){ - // summary: - // Scroll the passed node into view, if it is not already. - // Deprecated, use `windowUtils.scrollIntoView` instead. - - windowUtils.scrollIntoView(node, pos); - }; -}); - -}, -'dijit/_TemplatedMixin':function(){ -define("dijit/_TemplatedMixin", [ - "dojo/_base/lang", // lang.getObject - "dojo/touch", - "./_WidgetBase", - "dojo/string", // string.substitute string.trim - "dojo/cache", // dojo.cache - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom - "dojo/sniff", // has("ie") - "dojo/_base/unload" // unload.addOnWindowUnload -], function(lang, touch, _WidgetBase, string, cache, array, declare, domConstruct, has, unload) { - - // module: - // dijit/_TemplatedMixin - - var _TemplatedMixin = declare("dijit._TemplatedMixin", null, { - // summary: - // Mixin for widgets that are instantiated from a template - - // templateString: [protected] String - // A string that represents the widget template. - // Use in conjunction with dojo.cache() to load from a file. - templateString: null, - - // templatePath: [protected deprecated] String - // Path to template (HTML file) for this widget relative to dojo.baseUrl. - // Deprecated: use templateString with require([... "dojo/text!..."], ...) instead - templatePath: null, - - // skipNodeCache: [protected] Boolean - // If using a cached widget template nodes poses issues for a - // particular widget class, it can set this property to ensure - // that its template is always re-built from a string - _skipNodeCache: false, - - // _earlyTemplatedStartup: Boolean - // A fallback to preserve the 1.0 - 1.3 behavior of children in - // templates having their startup called before the parent widget - // fires postCreate. Defaults to 'false', causing child widgets to - // have their .startup() called immediately before a parent widget - // .startup(), but always after the parent .postCreate(). Set to - // 'true' to re-enable to previous, arguably broken, behavior. - _earlyTemplatedStartup: false, - -/*===== - // _attachPoints: [private] String[] - // List of widget attribute names associated with data-dojo-attach-point=... in the - // template, ex: ["containerNode", "labelNode"] - _attachPoints: [], - - // _attachEvents: [private] Handle[] - // List of connections associated with data-dojo-attach-event=... in the - // template - _attachEvents: [], - =====*/ - - constructor: function(/*===== params, srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree. - - this._attachPoints = []; - this._attachEvents = []; - }, - - _stringRepl: function(tmpl){ - // summary: - // Does substitution of ${foo} type properties in template string - // tags: - // private - var className = this.declaredClass, _this = this; - // Cache contains a string because we need to do property replacement - // do the property replacement - return string.substitute(tmpl, this, function(value, key){ - if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); } - if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide - if(value == null){ return ""; } - - // Substitution keys beginning with ! will skip the transform step, - // in case a user wishes to insert unescaped markup, e.g. ${!foo} - return key.charAt(0) == "!" ? value : - // Safer substitution, see heading "Attribute values" in - // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2 - value.toString().replace(/"/g,"""); //TODO: add &? use encodeXML method? - }, this); - }, - - buildRendering: function(){ - // summary: - // Construct the UI for this widget from a template, setting this.domNode. - // tags: - // protected - - if(!this.templateString){ - this.templateString = cache(this.templatePath, {sanitize: true}); - } - - // Lookup cached version of template, and download to cache if it - // isn't there already. Returns either a DomNode or a string, depending on - // whether or not the template contains ${foo} replacement parameters. - var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache, this.ownerDocument); - - var node; - if(lang.isString(cached)){ - node = domConstruct.toDom(this._stringRepl(cached), this.ownerDocument); - if(node.nodeType != 1){ - // Flag common problems such as templates with multiple top level nodes (nodeType == 11) - throw new Error("Invalid template: " + cached); - } - }else{ - // if it's a node, all we have to do is clone it - node = cached.cloneNode(true); - } - - this.domNode = node; - - // Call down to _Widget.buildRendering() to get base classes assigned - // TODO: change the baseClass assignment to _setBaseClassAttr - this.inherited(arguments); - - // recurse through the node, looking for, and attaching to, our - // attachment points and events, which should be defined on the template node. - this._attachTemplateNodes(node, function(n,p){ return n.getAttribute(p); }); - - this._beforeFillContent(); // hook for _WidgetsInTemplateMixin - - this._fillContent(this.srcNodeRef); - }, - - _beforeFillContent: function(){ - }, - - _fillContent: function(/*DomNode*/ source){ - // summary: - // Relocate source contents to templated container node. - // this.containerNode must be able to receive children, or exceptions will be thrown. - // tags: - // protected - var dest = this.containerNode; - if(source && dest){ - while(source.hasChildNodes()){ - dest.appendChild(source.firstChild); - } - } - }, - - _attachTemplateNodes: function(rootNode, getAttrFunc){ - // summary: - // Iterate through the template and attach functions and nodes accordingly. - // Alternately, if rootNode is an array of widgets, then will process data-dojo-attach-point - // etc. for those widgets. - // description: - // Map widget properties and functions to the handlers specified in - // the dom node and it's descendants. This function iterates over all - // nodes and looks for these properties: - // - // - dojoAttachPoint/data-dojo-attach-point - // - dojoAttachEvent/data-dojo-attach-event - // rootNode: DomNode|Widget[] - // the node to search for properties. All children will be searched. - // getAttrFunc: Function - // a function which will be used to obtain property for a given - // DomNode/Widget - // tags: - // private - - var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*")); - var x = lang.isArray(rootNode) ? 0 : -1; - for(; x < 0 || nodes[x]; x++){ // don't access nodes.length on IE, see #14346 - var baseNode = (x == -1) ? rootNode : nodes[x]; - if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){ - continue; - } - // Process data-dojo-attach-point - var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point"); - if(attachPoint){ - var point, points = attachPoint.split(/\s*,\s*/); - while((point = points.shift())){ - if(lang.isArray(this[point])){ - this[point].push(baseNode); - }else{ - this[point]=baseNode; - } - this._attachPoints.push(point); - } - } - - // Process data-dojo-attach-event - var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event"); - if(attachEvent){ - // NOTE: we want to support attributes that have the form - // "domEvent: nativeEvent; ..." - var event, events = attachEvent.split(/\s*,\s*/); - var trim = lang.trim; - while((event = events.shift())){ - if(event){ - var thisFunc = null; - if(event.indexOf(":") != -1){ - // oh, if only JS had tuple assignment - var funcNameArr = event.split(":"); - event = trim(funcNameArr[0]); - thisFunc = trim(funcNameArr[1]); - }else{ - event = trim(event); - } - if(!thisFunc){ - thisFunc = event; - } - // Map "press", "move" and "release" to keys.touch, keys.move, keys.release - this._attachEvents.push(this.connect(baseNode, touch[event] || event, thisFunc)); - } - } - } - } - }, - - destroyRendering: function(){ - // Delete all attach points to prevent IE6 memory leaks. - array.forEach(this._attachPoints, function(point){ - delete this[point]; - }, this); - this._attachPoints = []; - - // And same for event handlers - array.forEach(this._attachEvents, this.disconnect, this); - this._attachEvents = []; - - this.inherited(arguments); - } - }); - - // key is templateString; object is either string or DOM tree - _TemplatedMixin._templateCache = {}; - - _TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString, doc){ - // summary: - // Static method to get a template based on the templatePath or - // templateString key - // templateString: String - // The template - // alwaysUseString: Boolean - // Don't cache the DOM tree for this template, even if it doesn't have any variables - // doc: Document? - // The target document. Defaults to document global if unspecified. - // returns: Mixed - // Either string (if there are ${} variables that need to be replaced) or just - // a DOM tree (if the node can be cloned directly) - - // is it already cached? - var tmplts = _TemplatedMixin._templateCache; - var key = templateString; - var cached = tmplts[key]; - if(cached){ - try{ - // if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the - // current document, then use the current cached value - if(!cached.ownerDocument || cached.ownerDocument == (doc || document)){ - // string or node of the same document - return cached; - } - }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded - domConstruct.destroy(cached); - } - - templateString = string.trim(templateString); - - if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){ - // there are variables in the template so all we can do is cache the string - return (tmplts[key] = templateString); //String - }else{ - // there are no variables in the template so we can cache the DOM tree - var node = domConstruct.toDom(templateString, doc); - if(node.nodeType != 1){ - throw new Error("Invalid template: " + templateString); - } - return (tmplts[key] = node); //Node - } - }; - - if(has("ie")){ - unload.addOnWindowUnload(function(){ - var cache = _TemplatedMixin._templateCache; - for(var key in cache){ - var value = cache[key]; - if(typeof value == "object"){ // value is either a string or a DOM node template - domConstruct.destroy(value); - } - delete cache[key]; - } - }); - } - - // These arguments can be specified for widgets which are used in templates. - // Since any widget can be specified as sub widgets in template, mix it - // into the base widget class. (This is a hack, but it's effective.). - // Remove for 2.0. Also, hide from API doc parser. - lang.extend(_WidgetBase, /*===== {} || =====*/ { - dojoAttachEvent: "", - dojoAttachPoint: "" - }); - - return _TemplatedMixin; -}); - -}, -'dijit/_CssStateMixin':function(){ -define("dijit/_CssStateMixin", [ - "dojo/_base/array", // array.forEach array.map - "dojo/_base/declare", // declare - "dojo/dom", // dom.isDescendant() - "dojo/dom-class", // domClass.toggle - "dojo/has", - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/ready", - "dojo/_base/window", // win.body - "./registry" -], function(array, declare, dom, domClass, has, lang, on, ready, win, registry){ - -// module: -// dijit/_CssStateMixin - -var CssStateMixin = declare("dijit._CssStateMixin", [], { - // summary: - // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus - // state changes, and also higher-level state changes such becoming disabled or selected. - // - // description: - // By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically - // maintain CSS classes on the widget root node (this.domNode) depending on hover, - // active, focus, etc. state. Ex: with a baseClass of dijitButton, it will apply the classes - // dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it. - // - // It also sets CSS like dijitButtonDisabled based on widget semantic state. - // - // By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons - // within the widget). - - // cssStateNodes: [protected] Object - // List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus - // - // Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names - // (like "dijitUpArrowButton"). Example: - // | { - // | "upArrowButton": "dijitUpArrowButton", - // | "downArrowButton": "dijitDownArrowButton" - // | } - // The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it - // is hovered, etc. - cssStateNodes: {}, - - // hovering: [readonly] Boolean - // True if cursor is over this widget - hovering: false, - - // active: [readonly] Boolean - // True if mouse was pressed while over this widget, and hasn't been released yet - active: false, - - _applyAttributes: function(){ - // This code would typically be in postCreate(), but putting in _applyAttributes() for - // performance: so the class changes happen before DOM is inserted into the document. - // Change back to postCreate() in 2.0. See #11635. - - this.inherited(arguments); - - // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node - array.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active", "_opened"], function(attr){ - this.watch(attr, lang.hitch(this, "_setStateClass")); - }, this); - - // Track hover and active mouse events on widget root node, plus possibly on subnodes - for(var ap in this.cssStateNodes){ - this._trackMouseState(this[ap], this.cssStateNodes[ap]); - } - this._trackMouseState(this.domNode, this.baseClass); - - // Set state initially; there's probably no hover/active/focus state but widget might be - // disabled/readonly/checked/selected so we want to set CSS classes for those conditions. - this._setStateClass(); - }, - - _cssMouseEvent: function(/*Event*/ event){ - // summary: - // Handler for CSS event on this.domNode. Sets hovering and active properties depending on mouse state, - // which triggers _setStateClass() to set appropriate CSS classes for this.domNode. - - if(!this.disabled){ - switch(event.type){ - case "mouseover": - this._set("hovering", true); - this._set("active", this._mouseDown); - break; - case "mouseout": - this._set("hovering", false); - this._set("active", false); - break; - case "mousedown": - case "touchstart": - this._set("active", true); - break; - case "mouseup": - case "touchend": - this._set("active", false); - break; - } - } - }, - - _setStateClass: function(){ - // summary: - // Update the visual state of the widget by setting the css classes on this.domNode - // (or this.stateNode if defined) by combining this.baseClass with - // various suffixes that represent the current widget state(s). - // - // description: - // In the case where a widget has multiple - // states, it sets the class based on all possible - // combinations. For example, an invalid form widget that is being hovered - // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover". - // - // The widget may have one or more of the following states, determined - // by this.state, this.checked, this.valid, and this.selected: - // - // - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid - // - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet - // - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true - // - Selected - ex: currently selected tab will have this.selected==true - // - // In addition, it may have one or more of the following states, - // based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused): - // - // - Disabled - if the widget is disabled - // - Active - if the mouse (or space/enter key?) is being pressed down - // - Focused - if the widget has focus - // - Hover - if the mouse is over the widget - - // Compute new set of classes - var newStateClasses = this.baseClass.split(" "); - - function multiply(modifier){ - newStateClasses = newStateClasses.concat(array.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier); - } - - if(!this.isLeftToRight()){ - // For RTL mode we need to set an addition class like dijitTextBoxRtl. - multiply("Rtl"); - } - - var checkedState = this.checked == "mixed" ? "Mixed" : (this.checked ? "Checked" : ""); - if(this.checked){ - multiply(checkedState); - } - if(this.state){ - multiply(this.state); - } - if(this.selected){ - multiply("Selected"); - } - if(this._opened){ - multiply("Opened"); - } - - if(this.disabled){ - multiply("Disabled"); - }else if(this.readOnly){ - multiply("ReadOnly"); - }else{ - if(this.active){ - multiply("Active"); - }else if(this.hovering){ - multiply("Hover"); - } - } - - if(this.focused){ - multiply("Focused"); - } - - // Remove old state classes and add new ones. - // For performance concerns we only write into domNode.className once. - var tn = this.stateNode || this.domNode, - classHash = {}; // set of all classes (state and otherwise) for node - - array.forEach(tn.className.split(" "), function(c){ classHash[c] = true; }); - - if("_stateClasses" in this){ - array.forEach(this._stateClasses, function(c){ delete classHash[c]; }); - } - - array.forEach(newStateClasses, function(c){ classHash[c] = true; }); - - var newClasses = []; - for(var c in classHash){ - newClasses.push(c); - } - tn.className = newClasses.join(" "); - - this._stateClasses = newStateClasses; - }, - - _subnodeCssMouseEvent: function(node, clazz, evt){ - // summary: - // Handler for hover/active mouse event on widget's subnode - if(this.disabled || this.readOnly){ - return; - } - function hover(isHovering){ - domClass.toggle(node, clazz+"Hover", isHovering); - } - function active(isActive){ - domClass.toggle(node, clazz+"Active", isActive); - } - function focused(isFocused){ - domClass.toggle(node, clazz+"Focused", isFocused); - } - switch(evt.type){ - case "mouseover": - hover(true); - break; - case "mouseout": - hover(false); - active(false); - break; - case "mousedown": - case "touchstart": - active(true); - break; - case "mouseup": - case "touchend": - active(false); - break; - case "focus": - case "focusin": - focused(true); - break; - case "blur": - case "focusout": - focused(false); - break; - } - }, - - _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){ - // summary: - // Track mouse/focus events on specified node and set CSS class on that node to indicate - // current state. Usually not called directly, but via cssStateNodes attribute. - // description: - // Given class=foo, will set the following CSS class on the node - // - // - fooActive: if the user is currently pressing down the mouse button while over the node - // - fooHover: if the user is hovering the mouse over the node, but not pressing down a button - // - fooFocus: if the node is focused - // - // Note that it won't set any classes if the widget is disabled. - // node: DomNode - // Should be a sub-node of the widget, not the top node (this.domNode), since the top node - // is handled specially and automatically just by mixing in this class. - // clazz: String - // CSS class name (ex: dijitSliderUpArrow) - - // Flag for listener code below to call this._cssMouseEvent() or this._subnodeCssMouseEvent() - // when node is hovered/active - node._cssState = clazz; - } -}); - -ready(function(){ - // Document level listener to catch hover etc. events on widget root nodes and subnodes. - // Note that when the mouse is moved quickly, a single onmouseenter event could signal that multiple widgets - // have been hovered or unhovered (try test_Accordion.html) - function handler(evt){ - // Poor man's event propagation. Don't propagate event to ancestors of evt.relatedTarget, - // to avoid processing mouseout events moving from a widget's domNode to a descendant node; - // such events shouldn't be interpreted as a mouseleave on the widget. - if(!dom.isDescendant(evt.relatedTarget, evt.target)){ - for(var node = evt.target; node && node != evt.relatedTarget; node = node.parentNode){ - // Process any nodes with _cssState property. They are generally widget root nodes, - // but could also be sub-nodes within a widget - if(node._cssState){ - var widget = registry.getEnclosingWidget(node); - if(widget){ - if(node == widget.domNode){ - // event on the widget's root node - widget._cssMouseEvent(evt); - }else{ - // event on widget's sub-node - widget._subnodeCssMouseEvent(node, node._cssState, evt); - } - } - } - } - } - } - function ieHandler(evt){ - evt.target = evt.srcElement; - handler(evt); - } - - // Use addEventListener() (and attachEvent() on IE) to catch the relevant events even if other handlers - // (on individual nodes) call evt.stopPropagation() or event.stopEvent(). - // Currently typematic.js is doing that, not sure why. - // Don't monitor mouseover/mouseout on mobile because iOS generates "phantom" mouseover/mouseout events when - // drag-scrolling, at the point in the viewport where the drag originated. Test the Tree in api viewer. - var body = win.body(), - types = (has("touch") ? [] : ["mouseover", "mouseout"]).concat(["mousedown", "touchstart", "mouseup", "touchend"]); - array.forEach(types, function(type){ - if(body.addEventListener){ - body.addEventListener(type, handler, true); // W3C - }else{ - body.attachEvent("on"+type, ieHandler); // IE - } - }); - - // Track focus events on widget sub-nodes that have been registered via _trackMouseState(). - // However, don't track focus events on the widget root nodes, because focus is tracked via the - // focus manager (and it's not really tracking focus, but rather tracking that focus is on one of the widget's - // nodes or a subwidget's node or a popup node, etc.) - // Remove for 2.0 (if focus CSS needed, just use :focus pseudo-selector). - on(body, "focusin, focusout", function(evt){ - var node = evt.target; - if(node._cssState && !node.getAttribute("widgetId")){ - var widget = registry.getEnclosingWidget(node); - widget._subnodeCssMouseEvent(node, node._cssState, evt); - } - }); -}); - -return CssStateMixin; -}); - -}, -'dijit/layout/ScrollingTabController':function(){ -require({cache:{ -'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">▼</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">◀</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">▶</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>", -'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\" class=\"dijitTabInnerDiv dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"focusNode\">\n\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n</div>"}}); -define("dijit/layout/ScrollingTabController", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.contains - "dojo/dom-geometry", // domGeometry.contentBox - "dojo/dom-style", // domStyle.style - "dojo/_base/fx", // Animation - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/query", // query - "dojo/sniff", // has("ie"), has("webkit"), has("quirks") - "../registry", // registry.byId() - "dojo/text!./templates/ScrollingTabController.html", - "dojo/text!./templates/_ScrollingTabControllerButton.html", - "./TabController", - "./utils", // marginBox2contextBox, layoutChildren - "../_WidgetsInTemplateMixin", - "../Menu", - "../MenuItem", - "../form/Button", - "../_HasDropDown", - "dojo/NodeList-dom" // NodeList.style -], function(array, declare, domClass, domGeometry, domStyle, fx, lang, on, query, has, - registry, tabControllerTemplate, buttonTemplate, TabController, layoutUtils, _WidgetsInTemplateMixin, - Menu, MenuItem, Button, _HasDropDown){ - -// module: -// dijit/layout/ScrollingTabController - - -var ScrollingTabController = declare("dijit.layout.ScrollingTabController", [TabController, _WidgetsInTemplateMixin], { - // summary: - // Set of tabs with left/right arrow keys and a menu to switch between tabs not - // all fitting on a single row. - // Works only for horizontal tabs (either above or below the content, not to the left - // or right). - // tags: - // private - - baseClass: "dijitTabController dijitScrollingTabController", - - templateString: tabControllerTemplate, - - // useMenu: [const] Boolean - // True if a menu should be used to select tabs when they are too - // wide to fit the TabContainer, false otherwise. - useMenu: true, - - // useSlider: [const] Boolean - // True if a slider should be used to select tabs when they are too - // wide to fit the TabContainer, false otherwise. - useSlider: true, - - // tabStripClass: [const] String - // The css class to apply to the tab strip, if it is visible. - tabStripClass: "", - - widgetsInTemplate: true, - - // _minScroll: Number - // The distance in pixels from the edge of the tab strip which, - // if a scroll animation is less than, forces the scroll to - // go all the way to the left/right. - _minScroll: 5, - - // Override default behavior mapping class to DOMNode - _setClassAttr: { node: "containerNode", type: "class" }, - - buildRendering: function(){ - this.inherited(arguments); - var n = this.domNode; - - this.scrollNode = this.tablistWrapper; - this._initButtons(); - - if(!this.tabStripClass){ - this.tabStripClass = "dijitTabContainer" + - this.tabPosition.charAt(0).toUpperCase() + - this.tabPosition.substr(1).replace(/-.*/, "") + - "None"; - domClass.add(n, "tabStrip-disabled") - } - - domClass.add(this.tablistWrapper, this.tabStripClass); - }, - - onStartup: function(){ - this.inherited(arguments); - - // TabController is hidden until it finishes drawing, to give - // a less visually jumpy instantiation. When it's finished, set visibility to "" - // to that the tabs are hidden/shown depending on the container's visibility setting. - domStyle.set(this.domNode, "visibility", ""); - this._postStartup = true; - - // changes to the tab button label or iconClass will have changed the width of the - // buttons, so do a resize - this.own(on(this.containerNode, "attrmodified-label, attrmodified-iconclass", lang.hitch(this, function(evt){ - if(this._dim){ - this.resize(this._dim); - } - }))); - }, - - onAddChild: function(page, insertIndex){ - this.inherited(arguments); - - // Increment the width of the wrapper when a tab is added - // This makes sure that the buttons never wrap. - // The value 200 is chosen as it should be bigger than most - // Tab button widths. - domStyle.set(this.containerNode, "width", - (domStyle.get(this.containerNode, "width") + 200) + "px"); - }, - - onRemoveChild: function(page, insertIndex){ - // null out _selectedTab because we are about to delete that dom node - var button = this.pane2button[page.id]; - if(this._selectedTab === button.domNode){ - this._selectedTab = null; - } - - this.inherited(arguments); - }, - - _initButtons: function(){ - // summary: - // Creates the buttons used to scroll to view tabs that - // may not be visible if the TabContainer is too narrow. - - // Make a list of the buttons to display when the tab labels become - // wider than the TabContainer, and hide the other buttons. - // Also gets the total width of the displayed buttons. - this._btnWidth = 0; - this._buttons = query("> .tabStripButton", this.domNode).filter(function(btn){ - if((this.useMenu && btn == this._menuBtn.domNode) || - (this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){ - this._btnWidth += domGeometry.getMarginSize(btn).w; - return true; - }else{ - domStyle.set(btn, "display", "none"); - return false; - } - }, this); - }, - - _getTabsWidth: function(){ - var children = this.getChildren(); - if(children.length){ - var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode, - rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode; - return rightTab.offsetLeft + rightTab.offsetWidth - leftTab.offsetLeft; - }else{ - return 0; - } - }, - - _enableBtn: function(width){ - // summary: - // Determines if the tabs are wider than the width of the TabContainer, and - // thus that we need to display left/right/menu navigation buttons. - var tabsWidth = this._getTabsWidth(); - width = width || domStyle.get(this.scrollNode, "width"); - return tabsWidth > 0 && width < tabsWidth; - }, - - resize: function(dim){ - // summary: - // Hides or displays the buttons used to scroll the tab list and launch the menu - // that selects tabs. - - // Save the dimensions to be used when a child is renamed. - this._dim = dim; - - // Set my height to be my natural height (tall enough for one row of tab labels), - // and my content-box width based on margin-box width specified in dim parameter. - // But first reset scrollNode.height in case it was set by layoutChildren() call - // in a previous run of this method. - this.scrollNode.style.height = "auto"; - var cb = this._contentBox = layoutUtils.marginBox2contentBox(this.domNode, {h: 0, w: dim.w}); - cb.h = this.scrollNode.offsetHeight; - domGeometry.setContentSize(this.domNode, cb); - - // Show/hide the left/right/menu navigation buttons depending on whether or not they - // are needed. - var enable = this._enableBtn(this._contentBox.w); - this._buttons.style("display", enable ? "" : "none"); - - // Position and size the navigation buttons and the tablist - this._leftBtn.layoutAlign = "left"; - this._rightBtn.layoutAlign = "right"; - this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left"; - layoutUtils.layoutChildren(this.domNode, this._contentBox, - [this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]); - - // set proper scroll so that selected tab is visible - if(this._selectedTab){ - if(this._anim && this._anim.status() == "playing"){ - this._anim.stop(); - } - this.scrollNode.scrollLeft = this._convertToScrollLeft(this._getScrollForSelectedTab()); - } - - // Enable/disabled left right buttons depending on whether or not user can scroll to left or right - this._setButtonClass(this._getScroll()); - - this._postResize = true; - - // Return my size so layoutChildren() can use it. - // Also avoids IE9 layout glitch on browser resize when scroll buttons present - return {h: this._contentBox.h, w: dim.w}; - }, - - _getScroll: function(){ - // summary: - // Returns the current scroll of the tabs where 0 means - // "scrolled all the way to the left" and some positive number, based on # - // of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right" - return (this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")) ? this.scrollNode.scrollLeft : - domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width") - + (has("ie") >= 8 ? -1 : 1) * this.scrollNode.scrollLeft; - }, - - _convertToScrollLeft: function(val){ - // summary: - // Given a scroll value where 0 means "scrolled all the way to the left" - // and some positive number, based on # of pixels of possible scroll (ex: 1000) - // means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft - // to achieve that scroll. - // - // This method is to adjust for RTL funniness in various browsers and versions. - if(this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")){ - return val; - }else{ - var maxScroll = domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width"); - return (has("ie") >= 8 ? -1 : 1) * (val - maxScroll); - } - }, - - onSelectChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Smoothly scrolls to a tab when it is selected. - - var tab = this.pane2button[page.id]; - if(!tab || !page){return;} - - var node = tab.domNode; - - // Save the selection - if(node != this._selectedTab){ - this._selectedTab = node; - - // Scroll to the selected tab, except on startup, when scrolling is handled in resize() - if(this._postResize){ - var sl = this._getScroll(); - - if(sl > node.offsetLeft || - sl + domStyle.get(this.scrollNode, "width") < - node.offsetLeft + domStyle.get(node, "width")){ - this.createSmoothScroll().play(); - } - } - } - - this.inherited(arguments); - }, - - _getScrollBounds: function(){ - // summary: - // Returns the minimum and maximum scroll setting to show the leftmost and rightmost - // tabs (respectively) - var children = this.getChildren(), - scrollNodeWidth = domStyle.get(this.scrollNode, "width"), // about 500px - containerWidth = domStyle.get(this.containerNode, "width"), // 50,000px - maxPossibleScroll = containerWidth - scrollNodeWidth, // scrolling until right edge of containerNode visible - tabsWidth = this._getTabsWidth(); - - if(children.length && tabsWidth > scrollNodeWidth){ - // Scrolling should happen - return { - min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft, - max: this.isLeftToRight() ? - (children[children.length-1].domNode.offsetLeft + children[children.length-1].domNode.offsetWidth) - scrollNodeWidth : - maxPossibleScroll - }; - }else{ - // No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir) - var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll; - return { - min: onlyScrollPosition, - max: onlyScrollPosition - }; - } - }, - - _getScrollForSelectedTab: function(){ - // summary: - // Returns the scroll value setting so that the selected tab - // will appear in the center - var w = this.scrollNode, - n = this._selectedTab, - scrollNodeWidth = domStyle.get(this.scrollNode, "width"), - scrollBounds = this._getScrollBounds(); - - // TODO: scroll minimal amount (to either right or left) so that - // selected tab is fully visible, and just return if it's already visible? - var pos = (n.offsetLeft + domStyle.get(n, "width")/2) - scrollNodeWidth/2; - pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max); - - // TODO: - // If scrolling close to the left side or right side, scroll - // all the way to the left or right. See this._minScroll. - // (But need to make sure that doesn't scroll the tab out of view...) - return pos; - }, - - createSmoothScroll: function(x){ - // summary: - // Creates a dojo._Animation object that smoothly scrolls the tab list - // either to a fixed horizontal pixel value, or to the selected tab. - // description: - // If an number argument is passed to the function, that horizontal - // pixel position is scrolled to. Otherwise the currently selected - // tab is scrolled to. - // x: Integer? - // An optional pixel value to scroll to, indicating distance from left. - - // Calculate position to scroll to - if(arguments.length > 0){ - // position specified by caller, just make sure it's within bounds - var scrollBounds = this._getScrollBounds(); - x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max); - }else{ - // scroll to center the current tab - x = this._getScrollForSelectedTab(); - } - - if(this._anim && this._anim.status() == "playing"){ - this._anim.stop(); - } - - var self = this, - w = this.scrollNode, - anim = new fx.Animation({ - beforeBegin: function(){ - if(this.curve){ delete this.curve; } - var oldS = w.scrollLeft, - newS = self._convertToScrollLeft(x); - anim.curve = new fx._Line(oldS, newS); - }, - onAnimate: function(val){ - w.scrollLeft = val; - } - }); - this._anim = anim; - - // Disable/enable left/right buttons according to new scroll position - this._setButtonClass(x); - - return anim; // dojo/_base/fx/Animation - }, - - _getBtnNode: function(/*Event*/ e){ - // summary: - // Gets a button DOM node from a mouse click event. - // e: - // The mouse click event. - var n = e.target; - while(n && !domClass.contains(n, "tabStripButton")){ - n = n.parentNode; - } - return n; - }, - - doSlideRight: function(/*Event*/ e){ - // summary: - // Scrolls the menu to the right. - // e: - // The mouse click event. - this.doSlide(1, this._getBtnNode(e)); - }, - - doSlideLeft: function(/*Event*/ e){ - // summary: - // Scrolls the menu to the left. - // e: - // The mouse click event. - this.doSlide(-1,this._getBtnNode(e)); - }, - - doSlide: function(/*Number*/ direction, /*DomNode*/ node){ - // summary: - // Scrolls the tab list to the left or right by 75% of the widget width. - // direction: - // If the direction is 1, the widget scrolls to the right, if it is -1, - // it scrolls to the left. - - if(node && domClass.contains(node, "dijitTabDisabled")){return;} - - var sWidth = domStyle.get(this.scrollNode, "width"); - var d = (sWidth * 0.75) * direction; - - var to = this._getScroll() + d; - - this._setButtonClass(to); - - this.createSmoothScroll(to).play(); - }, - - _setButtonClass: function(/*Number*/ scroll){ - // summary: - // Disables the left scroll button if the tabs are scrolled all the way to the left, - // or the right scroll button in the opposite case. - // scroll: Integer - // amount of horizontal scroll - - var scrollBounds = this._getScrollBounds(); - this._leftBtn.set("disabled", scroll <= scrollBounds.min); - this._rightBtn.set("disabled", scroll >= scrollBounds.max); - } -}); - - -var ScrollingTabControllerButtonMixin = declare("dijit.layout._ScrollingTabControllerButtonMixin", null, { - baseClass: "dijitTab tabStripButton", - - templateString: buttonTemplate, - - // Override inherited tabIndex: 0 from dijit/form/Button, because user shouldn't be - // able to tab to the left/right/menu buttons - tabIndex: "", - - // Similarly, override FormWidget.isFocusable() because clicking a button shouldn't focus it - // either (this override avoids focus() call in FormWidget.js) - isFocusable: function(){ return false; } -}); - -// Class used in template -declare("dijit.layout._ScrollingTabControllerButton", - [Button, ScrollingTabControllerButtonMixin]); - -// Class used in template -declare( - "dijit.layout._ScrollingTabControllerMenuButton", - [Button, _HasDropDown, ScrollingTabControllerButtonMixin], -{ - // id of the TabContainer itself - containerId: "", - - // -1 so user can't tab into the button, but so that button can still be focused programatically. - // Because need to move focus to the button (or somewhere) before the menu is hidden or IE6 will crash. - tabIndex: "-1", - - isLoaded: function(){ - // recreate menu every time, in case the TabContainer's list of children (or their icons/labels) have changed - return false; - }, - - loadDropDown: function(callback){ - this.dropDown = new Menu({ - id: this.containerId + "_menu", - ownerDocument: this.ownerDocument, - dir: this.dir, - lang: this.lang, - textDir: this.textDir - }); - var container = registry.byId(this.containerId); - array.forEach(container.getChildren(), function(page){ - var menuItem = new MenuItem({ - id: page.id + "_stcMi", - label: page.title, - iconClass: page.iconClass, - disabled: page.disabled, - ownerDocument: this.ownerDocument, - dir: page.dir, - lang: page.lang, - textDir: page.textDir, - onClick: function(){ - container.selectChild(page); - } - }); - this.dropDown.addChild(menuItem); - }, this); - callback(); - }, - - closeDropDown: function(/*Boolean*/ focus){ - this.inherited(arguments); - if(this.dropDown){ - this.dropDown.destroyRecursive(); - delete this.dropDown; - } - } -}); - -return ScrollingTabController; -}); - -}, -'url:dijit/form/templates/ComboButton.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tcellspacing='0' cellpadding='0' role=\"presentation\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonNode\" data-dojo-attach-point=\"buttonNode\" data-dojo-attach-event=\"ondijitclick:_onClick,onkeypress:_onButtonKeyPress\"\n\t\t><div id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" data-dojo-attach-point=\"containerNode\" role=\"presentation\"></div\n\t\t></div\n\t\t></td\n\t\t><td id=\"${id}_arrow\" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'\n\t\t\tdata-dojo-attach-point=\"_popupStateNode,focusNode,_buttonNode\"\n\t\t\tdata-dojo-attach-event=\"onkeypress:_onArrowKeyPress\"\n\t\t\ttitle=\"${optionsTitle}\"\n\t\t\trole=\"button\" aria-haspopup=\"true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">▼</div\n\t\t></td\n\t\t><td style=\"display:none !important;\"\n\t\t\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" data-dojo-attach-point=\"valueNode\" role=\"presentation\"\n\t\t/></td></tr></tbody\n></table>\n", -'dijit/DialogUnderlay':function(){ -define("dijit/DialogUnderlay", [ - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/window", // winUtils.getBox - "./_Widget", - "./_TemplatedMixin", - "./BackgroundIframe" -], function(declare, domAttr, winUtils, _Widget, _TemplatedMixin, BackgroundIframe){ - - // module: - // dijit/DialogUnderlay - - return declare("dijit.DialogUnderlay", [_Widget, _TemplatedMixin], { - // summary: - // The component that blocks the screen behind a `dijit.Dialog` - // - // description: - // A component used to block input behind a `dijit.Dialog`. Only a single - // instance of this widget is created by `dijit.Dialog`, and saved as - // a reference to be shared between all Dialogs as `dijit._underlay` - // - // The underlay itself can be styled based on and id: - // | #myDialog_underlay { background-color:red; } - // - // In the case of `dijit.Dialog`, this id is based on the id of the Dialog, - // suffixed with _underlay. - - // Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe. - // Inner div has opacity specified in CSS file. - templateString: "<div class='dijitDialogUnderlayWrapper'><div class='dijitDialogUnderlay' data-dojo-attach-point='node'></div></div>", - - // Parameters on creation or updatable later - - // dialogId: String - // Id of the dialog.... DialogUnderlay's id is based on this id - dialogId: "", - - // class: String - // This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay - "class": "", - - _setDialogIdAttr: function(id){ - domAttr.set(this.node, "id", id + "_underlay"); - this._set("dialogId", id); - }, - - _setClassAttr: function(clazz){ - this.node.className = "dijitDialogUnderlay " + clazz; - this._set("class", clazz); - }, - - postCreate: function(){ - // summary: - // Append the underlay to the body - this.ownerDocumentBody.appendChild(this.domNode); - }, - - layout: function(){ - // summary: - // Sets the background to the size of the viewport - // - // description: - // Sets the background to the size of the viewport (rather than the size - // of the document) since we need to cover the whole browser window, even - // if the document is only a few lines long. - // tags: - // private - - var is = this.node.style, - os = this.domNode.style; - - // hide the background temporarily, so that the background itself isn't - // causing scrollbars to appear (might happen when user shrinks browser - // window and then we are called to resize) - os.display = "none"; - - // then resize and show - var viewport = winUtils.getBox(this.ownerDocument); - os.top = viewport.t + "px"; - os.left = viewport.l + "px"; - is.width = viewport.w + "px"; - is.height = viewport.h + "px"; - os.display = "block"; - }, - - show: function(){ - // summary: - // Show the dialog underlay - this.domNode.style.display = "block"; - this.layout(); - this.bgIframe = new BackgroundIframe(this.domNode); - }, - - hide: function(){ - // summary: - // Hides the dialog underlay - this.bgIframe.destroy(); - delete this.bgIframe; - this.domNode.style.display = "none"; - } - }); -}); - -}, -'dijit/place':function(){ -define("dijit/place", [ - "dojo/_base/array", // array.forEach array.map array.some - "dojo/dom-geometry", // domGeometry.position - "dojo/dom-style", // domStyle.getComputedStyle - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/window", // win.body - "dojo/window", // winUtils.getBox - "./main" // dijit (defining dijit.place to match API doc) -], function(array, domGeometry, domStyle, kernel, win, winUtils, dijit){ - - // module: - // dijit/place - - - function _place(/*DomNode*/ node, choices, layoutNode, aroundNodeCoords){ - // summary: - // Given a list of spots to put node, put it at the first spot where it fits, - // of if it doesn't fit anywhere then the place with the least overflow - // choices: Array - // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} } - // Above example says to put the top-left corner of the node at (10,20) - // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size) - // for things like tooltip, they are displayed differently (and have different dimensions) - // based on their orientation relative to the parent. This adjusts the popup based on orientation. - // It also passes in the available size for the popup, which is useful for tooltips to - // tell them that their width is limited to a certain amount. layoutNode() may return a value expressing - // how much the popup had to be modified to fit into the available space. This is used to determine - // what the best placement is. - // aroundNodeCoords: Object - // Size of aroundNode, ex: {w: 200, h: 50} - - // get {x: 10, y: 10, w: 100, h:100} type obj representing position of - // viewport over document - var view = winUtils.getBox(node.ownerDocument); - - // This won't work if the node is inside a <div style="position: relative">, - // so reattach it to win.doc.body. (Otherwise, the positioning will be wrong - // and also it might get cutoff) - if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){ - win.body(node.ownerDocument).appendChild(node); - } - - var best = null; - array.some(choices, function(choice){ - var corner = choice.corner; - var pos = choice.pos; - var overflow = 0; - - // calculate amount of space available given specified position of node - var spaceAvailable = { - w: { - 'L': view.l + view.w - pos.x, - 'R': pos.x - view.l, - 'M': view.w - }[corner.charAt(1)], - h: { - 'T': view.t + view.h - pos.y, - 'B': pos.y - view.t, - 'M': view.h - }[corner.charAt(0)] - }; - - // Clear left/right position settings set earlier so they don't interfere with calculations, - // specifically when layoutNode() (a.k.a. Tooltip.orient()) measures natural width of Tooltip - var s = node.style; - s.left = s.right = "auto"; - - // configure node to be displayed in given position relative to button - // (need to do this in order to get an accurate size for the node, because - // a tooltip's size changes based on position, due to triangle) - if(layoutNode){ - var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords); - overflow = typeof res == "undefined" ? 0 : res; - } - - // get node's size - var style = node.style; - var oldDisplay = style.display; - var oldVis = style.visibility; - if(style.display == "none"){ - style.visibility = "hidden"; - style.display = ""; - } - var bb = domGeometry.position(node); - style.display = oldDisplay; - style.visibility = oldVis; - - // coordinates and size of node with specified corner placed at pos, - // and clipped by viewport - var - startXpos = { - 'L': pos.x, - 'R': pos.x - bb.w, - 'M': Math.max(view.l, Math.min(view.l + view.w, pos.x + (bb.w >> 1)) - bb.w) // M orientation is more flexible - }[corner.charAt(1)], - startYpos = { - 'T': pos.y, - 'B': pos.y - bb.h, - 'M': Math.max(view.t, Math.min(view.t + view.h, pos.y + (bb.h >> 1)) - bb.h) - }[corner.charAt(0)], - startX = Math.max(view.l, startXpos), - startY = Math.max(view.t, startYpos), - endX = Math.min(view.l + view.w, startXpos + bb.w), - endY = Math.min(view.t + view.h, startYpos + bb.h), - width = endX - startX, - height = endY - startY; - - overflow += (bb.w - width) + (bb.h - height); - - if(best == null || overflow < best.overflow){ - best = { - corner: corner, - aroundCorner: choice.aroundCorner, - x: startX, - y: startY, - w: width, - h: height, - overflow: overflow, - spaceAvailable: spaceAvailable - }; - } - - return !overflow; - }); - - // In case the best position is not the last one we checked, need to call - // layoutNode() again. - if(best.overflow && layoutNode){ - layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords); - } - - // And then position the node. Do this last, after the layoutNode() above - // has sized the node, due to browser quirks when the viewport is scrolled - // (specifically that a Tooltip will shrink to fit as though the window was - // scrolled to the left). - // - // In RTL mode, set style.right rather than style.left so in the common case, - // window resizes move the popup along with the aroundNode. - var l = domGeometry.isBodyLtr(node.ownerDocument), - s = node.style; - s.top = best.y + "px"; - s[l ? "left" : "right"] = (l ? best.x : view.w - best.x - best.w) + "px"; - s[l ? "right" : "left"] = "auto"; // needed for FF or else tooltip goes to far left - - return best; - } - - var place = { - // summary: - // Code to place a DOMNode relative to another DOMNode. - // Load using require(["dijit/place"], function(place){ ... }). - - at: function(node, pos, corners, padding){ - // summary: - // Positions one of the node's corners at specified position - // such that node is fully visible in viewport. - // description: - // NOTE: node is assumed to be absolutely or relatively positioned. - // node: DOMNode - // The node to position - // pos: dijit/place.__Position - // Object like {x: 10, y: 20} - // corners: String[] - // Array of Strings representing order to try corners in, like ["TR", "BL"]. - // Possible values are: - // - // - "BL" - bottom left - // - "BR" - bottom right - // - "TL" - top left - // - "TR" - top right - // padding: dijit/place.__Position? - // optional param to set padding, to put some buffer around the element you want to position. - // example: - // Try to place node's top right corner at (10,20). - // If that makes node go (partially) off screen, then try placing - // bottom left corner at (10,20). - // | place(node, {x: 10, y: 20}, ["TR", "BL"]) - var choices = array.map(corners, function(corner){ - var c = { corner: corner, pos: {x:pos.x,y:pos.y} }; - if(padding){ - c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x; - c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y; - } - return c; - }); - - return _place(node, choices); - }, - - around: function( - /*DomNode*/ node, - /*DomNode|dijit/place.__Rectangle*/ anchor, - /*String[]*/ positions, - /*Boolean*/ leftToRight, - /*Function?*/ layoutNode){ - - // summary: - // Position node adjacent or kitty-corner to anchor - // such that it's fully visible in viewport. - // description: - // Place node such that corner of node touches a corner of - // aroundNode, and that node is fully visible. - // anchor: - // Either a DOMNode or a rectangle (object with x, y, width, height). - // positions: - // Ordered list of positions to try matching up. - // - // - before: places drop down to the left of the anchor node/widget, or to the right in the case - // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down - // with the top of the anchor, or the bottom of the drop down with bottom of the anchor. - // - after: places drop down to the right of the anchor node/widget, or to the left in the case - // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down - // with the top of the anchor, or the bottom of the drop down with bottom of the anchor. - // - before-centered: centers drop down to the left of the anchor node/widget, or to the right - // in the case of RTL scripts like Hebrew and Arabic - // - after-centered: centers drop down to the right of the anchor node/widget, or to the left - // in the case of RTL scripts like Hebrew and Arabic - // - above-centered: drop down is centered above anchor node - // - above: drop down goes above anchor node, left sides aligned - // - above-alt: drop down goes above anchor node, right sides aligned - // - below-centered: drop down is centered above anchor node - // - below: drop down goes below anchor node - // - below-alt: drop down goes below anchor node, right sides aligned - // layoutNode: Function(node, aroundNodeCorner, nodeCorner) - // For things like tooltip, they are displayed differently (and have different dimensions) - // based on their orientation relative to the parent. This adjusts the popup based on orientation. - // leftToRight: - // True if widget is LTR, false if widget is RTL. Affects the behavior of "above" and "below" - // positions slightly. - // example: - // | placeAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'}); - // This will try to position node such that node's top-left corner is at the same position - // as the bottom left corner of the aroundNode (ie, put node below - // aroundNode, with left edges aligned). If that fails it will try to put - // the bottom-right corner of node where the top right corner of aroundNode is - // (ie, put node above aroundNode, with right edges aligned) - // - - // if around is a DOMNode (or DOMNode id), convert to coordinates - var aroundNodePos = (typeof anchor == "string" || "offsetWidth" in anchor) - ? domGeometry.position(anchor, true) - : anchor; - - // Compute position and size of visible part of anchor (it may be partially hidden by ancestor nodes w/scrollbars) - if(anchor.parentNode){ - // ignore nodes between position:relative and position:absolute - var sawPosAbsolute = domStyle.getComputedStyle(anchor).position == "absolute"; - var parent = anchor.parentNode; - while(parent && parent.nodeType == 1 && parent.nodeName != "BODY"){ //ignoring the body will help performance - var parentPos = domGeometry.position(parent, true), - pcs = domStyle.getComputedStyle(parent); - if(/relative|absolute/.test(pcs.position)){ - sawPosAbsolute = false; - } - if(!sawPosAbsolute && /hidden|auto|scroll/.test(pcs.overflow)){ - var bottomYCoord = Math.min(aroundNodePos.y + aroundNodePos.h, parentPos.y + parentPos.h); - var rightXCoord = Math.min(aroundNodePos.x + aroundNodePos.w, parentPos.x + parentPos.w); - aroundNodePos.x = Math.max(aroundNodePos.x, parentPos.x); - aroundNodePos.y = Math.max(aroundNodePos.y, parentPos.y); - aroundNodePos.h = bottomYCoord - aroundNodePos.y; - aroundNodePos.w = rightXCoord - aroundNodePos.x; - } - if(pcs.position == "absolute"){ - sawPosAbsolute = true; - } - parent = parent.parentNode; - } - } - - var x = aroundNodePos.x, - y = aroundNodePos.y, - width = "w" in aroundNodePos ? aroundNodePos.w : (aroundNodePos.w = aroundNodePos.width), - height = "h" in aroundNodePos ? aroundNodePos.h : (kernel.deprecated("place.around: dijit/place.__Rectangle: { x:"+x+", y:"+y+", height:"+aroundNodePos.height+", width:"+width+" } has been deprecated. Please use { x:"+x+", y:"+y+", h:"+aroundNodePos.height+", w:"+width+" }", "", "2.0"), aroundNodePos.h = aroundNodePos.height); - - // Convert positions arguments into choices argument for _place() - var choices = []; - function push(aroundCorner, corner){ - choices.push({ - aroundCorner: aroundCorner, - corner: corner, - pos: { - x: { - 'L': x, - 'R': x + width, - 'M': x + (width >> 1) - }[aroundCorner.charAt(1)], - y: { - 'T': y, - 'B': y + height, - 'M': y + (height >> 1) - }[aroundCorner.charAt(0)] - } - }) - } - array.forEach(positions, function(pos){ - var ltr = leftToRight; - switch(pos){ - case "above-centered": - push("TM", "BM"); - break; - case "below-centered": - push("BM", "TM"); - break; - case "after-centered": - ltr = !ltr; - // fall through - case "before-centered": - push(ltr ? "ML" : "MR", ltr ? "MR" : "ML"); - break; - case "after": - ltr = !ltr; - // fall through - case "before": - push(ltr ? "TL" : "TR", ltr ? "TR" : "TL"); - push(ltr ? "BL" : "BR", ltr ? "BR" : "BL"); - break; - case "below-alt": - ltr = !ltr; - // fall through - case "below": - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - push(ltr ? "BL" : "BR", ltr ? "TL" : "TR"); - push(ltr ? "BR" : "BL", ltr ? "TR" : "TL"); - break; - case "above-alt": - ltr = !ltr; - // fall through - case "above": - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - push(ltr ? "TL" : "TR", ltr ? "BL" : "BR"); - push(ltr ? "TR" : "TL", ltr ? "BR" : "BL"); - break; - default: - // To assist dijit/_base/place, accept arguments of type {aroundCorner: "BL", corner: "TL"}. - // Not meant to be used directly. - push(pos.aroundCorner, pos.corner); - } - }); - - var position = _place(node, choices, layoutNode, {w: width, h: height}); - position.aroundNodePos = aroundNodePos; - - return position; - } - }; - - /*===== - place.__Position = { - // x: Integer - // horizontal coordinate in pixels, relative to document body - // y: Integer - // vertical coordinate in pixels, relative to document body - }; - place.__Rectangle = { - // x: Integer - // horizontal offset in pixels, relative to document body - // y: Integer - // vertical offset in pixels, relative to document body - // w: Integer - // width in pixels. Can also be specified as "width" for backwards-compatibility. - // h: Integer - // height in pixels. Can also be specified as "height" for backwards-compatibility. - }; - =====*/ - - return dijit.place = place; // setting dijit.place for back-compat, remove for 2.0 -}); - -}, -'dijit/_HasDropDown':function(){ -define("dijit/_HasDropDown", [ - "dojo/_base/declare", // declare - "dojo/_base/Deferred", - "dojo/_base/event", // event.stop - "dojo/dom", // dom.isDescendant - "dojo/dom-attr", // domAttr.set - "dojo/dom-class", // domClass.add domClass.contains domClass.remove - "dojo/dom-geometry", // domGeometry.marginBox domGeometry.position - "dojo/dom-style", // domStyle.set - "dojo/has", // has("touch") - "dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE - "dojo/_base/lang", // lang.hitch lang.isFunction - "dojo/on", - "dojo/window", // winUtils.getBox - "./registry", // registry.byNode() - "./focus", - "./popup", - "./_FocusMixin" -], function(declare, Deferred, event,dom, domAttr, domClass, domGeometry, domStyle, has, keys, lang, on, - winUtils, registry, focus, popup, _FocusMixin){ - - - // module: - // dijit/_HasDropDown - - return declare("dijit._HasDropDown", _FocusMixin, { - // summary: - // Mixin for widgets that need drop down ability. - - // _buttonNode: [protected] DomNode - // The button/icon/node to click to display the drop down. - // Can be set via a data-dojo-attach-point assignment. - // If missing, then either focusNode or domNode (if focusNode is also missing) will be used. - _buttonNode: null, - - // _arrowWrapperNode: [protected] DomNode - // Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending - // on where the drop down is set to be positioned. - // Can be set via a data-dojo-attach-point assignment. - // If missing, then _buttonNode will be used. - _arrowWrapperNode: null, - - // _popupStateNode: [protected] DomNode - // The node to set the popupActive class on. - // Can be set via a data-dojo-attach-point assignment. - // If missing, then focusNode or _buttonNode (if focusNode is missing) will be used. - _popupStateNode: null, - - // _aroundNode: [protected] DomNode - // The node to display the popup around. - // Can be set via a data-dojo-attach-point assignment. - // If missing, then domNode will be used. - _aroundNode: null, - - // dropDown: [protected] Widget - // The widget to display as a popup. This widget *must* be - // defined before the startup function is called. - dropDown: null, - - // autoWidth: [protected] Boolean - // Set to true to make the drop down at least as wide as this - // widget. Set to false if the drop down should just be its - // default width - autoWidth: true, - - // forceWidth: [protected] Boolean - // Set to true to make the drop down exactly as wide as this - // widget. Overrides autoWidth. - forceWidth: false, - - // maxHeight: [protected] Integer - // The max height for our dropdown. - // Any dropdown taller than this will have scrollbars. - // Set to 0 for no max height, or -1 to limit height to available space in viewport - maxHeight: 0, - - // dropDownPosition: [const] String[] - // This variable controls the position of the drop down. - // It's an array of strings with the following values: - // - // - before: places drop down to the left of the target node/widget, or to the right in - // the case of RTL scripts like Hebrew and Arabic - // - after: places drop down to the right of the target node/widget, or to the left in - // the case of RTL scripts like Hebrew and Arabic - // - above: drop down goes above target node - // - below: drop down goes below target node - // - // The list is positions is tried, in order, until a position is found where the drop down fits - // within the viewport. - // - dropDownPosition: ["below","above"], - - // _stopClickEvents: Boolean - // When set to false, the click events will not be stopped, in - // case you want to use them in your subclass - _stopClickEvents: true, - - _onDropDownMouseDown: function(/*Event*/ e){ - // summary: - // Callback when the user mousedown's on the arrow icon - if(this.disabled || this.readOnly){ return; } - - // Prevent default to stop things like text selection, but don't stop propagation, so that: - // 1. TimeTextBox etc. can focus the <input> on mousedown - // 2. dropDownButtonActive class applied by _CssStateMixin (on button depress) - // 3. user defined onMouseDown handler fires - e.preventDefault(); - - this._docHandler = this.connect(this.ownerDocument, "mouseup", "_onDropDownMouseUp"); - - this.toggleDropDown(); - }, - - _onDropDownMouseUp: function(/*Event?*/ e){ - // summary: - // Callback when the user lifts their mouse after mouse down on the arrow icon. - // If the drop down is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our - // drop down widget. If the event is missing, then we are not - // a mouseup event. - // - // This is useful for the common mouse movement pattern - // with native browser `<select>` nodes: - // - // 1. mouse down on the select node (probably on the arrow) - // 2. move mouse to a menu item while holding down the mouse button - // 3. mouse up. this selects the menu item as though the user had clicked it. - if(e && this._docHandler){ - this.disconnect(this._docHandler); - } - var dropDown = this.dropDown, overMenu = false; - - if(e && this._opened){ - // This code deals with the corner-case when the drop down covers the original widget, - // because it's so large. In that case mouse-up shouldn't select a value from the menu. - // Find out if our target is somewhere in our dropdown widget, - // but not over our _buttonNode (the clickable node) - var c = domGeometry.position(this._buttonNode, true); - if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) || - !(e.pageY >= c.y && e.pageY <= c.y + c.h)){ - var t = e.target; - while(t && !overMenu){ - if(domClass.contains(t, "dijitPopup")){ - overMenu = true; - }else{ - t = t.parentNode; - } - } - if(overMenu){ - t = e.target; - if(dropDown.onItemClick){ - var menuItem; - while(t && !(menuItem = registry.byNode(t))){ - t = t.parentNode; - } - if(menuItem && menuItem.onClick && menuItem.getParent){ - menuItem.getParent().onItemClick(menuItem, e); - } - } - return; - } - } - } - if(this._opened){ - if(dropDown.focus && dropDown.autoFocus !== false){ - // Focus the dropdown widget - do it on a delay so that we - // don't steal back focus from the dropdown. - this._focusDropDownTimer = this.defer(function(){ - dropDown.focus(); - delete this._focusDropDownTimer; - }); - } - }else{ - // The drop down arrow icon probably can't receive focus, but widget itself should get focus. - // defer() needed to make it work on IE (test DateTextBox) - this.defer("focus"); - } - - if(has("touch")){ - this._justGotMouseUp = true; - this.defer(function(){ - this._justGotMouseUp = false; - }); - } - }, - - _onDropDownClick: function(/*Event*/ e){ - if(has("touch") && !this._justGotMouseUp){ - // If there was no preceding mousedown/mouseup (like on android), then simulate them to - // toggle the drop down. - // - // The if(has("touch") is necessary since IE and desktop safari get spurious onclick events - // when there are nested tables (specifically, clicking on a table that holds a dijit/form/Select, - // but not on the Select itself, causes an onclick event on the Select) - this._onDropDownMouseDown(e); - this._onDropDownMouseUp(e); - } - - // The drop down was already opened on mousedown/keydown; just need to call stopEvent(). - if(this._stopClickEvents){ - event.stop(e); - } - }, - - buildRendering: function(){ - this.inherited(arguments); - - this._buttonNode = this._buttonNode || this.focusNode || this.domNode; - this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode; - - // Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow - // based on where drop down will normally appear - var defaultPos = { - "after" : this.isLeftToRight() ? "Right" : "Left", - "before" : this.isLeftToRight() ? "Left" : "Right", - "above" : "Up", - "below" : "Down", - "left" : "Left", - "right" : "Right" - }[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down"; - domClass.add(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton"); - }, - - postCreate: function(){ - // summary: - // set up nodes and connect our mouse and keyboard events - - this.inherited(arguments); - - var keyboardEventNode = this.focusNode || this.domNode; - this.own( - on(this._buttonNode, "mousedown", lang.hitch(this, "_onDropDownMouseDown")), - on(this._buttonNode, "click", lang.hitch(this, "_onDropDownClick")), - on(keyboardEventNode, "keydown", lang.hitch(this, "_onKey")), - on(keyboardEventNode, "keyup", lang.hitch(this, "_onKeyUp")) - ); - }, - - destroy: function(){ - if(this.dropDown){ - // Destroy the drop down, unless it's already been destroyed. This can happen because - // the drop down is a direct child of <body> even though it's logically my child. - if(!this.dropDown._destroyed){ - this.dropDown.destroyRecursive(); - } - delete this.dropDown; - } - this.inherited(arguments); - }, - - _onKey: function(/*Event*/ e){ - // summary: - // Callback when the user presses a key while focused on the button node - - if(this.disabled || this.readOnly){ return; } - var d = this.dropDown, target = e.target; - if(d && this._opened && d.handleKey){ - if(d.handleKey(e) === false){ - /* false return code means that the drop down handled the key */ - event.stop(e); - return; - } - } - if(d && this._opened && e.keyCode == keys.ESCAPE){ - this.closeDropDown(); - event.stop(e); - }else if(!this._opened && - (e.keyCode == keys.DOWN_ARROW || - ( (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) && - //ignore enter and space if the event is for a text input - ((target.tagName || "").toLowerCase() !== 'input' || - (target.type && target.type.toLowerCase() !== 'text'))))){ - // Toggle the drop down, but wait until keyup so that the drop down doesn't - // get a stray keyup event, or in the case of key-repeat (because user held - // down key for too long), stray keydown events - this._toggleOnKeyUp = true; - event.stop(e); - } - }, - - _onKeyUp: function(){ - if(this._toggleOnKeyUp){ - delete this._toggleOnKeyUp; - this.toggleDropDown(); - var d = this.dropDown; // drop down may not exist until toggleDropDown() call - if(d && d.focus){ - this.defer(lang.hitch(d, "focus"), 1); - } - } - }, - - _onBlur: function(){ - // summary: - // Called magically when focus has shifted away from this widget and it's dropdown - - // Don't focus on button if the user has explicitly focused on something else (happens - // when user clicks another control causing the current popup to close).. - // But if focus is inside of the drop down then reset focus to me, because IE doesn't like - // it when you display:none a node with focus. - var focusMe = focus.curNode && this.dropDown && dom.isDescendant(focus.curNode, this.dropDown.domNode); - - this.closeDropDown(focusMe); - - this.inherited(arguments); - }, - - isLoaded: function(){ - // summary: - // Returns true if the dropdown exists and it's data is loaded. This can - // be overridden in order to force a call to loadDropDown(). - // tags: - // protected - - return true; - }, - - loadDropDown: function(/*Function*/ loadCallback){ - // summary: - // Creates the drop down if it doesn't exist, loads the data - // if there's an href and it hasn't been loaded yet, and then calls - // the given callback. - // tags: - // protected - - // TODO: for 2.0, change API to return a Deferred, instead of calling loadCallback? - loadCallback(); - }, - - loadAndOpenDropDown: function(){ - // summary: - // Creates the drop down if it doesn't exist, loads the data - // if there's an href and it hasn't been loaded yet, and - // then opens the drop down. This is basically a callback when the - // user presses the down arrow button to open the drop down. - // returns: Deferred - // Deferred for the drop down widget that - // fires when drop down is created and loaded - // tags: - // protected - var d = new Deferred(), - afterLoad = lang.hitch(this, function(){ - this.openDropDown(); - d.resolve(this.dropDown); - }); - if(!this.isLoaded()){ - this.loadDropDown(afterLoad); - }else{ - afterLoad(); - } - return d; - }, - - toggleDropDown: function(){ - // summary: - // Callback when the user presses the down arrow button or presses - // the down arrow key to open/close the drop down. - // Toggle the drop-down widget; if it is up, close it, if not, open it - // tags: - // protected - - if(this.disabled || this.readOnly){ return; } - if(!this._opened){ - this.loadAndOpenDropDown(); - }else{ - this.closeDropDown(); - } - }, - - openDropDown: function(){ - // summary: - // Opens the dropdown for this widget. To be called only when this.dropDown - // has been created and is ready to display (ie, it's data is loaded). - // returns: - // return value of dijit/popup.open() - // tags: - // protected - - var dropDown = this.dropDown, - ddNode = dropDown.domNode, - aroundNode = this._aroundNode || this.domNode, - self = this; - - // Prepare our popup's height and honor maxHeight if it exists. - - // TODO: isn't maxHeight dependent on the return value from dijit/popup.open(), - // ie, dependent on how much space is available (BK) - - if(!this._preparedNode){ - this._preparedNode = true; - // Check if we have explicitly set width and height on the dropdown widget dom node - if(ddNode.style.width){ - this._explicitDDWidth = true; - } - if(ddNode.style.height){ - this._explicitDDHeight = true; - } - } - - // Code for resizing dropdown (height limitation, or increasing width to match my width) - if(this.maxHeight || this.forceWidth || this.autoWidth){ - var myStyle = { - display: "", - visibility: "hidden" - }; - if(!this._explicitDDWidth){ - myStyle.width = ""; - } - if(!this._explicitDDHeight){ - myStyle.height = ""; - } - domStyle.set(ddNode, myStyle); - - // Figure out maximum height allowed (if there is a height restriction) - var maxHeight = this.maxHeight; - if(maxHeight == -1){ - // limit height to space available in viewport either above or below my domNode - // (whichever side has more room) - var viewport = winUtils.getBox(this.ownerDocument), - position = domGeometry.position(aroundNode, false); - maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h))); - } - - // Attach dropDown to DOM and make make visibility:hidden rather than display:none - // so we call startup() and also get the size - popup.moveOffScreen(dropDown); - - if(dropDown.startup && !dropDown._started){ - dropDown.startup(); // this has to be done after being added to the DOM - } - // Get size of drop down, and determine if vertical scroll bar needed. If no scroll bar needed, - // use overflow:visible rather than overflow:hidden so off-by-one errors don't hide drop down border. - var mb = domGeometry.getMarginSize(ddNode); - var overHeight = (maxHeight && mb.h > maxHeight); - domStyle.set(ddNode, { - overflowX: "visible", - overflowY: overHeight ? "auto" : "visible" - }); - if(overHeight){ - mb.h = maxHeight; - if("w" in mb){ - mb.w += 16; // room for vertical scrollbar - } - }else{ - delete mb.h; - } - - // Adjust dropdown width to match or be larger than my width - if(this.forceWidth){ - mb.w = aroundNode.offsetWidth; - }else if(this.autoWidth){ - mb.w = Math.max(mb.w, aroundNode.offsetWidth); - }else{ - delete mb.w; - } - - // And finally, resize the dropdown to calculated height and width - if(lang.isFunction(dropDown.resize)){ - dropDown.resize(mb); - }else{ - domGeometry.setMarginBox(ddNode, mb); - } - } - - var retVal = popup.open({ - parent: this, - popup: dropDown, - around: aroundNode, - orient: this.dropDownPosition, - onExecute: function(){ - self.closeDropDown(true); - }, - onCancel: function(){ - self.closeDropDown(true); - }, - onClose: function(){ - domAttr.set(self._popupStateNode, "popupActive", false); - domClass.remove(self._popupStateNode, "dijitHasDropDownOpen"); - self._set("_opened", false); // use set() because _CssStateMixin is watching - } - }); - domAttr.set(this._popupStateNode, "popupActive", "true"); - domClass.add(this._popupStateNode, "dijitHasDropDownOpen"); - this._set("_opened", true); // use set() because _CssStateMixin is watching - this.domNode.setAttribute("aria-expanded", "true"); - - return retVal; - }, - - closeDropDown: function(/*Boolean*/ focus){ - // summary: - // Closes the drop down on this widget - // focus: - // If true, refocuses the button widget - // tags: - // protected - - if(this._focusDropDownTimer){ - this._focusDropDownTimer.remove(); - delete this._focusDropDownTimer; - } - if(this._opened){ - this.domNode.setAttribute("aria-expanded", "false"); - if(focus){ this.focus(); } - popup.close(this.dropDown); - this._opened = false; - } - } - - }); -}); - -}, -'dijit/tree/TreeStoreModel':function(){ -define("dijit/tree/TreeStoreModel", [ - "dojo/_base/array", // array.filter array.forEach array.indexOf array.some - "dojo/aspect", // aspect.after - "dojo/_base/declare", // declare - "dojo/_base/lang" // lang.hitch -], function(array, aspect, declare, lang){ - - // module: - // dijit/tree/TreeStoreModel - - return declare("dijit.tree.TreeStoreModel", null, { - // summary: - // Implements dijit/Tree/model connecting to a dojo.data store with a single - // root item. Any methods passed into the constructor will override - // the ones defined here. - - // store: dojo/data/api/Read - // Underlying store - store: null, - - // childrenAttrs: String[] - // One or more attribute names (attributes in the dojo.data item) that specify that item's children - childrenAttrs: ["children"], - - // newItemIdAttr: String - // Name of attribute in the Object passed to newItem() that specifies the id. - // - // If newItemIdAttr is set then it's used when newItem() is called to see if an - // item with the same id already exists, and if so just links to the old item - // (so that the old item ends up with two parents). - // - // Setting this to null or "" will make every drop create a new item. - newItemIdAttr: "id", - - // labelAttr: String - // If specified, get label for tree node from this attribute, rather - // than by calling store.getLabel() - labelAttr: "", - - // root: [readonly] dojo/data/Item - // Pointer to the root item (read only, not a parameter) - root: null, - - // query: anything - // Specifies datastore query to return the root item for the tree. - // Must only return a single item. Alternately can just pass in pointer - // to root item. - // example: - // | {id:'ROOT'} - query: null, - - // deferItemLoadingUntilExpand: Boolean - // Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes - // until they are expanded. This allows for lazying loading where only one - // loadItem (and generally one network call, consequently) per expansion - // (rather than one for each child). - // This relies on partial loading of the children items; each children item of a - // fully loaded item should contain the label and info about having children. - deferItemLoadingUntilExpand: false, - - constructor: function(/* Object */ args){ - // summary: - // Passed the arguments listed above (store, etc) - // tags: - // private - - lang.mixin(this, args); - - this.connects = []; - - var store = this.store; - if(!store.getFeatures()['dojo.data.api.Identity']){ - throw new Error("dijit.tree.TreeStoreModel: store must support dojo.data.Identity"); - } - - // if the store supports Notification, subscribe to the notification events - if(store.getFeatures()['dojo.data.api.Notification']){ - this.connects = this.connects.concat([ - aspect.after(store, "onNew", lang.hitch(this, "onNewItem"), true), - aspect.after(store, "onDelete", lang.hitch(this, "onDeleteItem"), true), - aspect.after(store, "onSet", lang.hitch(this, "onSetItem"), true) - ]); - } - }, - - destroy: function(){ - var h; - while(h = this.connects.pop()){ h.remove(); } - // TODO: should cancel any in-progress processing of getRoot(), getChildren() - }, - - // ======================================================================= - // Methods for traversing hierarchy - - getRoot: function(onItem, onError){ - // summary: - // Calls onItem with the root item for the tree, possibly a fabricated item. - // Calls onError on error. - if(this.root){ - onItem(this.root); - }else{ - this.store.fetch({ - query: this.query, - onComplete: lang.hitch(this, function(items){ - if(items.length != 1){ - throw new Error("dijit.tree.TreeStoreModel: root query returned " + items.length + - " items, but must return exactly one"); - } - this.root = items[0]; - onItem(this.root); - }), - onError: onError - }); - } - }, - - mayHaveChildren: function(/*dojo/data/Item*/ item){ - // summary: - // Tells if an item has or may have children. Implementing logic here - // avoids showing +/- expando icon for nodes that we know don't have children. - // (For efficiency reasons we may not want to check if an element actually - // has children until user clicks the expando node) - return array.some(this.childrenAttrs, function(attr){ - return this.store.hasAttribute(item, attr); - }, this); - }, - - getChildren: function(/*dojo/data/Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){ - // summary: - // Calls onComplete() with array of child items of given parent item, all loaded. - - var store = this.store; - if(!store.isItemLoaded(parentItem)){ - // The parent is not loaded yet, we must be in deferItemLoadingUntilExpand - // mode, so we will load it and just return the children (without loading each - // child item) - var getChildren = lang.hitch(this, arguments.callee); - store.loadItem({ - item: parentItem, - onItem: function(parentItem){ - getChildren(parentItem, onComplete, onError); - }, - onError: onError - }); - return; - } - // get children of specified item - var childItems = []; - for(var i=0; i<this.childrenAttrs.length; i++){ - var vals = store.getValues(parentItem, this.childrenAttrs[i]); - childItems = childItems.concat(vals); - } - - // count how many items need to be loaded - var _waitCount = 0; - if(!this.deferItemLoadingUntilExpand){ - array.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } }); - } - - if(_waitCount == 0){ - // all items are already loaded (or we aren't loading them). proceed... - onComplete(childItems); - }else{ - // still waiting for some or all of the items to load - array.forEach(childItems, function(item, idx){ - if(!store.isItemLoaded(item)){ - store.loadItem({ - item: item, - onItem: function(item){ - childItems[idx] = item; - if(--_waitCount == 0){ - // all nodes have been loaded, send them to the tree - onComplete(childItems); - } - }, - onError: onError - }); - } - }); - } - }, - - // ======================================================================= - // Inspecting items - - isItem: function(/* anything */ something){ - return this.store.isItem(something); // Boolean - }, - - fetchItemByIdentity: function(/* object */ keywordArgs){ - this.store.fetchItemByIdentity(keywordArgs); - }, - - getIdentity: function(/* item */ item){ - return this.store.getIdentity(item); // Object - }, - - getLabel: function(/*dojo/data/Item*/ item){ - // summary: - // Get the label for an item - if(this.labelAttr){ - return this.store.getValue(item,this.labelAttr); // String - }else{ - return this.store.getLabel(item); // String - } - }, - - // ======================================================================= - // Write interface - - newItem: function(/* dijit/tree/dndSource.__Item */ args, /*dojo/data/api/Item*/ parent, /*int?*/ insertIndex){ - // summary: - // Creates a new item. See `dojo/data/api/Write` for details on args. - // Used in drag & drop when item from external source dropped onto tree. - // description: - // Developers will need to override this method if new items get added - // to parents with multiple children attributes, in order to define which - // children attribute points to the new item. - - var pInfo = {parent: parent, attribute: this.childrenAttrs[0]}, LnewItem; - - if(this.newItemIdAttr && args[this.newItemIdAttr]){ - // Maybe there's already a corresponding item in the store; if so, reuse it. - this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){ - if(item){ - // There's already a matching item in store, use it - this.pasteItem(item, null, parent, true, insertIndex); - }else{ - // Create new item in the tree, based on the drag source. - LnewItem=this.store.newItem(args, pInfo); - if(LnewItem && (insertIndex!=undefined)){ - // Move new item to desired position - this.pasteItem(LnewItem, parent, parent, false, insertIndex); - } - } - }}); - }else{ - // [as far as we know] there is no id so we must assume this is a new item - LnewItem=this.store.newItem(args, pInfo); - if(LnewItem && (insertIndex!=undefined)){ - // Move new item to desired position - this.pasteItem(LnewItem, parent, parent, false, insertIndex); - } - } - }, - - pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){ - // summary: - // Move or copy an item from one parent item to another. - // Used in drag & drop - var store = this.store, - parentAttr = this.childrenAttrs[0]; // name of "children" attr in parent item - - // remove child from source item, and record the attribute that child occurred in - if(oldParentItem){ - array.forEach(this.childrenAttrs, function(attr){ - if(store.containsValue(oldParentItem, attr, childItem)){ - if(!bCopy){ - var values = array.filter(store.getValues(oldParentItem, attr), function(x){ - return x != childItem; - }); - store.setValues(oldParentItem, attr, values); - } - parentAttr = attr; - } - }); - } - - // modify target item's children attribute to include this item - if(newParentItem){ - if(typeof insertIndex == "number"){ - // call slice() to avoid modifying the original array, confusing the data store - var childItems = store.getValues(newParentItem, parentAttr).slice(); - childItems.splice(insertIndex, 0, childItem); - store.setValues(newParentItem, parentAttr, childItems); - }else{ - store.setValues(newParentItem, parentAttr, - store.getValues(newParentItem, parentAttr).concat(childItem)); - } - } - }, - - // ======================================================================= - // Callbacks - - onChange: function(/*dojo/data/Item*/ /*===== item =====*/){ - // summary: - // Callback whenever an item has changed, so that Tree - // can update the label, icon, etc. Note that changes - // to an item's children or parent(s) will trigger an - // onChildrenChange() so you can ignore those changes here. - // tags: - // callback - }, - - onChildrenChange: function(/*===== parent, newChildrenList =====*/){ - // summary: - // Callback to do notifications about new, updated, or deleted items. - // parent: dojo/data/Item - // newChildrenList: dojo/data/Item[] - // tags: - // callback - }, - - onDelete: function(/*dojo/data/Item*/ /*===== item =====*/){ - // summary: - // Callback when an item has been deleted. - // description: - // Note that there will also be an onChildrenChange() callback for the parent - // of this item. - // tags: - // callback - }, - - // ======================================================================= - // Events from data store - - onNewItem: function(/* dojo/data/Item */ item, /* Object */ parentInfo){ - // summary: - // Handler for when new items appear in the store, either from a drop operation - // or some other way. Updates the tree view (if necessary). - // description: - // If the new item is a child of an existing item, - // calls onChildrenChange() with the new list of children - // for that existing item. - // - // tags: - // extension - - // We only care about the new item if it has a parent that corresponds to a TreeNode - // we are currently displaying - if(!parentInfo){ - return; - } - - // Call onChildrenChange() on parent (ie, existing) item with new list of children - // In the common case, the new list of children is simply parentInfo.newValue or - // [ parentInfo.newValue ], although if items in the store has multiple - // child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue, - // so call getChildren() to be sure to get right answer. - this.getChildren(parentInfo.item, lang.hitch(this, function(children){ - this.onChildrenChange(parentInfo.item, children); - })); - }, - - onDeleteItem: function(/*Object*/ item){ - // summary: - // Handler for delete notifications from underlying store - this.onDelete(item); - }, - - onSetItem: function(item, attribute /*===== , oldValue, newValue =====*/){ - // summary: - // Updates the tree view according to changes in the data store. - // description: - // Handles updates to an item's children by calling onChildrenChange(), and - // other updates to an item by calling onChange(). - // - // See `onNewItem` for more details on handling updates to an item's children. - // item: Item - // attribute: attribute-name-string - // oldValue: Object|Array - // newValue: Object|Array - // tags: - // extension - - if(array.indexOf(this.childrenAttrs, attribute) != -1){ - // item's children list changed - this.getChildren(item, lang.hitch(this, function(children){ - // See comments in onNewItem() about calling getChildren() - this.onChildrenChange(item, children); - })); - }else{ - // item's label/icon/etc. changed. - this.onChange(item); - } - } - }); -}); - -}, -'dijit/_MenuBase':function(){ -define("dijit/_MenuBase", [ - "dojo/_base/array", // array.indexOf - "dojo/_base/declare", // declare - "dojo/dom", // dom.isDescendant domClass.replace - "dojo/dom-attr", - "dojo/dom-class", // domClass.replace - "dojo/_base/lang", // lang.hitch - "dojo/mouse", // mouse.enter, mouse.leave - "dojo/on", - "dojo/window", - "./a11yclick", - "./popup", - "./registry", - "./_Widget", - "./_KeyNavContainer", - "./_TemplatedMixin" -], function(array, declare, dom, domAttr, domClass, lang, mouse, on, winUtils, - a11yclick, pm, registry, _Widget, _KeyNavContainer, _TemplatedMixin){ - - -// module: -// dijit/_MenuBase - -return declare("dijit._MenuBase", - [_Widget, _TemplatedMixin, _KeyNavContainer], -{ - // summary: - // Base class for Menu and MenuBar - - // parentMenu: [readonly] Widget - // pointer to menu that displayed me - parentMenu: null, - - // popupDelay: Integer - // number of milliseconds before hovering (without clicking) causes the popup to automatically open. - popupDelay: 500, - - // autoFocus: Boolean - // A toggle to control whether or not a Menu gets focused when opened as a drop down from a MenuBar - // or DropDownButton/ComboButton. Note though that it always get focused when opened via the keyboard. - autoFocus: false, - - childSelector: function(/*DOMNode*/ node){ - // summary: - // Selector (passed to on.selector()) used to identify MenuItem child widgets, but exclude inert children - // like MenuSeparator. If subclass overrides to a string (ex: "> *"), the subclass must require dojo/query. - // tags: - // protected - - var widget = registry.byNode(node); - return node.parentNode == this.containerNode && widget && widget.focus; - }, - - postCreate: function(){ - var self = this, - matches = typeof this.childSelector == "string" ? this.childSelector : lang.hitch(this, "childSelector"); - this.own( - on(this.containerNode, on.selector(matches, mouse.enter), function(){ - self.onItemHover(registry.byNode(this)); - }), - on(this.containerNode, on.selector(matches, mouse.leave), function(){ - self.onItemUnhover(registry.byNode(this)); - }), - on(this.containerNode, on.selector(matches, a11yclick), function(evt){ - self.onItemClick(registry.byNode(this), evt); - evt.stopPropagation(); - evt.preventDefault(); - }) - ); - this.inherited(arguments); - }, - - onExecute: function(){ - // summary: - // Attach point for notification about when a menu item has been executed. - // This is an internal mechanism used for Menus to signal to their parent to - // close them, because they are about to execute the onClick handler. In - // general developers should not attach to or override this method. - // tags: - // protected - }, - - onCancel: function(/*Boolean*/ /*===== closeAll =====*/){ - // summary: - // Attach point for notification about when the user cancels the current menu - // This is an internal mechanism used for Menus to signal to their parent to - // close them. In general developers should not attach to or override this method. - // tags: - // protected - }, - - _moveToPopup: function(/*Event*/ evt){ - // summary: - // This handles the right arrow key (left arrow key on RTL systems), - // which will either open a submenu, or move to the next item in the - // ancestor MenuBar - // tags: - // private - - if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){ - this.onItemClick(this.focusedChild, evt); - }else{ - var topMenu = this._getTopMenu(); - if(topMenu && topMenu._isMenuBar){ - topMenu.focusNext(); - } - } - }, - - _onPopupHover: function(/*Event*/ /*===== evt =====*/){ - // summary: - // This handler is called when the mouse moves over the popup. - // tags: - // private - - // if the mouse hovers over a menu popup that is in pending-close state, - // then stop the close operation. - // This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker) - if(this.currentPopup && this.currentPopup._pendingClose_timer){ - var parentMenu = this.currentPopup.parentMenu; - // highlight the parent menu item pointing to this popup - if(parentMenu.focusedChild){ - parentMenu.focusedChild._setSelected(false); - } - parentMenu.focusedChild = this.currentPopup.from_item; - parentMenu.focusedChild._setSelected(true); - // cancel the pending close - this._stopPendingCloseTimer(this.currentPopup); - } - }, - - onItemHover: function(/*MenuItem*/ item){ - // summary: - // Called when cursor is over a MenuItem. - // tags: - // protected - - // Don't do anything unless user has "activated" the menu by: - // 1) clicking it - // 2) opening it from a parent menu (which automatically focuses it) - if(this.isActive){ - this.focusChild(item); - if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){ - this.hover_timer = this.defer("_openPopup", this.popupDelay); - } - } - // if the user is mixing mouse and keyboard navigation, - // then the menu may not be active but a menu item has focus, - // but it's not the item that the mouse just hovered over. - // To avoid both keyboard and mouse selections, use the latest. - if(this.focusedChild){ - this.focusChild(item); - } - this._hoveredChild = item; - - item._set("hovering", true); - }, - - _onChildBlur: function(item){ - // summary: - // Called when a child MenuItem becomes inactive because focus - // has been removed from the MenuItem *and* it's descendant menus. - // tags: - // private - this._stopPopupTimer(); - item._setSelected(false); - // Close all popups that are open and descendants of this menu - var itemPopup = item.popup; - if(itemPopup){ - this._stopPendingCloseTimer(itemPopup); - itemPopup._pendingClose_timer = this.defer(function(){ - itemPopup._pendingClose_timer = null; - if(itemPopup.parentMenu){ - itemPopup.parentMenu.currentPopup = null; - } - pm.close(itemPopup); // this calls onClose - }, this.popupDelay); - } - }, - - onItemUnhover: function(/*MenuItem*/ item){ - // summary: - // Callback fires when mouse exits a MenuItem - // tags: - // protected - - if(this.isActive){ - this._stopPopupTimer(); - } - if(this._hoveredChild == item){ this._hoveredChild = null; } - - item._set("hovering", false); - }, - - _stopPopupTimer: function(){ - // summary: - // Cancels the popup timer because the user has stop hovering - // on the MenuItem, etc. - // tags: - // private - if(this.hover_timer){ - this.hover_timer = this.hover_timer.remove(); - } - }, - - _stopPendingCloseTimer: function(/*dijit/_WidgetBase*/ popup){ - // summary: - // Cancels the pending-close timer because the close has been preempted - // tags: - // private - if(popup._pendingClose_timer){ - popup._pendingClose_timer = popup._pendingClose_timer.remove(); - } - }, - - _stopFocusTimer: function(){ - // summary: - // Cancels the pending-focus timer because the menu was closed before focus occured - // tags: - // private - if(this._focus_timer){ - this._focus_timer = this._focus_timer.remove(); - } - }, - - _getTopMenu: function(){ - // summary: - // Returns the top menu in this chain of Menus - // tags: - // private - for(var top=this; top.parentMenu; top=top.parentMenu); - return top; - }, - - onItemClick: function(/*dijit/_WidgetBase*/ item, /*Event*/ evt){ - // summary: - // Handle clicks on an item. - // tags: - // private - - // this can't be done in _onFocus since the _onFocus events occurs asynchronously - if(typeof this.isShowingNow == 'undefined'){ // non-popup menu - this._markActive(); - } - - this.focusChild(item); - - if(item.disabled){ return false; } - - if(item.popup){ - this._openPopup(evt.type == "keypress"); - }else{ - // before calling user defined handler, close hierarchy of menus - // and restore focus to place it was when menu was opened - this.onExecute(); - - // user defined handler for click - item._onClick ? item._onClick(evt) : item.onClick(evt); - } - }, - - _openPopup: function(/*Boolean*/ focus){ - // summary: - // Open the popup to the side of/underneath the current menu item, and optionally focus first item - // tags: - // protected - - this._stopPopupTimer(); - var from_item = this.focusedChild; - if(!from_item){ return; } // the focused child lost focus since the timer was started - var popup = from_item.popup; - if(!popup.isShowingNow){ - if(this.currentPopup){ - this._stopPendingCloseTimer(this.currentPopup); - pm.close(this.currentPopup); - } - popup.parentMenu = this; - popup.from_item = from_item; // helps finding the parent item that should be focused for this popup - var self = this; - pm.open({ - parent: this, - popup: popup, - around: from_item.domNode, - orient: this._orient || ["after", "before"], - onCancel: function(){ // called when the child menu is canceled - // set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus - // which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro) - self.focusChild(from_item); // put focus back on my node - self._cleanUp(); // close the submenu (be sure this is done _after_ focus is moved) - from_item._setSelected(true); // oops, _cleanUp() deselected the item - self.focusedChild = from_item; // and unset focusedChild - }, - onExecute: lang.hitch(this, "_cleanUp") - }); - - this.currentPopup = popup; - // detect mouseovers to handle lazy mouse movements that temporarily focus other menu items - popup.connect(popup.domNode, "onmouseenter", lang.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close - } - - if(focus && popup.focus){ - // If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar), then focus the popup. - // If the cursor happens to collide with the popup, it will generate an onmouseover event - // even though the mouse wasn't moved. Use defer() to call popup.focus so that - // our focus() call overrides the onmouseover event, rather than vice-versa. (#8742) - popup._focus_timer = this.defer(lang.hitch(popup, function(){ - this._focus_timer = null; - this.focus(); - })); - } - }, - - _markActive: function(){ - // summary: - // Mark this menu's state as active. - // Called when this Menu gets focus from: - // - // 1. clicking it (mouse or via space/arrow key) - // 2. being opened by a parent menu. - // - // This is not called just from mouse hover. - // Focusing a menu via TAB does NOT automatically set isActive - // since TAB is a navigation operation and not a selection one. - // For Windows apps, pressing the ALT key focuses the menubar - // menus (similar to TAB navigation) but the menu is not active - // (ie no dropdown) until an item is clicked. - this.isActive = true; - domClass.replace(this.domNode, "dijitMenuActive", "dijitMenuPassive"); - }, - - onOpen: function(/*Event*/ /*===== e =====*/){ - // summary: - // Callback when this menu is opened. - // This is called by the popup manager as notification that the menu - // was opened. - // tags: - // private - - this.isShowingNow = true; - this._markActive(); - }, - - _markInactive: function(){ - // summary: - // Mark this menu's state as inactive. - this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here - domClass.replace(this.domNode, "dijitMenuPassive", "dijitMenuActive"); - }, - - onClose: function(){ - // summary: - // Callback when this menu is closed. - // This is called by the popup manager as notification that the menu - // was closed. - // tags: - // private - - this._stopFocusTimer(); - this._markInactive(); - this.isShowingNow = false; - this.parentMenu = null; - }, - - _closeChild: function(){ - // summary: - // Called when submenu is clicked or focus is lost. Close hierarchy of menus. - // tags: - // private - this._stopPopupTimer(); - - if(this.currentPopup){ - // If focus is on a descendant MenuItem then move focus to me, - // because IE doesn't like it when you display:none a node with focus, - // and also so keyboard users don't lose control. - // Likely, immediately after a user defined onClick handler will move focus somewhere - // else, like a Dialog. - if(array.indexOf(this._focusManager.activeStack, this.id) >= 0){ - domAttr.set(this.focusedChild.focusNode, "tabIndex", this.tabIndex); - this.focusedChild.focusNode.focus(); - } - // Close all popups that are open and descendants of this menu - pm.close(this.currentPopup); - this.currentPopup = null; - } - - if(this.focusedChild){ // unhighlight the focused item - this.focusedChild._setSelected(false); - this.onItemUnhover(this.focusedChild); - this.focusedChild = null; - } - }, - - _onItemFocus: function(/*MenuItem*/ item){ - // summary: - // Called when child of this Menu gets focus from: - // - // 1. clicking it - // 2. tabbing into it - // 3. being opened by a parent menu. - // - // This is not called just from mouse hover. - if(this._hoveredChild && this._hoveredChild != item){ - this.onItemUnhover(this._hoveredChild); // any previous mouse movement is trumped by focus selection - } - }, - - _onBlur: function(){ - // summary: - // Called when focus is moved away from this Menu and it's submenus. - // tags: - // protected - this._cleanUp(); - this.inherited(arguments); - }, - - _cleanUp: function(){ - // summary: - // Called when the user is done with this menu. Closes hierarchy of menus. - // tags: - // private - - this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close - if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose - this._markInactive(); - } - } -}); - -}); - -}, -'dijit/focus':function(){ -define("dijit/focus", [ - "dojo/aspect", - "dojo/_base/declare", // declare - "dojo/dom", // domAttr.get dom.isDescendant - "dojo/dom-attr", // domAttr.get dom.isDescendant - "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy - "dojo/Evented", - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/ready", - "dojo/sniff", // has("ie") - "dojo/Stateful", - "dojo/_base/unload", // unload.addOnWindowUnload - "dojo/_base/window", // win.body - "dojo/window", // winUtils.get - "./a11y", // a11y.isTabNavigable - "./registry", // registry.byId - "./main" // to set dijit.focus -], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, ready, has, Stateful, unload, win, winUtils, - a11y, registry, dijit){ - - // module: - // dijit/focus - - var FocusManager = declare([Stateful, Evented], { - // summary: - // Tracks the currently focused node, and which widgets are currently "active". - // Access via require(["dijit/focus"], function(focus){ ... }). - // - // A widget is considered active if it or a descendant widget has focus, - // or if a non-focusable node of this widget or a descendant was recently clicked. - // - // Call focus.watch("curNode", callback) to track the current focused DOMNode, - // or focus.watch("activeStack", callback) to track the currently focused stack of widgets. - // - // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when - // when widgets become active/inactive - // - // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist. - - // curNode: DomNode - // Currently focused item on screen - curNode: null, - - // activeStack: dijit/_WidgetBase[] - // List of currently active widgets (focused widget and it's ancestors) - activeStack: [], - - constructor: function(){ - // Don't leave curNode/prevNode pointing to bogus elements - var check = lang.hitch(this, function(node){ - if(dom.isDescendant(this.curNode, node)){ - this.set("curNode", null); - } - if(dom.isDescendant(this.prevNode, node)){ - this.set("prevNode", null); - } - }); - aspect.before(domConstruct, "empty", check); - aspect.before(domConstruct, "destroy", check); - }, - - registerIframe: function(/*DomNode*/ iframe){ - // summary: - // Registers listeners on the specified iframe so that any click - // or focus event on that iframe (or anything in it) is reported - // as a focus/click event on the `<iframe>` itself. - // description: - // Currently only used by editor. - // returns: - // Handle with remove() method to deregister. - return this.registerWin(iframe.contentWindow, iframe); - }, - - registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){ - // summary: - // Registers listeners on the specified window (either the main - // window or an iframe's window) to detect when the user has clicked somewhere - // or focused somewhere. - // description: - // Users should call registerIframe() instead of this method. - // targetWindow: - // If specified this is the window associated with the iframe, - // i.e. iframe.contentWindow. - // effectiveNode: - // If specified, report any focus events inside targetWindow as - // an event on effectiveNode, rather than on evt.target. - // returns: - // Handle with remove() method to deregister. - - // TODO: make this function private in 2.0; Editor/users should call registerIframe(), - - var _this = this; - var mousedownListener = function(evt){ - _this._justMouseDowned = true; - setTimeout(function(){ _this._justMouseDowned = false; }, 0); - - // workaround weird IE bug where the click is on an orphaned node - // (first time clicking a Select/DropDownButton inside a TooltipDialog) - if(has("ie") && evt && evt.srcElement && evt.srcElement.parentNode == null){ - return; - } - - _this._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse"); - }; - - // Listen for blur and focus events on targetWindow's document. - // Using attachEvent()/addEventListener() rather than on() to try to catch mouseDown events even - // if other code calls evt.stopPropagation(). But rethink for 2.0 since that doesn't work for attachEvent(), - // which watches events at the bubbling phase rather than capturing phase, like addEventListener(..., false). - // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because - // (at least for FF) the focus event doesn't fire on <html> or <body>. - var doc = has("ie") ? targetWindow.document.documentElement : targetWindow.document; - if(doc){ - if(has("ie")){ - targetWindow.document.body.attachEvent('onmousedown', mousedownListener); - var focusinListener = function(evt){ - // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1, - // ignore those events - var tag = evt.srcElement.tagName.toLowerCase(); - if(tag == "#document" || tag == "body"){ return; } - - // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can - // probably just ignore such an event as it will be handled by onmousedown handler above, but - // leaving the code for now. - if(a11y.isTabNavigable(evt.srcElement)){ - _this._onFocusNode(effectiveNode || evt.srcElement); - }else{ - _this._onTouchNode(effectiveNode || evt.srcElement); - } - }; - doc.attachEvent('onfocusin', focusinListener); - var focusoutListener = function(evt){ - _this._onBlurNode(effectiveNode || evt.srcElement); - }; - doc.attachEvent('onfocusout', focusoutListener); - - return { - remove: function(){ - targetWindow.document.detachEvent('onmousedown', mousedownListener); - doc.detachEvent('onfocusin', focusinListener); - doc.detachEvent('onfocusout', focusoutListener); - doc = null; // prevent memory leak (apparent circular reference via closure) - } - }; - }else{ - doc.body.addEventListener('mousedown', mousedownListener, true); - doc.body.addEventListener('touchstart', mousedownListener, true); - var focusListener = function(evt){ - _this._onFocusNode(effectiveNode || evt.target); - }; - doc.addEventListener('focus', focusListener, true); - var blurListener = function(evt){ - _this._onBlurNode(effectiveNode || evt.target); - }; - doc.addEventListener('blur', blurListener, true); - - return { - remove: function(){ - doc.body.removeEventListener('mousedown', mousedownListener, true); - doc.body.removeEventListener('touchstart', mousedownListener, true); - doc.removeEventListener('focus', focusListener, true); - doc.removeEventListener('blur', blurListener, true); - doc = null; // prevent memory leak (apparent circular reference via closure) - } - }; - } - } - }, - - _onBlurNode: function(/*DomNode*/ node){ - // summary: - // Called when focus leaves a node. - // Usually ignored, _unless_ it *isn't* followed by touching another node, - // which indicates that we tabbed off the last field on the page, - // in which case every widget is marked inactive - - // If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable, - // so clear focus. - if(this._clearFocusTimer){ - clearTimeout(this._clearFocusTimer); - } - this._clearFocusTimer = setTimeout(lang.hitch(this, function(){ - this.set("prevNode", this.curNode); - this.set("curNode", null); - }), 0); - - if(this._justMouseDowned){ - // the mouse down caused a new widget to be marked as active; this blur event - // is coming late, so ignore it. - return; - } - - // If the blur event isn't followed by a focus or touch event then mark all widgets as inactive. - if(this._clearActiveWidgetsTimer){ - clearTimeout(this._clearActiveWidgetsTimer); - } - this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){ - delete this._clearActiveWidgetsTimer; - this._setStack([]); - }), 0); - }, - - _onTouchNode: function(/*DomNode*/ node, /*String*/ by){ - // summary: - // Callback when node is focused or mouse-downed - // node: - // The node that was touched. - // by: - // "mouse" if the focus/touch was caused by a mouse down event - - // ignore the recent blurNode event - if(this._clearActiveWidgetsTimer){ - clearTimeout(this._clearActiveWidgetsTimer); - delete this._clearActiveWidgetsTimer; - } - - // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem) - var newStack=[]; - try{ - while(node){ - var popupParent = domAttr.get(node, "dijitPopupParent"); - if(popupParent){ - node=registry.byId(popupParent).domNode; - }else if(node.tagName && node.tagName.toLowerCase() == "body"){ - // is this the root of the document or just the root of an iframe? - if(node === win.body()){ - // node is the root of the main document - break; - } - // otherwise, find the iframe this node refers to (can't access it via parentNode, - // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit - node=winUtils.get(node.ownerDocument).frameElement; - }else{ - // if this node is the root node of a widget, then add widget id to stack, - // except ignore clicks on disabled widgets (actually focusing a disabled widget still works, - // to support MenuItem) - var id = node.getAttribute && node.getAttribute("widgetId"), - widget = id && registry.byId(id); - if(widget && !(by == "mouse" && widget.get("disabled"))){ - newStack.unshift(id); - } - node=node.parentNode; - } - } - }catch(e){ /* squelch */ } - - this._setStack(newStack, by); - }, - - _onFocusNode: function(/*DomNode*/ node){ - // summary: - // Callback when node is focused - - if(!node){ - return; - } - - if(node.nodeType == 9){ - // Ignore focus events on the document itself. This is here so that - // (for example) clicking the up/down arrows of a spinner - // (which don't get focus) won't cause that widget to blur. (FF issue) - return; - } - - // There was probably a blur event right before this event, but since we have a new focus, don't - // do anything with the blur - if(this._clearFocusTimer){ - clearTimeout(this._clearFocusTimer); - delete this._clearFocusTimer; - } - - this._onTouchNode(node); - - if(node == this.curNode){ return; } - this.set("prevNode", this.curNode); - this.set("curNode", node); - }, - - _setStack: function(/*String[]*/ newStack, /*String*/ by){ - // summary: - // The stack of active widgets has changed. Send out appropriate events and records new stack. - // newStack: - // array of widget id's, starting from the top (outermost) widget - // by: - // "mouse" if the focus/touch was caused by a mouse down event - - var oldStack = this.activeStack; - this.set("activeStack", newStack); - - // compare old stack to new stack to see how many elements they have in common - for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){ - if(oldStack[nCommon] != newStack[nCommon]){ - break; - } - } - - var widget; - // for all elements that have gone out of focus, set focused=false - for(var i=oldStack.length-1; i>=nCommon; i--){ - widget = registry.byId(oldStack[i]); - if(widget){ - widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there - widget.set("focused", false); - if(widget._focusManager == this){ - widget._onBlur(by); - } - this.emit("widget-blur", widget, by); - } - } - - // for all element that have come into focus, set focused=true - for(i=nCommon; i<newStack.length; i++){ - widget = registry.byId(newStack[i]); - if(widget){ - widget.set("focused", true); - if(widget._focusManager == this){ - widget._onFocus(by); - } - this.emit("widget-focus", widget, by); - } - } - }, - - focus: function(node){ - // summary: - // Focus the specified node, suppressing errors if they occur - if(node){ - try{ node.focus(); }catch(e){/*quiet*/} - } - } - }); - - var singleton = new FocusManager(); - - // register top window and all the iframes it contains - ready(function(){ - var handle = singleton.registerWin(winUtils.get(win.doc)); - if(has("ie")){ - unload.addOnWindowUnload(function(){ - if(handle){ // because this gets called twice when doh.robot is running - handle.remove(); - handle = null; - } - }); - } - }); - - // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility) - // as a function to set focus. Remove for 2.0. - dijit.focus = function(node){ - singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior - }; - for(var attr in singleton){ - if(!/^_/.test(attr)){ - dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr]; - } - } - singleton.watch(function(attr, oldVal, newVal){ - dijit.focus[attr] = newVal; - }); - - return singleton; -}); - -}, -'dojo/i18n':function(){ -define("dojo/i18n", ["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json", "module"], - function(dojo, require, has, array, config, lang, xhr, json, module){ - - // module: - // dojo/i18n - - has.add("dojo-preload-i18n-Api", - // if true, define the preload localizations machinery - 1 - ); - - 1 || has.add("dojo-v1x-i18n-Api", - // if true, define the v1.x i18n functions - 1 - ); - - var - thisModule = dojo.i18n = - { - // summary: - // This module implements the dojo/i18n! plugin and the v1.6- i18n API - // description: - // We choose to include our own plugin to leverage functionality already contained in dojo - // and thereby reduce the size of the plugin compared to various loader implementations. Also, this - // allows foreign AMD loaders to be used without their plugins. - }, - - nlsRe = - // regexp for reconstructing the master bundle name from parts of the regexp match - // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives: - // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"] - // nlsRe.exec("foo/bar/baz/nls/foo") gives: - // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""] - // so, if match[5] is blank, it means this is the top bundle definition. - // courtesy of http://requirejs.org - /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/, - - getAvailableLocales = function( - root, - locale, - bundlePath, - bundleName - ){ - // summary: - // return a vector of module ids containing all available locales with respect to the target locale - // For example, assuming: - // - // - the root bundle indicates specific bundles for "fr" and "fr-ca", - // - bundlePath is "myPackage/nls" - // - bundleName is "myBundle" - // - // Then a locale argument of "fr-ca" would return - // - // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"] - // - // Notice that bundles are returned least-specific to most-specific, starting with the root. - // - // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales; - // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available - - for(var result = [bundlePath + bundleName], localeParts = locale.split("-"), current = "", i = 0; i<localeParts.length; i++){ - current += (current ? "-" : "") + localeParts[i]; - if(!root || root[current]){ - result.push(bundlePath + current + "/" + bundleName); - } - } - return result; - }, - - cache = {}, - - getBundleName = function(moduleName, bundleName, locale){ - locale = locale ? locale.toLowerCase() : dojo.locale; - moduleName = moduleName.replace(/\./g, "/"); - bundleName = bundleName.replace(/\./g, "/"); - return (/root/i.test(locale)) ? - (moduleName + "/nls/" + bundleName) : - (moduleName + "/nls/" + locale + "/" + bundleName); - }, - - getL10nName = dojo.getL10nName = function(moduleName, bundleName, locale){ - return moduleName = module.id + "!" + getBundleName(moduleName, bundleName, locale); - }, - - doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){ - // summary: - // get the root bundle which instructs which other bundles are required to construct the localized bundle - require([bundlePathAndName], function(root){ - var current = lang.clone(root.root), - availableLocales = getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName); - require(availableLocales, function(){ - for (var i = 1; i<availableLocales.length; i++){ - current = lang.mixin(lang.clone(current), arguments[i]); - } - // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested) - var target = bundlePathAndName + "/" + locale; - cache[target] = current; - load(); - }); - }); - }, - - normalize = function(id, toAbsMid){ - // summary: - // id may be relative. - // preload has form `*preload*<path>/nls/<module>*<flattened locales>` and - // therefore never looks like a relative - return /^\./.test(id) ? toAbsMid(id) : id; - }, - - getLocalesToLoad = function(targetLocale){ - var list = config.extraLocale || []; - list = lang.isArray(list) ? list : [list]; - list.push(targetLocale); - return list; - }, - - load = function(id, require, load){ - // summary: - // id is in one of the following formats - // - // 1. <path>/nls/<bundle> - // => load the bundle, localized to config.locale; load all bundles localized to - // config.extraLocale (if any); return the loaded bundle localized to config.locale. - // - // 2. <path>/nls/<locale>/<bundle> - // => load then return the bundle localized to <locale> - // - // 3. *preload*<path>/nls/<module>*<JSON array of available locales> - // => for config.locale and all config.extraLocale, load all bundles found - // in the best-matching bundle rollup. A value of 1 is returned, which - // is meaningless other than to say the plugin is executing the requested - // preloads - // - // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see - // normalize. In case 3, it <path> is assumed to be absolute; this is arranged by the builder. - // - // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle - // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key - // - // <path>/nls/<bundle>/<locale> - // - // will hold the value. Similarly, then plugin will publish this value to the loader by - // - // define("<path>/nls/<bundle>/<locale>", <bundle-value>); - // - // Given this algorithm, other machinery can provide fast load paths be preplacing - // values in the plugin's cache, which is public. When a load is demanded the - // cache is inspected before starting any loading. Explicitly placing values in the plugin - // cache is an advanced/experimental feature that should not be needed; use at your own risk. - // - // For the normal AMD algorithm, the root bundle is loaded first, which instructs the - // plugin what additional localized bundles are required for a particular locale. These - // additional locales are loaded and a mix of the root and each progressively-specific - // locale is returned. For example: - // - // 1. The client demands "dojo/i18n!some/path/nls/someBundle - // - // 2. The loader demands load(some/path/nls/someBundle) - // - // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle. - // - // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations - // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin - // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle" - // - // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle - // ab-cd-ef as... - // - // mixin(mixin(mixin({}, require("some/path/nls/someBundle"), - // require("some/path/nls/ab/someBundle")), - // require("some/path/nls/ab-cd-ef/someBundle")); - // - // This value is inserted into the cache and published to the loader at the - // key/module-id some/path/nls/someBundle/ab-cd-ef. - // - // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests - // (further preload requests will be serviced) until all ongoing preloading has completed. - // - // The preload signature instructs the plugin that a special rollup module is available that contains - // one or more flattened, localized bundles. The JSON array of available locales indicates which locales - // are available. Here is an example: - // - // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"] - // - // This indicates the following rollup modules are available: - // - // some/path/nls/someModule_ROOT - // some/path/nls/someModule_ab - // some/path/nls/someModule_ab-cd-ef - // - // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash. - // For example, assume someModule contained the bundles some/bundle/path/someBundle and - // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as follows: - // - // define({ - // some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>, - // some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>, - // }); - // - // E.g., given this design, preloading for locale=="ab" can execute the following algorithm: - // - // require(["some/path/nls/someModule_ab"], function(rollup){ - // for(var p in rollup){ - // var id = p + "/ab", - // cache[id] = rollup[p]; - // define(id, rollup[p]); - // } - // }); - // - // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and - // load accordingly. - // - // The builder will write such rollups for every layer if a non-empty localeList profile property is - // provided. Further, the builder will include the following cache entry in the cache associated with - // any layer. - // - // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);} - // - // The *now special cache module instructs the loader to apply the provided function to context-require - // with respect to the particular layer being defined. This causes the plugin to hold all normal service - // requests until all preloading is complete. - // - // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case - // where the target locale has a single segment and a layer depends on a single bundle: - // - // Without Preloads: - // - // 1. Layer loads root bundle. - // 2. bundle is demanded; plugin loads single localized bundle. - // - // With Preloads: - // - // 1. Layer causes preloading of target bundle. - // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned. - // - // In each case a single transaction is required to load the target bundle. In cases where multiple bundles - // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas - // the normal path requires an additional transaction for each additional bundle/locale-segment. However all - // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading - // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false. - - if(has("dojo-preload-i18n-Api")){ - var split = id.split("*"), - preloadDemand = split[1] == "preload"; - if(preloadDemand){ - if(!cache[id]){ - // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but - // who knows what over-aggressive human optimizers may attempt - cache[id] = 1; - preloadL10n(split[2], json.parse(split[3]), 1, require); - } - // don't stall the loader! - load(1); - } - if(preloadDemand || waitForPreloads(id, require, load)){ - return; - } - } - - var match = nlsRe.exec(id), - bundlePath = match[1] + "/", - bundleName = match[5] || match[4], - bundlePathAndName = bundlePath + bundleName, - localeSpecified = (match[5] && match[4]), - targetLocale = localeSpecified || dojo.locale, - loadTarget = bundlePathAndName + "/" + targetLocale, - loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale), - remaining = loadList.length, - finish = function(){ - if(!--remaining){ - load(lang.delegate(cache[loadTarget])); - } - }; - array.forEach(loadList, function(locale){ - var target = bundlePathAndName + "/" + locale; - if(has("dojo-preload-i18n-Api")){ - checkForLegacyModules(target); - } - if(!cache[target]){ - doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish); - }else{ - finish(); - } - }); - }; - - if(has("dojo-unit-tests")){ - var unitTests = thisModule.unitTests = []; - } - - if(has("dojo-preload-i18n-Api") || 1 ){ - var normalizeLocale = thisModule.normalizeLocale = function(locale){ - var result = locale ? locale.toLowerCase() : dojo.locale; - return result == "root" ? "ROOT" : result; - }, - - isXd = function(mid, contextRequire){ - return ( 1 && 1 ) ? - contextRequire.isXdUrl(require.toUrl(mid + ".js")) : - true; - }, - - preloading = 0, - - preloadWaitQueue = [], - - preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean?*/ guaranteedAmdFormat, /*function?*/ contextRequire){ - // summary: - // Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any) - // description: - // Only called by built layer files. The entire locale hierarchy is loaded. For example, - // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6- - // in that the v1.6- would only load ab-cd...which was *always* flattened. - // - // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm - // and the extra possible extra transaction. - - // If this function is called from legacy code, then guaranteedAmdFormat and contextRequire will be undefined. Since the function - // needs a require in order to resolve module ids, fall back to the context-require associated with this dojo/i18n module, which - // itself may have been mapped. - contextRequire = contextRequire || require; - - function doRequire(mid, callback){ - if(isXd(mid, contextRequire) || guaranteedAmdFormat){ - contextRequire([mid], callback); - }else{ - syncRequire([mid], callback, contextRequire); - } - } - - function forEachLocale(locale, func){ - // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy - var parts = locale.split("-"); - while(parts.length){ - if(func(parts.join("-"))){ - return; - } - parts.pop(); - } - func("ROOT"); - } - - function preload(locale){ - locale = normalizeLocale(locale); - forEachLocale(locale, function(loc){ - if(array.indexOf(localesGenerated, loc)>=0){ - var mid = bundlePrefix.replace(/\./g, "/")+"_"+loc; - preloading++; - doRequire(mid, function(rollup){ - for(var p in rollup){ - cache[require.toAbsMid(p) + "/" + loc] = rollup[p]; - } - --preloading; - while(!preloading && preloadWaitQueue.length){ - load.apply(null, preloadWaitQueue.shift()); - } - }); - return true; - } - return false; - }); - } - - preload(); - array.forEach(dojo.config.extraLocale, preload); - }, - - waitForPreloads = function(id, require, load){ - if(preloading){ - preloadWaitQueue.push([id, require, load]); - } - return preloading; - }, - - checkForLegacyModules = function() - {}; - } - - if( 1 ){ - // this code path assumes the dojo loader and won't work with a standard AMD loader - var amdValue = {}, - evalBundle = - // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary) - new Function( - "__bundle", // the bundle to evalutate - "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space - "__mid", // the mid that __bundle is intended to define - "__amdValue", - - // returns one of: - // 1 => the bundle was an AMD bundle - // a legacy bundle object that is the value of __mid - // instance of Error => could not figure out how to evaluate bundle - - // used to detect when __bundle calls define - "var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;}," - + " require = function(){define.called = 1;};" - - + "try{" - + "define.called = 0;" - + "eval(__bundle);" - + "if(define.called==1)" - // bundle called define; therefore signal it's an AMD bundle - + "return __amdValue;" - - + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))" - // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space - + "return __checkForLegacyModules;" - - + "}catch(e){}" - // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle - // either way, re-eval *after* surrounding with parentheses - - + "try{" - + "return eval('('+__bundle+')');" - + "}catch(e){" - + "return e;" - + "}" - ), - - syncRequire = function(deps, callback, require){ - var results = []; - array.forEach(deps, function(mid){ - var url = require.toUrl(mid + ".js"); - - function load(text){ - var result = evalBundle(text, checkForLegacyModules, mid, amdValue); - if(result===amdValue){ - // the bundle was an AMD module; re-inject it through the normal AMD path - // we gotta do this since it could be an anonymous module and simply evaluating - // the text here won't provide the loader with the context to know what - // module is being defined()'d. With browser caching, this should be free; further - // this entire code path can be circumvented by using the AMD format to begin with - results.push(cache[url] = amdValue.result); - }else{ - if(result instanceof Error){ - console.error("failed to evaluate i18n bundle; url=" + url, result); - result = {}; - } - // nls/<locale>/<bundle-name> indicates not the root. - results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1})); - } - } - - if(cache[url]){ - results.push(cache[url]); - }else{ - var bundle = require.syncLoadNls(mid); - // don't need to check for legacy since syncLoadNls returns a module if the module - // (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called - // from getLocalization --> load, then load will have called checkForLegacyModules() before - // calling syncRequire; if syncRequire is called from preloadLocalizations, then we - // don't care about checkForLegacyModules() because that will be done when a particular - // bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant - // because cached modules are always v1.7+ built modules. - if(bundle){ - results.push(bundle); - }else{ - if(!xhr){ - try{ - require.getText(url, true, load); - }catch(e){ - results.push(cache[url] = {}); - } - }else{ - xhr.get({ - url:url, - sync:true, - load:load, - error:function(){ - results.push(cache[url] = {}); - } - }); - } - } - } - }); - callback && callback.apply(null, results); - }; - - checkForLegacyModules = function(target){ - // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache - for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){} - if(object){ - result = object[names[i]]; - if(!result){ - // fallback for incorrect bundle build of 1.6 - result = object[names[i].replace(/-/g,"_")]; - } - if(result){ - cache[target] = result; - } - } - return result; - }; - - thisModule.getLocalization = function(moduleName, bundleName, locale){ - var result, - l10nName = getBundleName(moduleName, bundleName, locale); - load( - l10nName, - - // isXd() and syncRequire() need a context-require in order to resolve the mid with respect to a reference module. - // Since this legacy function does not have the concept of a reference module, resolve with respect to this - // dojo/i18n module, which, itself may have been mapped. - (!isXd(l10nName, require) ? function(deps, callback){ syncRequire(deps, callback, require); } : require), - - function(result_){ result = result_; } - ); - return result; - }; - - if(has("dojo-unit-tests")){ - unitTests.push(function(doh){ - doh.register("tests.i18n.unit", function(t){ - var check; - - check = evalBundle("{prop:1}", checkForLegacyModules, "nonsense", amdValue); - t.is({prop:1}, check); t.is(undefined, check[1]); - - check = evalBundle("({prop:1})", checkForLegacyModules, "nonsense", amdValue); - t.is({prop:1}, check); t.is(undefined, check[1]); - - check = evalBundle("{'prop-x':1}", checkForLegacyModules, "nonsense", amdValue); - t.is({'prop-x':1}, check); t.is(undefined, check[1]); - - check = evalBundle("({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); - t.is({'prop-x':1}, check); t.is(undefined, check[1]); - - check = evalBundle("define({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); - t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result); - - check = evalBundle("define('some/module', {'prop-x':1})", checkForLegacyModules, "nonsense", amdValue); - t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result); - - check = evalBundle("this is total nonsense and should throw an error", checkForLegacyModules, "nonsense", amdValue); - t.is(check instanceof Error, true); - }); - }); - } - } - - return lang.mixin(thisModule, { - dynamic:true, - normalize:normalize, - load:load, - cache:cache - }); -}); - -}, -'dijit/hccss':function(){ -define("dijit/hccss", ["dojo/dom-class", "dojo/hccss", "dojo/ready", "dojo/_base/window"], function(domClass, has, ready, win){ - - // module: - // dijit/hccss - - /*===== - return function(){ - // summary: - // Test if computer is in high contrast mode, and sets `dijit_a11y` flag on `<body>` if it is. - // Deprecated, use ``dojo/hccss`` instead. - }; - =====*/ - - // Priority is 90 to run ahead of parser priority of 100. For 2.0, remove the ready() call and instead - // change this module to depend on dojo/domReady! - ready(90, function(){ - if(has("highcontrast")){ - domClass.add(win.body(), "dijit_a11y"); - } - }); - - return has; -}); - -}, -'dijit/tree/ForestStoreModel':function(){ -define("dijit/tree/ForestStoreModel", [ - "dojo/_base/array", // array.indexOf array.some - "dojo/_base/declare", // declare - "dojo/_base/kernel", // global - "dojo/_base/lang", // lang.hitch - "./TreeStoreModel" -], function(array, declare, kernel, lang, TreeStoreModel){ - -// module: -// dijit/tree/ForestStoreModel - -return declare("dijit.tree.ForestStoreModel", TreeStoreModel, { - // summary: - // Interface between a dijit.Tree and a dojo.data store that doesn't have a root item, - // a.k.a. a store that has multiple "top level" items. - // - // description: - // Use this class to wrap a dojo.data store, making all the items matching the specified query - // appear as children of a fabricated "root item". If no query is specified then all the - // items returned by fetch() on the underlying store become children of the root item. - // This class allows dijit.Tree to assume a single root item, even if the store doesn't have one. - // - // When using this class the developer must override a number of methods according to their app and - // data, including: - // - // - onNewRootItem - // - onAddToRoot - // - onLeaveRoot - // - onNewItem - // - onSetItem - - // Parameters to constructor - - // rootId: String - // ID of fabricated root item - rootId: "$root$", - - // rootLabel: String - // Label of fabricated root item - rootLabel: "ROOT", - - // query: String - // Specifies the set of children of the root item. - // example: - // | {type:'continent'} - query: null, - - // End of parameters to constructor - - constructor: function(params){ - // summary: - // Sets up variables, etc. - // tags: - // private - - // Make dummy root item - this.root = { - store: this, - root: true, - id: params.rootId, - label: params.rootLabel, - children: params.rootChildren // optional param - }; - }, - - // ======================================================================= - // Methods for traversing hierarchy - - mayHaveChildren: function(/*dojo/data/Item*/ item){ - // summary: - // Tells if an item has or may have children. Implementing logic here - // avoids showing +/- expando icon for nodes that we know don't have children. - // (For efficiency reasons we may not want to check if an element actually - // has children until user clicks the expando node) - // tags: - // extension - return item === this.root || this.inherited(arguments); - }, - - getChildren: function(/*dojo/data/Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){ - // summary: - // Calls onComplete() with array of child items of given parent item, all loaded. - if(parentItem === this.root){ - if(this.root.children){ - // already loaded, just return - callback(this.root.children); - }else{ - this.store.fetch({ - query: this.query, - onComplete: lang.hitch(this, function(items){ - this.root.children = items; - callback(items); - }), - onError: onError - }); - } - }else{ - this.inherited(arguments); - } - }, - - // ======================================================================= - // Inspecting items - - isItem: function(/* anything */ something){ - return (something === this.root) ? true : this.inherited(arguments); - }, - - fetchItemByIdentity: function(/* object */ keywordArgs){ - if(keywordArgs.identity == this.root.id){ - var scope = keywordArgs.scope || kernel.global; - if(keywordArgs.onItem){ - keywordArgs.onItem.call(scope, this.root); - } - }else{ - this.inherited(arguments); - } - }, - - getIdentity: function(/* item */ item){ - return (item === this.root) ? this.root.id : this.inherited(arguments); - }, - - getLabel: function(/* item */ item){ - return (item === this.root) ? this.root.label : this.inherited(arguments); - }, - - // ======================================================================= - // Write interface - - newItem: function(/* dijit/tree/dndSource.__Item */ args, /*Item*/ parent, /*int?*/ insertIndex){ - // summary: - // Creates a new item. See dojo/data/api/Write for details on args. - // Used in drag & drop when item from external source dropped onto tree. - if(parent === this.root){ - this.onNewRootItem(args); - return this.store.newItem(args); - }else{ - return this.inherited(arguments); - } - }, - - onNewRootItem: function(/* dijit/tree/dndSource.__Item */ /*===== args =====*/){ - // summary: - // User can override this method to modify a new element that's being - // added to the root of the tree, for example to add a flag like root=true - }, - - pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){ - // summary: - // Move or copy an item from one parent item to another. - // Used in drag & drop - if(oldParentItem === this.root){ - if(!bCopy){ - // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches - // this.query... thus triggering an onChildrenChange() event to notify the Tree - // that this element is no longer a child of the root node - this.onLeaveRoot(childItem); - } - } - this.inherited(arguments, [childItem, - oldParentItem === this.root ? null : oldParentItem, - newParentItem === this.root ? null : newParentItem, - bCopy, - insertIndex - ]); - if(newParentItem === this.root){ - // It's onAddToRoot()'s responsibility to modify the item so it matches - // this.query... thus triggering an onChildrenChange() event to notify the Tree - // that this element is now a child of the root node - this.onAddToRoot(childItem); - } - }, - - // ======================================================================= - // Handling for top level children - - onAddToRoot: function(/* item */ item){ - // summary: - // Called when item added to root of tree; user must override this method - // to modify the item so that it matches the query for top level items - // example: - // | store.setValue(item, "root", true); - // tags: - // extension - console.log(this, ": item ", item, " added to root"); - }, - - onLeaveRoot: function(/* item */ item){ - // summary: - // Called when item removed from root of tree; user must override this method - // to modify the item so it doesn't match the query for top level items - // example: - // | store.unsetAttribute(item, "root"); - // tags: - // extension - console.log(this, ": item ", item, " removed from root"); - }, - - // ======================================================================= - // Events from data store - - _requeryTop: function(){ - // reruns the query for the children of the root node, - // sending out an onSet notification if those children have changed - var oldChildren = this.root.children || []; - this.store.fetch({ - query: this.query, - onComplete: lang.hitch(this, function(newChildren){ - this.root.children = newChildren; - - // If the list of children or the order of children has changed... - if(oldChildren.length != newChildren.length || - array.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){ - this.onChildrenChange(this.root, newChildren); - } - }) - }); - }, - - onNewItem: function(/* dojo/data/api/Item */ item, /* Object */ parentInfo){ - // summary: - // Handler for when new items appear in the store. Developers should override this - // method to be more efficient based on their app/data. - // description: - // Note that the default implementation requeries the top level items every time - // a new item is created, since any new item could be a top level item (even in - // addition to being a child of another item, since items can have multiple parents). - // - // If developers can detect which items are possible top level items (based on the item and the - // parentInfo parameters), they should override this method to only call _requeryTop() for top - // level items. Often all top level items have parentInfo==null, but - // that will depend on which store you use and what your data is like. - // tags: - // extension - this._requeryTop(); - - this.inherited(arguments); - }, - - onDeleteItem: function(/*Object*/ item){ - // summary: - // Handler for delete notifications from underlying store - - // check if this was a child of root, and if so send notification that root's children - // have changed - if(array.indexOf(this.root.children, item) != -1){ - this._requeryTop(); - } - - this.inherited(arguments); - }, - - onSetItem: function(/* item */ item, - /* attribute-name-string */ attribute, - /* Object|Array */ oldValue, - /* Object|Array */ newValue){ - // summary: - // Updates the tree view according to changes to an item in the data store. - // Developers should override this method to be more efficient based on their app/data. - // description: - // Handles updates to an item's children by calling onChildrenChange(), and - // other updates to an item by calling onChange(). - // - // Also, any change to any item re-executes the query for the tree's top-level items, - // since this modified item may have started/stopped matching the query for top level items. - // - // If possible, developers should override this function to only call _requeryTop() when - // the change to the item has caused it to stop/start being a top level item in the tree. - // tags: - // extension - - this._requeryTop(); - this.inherited(arguments); - } - -}); - -}); - -}, -'url:dijit/layout/templates/AccordionButton.html':"<div data-dojo-attach-event='onclick:_onTitleClick' class='dijitAccordionTitle' role=\"presentation\">\n\t<div data-dojo-attach-point='titleNode,focusNode' data-dojo-attach-event='onkeypress:_onTitleKeyPress'\n\t\t\tclass='dijitAccordionTitleFocus' role=\"tab\" aria-expanded=\"false\"\n\t\t><span class='dijitInline dijitAccordionArrow' role=\"presentation\"></span\n\t\t><span class='arrowTextUp' role=\"presentation\">+</span\n\t\t><span class='arrowTextDown' role=\"presentation\">-</span\n\t\t><img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" data-dojo-attach-point='iconNode' style=\"vertical-align: middle\" role=\"presentation\"/>\n\t\t<span role=\"presentation\" data-dojo-attach-point='titleTextNode' class='dijitAccordionText'></span>\n\t</div>\n</div>\n", -'dijit/form/_ComboBoxMenuMixin':function(){ -define("dijit/form/_ComboBoxMenuMixin", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/i18n", // i18n.getLocalization - "dojo/i18n!./nls/ComboBox" -], function(array, declare, domAttr, i18n){ - -// module: -// dijit/form/_ComboBoxMenuMixin - -return declare( "dijit.form._ComboBoxMenuMixin", null, { - // summary: - // Focus-less menu for internal use in `dijit/form/ComboBox` - // tags: - // private - - // _messages: Object - // Holds "next" and "previous" text for paging buttons on drop down - _messages: null, - - postMixInProperties: function(){ - this.inherited(arguments); - this._messages = i18n.getLocalization("dijit.form", "ComboBox", this.lang); - }, - - buildRendering: function(){ - this.inherited(arguments); - - // fill in template with i18n messages - this.previousButton.innerHTML = this._messages["previousMessage"]; - this.nextButton.innerHTML = this._messages["nextMessage"]; - }, - - _setValueAttr: function(/*Object*/ value){ - this.value = value; - this.onChange(value); - }, - - onClick: function(/*DomNode*/ node){ - if(node == this.previousButton){ - this._setSelectedAttr(null); - this.onPage(-1); - }else if(node == this.nextButton){ - this._setSelectedAttr(null); - this.onPage(1); - }else{ - this.onChange(node); - } - }, - - // stubs - onChange: function(/*Number*/ /*===== direction =====*/){ - // summary: - // Notifies ComboBox/FilteringSelect that user selected an option. - // tags: - // callback - }, - - onPage: function(/*Number*/ /*===== direction =====*/){ - // summary: - // Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page. - // tags: - // callback - }, - - onClose: function(){ - // summary: - // Callback from dijit.popup code to this widget, notifying it that it closed - // tags: - // private - this._setSelectedAttr(null); - }, - - _createOption: function(/*Object*/ item, labelFunc){ - // summary: - // Creates an option to appear on the popup menu subclassed by - // `dijit/form/FilteringSelect`. - - var menuitem = this._createMenuItem(); - var labelObject = labelFunc(item); - if(labelObject.html){ - menuitem.innerHTML = labelObject.label; - }else{ - menuitem.appendChild( - menuitem.ownerDocument.createTextNode(labelObject.label) - ); - } - // #3250: in blank options, assign a normal height - if(menuitem.innerHTML == ""){ - menuitem.innerHTML = " "; // - } - - // update menuitem.dir if BidiSupport was required - this.applyTextDir(menuitem, (menuitem.innerText || menuitem.textContent || "")); - - return menuitem; - }, - - createOptions: function(results, options, labelFunc){ - // summary: - // Fills in the items in the drop down list - // results: - // Array of items - // options: - // The options to the query function of the store - // - // labelFunc: - // Function to produce a label in the drop down list from a dojo.data item - - this.items = results; - - // display "Previous . . ." button - this.previousButton.style.display = (options.start == 0) ? "none" : ""; - domAttr.set(this.previousButton, "id", this.id + "_prev"); - // create options using _createOption function defined by parent - // ComboBox (or FilteringSelect) class - // #2309: - // iterate over cache nondestructively - array.forEach(results, function(item, i){ - var menuitem = this._createOption(item, labelFunc); - menuitem.setAttribute("item", i); // index to this.items; use indirection to avoid mem leak - domAttr.set(menuitem, "id", this.id + i); - this.nextButton.parentNode.insertBefore(menuitem, this.nextButton); - }, this); - // display "Next . . ." button - var displayMore = false; - // Try to determine if we should show 'more'... - if(results.total && !results.total.then && results.total != -1){ - if((options.start + options.count) < results.total){ - displayMore = true; - }else if((options.start + options.count) > results.total && options.count == results.length){ - // Weird return from a data store, where a start + count > maxOptions - // implies maxOptions isn't really valid and we have to go into faking it. - // And more or less assume more if count == results.length - displayMore = true; - } - }else if(options.count == results.length){ - //Don't know the size, so we do the best we can based off count alone. - //So, if we have an exact match to count, assume more. - displayMore = true; - } - - this.nextButton.style.display = displayMore ? "" : "none"; - domAttr.set(this.nextButton,"id", this.id + "_next"); - }, - - clearResultList: function(){ - // summary: - // Clears the entries in the drop down list, but of course keeps the previous and next buttons. - var container = this.containerNode; - while(container.childNodes.length > 2){ - container.removeChild(container.childNodes[container.childNodes.length-2]); - } - this._setSelectedAttr(null); - }, - - highlightFirstOption: function(){ - // summary: - // Highlight the first real item in the list (not Previous Choices). - this.selectFirstNode(); - }, - - highlightLastOption: function(){ - // summary: - // Highlight the last real item in the list (not More Choices). - this.selectLastNode(); - }, - - selectFirstNode: function(){ - this.inherited(arguments); - if(this.getHighlightedOption() == this.previousButton){ - this.selectNextNode(); - } - }, - - selectLastNode: function(){ - this.inherited(arguments); - if(this.getHighlightedOption() == this.nextButton){ - this.selectPreviousNode(); - } - }, - - getHighlightedOption: function(){ - return this.selected; - } -}); - -}); - -}, -'dijit/form/_SearchMixin':function(){ -define("dijit/form/_SearchMixin", [ - "dojo/data/util/filter", // patternToRegExp - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "dojo/_base/lang", // lang.clone lang.hitch - "dojo/query", // query - "dojo/sniff", // has("ie") - "dojo/string", // string.substitute - "dojo/when", - "../registry" // registry.byId -], function(filter, declare, event, keys, lang, query, has, string, when, registry){ - - // module: - // dijit/form/_SearchMixin - - - return declare("dijit.form._SearchMixin", null, { - // summary: - // A mixin that implements the base functionality to search a store based upon user-entered text such as - // with `dijit/form/ComboBox` or `dijit/form/FilteringSelect` - // tags: - // protected - - // pageSize: Integer - // Argument to data provider. - // Specifies maximum number of search results to return per query - pageSize: Infinity, - - // store: [const] dojo/store/api/Store - // Reference to data provider object used by this ComboBox. - // The store must accept an object hash of properties for its query. See `query` and `queryExpr` for details. - store: null, - - // fetchProperties: Object - // Mixin to the store's fetch. - // For example, to set the sort order of the ComboBox menu, pass: - // | { sort: [{attribute:"name",descending: true}] } - // To override the default queryOptions so that deep=false, do: - // | { queryOptions: {ignoreCase: true, deep: false} } - fetchProperties:{}, - - // query: Object - // A query that can be passed to `store` to initially filter the items. - // ComboBox overwrites any reference to the `searchAttr` and sets it to the `queryExpr` with the user's input substituted. - query: {}, - - // searchDelay: Integer - // Delay in milliseconds between when user types something and we start - // searching based on that value - searchDelay: 200, - - // searchAttr: String - // Search for items in the data store where this attribute (in the item) - // matches what the user typed - searchAttr: "name", - - // queryExpr: String - // This specifies what query is sent to the data store, - // based on what the user has typed. Changing this expression will modify - // whether the results are only exact matches, a "starting with" match, - // etc. - // dojo.data query expression pattern. - // `${0}` will be substituted for the user text. - // `*` is used for wildcards. - // `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is" - queryExpr: "${0}*", - - // ignoreCase: Boolean - // Set true if the query should ignore case when matching possible items - ignoreCase: true, - - _abortQuery: function(){ - // stop in-progress query - if(this.searchTimer){ - this.searchTimer = this.searchTimer.remove(); - } - if(this._queryDeferHandle){ - this._queryDeferHandle = this._queryDeferHandle.remove(); - } - if(this._fetchHandle){ - if(this._fetchHandle.abort){ - this._cancelingQuery = true; - this._fetchHandle.abort(); - this._cancelingQuery = false; - } - if(this._fetchHandle.cancel){ - this._cancelingQuery = true; - this._fetchHandle.cancel(); - this._cancelingQuery = false; - } - this._fetchHandle = null; - } - }, - - _processInput: function(/*Event*/ evt){ - // summary: - // Handles input (keyboard/paste) events - if(this.disabled || this.readOnly){ return; } - var key = evt.charOrCode; - - // except for cutting/pasting case - ctrl + x/v - if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 'x' && key != 'v')) || key == keys.SHIFT){ - return; // throw out weird key combinations and spurious events - } - - var doSearch = false; - this._prev_key_backspace = false; - - switch(key){ - case keys.DELETE: - case keys.BACKSPACE: - this._prev_key_backspace = true; - this._maskValidSubsetError = true; - doSearch = true; - break; - - default: - // Non char keys (F1-F12 etc..) shouldn't start a search.. - // Ascii characters and IME input (Chinese, Japanese etc.) should. - //IME input produces keycode == 229. - doSearch = typeof key == 'string' || key == 229; - } - if(doSearch){ - // need to wait a tad before start search so that the event - // bubbles through DOM and we have value visible - if(!this.store){ - this.onSearch(); - }else{ - this.searchTimer = this.defer("_startSearchFromInput", 1); - } - } - }, - - onSearch: function(/*===== results, query, options =====*/){ - // summary: - // Callback when a search completes. - // - // results: Object - // An array of items from the originating _SearchMixin's store. - // - // query: Object - // A copy of the originating _SearchMixin's query property. - // - // options: Object - // The additional parameters sent to the originating _SearchMixin's store, including: start, count, queryOptions. - // - // tags: - // callback - }, - - _startSearchFromInput: function(){ - this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1")); - }, - - _startSearch: function(/*String*/ text){ - // summary: - // Starts a search for elements matching text (text=="" means to return all items), - // and calls onSearch(...) when the search completes, to display the results. - - this._abortQuery(); - var - _this = this, - // Setup parameters to be passed to store.query(). - // Create a new query to prevent accidentally querying for a hidden - // value from FilteringSelect's keyField - query = lang.clone(this.query), // #5970 - options = { - start: 0, - count: this.pageSize, - queryOptions: { // remove for 2.0 - ignoreCase: this.ignoreCase, - deep: true - } - }, - qs = string.substitute(this.queryExpr, [text]), - q, - startQuery = function(){ - var resPromise = _this._fetchHandle = _this.store.query(query, options); - if(_this.disabled || _this.readOnly || (q !== _this._lastQuery)){ - return; - } // avoid getting unwanted notify - when(resPromise, function(res){ - _this._fetchHandle = null; - if(!_this.disabled && !_this.readOnly && (q === _this._lastQuery)){ // avoid getting unwanted notify - when(resPromise.total, function(total){ - res.total = total; - var pageSize = _this.pageSize; - if(isNaN(pageSize) || pageSize > res.total){ pageSize = res.total; } - // Setup method to fetching the next page of results - res.nextPage = function(direction){ - // tell callback the direction of the paging so the screen - // reader knows which menu option to shout - options.direction = direction = direction !== false; - options.count = pageSize; - if(direction){ - options.start += res.length; - if(options.start >= res.total){ - options.count = 0; - } - }else{ - options.start -= pageSize; - if(options.start < 0){ - options.count = Math.max(pageSize + options.start, 0); - options.start = 0; - } - } - if(options.count <= 0){ - res.length = 0; - _this.onSearch(res, query, options); - }else{ - startQuery(); - } - }; - _this.onSearch(res, query, options); - }); - } - }, function(err){ - _this._fetchHandle = null; - if(!_this._cancelingQuery){ // don't treat canceled query as an error - console.error(_this.declaredClass + ' ' + err.toString()); - } - }); - }; - - lang.mixin(options, this.fetchProperties); - - // Generate query - if(this.store._oldAPI){ - // remove this branch for 2.0 - q = qs; - }else{ - // Query on searchAttr is a regex for benefit of dojo/store/Memory, - // but with a toString() method to help dojo/store/JsonRest. - // Search string like "Co*" converted to regex like /^Co.*$/i. - q = filter.patternToRegExp(qs, this.ignoreCase); - q.toString = function(){ return qs; }; - } - - // set _lastQuery, *then* start the timeout - // otherwise, if the user types and the last query returns before the timeout, - // _lastQuery won't be set and their input gets rewritten - this._lastQuery = query[this.searchAttr] = q; - this._queryDeferHandle = this.defer(startQuery, this.searchDelay); - }, - - //////////// INITIALIZATION METHODS /////////////////////////////////////// - - constructor: function(){ - this.query={}; - this.fetchProperties={}; - }, - - postMixInProperties: function(){ - if(!this.store){ - var list = this.list; - if(list){ - this.store = registry.byId(list); - } - } - this.inherited(arguments); - } - }); -}); - -}, -'dojo/parser':function(){ -define( - "dojo/parser", ["require", "./_base/kernel", "./_base/lang", "./_base/array", "./_base/config", "./_base/html", "./_base/window", - "./_base/url", "./_base/json", "./aspect", "./date/stamp", "./Deferred", "./has", "./query", "./on", "./ready"], - function(require, dojo, dlang, darray, config, dhtml, dwindow, _Url, djson, aspect, dates, Deferred, has, query, don, ready){ - - // module: - // dojo/parser - - new Date("X"); // workaround for #11279, new Date("") == NaN - - - // Widgets like BorderContainer add properties to _Widget via dojo.extend(). - // If BorderContainer is loaded after _Widget's parameter list has been cached, - // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget). - var extendCnt = 0; - aspect.after(dlang, "extend", function(){ - extendCnt++; - }, true); - - function getNameMap(ctor){ - // summary: - // Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"} - var map = ctor._nameCaseMap, proto = ctor.prototype; - - // Create the map if it's undefined. - // Refresh the map if a superclass was possibly extended with new methods since the map was created. - if(!map || map._extendCnt < extendCnt){ - map = ctor._nameCaseMap = {}; - for(var name in proto){ - if(name.charAt(0) === "_"){ continue; } // skip internal properties - map[name.toLowerCase()] = name; - } - map._extendCnt = extendCnt; - } - return map; - } - - // Map from widget name or list of widget names(ex: "dijit/form/Button,acme/MyMixin") to a constructor. - var _ctorMap = {}; - - function getCtor(/*String[]*/ types){ - // summary: - // Retrieves a constructor. If the types array contains more than one class/MID then the - // subsequent classes will be mixed into the first class and a unique constructor will be - // returned for that array. - - var ts = types.join(); - if(!_ctorMap[ts]){ - var mixins = []; - for(var i = 0, l = types.length; i < l; i++){ - var t = types[i]; - // TODO: Consider swapping getObject and require in the future - mixins[mixins.length] = (_ctorMap[t] = _ctorMap[t] || (dlang.getObject(t) || (~t.indexOf('/') && require(t)))); - } - var ctor = mixins.shift(); - _ctorMap[ts] = mixins.length ? (ctor.createSubclass ? ctor.createSubclass(mixins) : ctor.extend.apply(ctor, mixins)) : ctor; - } - - return _ctorMap[ts]; - } - - var parser = { - // summary: - // The Dom/Widget parsing package - - _clearCache: function(){ - // summary: - // Clear cached data. Used mainly for benchmarking. - extendCnt++; - _ctorMap = {}; - }, - - _functionFromScript: function(script, attrData){ - // summary: - // Convert a `<script type="dojo/method" args="a, b, c"> ... </script>` - // into a function - // script: DOMNode - // The `<script>` DOMNode - // attrData: String - // For HTML5 compliance, searches for attrData + "args" (typically - // "data-dojo-args") instead of "args" - var preamble = "", - suffix = "", - argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args")), - withStr = script.getAttribute("with"); - - // Convert any arguments supplied in script tag into an array to be passed to the - var fnArgs = (argsStr || "").split(/\s*,\s*/); - - if(withStr && withStr.length){ - darray.forEach(withStr.split(/\s*,\s*/), function(part){ - preamble += "with("+part+"){"; - suffix += "}"; - }); - } - - return new Function(fnArgs, preamble + script.innerHTML + suffix); - }, - - instantiate: function(nodes, mixin, options){ - // summary: - // Takes array of nodes, and turns them into class instances and - // potentially calls a startup method to allow them to connect with - // any children. - // nodes: Array - // Array of DOM nodes - // mixin: Object? - // An object that will be mixed in with each node in the array. - // Values in the mixin will override values in the node, if they - // exist. - // options: Object? - // An object used to hold kwArgs for instantiation. - // See parse.options argument for details. - - mixin = mixin || {}; - options = options || {}; - - var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType" - attrData = "data-" + (options.scope || dojo._scopeName) + "-",// typically "data-dojo-" - dataDojoType = attrData + "type", // typically "data-dojo-type" - dataDojoMixins = attrData + "mixins"; // typically "data-dojo-mixins" - - var list = []; - darray.forEach(nodes, function(node){ - var type = dojoType in mixin ? mixin[dojoType] : node.getAttribute(dataDojoType) || node.getAttribute(dojoType); - if(type){ - var mixinsValue = node.getAttribute(dataDojoMixins), - types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type]; - - list.push({ - node: node, - types: types - }); - } - }); - - // Instantiate the nodes and return the objects - return this._instantiate(list, mixin, options); - }, - - _instantiate: function(nodes, mixin, options){ - // summary: - // Takes array of objects representing nodes, and turns them into class instances and - // potentially calls a startup method to allow them to connect with - // any children. - // nodes: Array - // Array of objects like - // | { - // | ctor: Function (may be null) - // | types: ["dijit/form/Button", "acme/MyMixin"] (used if ctor not specified) - // | node: DOMNode, - // | scripts: [ ... ], // array of <script type="dojo/..."> children of node - // | inherited: { ... } // settings inherited from ancestors like dir, theme, etc. - // | } - // mixin: Object - // An object that will be mixed in with each node in the array. - // Values in the mixin will override values in the node, if they - // exist. - // options: Object - // An options object used to hold kwArgs for instantiation. - // See parse.options argument for details. - - // Call widget constructors - var thelist = darray.map(nodes, function(obj){ - var ctor = obj.ctor || getCtor(obj.types); - // If we still haven't resolved a ctor, it is fatal now - if(!ctor){ - throw new Error("Unable to resolve constructor for: '" + obj.types.join() + "'"); - } - return this.construct(ctor, obj.node, mixin, options, obj.scripts, obj.inherited); - }, this); - - // Call startup on each top level instance if it makes sense (as for - // widgets). Parent widgets will recursively call startup on their - // (non-top level) children - if(!mixin._started && !options.noStart){ - darray.forEach(thelist, function(instance){ - if(typeof instance.startup === "function" && !instance._started){ - instance.startup(); - } - }); - } - - return thelist; - }, - - construct: function(ctor, node, mixin, options, scripts, inherited){ - // summary: - // Calls new ctor(params, node), where params is the hash of parameters specified on the node, - // excluding data-dojo-type and data-dojo-mixins. Does not call startup(). Returns the widget. - // ctor: Function - // Widget constructor. - // node: DOMNode - // This node will be replaced/attached to by the widget. It also specifies the arguments to pass to ctor. - // mixin: Object? - // Attributes in this object will be passed as parameters to ctor, - // overriding attributes specified on the node. - // options: Object? - // An options object used to hold kwArgs for instantiation. See parse.options argument for details. - // scripts: DomNode[]? - // Array of `<script type="dojo/*">` DOMNodes. If not specified, will search for `<script>` tags inside node. - // inherited: Object? - // Settings from dir=rtl or lang=... on a node above this node. Overrides options.inherited. - - var proto = ctor && ctor.prototype; - options = options || {}; - - // Setup hash to hold parameter settings for this widget. Start with the parameter - // settings inherited from ancestors ("dir" and "lang"). - // Inherited setting may later be overridden by explicit settings on node itself. - var params = {}; - - if(options.defaults){ - // settings for the document itself (or whatever subtree is being parsed) - dlang.mixin(params, options.defaults); - } - if(inherited){ - // settings from dir=rtl or lang=... on a node above this node - dlang.mixin(params, inherited); - } - - // Get list of attributes explicitly listed in the markup - var attributes; - if(has("dom-attributes-explicit")){ - // Standard path to get list of user specified attributes - attributes = node.attributes; - }else if(has("dom-attributes-specified-flag")){ - // Special processing needed for IE8, to skip a few faux values in attributes[] - attributes = darray.filter(node.attributes, function(a){ return a.specified;}); - }else{ - // Special path for IE6-7, avoid (sometimes >100) bogus entries in node.attributes - var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false), - attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*\s*/, "").replace(/\s*>.*$/, ""); - - attributes = darray.map(attrs.split(/\s+/), function(name){ - var lcName = name.toLowerCase(); - return { - name: name, - // getAttribute() doesn't work for button.value, returns innerHTML of button. - // but getAttributeNode().value doesn't work for the form.encType or li.value - value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ? - node.getAttribute(lcName) : node.getAttributeNode(lcName).value - }; - }); - } - - // Hash to convert scoped attribute name (ex: data-dojo17-params) to something friendly (ex: data-dojo-params) - // TODO: remove scope for 2.0 - var scope = options.scope || dojo._scopeName, - attrData = "data-" + scope + "-", // typically "data-dojo-" - hash = {}; - if(scope !== "dojo"){ - hash[attrData + "props"] = "data-dojo-props"; - hash[attrData + "type"] = "data-dojo-type"; - hash[attrData + "mixins"] = "data-dojo-mixins"; - hash[scope + "type"] = "dojoType"; - hash[attrData + "id"] = "data-dojo-id"; - } - - // Read in attributes and process them, including data-dojo-props, data-dojo-type, - // dojoAttachPoint, etc., as well as normal foo=bar attributes. - var i=0, item, funcAttrs=[], jsname, extra; - while(item = attributes[i++]){ - var name = item.name, - lcName = name.toLowerCase(), - value = item.value; - - switch(hash[lcName] || lcName){ - // Already processed, just ignore - case "data-dojo-type": - case "dojotype": - case "data-dojo-mixins": - break; - - // Data-dojo-props. Save for later to make sure it overrides direct foo=bar settings - case "data-dojo-props": - extra = value; - break; - - // data-dojo-id or jsId. TODO: drop jsId in 2.0 - case "data-dojo-id": - case "jsid": - jsname = value; - break; - - // For the benefit of _Templated - case "data-dojo-attach-point": - case "dojoattachpoint": - params.dojoAttachPoint = value; - break; - case "data-dojo-attach-event": - case "dojoattachevent": - params.dojoAttachEvent = value; - break; - - // Special parameter handling needed for IE - case "class": - params["class"] = node.className; - break; - case "style": - params["style"] = node.style && node.style.cssText; - break; - default: - // Normal attribute, ex: value="123" - - // Find attribute in widget corresponding to specified name. - // May involve case conversion, ex: onclick --> onClick - if(!(name in proto)){ - var map = getNameMap(ctor); - name = map[lcName] || name; - } - - // Set params[name] to value, doing type conversion - if(name in proto){ - switch(typeof proto[name]){ - case "string": - params[name] = value; - break; - case "number": - params[name] = value.length ? Number(value) : NaN; - break; - case "boolean": - // for checked/disabled value might be "" or "checked". interpret as true. - params[name] = value.toLowerCase() != "false"; - break; - case "function": - if(value === "" || value.search(/[^\w\.]+/i) != -1){ - // The user has specified some text for a function like "return x+5" - params[name] = new Function(value); - }else{ - // The user has specified the name of a global function like "myOnClick" - // or a single word function "return" - params[name] = dlang.getObject(value, false) || new Function(value); - } - funcAttrs.push(name); // prevent "double connect", see #15026 - break; - default: - var pVal = proto[name]; - params[name] = - (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) : // array - (pVal instanceof Date) ? - (value == "" ? new Date("") : // the NaN of dates - value == "now" ? new Date() : // current date - dates.fromISOString(value)) : - (pVal instanceof _Url) ? (dojo.baseUrl + value) : - djson.fromJson(value); - } - }else{ - params[name] = value; - } - } - } - - // Remove function attributes from DOMNode to prevent "double connect" problem, see #15026. - // Do this as a separate loop since attributes[] is often a live collection (depends on the browser though). - for(var j=0; j<funcAttrs.length; j++){ - var lcfname = funcAttrs[j].toLowerCase(); - node.removeAttribute(lcfname); - node[lcfname] = null; - } - - // Mix things found in data-dojo-props into the params, overriding any direct settings - if(extra){ - try{ - extra = djson.fromJson.call(options.propsThis, "{" + extra + "}"); - dlang.mixin(params, extra); - }catch(e){ - // give the user a pointer to their invalid parameters. FIXME: can we kill this in production? - throw new Error(e.toString() + " in data-dojo-props='" + extra + "'"); - } - } - - // Any parameters specified in "mixin" override everything else. - dlang.mixin(params, mixin); - - // Get <script> nodes associated with this widget, if they weren't specified explicitly - if(!scripts){ - scripts = (ctor && (ctor._noScript || proto._noScript) ? [] : query("> script[type^='dojo/']", node)); - } - - // Process <script type="dojo/*"> script tags - // <script type="dojo/method" event="foo"> tags are added to params, and passed to - // the widget on instantiation. - // <script type="dojo/method"> tags (with no event) are executed after instantiation - // <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation - // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation - // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation - // note: dojo/* script tags cannot exist in self closing widgets, like <input /> - var aspects = [], // aspects to connect after instantiation - calls = [], // functions to call after instantiation - watches = [], // functions to watch after instantiation - ons = []; // functions to on after instantiation - - if(scripts){ - for(i=0; i<scripts.length; i++){ - var script = scripts[i]; - node.removeChild(script); - // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead - var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")), - prop = script.getAttribute(attrData + "prop"), - method = script.getAttribute(attrData + "method"), - advice = script.getAttribute(attrData + "advice"), - scriptType = script.getAttribute("type"), - nf = this._functionFromScript(script, attrData); - if(event){ - if(scriptType == "dojo/connect"){ - aspects.push({ method: event, func: nf }); - }else if(scriptType == "dojo/on"){ - ons.push({ event: event, func: nf }); - }else{ - params[event] = nf; - } - }else if(scriptType == "dojo/aspect"){ - aspects.push({ method: method, advice: advice, func: nf }); - }else if(scriptType == "dojo/watch"){ - watches.push({ prop: prop, func: nf }); - }else{ - calls.push(nf); - } - } - } - - // create the instance - var markupFactory = ctor.markupFactory || proto.markupFactory; - var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node); - - // map it to the JS namespace if that makes sense - if(jsname){ - dlang.setObject(jsname, instance); - } - - // process connections and startup functions - for(i=0; i<aspects.length; i++){ - aspect[aspects[i].advice || "after"](instance, aspects[i].method, dlang.hitch(instance, aspects[i].func), true); - } - for(i=0; i<calls.length; i++){ - calls[i].call(instance); - } - for(i=0; i<watches.length; i++){ - instance.watch(watches[i].prop, watches[i].func); - } - for(i=0; i<ons.length; i++){ - don(instance, ons[i].event, ons[i].func); - } - - return instance; - }, - - scan: function(root, options){ - // summary: - // Scan a DOM tree and return an array of objects representing the DOMNodes - // that need to be turned into widgets. - // description: - // Search specified node (or document root node) recursively for class instances - // and return an array of objects that represent potential widgets to be - // instantiated. Searches for either data-dojo-type="MID" or dojoType="MID" where - // "MID" is a module ID like "dijit/form/Button" or a fully qualified Class name - // like "dijit/form/Button". If the MID is not currently available, scan will - // attempt to require() in the module. - // - // See parser.parse() for details of markup. - // root: DomNode? - // A default starting root node from which to start the parsing. Can be - // omitted, defaulting to the entire document. If omitted, the `options` - // object can be passed in this place. If the `options` object has a - // `rootNode` member, that is used. - // options: Object - // a kwArgs options object, see parse() for details - // - // returns: Promise - // A promise that is resolved with the nodes that have been parsed. - - var list = [], // Output List - mids = [], // An array of modules that are not yet loaded - midsHash = {}; // Used to keep the mids array unique - - var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType" - attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-" - dataDojoType = attrData + "type", // typically "data-dojo-type" - dataDojoTextDir = attrData + "textdir", // typically "data-dojo-textdir" - dataDojoMixins = attrData + "mixins"; // typically "data-dojo-mixins" - - // Info on DOMNode currently being processed - var node = root.firstChild; - - // Info on parent of DOMNode currently being processed - // - inherited: dir, lang, and textDir setting of parent, or inherited by parent - // - parent: pointer to identical structure for my parent (or null if no parent) - // - scripts: if specified, collects <script type="dojo/..."> type nodes from children - var inherited = options.inherited; - if(!inherited){ - function findAncestorAttr(node, attr){ - return (node.getAttribute && node.getAttribute(attr)) || - (node.parentNode && findAncestorAttr(node.parentNode, attr)); - } - inherited = { - dir: findAncestorAttr(root, "dir"), - lang: findAncestorAttr(root, "lang"), - textDir: findAncestorAttr(root, dataDojoTextDir) - }; - for(var key in inherited){ - if(!inherited[key]){ delete inherited[key]; } - } - } - - // Metadata about parent node - var parent = { - inherited: inherited - }; - - // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect) - var scripts; - - // when true, only look for <script type="dojo/..."> tags, and don't recurse to children - var scriptsOnly; - - function getEffective(parent){ - // summary: - // Get effective dir, lang, textDir settings for specified obj - // (matching "parent" object structure above), and do caching. - // Take care not to return null entries. - if(!parent.inherited){ - parent.inherited = {}; - var node = parent.node, - grandparent = getEffective(parent.parent); - var inherited = { - dir: node.getAttribute("dir") || grandparent.dir, - lang: node.getAttribute("lang") || grandparent.lang, - textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir - }; - for(var key in inherited){ - if(inherited[key]){ - parent.inherited[key] = inherited[key]; - } - } - } - return parent.inherited; - } - - // DFS on DOM tree, collecting nodes with data-dojo-type specified. - while(true){ - if(!node){ - // Finished this level, continue to parent's next sibling - if(!parent || !parent.node){ - break; - } - node = parent.node.nextSibling; - scriptsOnly = false; - parent = parent.parent; - scripts = parent.scripts; - continue; - } - - if(node.nodeType != 1){ - // Text or comment node, skip to next sibling - node = node.nextSibling; - continue; - } - - if(scripts && node.nodeName.toLowerCase() == "script"){ - // Save <script type="dojo/..."> for parent, then continue to next sibling - type = node.getAttribute("type"); - if(type && /^dojo\/\w/i.test(type)){ - scripts.push(node); - } - node = node.nextSibling; - continue; - } - if(scriptsOnly){ - // scriptsOnly flag is set, we have already collected scripts if the parent wants them, so now we shouldn't - // continue further analysis of the node and will continue to the next sibling - node = node.nextSibling; - continue; - } - - // Check for data-dojo-type attribute, fallback to backward compatible dojoType - // TODO: Remove dojoType in 2.0 - var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType); - - // Short circuit for leaf nodes containing nothing [but text] - var firstChild = node.firstChild; - if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){ - node = node.nextSibling; - continue; - } - - // Meta data about current node - var current; - - var ctor = null; - if(type){ - // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate. - var mixinsValue = node.getAttribute(dataDojoMixins), - types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type]; - - // Note: won't find classes declared via dojo/Declaration or any modules that haven't been - // loaded yet so use try/catch to avoid throw from require() - try{ - ctor = getCtor(types); - }catch(e){} - - // If the constructor was not found, check to see if it has modules that can be loaded - if(!ctor){ - darray.forEach(types, function(t){ - if(~t.indexOf('/') && !midsHash[t]){ - // If the type looks like a MID and it currently isn't in the array of MIDs to load, add it. - midsHash[t] = true; - mids[mids.length] = t; - } - }); - } - - var childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children - - // Setup meta data about this widget node, and save it to list of nodes to instantiate - current = { - types: types, - ctor: ctor, - parent: parent, - node: node, - scripts: childScripts - }; - current.inherited = getEffective(current); // dir & lang settings for current node, explicit or inherited - list.push(current); - }else{ - // Meta data about this non-widget node - current = { - node: node, - scripts: scripts, - parent: parent - }; - } - - // Recurse, collecting <script type="dojo/..."> children, and also looking for - // descendant nodes with dojoType specified (unless the widget has the stopParser flag). - // When finished with children, go to my next sibling. - node = firstChild; - scripts = childScripts; - scriptsOnly = ctor && ctor.prototype.stopParser && !(options.template); - parent = current; - } - - var d = new Deferred(); - - // If there are modules to load then require them in - if(mids.length){ - // Warn that there are modules being auto-required - if(has("dojo-debug-messages")){ - console.warn("WARNING: Modules being Auto-Required: " + mids.join(", ")); - } - require(mids, function(){ - // Go through list of widget nodes, filling in missing constructors, and filtering out nodes that shouldn't - // be instantiated due to a stopParser flag on an ancestor that we belatedly learned about due to - // auto-require of a module like ContentPane. Assumes list is in DFS order. - d.resolve(darray.filter(list, function(widget){ - if(!widget.ctor){ - // Attempt to find the constructor again. Still won't find classes defined via - // dijit/Declaration so need to try/catch. - try{ - widget.ctor = getCtor(widget.types); - }catch(e){} - } - - // Get the parent widget - var parent = widget.parent; - while(parent && !parent.types){ - parent = parent.parent; - } - - // Return false if this node should be skipped due to stopParser on an ancestor. - // Since list[] is in DFS order, this loop will always set parent.instantiateChildren before - // trying to compute widget.instantiate. - var proto = widget.ctor && widget.ctor.prototype; - widget.instantiateChildren = !(proto && proto.stopParser && !(options.template)); - widget.instantiate = !parent || (parent.instantiate && parent.instantiateChildren); - return widget.instantiate; - })); - }); - }else{ - // There were no modules to load, so just resolve with the parsed nodes. This separate code path is for - // efficiency, to avoid running the require() and the callback code above. - d.resolve(list); - } - - // Return the promise - return d.promise; - }, - - _require: function(/*DOMNode*/ script){ - // summary: - // Helper for _scanAMD(). Takes a `<script type=dojo/require>bar: "acme/bar", ...</script>` node, - // calls require() to load the specified modules and (asynchronously) assign them to the specified global - // variables, and returns a Promise for when that operation completes. - // - // In the example above, it is effectively doing a require(["acme/bar", ...], function(a){ bar = a; }). - - var hash = djson.fromJson("{" + script.innerHTML + "}"), - vars = [], - mids = [], - d = new Deferred(); - - for(var name in hash){ - vars.push(name); - mids.push(hash[name]); - } - - require(mids, function(){ - for(var i=0; i<vars.length; i++){ - dlang.setObject(vars[i], arguments[i]); - } - d.resolve(arguments); - }); - - return d.promise; - }, - - _scanAmd: function(root){ - // summary: - // Scans the DOM for any declarative requires and returns their values. - // description: - // Looks for `<script type=dojo/require>bar: "acme/bar", ...</script>` node, calls require() to load the - // specified modules and (asynchronously) assign them to the specified global variables, - // and returns a Promise for when those operations complete. - // root: DomNode - // The node to base the scan from. - - // Promise that resolves when all the <script type=dojo/require> nodes have finished loading. - var deferred = new Deferred(), - promise = deferred.promise; - deferred.resolve(true); - - var self = this; - query("script[type='dojo/require']", root).forEach(function(node){ - // Fire off require() call for specified modules. Chain this require to fire after - // any previous requires complete, so that layers can be loaded before individual module require()'s fire. - promise = promise.then(function(){ return self._require(node); }); - - // Remove from DOM so it isn't seen again - node.parentNode.removeChild(node); - }); - - return promise; - }, - - parse: function(rootNode, options){ - // summary: - // Scan the DOM for class instances, and instantiate them. - // description: - // Search specified node (or root node) recursively for class instances, - // and instantiate them. Searches for either data-dojo-type="Class" or - // dojoType="Class" where "Class" is a a fully qualified class name, - // like `dijit/form/Button` - // - // Using `data-dojo-type`: - // Attributes using can be mixed into the parameters used to instantiate the - // Class by using a `data-dojo-props` attribute on the node being converted. - // `data-dojo-props` should be a string attribute to be converted from JSON. - // - // Using `dojoType`: - // Attributes are read from the original domNode and converted to appropriate - // types by looking up the Class prototype values. This is the default behavior - // from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will - // go away in Dojo 2.0. - // rootNode: DomNode? - // A default starting root node from which to start the parsing. Can be - // omitted, defaulting to the entire document. If omitted, the `options` - // object can be passed in this place. If the `options` object has a - // `rootNode` member, that is used. - // options: Object? - // A hash of options. - // - // - noStart: Boolean?: - // when set will prevent the parser from calling .startup() - // when locating the nodes. - // - rootNode: DomNode?: - // identical to the function's `rootNode` argument, though - // allowed to be passed in via this `options object. - // - template: Boolean: - // If true, ignores ContentPane's stopParser flag and parses contents inside of - // a ContentPane inside of a template. This allows dojoAttachPoint on widgets/nodes - // nested inside the ContentPane to work. - // - inherited: Object: - // Hash possibly containing dir and lang settings to be applied to - // parsed widgets, unless there's another setting on a sub-node that overrides - // - scope: String: - // Root for attribute names to search for. If scopeName is dojo, - // will search for data-dojo-type (or dojoType). For backwards compatibility - // reasons defaults to dojo._scopeName (which is "dojo" except when - // multi-version support is used, when it will be something like dojo16, dojo20, etc.) - // - propsThis: Object: - // If specified, "this" referenced from data-dojo-props will refer to propsThis. - // Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin` - // returns: Mixed - // Returns a blended object that is an array of the instantiated objects, but also can include - // a promise that is resolved with the instantiated objects. This is done for backwards - // compatibility. If the parser auto-requires modules, it will always behave in a promise - // fashion and `parser.parse().then(function(instances){...})` should be used. - // example: - // Parse all widgets on a page: - // | parser.parse(); - // example: - // Parse all classes within the node with id="foo" - // | parser.parse(dojo.byId('foo')); - // example: - // Parse all classes in a page, but do not call .startup() on any - // child - // | parser.parse({ noStart: true }) - // example: - // Parse all classes in a node, but do not call .startup() - // | parser.parse(someNode, { noStart:true }); - // | // or - // | parser.parse({ noStart:true, rootNode: someNode }); - - // determine the root node and options based on the passed arguments. - var root; - if(!options && rootNode && rootNode.rootNode){ - options = rootNode; - root = options.rootNode; - }else if(rootNode && dlang.isObject(rootNode) && !("nodeType" in rootNode)){ - options = rootNode; - }else{ - root = rootNode; - } - root = root ? dhtml.byId(root) : dwindow.body(); - - options = options || {}; - - var mixin = options.template ? { template: true } : {}, - instances = [], - self = this; - - // First scan for any <script type=dojo/require> nodes, and execute. - // Then scan for all nodes with data-dojo-type, and load any unloaded modules. - // Then build the object instances. Add instances to already existing (but empty) instances[] array, - // which may already have been returned to caller. Also, use otherwise to collect and throw any errors - // that occur during the parse(). - var p = - this._scanAmd(root, options).then(function(){ - return self.scan(root, options); - }).then(function(parsedNodes){ - return instances = instances.concat(self._instantiate(parsedNodes, mixin, options)); - }).otherwise(function(e){ - // TODO Modify to follow better pattern for promise error managment when available - console.error("dojo/parser::parse() error", e); - throw e; - }); - - // Blend the array with the promise - dlang.mixin(instances, p); - return instances; - } - }; - - if( 1 ){ - dojo.parser = parser; - } - - // Register the parser callback. It should be the first callback - // after the a11y test. - if(config.parseOnLoad){ - ready(100, parser, "parse"); - } - - return parser; -}); - -}, -'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">▼</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\" role=\"presentation\"\n/></span>\n", -'dojo/dnd/Manager':function(){ -define("dojo/dnd/Manager", [ - "../_base/array", "../_base/declare", "../_base/event", "../_base/lang", "../_base/window", - "../dom-class", "../Evented", "../has", "../keys", "../on", "../topic", "../touch", - "./common", "./autoscroll", "./Avatar" -], function(array, declare, event, lang, win, domClass, Evented, has, keys, on, topic, touch, - dnd, autoscroll, Avatar){ - -// module: -// dojo/dnd/Manager - -var Manager = declare("dojo.dnd.Manager", [Evented], { - // summary: - // the manager of DnD operations (usually a singleton) - constructor: function(){ - this.avatar = null; - this.source = null; - this.nodes = []; - this.copy = true; - this.target = null; - this.canDropFlag = false; - this.events = []; - }, - - // avatar's offset from the mouse - OFFSET_X: has("touch") ? 0 : 16, - OFFSET_Y: has("touch") ? -64 : 16, - - // methods - overSource: function(source){ - // summary: - // called when a source detected a mouse-over condition - // source: Object - // the reporter - if(this.avatar){ - this.target = (source && source.targetState != "Disabled") ? source : null; - this.canDropFlag = Boolean(this.target); - this.avatar.update(); - } - topic.publish("/dnd/source/over", source); - }, - outSource: function(source){ - // summary: - // called when a source detected a mouse-out condition - // source: Object - // the reporter - if(this.avatar){ - if(this.target == source){ - this.target = null; - this.canDropFlag = false; - this.avatar.update(); - topic.publish("/dnd/source/over", null); - } - }else{ - topic.publish("/dnd/source/over", null); - } - }, - startDrag: function(source, nodes, copy){ - // summary: - // called to initiate the DnD operation - // source: Object - // the source which provides items - // nodes: Array - // the list of transferred items - // copy: Boolean - // copy items, if true, move items otherwise - - // Tell autoscroll that a drag is starting - autoscroll.autoScrollStart(win.doc); - - this.source = source; - this.nodes = nodes; - this.copy = Boolean(copy); // normalizing to true boolean - this.avatar = this.makeAvatar(); - win.body().appendChild(this.avatar.node); - topic.publish("/dnd/start", source, nodes, this.copy); - this.events = [ - on(win.doc, touch.move, lang.hitch(this, "onMouseMove")), - on(win.doc, touch.release, lang.hitch(this, "onMouseUp")), - on(win.doc, "keydown", lang.hitch(this, "onKeyDown")), - on(win.doc, "keyup", lang.hitch(this, "onKeyUp")), - // cancel text selection and text dragging - on(win.doc, "dragstart", event.stop), - on(win.body(), "selectstart", event.stop) - ]; - var c = "dojoDnd" + (copy ? "Copy" : "Move"); - domClass.add(win.body(), c); - }, - canDrop: function(flag){ - // summary: - // called to notify if the current target can accept items - var canDropFlag = Boolean(this.target && flag); - if(this.canDropFlag != canDropFlag){ - this.canDropFlag = canDropFlag; - this.avatar.update(); - } - }, - stopDrag: function(){ - // summary: - // stop the DnD in progress - domClass.remove(win.body(), ["dojoDndCopy", "dojoDndMove"]); - array.forEach(this.events, function(handle){ handle.remove(); }); - this.events = []; - this.avatar.destroy(); - this.avatar = null; - this.source = this.target = null; - this.nodes = []; - }, - makeAvatar: function(){ - // summary: - // makes the avatar; it is separate to be overwritten dynamically, if needed - return new Avatar(this); - }, - updateAvatar: function(){ - // summary: - // updates the avatar; it is separate to be overwritten dynamically, if needed - this.avatar.update(); - }, - - // mouse event processors - onMouseMove: function(e){ - // summary: - // event processor for onmousemove - // e: Event - // mouse event - var a = this.avatar; - if(a){ - autoscroll.autoScrollNodes(e); - //autoscroll.autoScroll(e); - var s = a.node.style; - s.left = (e.pageX + this.OFFSET_X) + "px"; - s.top = (e.pageY + this.OFFSET_Y) + "px"; - var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e))); - if(this.copy != copy){ - this._setCopyStatus(copy); - } - } - if(has("touch")){ - // Prevent page from scrolling so that user can drag instead. - e.preventDefault(); - } - }, - onMouseUp: function(e){ - // summary: - // event processor for onmouseup - // e: Event - // mouse event - if(this.avatar){ - if(this.target && this.canDropFlag){ - var copy = Boolean(this.source.copyState(dnd.getCopyKeyState(e))); - topic.publish("/dnd/drop/before", this.source, this.nodes, copy, this.target, e); - topic.publish("/dnd/drop", this.source, this.nodes, copy, this.target, e); - }else{ - topic.publish("/dnd/cancel"); - } - this.stopDrag(); - } - }, - - // keyboard event processors - onKeyDown: function(e){ - // summary: - // event processor for onkeydown: - // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag - // e: Event - // keyboard event - if(this.avatar){ - switch(e.keyCode){ - case keys.CTRL: - var copy = Boolean(this.source.copyState(true)); - if(this.copy != copy){ - this._setCopyStatus(copy); - } - break; - case keys.ESCAPE: - topic.publish("/dnd/cancel"); - this.stopDrag(); - break; - } - } - }, - onKeyUp: function(e){ - // summary: - // event processor for onkeyup, watching for CTRL for copy/move status - // e: Event - // keyboard event - if(this.avatar && e.keyCode == keys.CTRL){ - var copy = Boolean(this.source.copyState(false)); - if(this.copy != copy){ - this._setCopyStatus(copy); - } - } - }, - - // utilities - _setCopyStatus: function(copy){ - // summary: - // changes the copy status - // copy: Boolean - // the copy status - this.copy = copy; - this.source._markDndStatus(this.copy); - this.updateAvatar(); - domClass.replace(win.body(), - "dojoDnd" + (this.copy ? "Copy" : "Move"), - "dojoDnd" + (this.copy ? "Move" : "Copy")); - } -}); - -// dnd._manager: -// The manager singleton variable. Can be overwritten if needed. -dnd._manager = null; - -Manager.manager = dnd.manager = function(){ - // summary: - // Returns the current DnD manager. Creates one if it is not created yet. - if(!dnd._manager){ - dnd._manager = new Manager(); - } - return dnd._manager; // Object -}; - -return Manager; -}); - -}, -'dijit/form/ToggleButton':function(){ -define("dijit/form/ToggleButton", [ - "dojo/_base/declare", // declare - "dojo/_base/kernel", // kernel.deprecated - "./Button", - "./_ToggleButtonMixin" -], function(declare, kernel, Button, _ToggleButtonMixin){ - - // module: - // dijit/form/ToggleButton - - - return declare("dijit.form.ToggleButton", [Button, _ToggleButtonMixin], { - // summary: - // A templated button widget that can be in two states (checked or not). - // Can be base class for things like tabs or checkbox or radio buttons. - - baseClass: "dijitToggleButton", - - setChecked: function(/*Boolean*/ checked){ - // summary: - // Deprecated. Use set('checked', true/false) instead. - kernel.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0"); - this.set('checked', checked); - } - }); -}); - -}, -'dojo/date/stamp':function(){ -define("dojo/date/stamp", ["../_base/lang", "../_base/array"], function(lang, array){ - -// module: -// dojo/date/stamp - -var stamp = { - // summary: - // TODOC -}; -lang.setObject("dojo.date.stamp", stamp); - -// Methods to convert dates to or from a wire (string) format using well-known conventions - -stamp.fromISOString = function(/*String*/ formattedString, /*Number?*/ defaultTime){ - // summary: - // Returns a Date object given a string formatted according to a subset of the ISO-8601 standard. - // - // description: - // Accepts a string formatted according to a profile of ISO8601 as defined by - // [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed. - // Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime) - // The following combinations are valid: - // - // - dates only - // - yyyy - // - yyyy-MM - // - yyyy-MM-dd - // - times only, with an optional time zone appended - // - THH:mm - // - THH:mm:ss - // - THH:mm:ss.SSS - // - and "datetimes" which could be any combination of the above - // - // timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm - // Assumes the local time zone if not specified. Does not validate. Improperly formatted - // input may return null. Arguments which are out of bounds will be handled - // by the Date constructor (e.g. January 32nd typically gets resolved to February 1st) - // Only years between 100 and 9999 are supported. - // formattedString: - // A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00 - // defaultTime: - // Used for defaults for fields omitted in the formattedString. - // Uses 1970-01-01T00:00:00.0Z by default. - - if(!stamp._isoRegExp){ - stamp._isoRegExp = -//TODO: could be more restrictive and check for 00-59, etc. - /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/; - } - - var match = stamp._isoRegExp.exec(formattedString), - result = null; - - if(match){ - match.shift(); - if(match[1]){match[1]--;} // Javascript Date months are 0-based - if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds - - if(defaultTime){ - // mix in defaultTime. Relatively expensive, so use || operators for the fast path of defaultTime === 0 - defaultTime = new Date(defaultTime); - array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){ - return defaultTime["get" + prop](); - }), function(value, index){ - match[index] = match[index] || value; - }); - } - result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults - if(match[0] < 100){ - result.setFullYear(match[0] || 1970); - } - - var offset = 0, - zoneSign = match[7] && match[7].charAt(0); - if(zoneSign != 'Z'){ - offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0); - if(zoneSign != '-'){ offset *= -1; } - } - if(zoneSign){ - offset -= result.getTimezoneOffset(); - } - if(offset){ - result.setTime(result.getTime() + offset * 60000); - } - } - - return result; // Date or null -}; - -/*===== -var __Options = { - // selector: String - // "date" or "time" for partial formatting of the Date object. - // Both date and time will be formatted by default. - // zulu: Boolean - // if true, UTC/GMT is used for a timezone - // milliseconds: Boolean - // if true, output milliseconds -}; -=====*/ - -stamp.toISOString = function(/*Date*/ dateObject, /*__Options?*/ options){ - // summary: - // Format a Date object as a string according a subset of the ISO-8601 standard - // - // description: - // When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt) - // The local time zone is included as an offset from GMT, except when selector=='time' (time without a date) - // Does not check bounds. Only years between 100 and 9999 are supported. - // - // dateObject: - // A Date object - - var _ = function(n){ return (n < 10) ? "0" + n : n; }; - options = options || {}; - var formattedDate = [], - getter = options.zulu ? "getUTC" : "get", - date = ""; - if(options.selector != "time"){ - var year = dateObject[getter+"FullYear"](); - date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-'); - } - formattedDate.push(date); - if(options.selector != "date"){ - var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':'); - var millis = dateObject[getter+"Milliseconds"](); - if(options.milliseconds){ - time += "."+ (millis < 100 ? "0" : "") + _(millis); - } - if(options.zulu){ - time += "Z"; - }else if(options.selector != "time"){ - var timezoneOffset = dateObject.getTimezoneOffset(); - var absOffset = Math.abs(timezoneOffset); - time += (timezoneOffset > 0 ? "-" : "+") + - _(Math.floor(absOffset/60)) + ":" + _(absOffset%60); - } - formattedDate.push(time); - } - return formattedDate.join('T'); // String -}; - -return stamp; -}); - -}, -'dojo/Stateful':function(){ -define("dojo/Stateful", ["./_base/declare", "./_base/lang", "./_base/array", "dojo/when"], function(declare, lang, array, when){ - // module: - // dojo/Stateful - -return declare("dojo.Stateful", null, { - // summary: - // Base class for objects that provide named properties with optional getter/setter - // control and the ability to watch for property changes - // - // The class also provides the functionality to auto-magically manage getters - // and setters for object attributes/properties. - // - // Getters and Setters should follow the format of _xxxGetter or _xxxSetter where - // the xxx is a name of the attribute to handle. So an attribute of "foo" - // would have a custom getter of _fooGetter and a custom setter of _fooSetter. - // - // example: - // | var obj = new dojo.Stateful(); - // | obj.watch("foo", function(){ - // | console.log("foo changed to " + this.get("foo")); - // | }); - // | obj.set("foo","bar"); - - // _attrPairNames: Hash - // Used across all instances a hash to cache attribute names and their getter - // and setter names. - _attrPairNames: {}, - - _getAttrNames: function(name){ - // summary: - // Helper function for get() and set(). - // Caches attribute name values so we don't do the string ops every time. - // tags: - // private - - var apn = this._attrPairNames; - if(apn[name]){ return apn[name]; } - return (apn[name] = { - s: "_" + name + "Setter", - g: "_" + name + "Getter" - }); - }, - - postscript: function(/*Object?*/ params){ - // Automatic setting of params during construction - if (params){ this.set(params); } - }, - - _get: function(name, names){ - // summary: - // Private function that does a get based off a hash of names - // names: - // Hash of names of custom attributes - return typeof this[names.g] === "function" ? this[names.g]() : this[name]; - }, - get: function(/*String*/name){ - // summary: - // Get a property on a Stateful instance. - // name: - // The property to get. - // returns: - // The property value on this Stateful instance. - // description: - // Get a named property on a Stateful object. The property may - // potentially be retrieved via a getter method in subclasses. In the base class - // this just retrieves the object's property. - // For example: - // | stateful = new dojo.Stateful({foo: 3}); - // | stateful.get("foo") // returns 3 - // | stateful.foo // returns 3 - - return this._get(name, this._getAttrNames(name)); //Any - }, - set: function(/*String*/name, /*Object*/value){ - // summary: - // Set a property on a Stateful instance - // name: - // The property to set. - // value: - // The value to set in the property. - // returns: - // The function returns this dojo.Stateful instance. - // description: - // Sets named properties on a stateful object and notifies any watchers of - // the property. A programmatic setter may be defined in subclasses. - // For example: - // | stateful = new dojo.Stateful(); - // | stateful.watch(function(name, oldValue, value){ - // | // this will be called on the set below - // | } - // | stateful.set(foo, 5); - // - // set() may also be called with a hash of name/value pairs, ex: - // | myObj.set({ - // | foo: "Howdy", - // | bar: 3 - // | }) - // This is equivalent to calling set(foo, "Howdy") and set(bar, 3) - - // If an object is used, iterate through object - if(typeof name === "object"){ - for(var x in name){ - if(name.hasOwnProperty(x) && x !="_watchCallbacks"){ - this.set(x, name[x]); - } - } - return this; - } - - var names = this._getAttrNames(name), - oldValue = this._get(name, names), - setter = this[names.s], - result; - if(typeof setter === "function"){ - // use the explicit setter - result = setter.apply(this, Array.prototype.slice.call(arguments, 1)); - }else{ - // no setter so set attribute directly - this[name] = value; - } - if(this._watchCallbacks){ - var self = this; - // If setter returned a promise, wait for it to complete, otherwise call watches immediatly - when(result, function(){ - self._watchCallbacks(name, oldValue, value); - }); - } - return this; // dojo/Stateful - }, - _changeAttrValue: function(name, value){ - // summary: - // Internal helper for directly changing an attribute value. - // - // name: String - // The property to set. - // value: Mixed - // The value to set in the property. - // - // description: - // Directly change the value of an attribute on an object, bypassing any - // accessor setter. Also handles the calling of watch and emitting events. - // It is designed to be used by descendent class when there are two values - // of attributes that are linked, but calling .set() is not appropriate. - - var oldValue = this.get(name); - this[name] = value; - if(this._watchCallbacks){ - this._watchCallbacks(name, oldValue, value); - } - return this; // dojo/Stateful - }, - watch: function(/*String?*/name, /*Function*/callback){ - // summary: - // Watches a property for changes - // name: - // Indicates the property to watch. This is optional (the callback may be the - // only parameter), and if omitted, all the properties will be watched - // returns: - // An object handle for the watch. The unwatch method of this object - // can be used to discontinue watching this property: - // | var watchHandle = obj.watch("foo", callback); - // | watchHandle.unwatch(); // callback won't be called now - // callback: - // The function to execute when the property changes. This will be called after - // the property has been changed. The callback will be called with the |this| - // set to the instance, the first argument as the name of the property, the - // second argument as the old value and the third argument as the new value. - - var callbacks = this._watchCallbacks; - if(!callbacks){ - var self = this; - callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){ - var notify = function(propertyCallbacks){ - if(propertyCallbacks){ - propertyCallbacks = propertyCallbacks.slice(); - for(var i = 0, l = propertyCallbacks.length; i < l; i++){ - propertyCallbacks[i].call(self, name, oldValue, value); - } - } - }; - notify(callbacks['_' + name]); - if(!ignoreCatchall){ - notify(callbacks["*"]); // the catch-all - } - }; // we use a function instead of an object so it will be ignored by JSON conversion - } - if(!callback && typeof name === "function"){ - callback = name; - name = "*"; - }else{ - // prepend with dash to prevent name conflicts with function (like "name" property) - name = '_' + name; - } - var propertyCallbacks = callbacks[name]; - if(typeof propertyCallbacks !== "object"){ - propertyCallbacks = callbacks[name] = []; - } - propertyCallbacks.push(callback); - - // TODO: Remove unwatch in 2.0 - var handle = {}; - handle.unwatch = handle.remove = function(){ - var index = array.indexOf(propertyCallbacks, callback); - if(index > -1){ - propertyCallbacks.splice(index, 1); - } - }; - return handle; //Object - } - -}); - -}); - -}, -'dijit/layout/AccordionContainer':function(){ -require({cache:{ -'url:dijit/layout/templates/AccordionButton.html':"<div data-dojo-attach-event='onclick:_onTitleClick' class='dijitAccordionTitle' role=\"presentation\">\n\t<div data-dojo-attach-point='titleNode,focusNode' data-dojo-attach-event='onkeypress:_onTitleKeyPress'\n\t\t\tclass='dijitAccordionTitleFocus' role=\"tab\" aria-expanded=\"false\"\n\t\t><span class='dijitInline dijitAccordionArrow' role=\"presentation\"></span\n\t\t><span class='arrowTextUp' role=\"presentation\">+</span\n\t\t><span class='arrowTextDown' role=\"presentation\">-</span\n\t\t><img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" data-dojo-attach-point='iconNode' style=\"vertical-align: middle\" role=\"presentation\"/>\n\t\t<span role=\"presentation\" data-dojo-attach-point='titleTextNode' class='dijitAccordionText'></span>\n\t</div>\n</div>\n"}}); -define("dijit/layout/AccordionContainer", [ - "require", - "dojo/_base/array", // array.forEach array.map - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/_base/fx", // fx.Animation - "dojo/dom", // dom.setSelectable - "dojo/dom-attr", // domAttr.attr - "dojo/dom-class", // domClass.remove - "dojo/dom-construct", // domConstruct.place - "dojo/dom-geometry", - "dojo/keys", // keys - "dojo/_base/lang", // lang.getObject lang.hitch - "dojo/sniff", // has("ie") has("dijit-legacy-requires") - "dojo/topic", // publish - "../focus", // focus.focus() - "../_base/manager", // manager.defaultDuration - "dojo/ready", - "../_Widget", - "../_Container", - "../_TemplatedMixin", - "../_CssStateMixin", - "./StackContainer", - "./ContentPane", - "dojo/text!./templates/AccordionButton.html" -], function(require, array, declare, event, fx, dom, domAttr, domClass, domConstruct, domGeometry, - keys, lang, has, topic, focus, manager, ready, - _Widget, _Container, _TemplatedMixin, _CssStateMixin, StackContainer, ContentPane, template){ - - // module: - // dijit/layout/AccordionContainer - - - // Design notes: - // - // An AccordionContainer is a StackContainer, but each child (typically ContentPane) - // is wrapped in a _AccordionInnerContainer. This is hidden from the caller. - // - // The resulting markup will look like: - // - // <div class=dijitAccordionContainer> - // <div class=dijitAccordionInnerContainer> (one pane) - // <div class=dijitAccordionTitle> (title bar) ... </div> - // <div class=dijtAccordionChildWrapper> (content pane) </div> - // </div> - // </div> - // - // Normally the dijtAccordionChildWrapper is hidden for all but one child (the shown - // child), so the space for the content pane is all the title bars + the one dijtAccordionChildWrapper, - // which on claro has a 1px border plus a 2px bottom margin. - // - // During animation there are two dijtAccordionChildWrapper's shown, so we need - // to compensate for that. - - - var AccordionButton = declare("dijit.layout._AccordionButton", [_Widget, _TemplatedMixin, _CssStateMixin], { - // summary: - // The title bar to click to open up an accordion pane. - // Internal widget used by AccordionContainer. - // tags: - // private - - templateString: template, - - // label: String - // Title of the pane - label: "", - _setLabelAttr: {node: "titleTextNode", type: "innerHTML" }, - - // title: String - // Tooltip that appears on hover - title: "", - _setTitleAttr: {node: "titleTextNode", type: "attribute", attribute: "title"}, - - // iconClassAttr: String - // CSS class for icon to left of label - iconClassAttr: "", - _setIconClassAttr: { node: "iconNode", type: "class" }, - - baseClass: "dijitAccordionTitle", - - getParent: function(){ - // summary: - // Returns the AccordionContainer parent. - // tags: - // private - return this.parent; - }, - - buildRendering: function(){ - this.inherited(arguments); - var titleTextNodeId = this.id.replace(' ','_'); - domAttr.set(this.titleTextNode, "id", titleTextNodeId+"_title"); - this.focusNode.setAttribute("aria-labelledby", domAttr.get(this.titleTextNode, "id")); - dom.setSelectable(this.domNode, false); - }, - - getTitleHeight: function(){ - // summary: - // Returns the height of the title dom node. - return domGeometry.getMarginSize(this.domNode).h; // Integer - }, - - // TODO: maybe the parent should set these methods directly rather than forcing the code - // into the button widget? - _onTitleClick: function(){ - // summary: - // Callback when someone clicks my title. - var parent = this.getParent(); - parent.selectChild(this.contentWidget, true); - focus.focus(this.focusNode); - }, - - _onTitleKeyPress: function(/*Event*/ evt){ - return this.getParent()._onKeyPress(evt, this.contentWidget); - }, - - _setSelectedAttr: function(/*Boolean*/ isSelected){ - this._set("selected", isSelected); - this.focusNode.setAttribute("aria-expanded", isSelected ? "true" : "false"); - this.focusNode.setAttribute("aria-selected", isSelected ? "true" : "false"); - this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1"); - } - }); - - var AccordionInnerContainer = declare("dijit.layout._AccordionInnerContainer", [_Widget, _CssStateMixin], { - // summary: - // Internal widget placed as direct child of AccordionContainer.containerNode. - // When other widgets are added as children to an AccordionContainer they are wrapped in - // this widget. - -/*===== - // buttonWidget: Function|String - // Class to use to instantiate title - // (Wish we didn't have a separate widget for just the title but maintaining it - // for backwards compatibility, is it worth it?) - buttonWidget: null, -=====*/ - -/*===== - // contentWidget: dijit/_WidgetBase - // Pointer to the real child widget - contentWidget: null, -=====*/ - - baseClass: "dijitAccordionInnerContainer", - - // tell nested layout widget that we will take care of sizing - isLayoutContainer: true, - - buildRendering: function(){ - // Builds a template like: - // <div class=dijitAccordionInnerContainer> - // Button - // <div class=dijitAccordionChildWrapper> - // ContentPane - // </div> - // </div> - - // Create wrapper div, placed where the child is now - this.domNode = domConstruct.place("<div class='" + this.baseClass + - "' role='presentation'>", this.contentWidget.domNode, "after"); - - // wrapper div's first child is the button widget (ie, the title bar) - var child = this.contentWidget, - cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget; - this.button = child._buttonWidget = (new cls({ - contentWidget: child, - label: child.title, - title: child.tooltip, - dir: child.dir, - lang: child.lang, - textDir: child.textDir, - iconClass: child.iconClass, - id: child.id + "_button", - parent: this.parent - })).placeAt(this.domNode); - - // and then the actual content widget (changing it from prior-sibling to last-child), - // wrapped by a <div class=dijitAccordionChildWrapper> - this.containerNode = domConstruct.place("<div class='dijitAccordionChildWrapper' style='display:none'>", this.domNode); - domConstruct.place(this.contentWidget.domNode, this.containerNode); - }, - - postCreate: function(){ - this.inherited(arguments); - - // Map changes in content widget's title etc. to changes in the button - var button = this.button; - this._contentWidgetWatches = [ - this.contentWidget.watch('title', lang.hitch(this, function(name, oldValue, newValue){ - button.set("label", newValue); - })), - this.contentWidget.watch('tooltip', lang.hitch(this, function(name, oldValue, newValue){ - button.set("title", newValue); - })), - this.contentWidget.watch('iconClass', lang.hitch(this, function(name, oldValue, newValue){ - button.set("iconClass", newValue); - })) - ]; - }, - - _setSelectedAttr: function(/*Boolean*/ isSelected){ - this._set("selected", isSelected); - this.button.set("selected", isSelected); - if(isSelected){ - var cw = this.contentWidget; - if(cw.onSelected){ cw.onSelected(); } - } - }, - - startup: function(){ - // Called by _Container.addChild() - this.contentWidget.startup(); - }, - - destroy: function(){ - this.button.destroyRecursive(); - - array.forEach(this._contentWidgetWatches || [], function(w){ w.unwatch(); }); - - delete this.contentWidget._buttonWidget; - delete this.contentWidget._wrapperWidget; - - this.inherited(arguments); - }, - - destroyDescendants: function(/*Boolean*/ preserveDom){ - // since getChildren isn't working for me, have to code this manually - this.contentWidget.destroyRecursive(preserveDom); - } - }); - - var AccordionContainer = declare("dijit.layout.AccordionContainer", StackContainer, { - // summary: - // Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time, - // and switching between panes is visualized by sliding the other panes up/down. - // example: - // | <div data-dojo-type="dijit/layout/AccordionContainer"> - // | <div data-dojo-type="dijit/layout/ContentPane" title="pane 1"> - // | </div> - // | <div data-dojo-type="dijit/layout/ContentPane" title="pane 2"> - // | <p>This is some text</p> - // | </div> - // | </div> - - // duration: Integer - // Amount of time (in ms) it takes to slide panes - duration: manager.defaultDuration, - - // buttonWidget: [const] String - // The name of the widget used to display the title of each pane - buttonWidget: AccordionButton, - -/*===== - // _verticalSpace: Number - // Pixels of space available for the open pane - // (my content box size minus the cumulative size of all the title bars) - _verticalSpace: 0, -=====*/ - baseClass: "dijitAccordionContainer", - - buildRendering: function(){ - this.inherited(arguments); - this.domNode.style.overflow = "hidden"; // TODO: put this in dijit.css - this.domNode.setAttribute("role", "tablist"); // TODO: put this in template - }, - - startup: function(){ - if(this._started){ return; } - this.inherited(arguments); - if(this.selectedChildWidget){ - this.selectedChildWidget._wrapperWidget.set("selected", true); - } - }, - - layout: function(){ - // Implement _LayoutWidget.layout() virtual method. - // Set the height of the open pane based on what room remains. - - var openPane = this.selectedChildWidget; - - if(!openPane){ return;} - - // space taken up by title, plus wrapper div (with border/margin) for open pane - var wrapperDomNode = openPane._wrapperWidget.domNode, - wrapperDomNodeMargin = domGeometry.getMarginExtents(wrapperDomNode), - wrapperDomNodePadBorder = domGeometry.getPadBorderExtents(wrapperDomNode), - wrapperContainerNode = openPane._wrapperWidget.containerNode, - wrapperContainerNodeMargin = domGeometry.getMarginExtents(wrapperContainerNode), - wrapperContainerNodePadBorder = domGeometry.getPadBorderExtents(wrapperContainerNode), - mySize = this._contentBox; - - // get cumulative height of all the unselected title bars - var totalCollapsedHeight = 0; - array.forEach(this.getChildren(), function(child){ - if(child != openPane){ - // Using domGeometry.getMarginSize() rather than domGeometry.position() since claro has 1px bottom margin - // to separate accordion panes. Not sure that works perfectly, it's probably putting a 1px - // margin below the bottom pane (even though we don't want one). - totalCollapsedHeight += domGeometry.getMarginSize(child._wrapperWidget.domNode).h; - } - }); - this._verticalSpace = mySize.h - totalCollapsedHeight - wrapperDomNodeMargin.h - - wrapperDomNodePadBorder.h - wrapperContainerNodeMargin.h - wrapperContainerNodePadBorder.h - - openPane._buttonWidget.getTitleHeight(); - - // Memo size to make displayed child - this._containerContentBox = { - h: this._verticalSpace, - w: this._contentBox.w - wrapperDomNodeMargin.w - wrapperDomNodePadBorder.w - - wrapperContainerNodeMargin.w - wrapperContainerNodePadBorder.w - }; - - if(openPane){ - openPane.resize(this._containerContentBox); - } - }, - - _setupChild: function(child){ - // Overrides _LayoutWidget._setupChild(). - // Put wrapper widget around the child widget, showing title - - child._wrapperWidget = AccordionInnerContainer({ - contentWidget: child, - buttonWidget: this.buttonWidget, - id: child.id + "_wrapper", - dir: child.dir, - lang: child.lang, - textDir: child.textDir, - parent: this - }); - - this.inherited(arguments); - }, - - addChild: function(/*dijit/_WidgetBase*/ child, /*Integer?*/ insertIndex){ - // Overrides _LayoutWidget.addChild(). - if(this._started){ - // Adding a child to a started Accordion is complicated because children have - // wrapper widgets. Default code path (calling this.inherited()) would add - // the new child inside another child's wrapper. - - // First add in child as a direct child of this AccordionContainer - var refNode = this.containerNode; - if(insertIndex && typeof insertIndex == "number"){ - var children = _Widget.prototype.getChildren.call(this); // get wrapper panes - if(children && children.length >= insertIndex){ - refNode = children[insertIndex-1].domNode; - insertIndex = "after"; - } - } - domConstruct.place(child.domNode, refNode, insertIndex); - - if(!child._started){ - child.startup(); - } - - // Then stick the wrapper widget around the child widget - this._setupChild(child); - - // Code below copied from StackContainer - topic.publish(this.id+"-addChild", child, insertIndex); // publish - this.layout(); - if(!this.selectedChildWidget){ - this.selectChild(child); - } - }else{ - // We haven't been started yet so just add in the child widget directly, - // and the wrapper will be created on startup() - this.inherited(arguments); - } - }, - - removeChild: function(child){ - // Overrides _LayoutWidget.removeChild(). - - // Destroy wrapper widget first, before StackContainer.getChildren() call. - // Replace wrapper widget with true child widget (ContentPane etc.). - // This step only happens if the AccordionContainer has been started; otherwise there's no wrapper. - if(child._wrapperWidget){ - domConstruct.place(child.domNode, child._wrapperWidget.domNode, "after"); - child._wrapperWidget.destroy(); - delete child._wrapperWidget; - } - - domClass.remove(child.domNode, "dijitHidden"); - - this.inherited(arguments); - }, - - getChildren: function(){ - // Overrides _Container.getChildren() to return content panes rather than internal AccordionInnerContainer panes - return array.map(this.inherited(arguments), function(child){ - return child.declaredClass == "dijit.layout._AccordionInnerContainer" ? child.contentWidget : child; - }, this); - }, - - destroy: function(){ - if(this._animation){ - this._animation.stop(); - } - array.forEach(this.getChildren(), function(child){ - // If AccordionContainer has been started, then each child has a wrapper widget which - // also needs to be destroyed. - if(child._wrapperWidget){ - child._wrapperWidget.destroy(); - }else{ - child.destroyRecursive(); - } - }); - this.inherited(arguments); - }, - - _showChild: function(child){ - // Override StackContainer._showChild() to set visibility of _wrapperWidget.containerNode - child._wrapperWidget.containerNode.style.display="block"; - return this.inherited(arguments); - }, - - _hideChild: function(child){ - // Override StackContainer._showChild() to set visibility of _wrapperWidget.containerNode - child._wrapperWidget.containerNode.style.display="none"; - this.inherited(arguments); - }, - - _transition: function(/*dijit/_WidgetBase?*/ newWidget, /*dijit/_WidgetBase?*/ oldWidget, /*Boolean*/ animate){ - // Overrides StackContainer._transition() to provide sliding of title bars etc. - - if(has("ie") < 8){ - // workaround animation bugs by not animating; not worth supporting animation for IE6 & 7 - animate = false; - } - - if(this._animation){ - // there's an in-progress animation. speedily end it so we can do the newly requested one - this._animation.stop(true); - delete this._animation; - } - - var self = this; - - if(newWidget){ - newWidget._wrapperWidget.set("selected", true); - - var d = this._showChild(newWidget); // prepare widget to be slid in - - // Size the new widget, in case this is the first time it's being shown, - // or I have been resized since the last time it was shown. - // Note that page must be visible for resizing to work. - if(this.doLayout && newWidget.resize){ - newWidget.resize(this._containerContentBox); - } - } - - if(oldWidget){ - oldWidget._wrapperWidget.set("selected", false); - if(!animate){ - this._hideChild(oldWidget); - } - } - - if(animate){ - var newContents = newWidget._wrapperWidget.containerNode, - oldContents = oldWidget._wrapperWidget.containerNode; - - // During the animation we will be showing two dijitAccordionChildWrapper nodes at once, - // which on claro takes up 4px extra space (compared to stable AccordionContainer). - // Have to compensate for that by immediately shrinking the pane being closed. - var wrapperContainerNode = newWidget._wrapperWidget.containerNode, - wrapperContainerNodeMargin = domGeometry.getMarginExtents(wrapperContainerNode), - wrapperContainerNodePadBorder = domGeometry.getPadBorderExtents(wrapperContainerNode), - animationHeightOverhead = wrapperContainerNodeMargin.h + wrapperContainerNodePadBorder.h; - - oldContents.style.height = (self._verticalSpace - animationHeightOverhead) + "px"; - - this._animation = new fx.Animation({ - node: newContents, - duration: this.duration, - curve: [1, this._verticalSpace - animationHeightOverhead - 1], - onAnimate: function(value){ - value = Math.floor(value); // avoid fractional values - newContents.style.height = value + "px"; - oldContents.style.height = (self._verticalSpace - animationHeightOverhead - value) + "px"; - }, - onEnd: function(){ - delete self._animation; - newContents.style.height = "auto"; - oldWidget._wrapperWidget.containerNode.style.display = "none"; - oldContents.style.height = "auto"; - self._hideChild(oldWidget); - } - }); - this._animation.onStop = this._animation.onEnd; - this._animation.play(); - } - - return d; // If child has an href, promise that fires when the widget has finished loading - }, - - // note: we are treating the container as controller here - _onKeyPress: function(/*Event*/ e, /*dijit/_WidgetBase*/ fromTitle){ - // summary: - // Handle keypress events - // description: - // This is called from a handler on AccordionContainer.domNode - // (setup in StackContainer), and is also called directly from - // the click handler for accordion labels - if(this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){ - return; - } - var c = e.charOrCode; - if((fromTitle && (c == keys.LEFT_ARROW || c == keys.UP_ARROW)) || - (e.ctrlKey && c == keys.PAGE_UP)){ - this._adjacent(false)._buttonWidget._onTitleClick(); - event.stop(e); - }else if((fromTitle && (c == keys.RIGHT_ARROW || c == keys.DOWN_ARROW)) || - (e.ctrlKey && (c == keys.PAGE_DOWN || c == keys.TAB))){ - this._adjacent(true)._buttonWidget._onTitleClick(); - event.stop(e); - } - } - }); - - // Back compat w/1.6, remove for 2.0 - if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/layout/AccordionPane"]; - require(requires); // use indirection so modules not rolled into a build - }); - } - - // For monkey patching - AccordionContainer._InnerContainer = AccordionInnerContainer; - AccordionContainer._Button = AccordionButton; - - return AccordionContainer; -}); - -}, -'dijit/form/ComboButton':function(){ -require({cache:{ -'url:dijit/form/templates/ComboButton.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tcellspacing='0' cellpadding='0' role=\"presentation\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonNode\" data-dojo-attach-point=\"buttonNode\" data-dojo-attach-event=\"ondijitclick:_onClick,onkeypress:_onButtonKeyPress\"\n\t\t><div id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" data-dojo-attach-point=\"containerNode\" role=\"presentation\"></div\n\t\t></div\n\t\t></td\n\t\t><td id=\"${id}_arrow\" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'\n\t\t\tdata-dojo-attach-point=\"_popupStateNode,focusNode,_buttonNode\"\n\t\t\tdata-dojo-attach-event=\"onkeypress:_onArrowKeyPress\"\n\t\t\ttitle=\"${optionsTitle}\"\n\t\t\trole=\"button\" aria-haspopup=\"true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">▼</div\n\t\t></td\n\t\t><td style=\"display:none !important;\"\n\t\t\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" data-dojo-attach-point=\"valueNode\" role=\"presentation\"\n\t\t/></td></tr></tbody\n></table>\n"}}); -define("dijit/form/ComboButton", [ - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "../focus", // focus.focus() - "./DropDownButton", - "dojo/text!./templates/ComboButton.html" -], function(declare, event, keys, focus, DropDownButton, template){ - -// module: -// dijit/form/ComboButton - -return declare("dijit.form.ComboButton", DropDownButton, { - // summary: - // A combination button and drop-down button. - // Users can click one side to "press" the button, or click an arrow - // icon to display the drop down. - // - // example: - // | <button data-dojo-type="dijit/form/ComboButton" onClick="..."> - // | <span>Hello world</span> - // | <div data-dojo-type="dijit/Menu">...</div> - // | </button> - // - // example: - // | var button1 = new ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"}); - // | dojo.body().appendChild(button1.domNode); - // - - templateString: template, - - // Map widget attributes to DOMNode attributes. - _setIdAttr: "", // override _FormWidgetMixin which puts id on the focusNode - _setTabIndexAttr: ["focusNode", "titleNode"], - _setTitleAttr: "titleNode", - - // optionsTitle: String - // Text that describes the options menu (accessibility) - optionsTitle: "", - - baseClass: "dijitComboButton", - - // Set classes like dijitButtonContentsHover or dijitArrowButtonActive depending on - // mouse action over specified node - cssStateNodes: { - "buttonNode": "dijitButtonNode", - "titleNode": "dijitButtonContents", - "_popupStateNode": "dijitDownArrowButton" - }, - - _focusedNode: null, - - _onButtonKeyPress: function(/*Event*/ evt){ - // summary: - // Handler for right arrow key when focus is on left part of button - if(evt.charOrCode == keys[this.isLeftToRight() ? "RIGHT_ARROW" : "LEFT_ARROW"]){ - focus.focus(this._popupStateNode); - event.stop(evt); - } - }, - - _onArrowKeyPress: function(/*Event*/ evt){ - // summary: - // Handler for left arrow key when focus is on right part of button - if(evt.charOrCode == keys[this.isLeftToRight() ? "LEFT_ARROW" : "RIGHT_ARROW"]){ - focus.focus(this.titleNode); - event.stop(evt); - } - }, - - focus: function(/*String*/ position){ - // summary: - // Focuses this widget to according to position, if specified, - // otherwise on arrow node - // position: - // "start" or "end" - if(!this.disabled){ - focus.focus(position == "start" ? this.titleNode : this._popupStateNode); - } - } -}); - -}); - -}, -'dijit/form/_AutoCompleterMixin':function(){ -define("dijit/form/_AutoCompleterMixin", [ - "dojo/data/util/filter", // patternToRegExp - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.get - "dojo/_base/event", // event.stop - "dojo/keys", - "dojo/_base/lang", // lang.clone lang.hitch - "dojo/query", // query - "dojo/regexp", // regexp.escapeString - "dojo/sniff", // has("ie") - "dojo/string", // string.substitute - "./DataList", - "../registry", // registry.byId - "./_TextBoxMixin", // defines _TextBoxMixin.selectInputText - "./_SearchMixin" -], function(filter, declare, domAttr, event, keys, lang, query, regexp, has, string, - DataList, registry, _TextBoxMixin, SearchMixin){ - - // module: - // dijit/form/_AutoCompleterMixin - - return declare("dijit.form._AutoCompleterMixin", SearchMixin, { - // summary: - // A mixin that implements the base functionality for `dijit/form/ComboBox`/`dijit/form/FilteringSelect` - // description: - // All widgets that mix in dijit/form/_AutoCompleterMixin must extend `dijit/form/_FormValueWidget`. - // tags: - // protected - - // item: Object - // This is the item returned by the dojo/store/api/Store implementation that - // provides the data for this ComboBox, it's the currently selected item. - item: null, - - // autoComplete: Boolean - // If user types in a partial string, and then tab out of the `<input>` box, - // automatically copy the first entry displayed in the drop down list to - // the `<input>` field - autoComplete: true, - - // highlightMatch: String - // One of: "first", "all" or "none". - // - // If the ComboBox/FilteringSelect opens with the search results and the searched - // string can be found, it will be highlighted. If set to "all" - // then will probably want to change `queryExpr` parameter to '*${0}*' - // - // Highlighting is only performed when `labelType` is "text", so as to not - // interfere with any HTML markup an HTML label might contain. - highlightMatch: "first", - - // labelAttr: String? - // The entries in the drop down list come from this attribute in the - // dojo.data items. - // If not specified, the searchAttr attribute is used instead. - labelAttr: "", - - // labelType: String - // Specifies how to interpret the labelAttr in the data store items. - // Can be "html" or "text". - labelType: "text", - - // Flags to _HasDropDown to limit height of drop down to make it fit in viewport - maxHeight: -1, - - // For backwards compatibility let onClick events propagate, even clicks on the down arrow button - _stopClickEvents: false, - - _getCaretPos: function(/*DomNode*/ element){ - // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22 - var pos = 0; - if(typeof(element.selectionStart) == "number"){ - // FIXME: this is totally borked on Moz < 1.3. Any recourse? - pos = element.selectionStart; - }else if(has("ie")){ - // in the case of a mouse click in a popup being handled, - // then the win.doc.selection is not the textarea, but the popup - // var r = win.doc.selection.createRange(); - // hack to get IE 6 to play nice. What a POS browser. - var tr = element.ownerDocument.selection.createRange().duplicate(); - var ntr = element.createTextRange(); - tr.move("character",0); - ntr.move("character",0); - try{ - // If control doesn't have focus, you get an exception. - // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes). - // There appears to be no workaround for this - googled for quite a while. - ntr.setEndPoint("EndToEnd", tr); - pos = String(ntr.text).replace(/\r/g,"").length; - }catch(e){ - // If focus has shifted, 0 is fine for caret pos. - } - } - return pos; - }, - - _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){ - location = parseInt(location); - _TextBoxMixin.selectInputText(element, location, location); - }, - - _setDisabledAttr: function(/*Boolean*/ value){ - // Additional code to set disabled state of ComboBox node. - // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr(). - this.inherited(arguments); - this.domNode.setAttribute("aria-disabled", value ? "true" : "false"); - }, - - _onKey: function(/*Event*/ evt){ - // summary: - // Handles keyboard events - - if(evt.charCode >= 32){ return; } // alphanumeric reserved for searching - - var key = evt.charCode || evt.keyCode; - - // except for cutting/pasting case - ctrl + x/v - if(key == keys.ALT || key == keys.CTRL || key == keys.META || key == keys.SHIFT){ - return; // throw out spurious events - } - - var pw = this.dropDown; - var highlighted = null; - this._abortQuery(); - - // _HasDropDown will do some of the work: - // - // 1. when drop down is not yet shown: - // - if user presses the down arrow key, call loadDropDown() - // 2. when drop down is already displayed: - // - on ESC key, call closeDropDown() - // - otherwise, call dropDown.handleKey() to process the keystroke - this.inherited(arguments); - - if(evt.altKey || evt.ctrlKey || evt.metaKey){ return; } // don't process keys with modifiers - but we want shift+TAB - - if(this._opened){ - highlighted = pw.getHighlightedOption(); - } - switch(key){ - case keys.PAGE_DOWN: - case keys.DOWN_ARROW: - case keys.PAGE_UP: - case keys.UP_ARROW: - // Keystroke caused ComboBox_menu to move to a different item. - // Copy new item to <input> box. - if(this._opened){ - this._announceOption(highlighted); - } - event.stop(evt); - break; - - case keys.ENTER: - // prevent submitting form if user presses enter. Also - // prevent accepting the value if either Next or Previous - // are selected - if(highlighted){ - // only stop event on prev/next - if(highlighted == pw.nextButton){ - this._nextSearch(1); - event.stop(evt); // prevent submit - break; - }else if(highlighted == pw.previousButton){ - this._nextSearch(-1); - event.stop(evt); // prevent submit - break; - } - event.stop(evt); // prevent submit if ENTER was to choose an item - }else{ - // Update 'value' (ex: KY) according to currently displayed text - this._setBlurValue(); // set value if needed - this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting - } - // fall through - - case keys.TAB: - var newvalue = this.get('displayedValue'); - // if the user had More Choices selected fall into the - // _onBlur handler - if(pw && ( - newvalue == pw._messages["previousMessage"] || - newvalue == pw._messages["nextMessage"]) - ){ - break; - } - if(highlighted){ - this._selectOption(highlighted); - } - // fall through - - case keys.ESCAPE: - if(this._opened){ - this._lastQuery = null; // in case results come back later - this.closeDropDown(); - } - break; - } - }, - - _autoCompleteText: function(/*String*/ text){ - // summary: - // Fill in the textbox with the first item from the drop down - // list, and highlight the characters that were - // auto-completed. For example, if user typed "CA" and the - // drop down list appeared, the textbox would be changed to - // "California" and "ifornia" would be highlighted. - - var fn = this.focusNode; - - // IE7: clear selection so next highlight works all the time - _TextBoxMixin.selectInputText(fn, fn.value.length); - // does text autoComplete the value in the textbox? - var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr'; - if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){ - var cpos = this.autoComplete ? this._getCaretPos(fn) : fn.value.length; - // only try to extend if we added the last character at the end of the input - if((cpos+1) > fn.value.length){ - // only add to input node as we would overwrite Capitalisation of chars - // actually, that is ok - fn.value = text;//.substr(cpos); - // visually highlight the autocompleted characters - _TextBoxMixin.selectInputText(fn, cpos); - } - }else{ - // text does not autoComplete; replace the whole value and highlight - fn.value = text; - _TextBoxMixin.selectInputText(fn); - } - }, - - _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){ - // summary: - // Callback when a search completes. - // description: - // 1. generates drop-down list and calls _showResultList() to display it - // 2. if this result list is from user pressing "more choices"/"previous choices" - // then tell screen reader to announce new option - var wasSelected = this.dropDown.getHighlightedOption(); - this.dropDown.clearResultList(); - if(!results.length && options.start == 0){ // if no results and not just the previous choices button - this.closeDropDown(); - return; - } - this._nextSearch = this.dropDown.onPage = lang.hitch(this, function(direction){ - results.nextPage(direction !== -1); - this.focus(); - }); - - // Fill in the textbox with the first item from the drop down list, - // and highlight the characters that were auto-completed. For - // example, if user typed "CA" and the drop down list appeared, the - // textbox would be changed to "California" and "ifornia" would be - // highlighted. - - this.dropDown.createOptions( - results, - options, - lang.hitch(this, "_getMenuLabelFromItem") - ); - - // show our list (only if we have content, else nothing) - this._showResultList(); - - // #4091: - // tell the screen reader that the paging callback finished by - // shouting the next choice - if("direction" in options){ - if(options.direction){ - this.dropDown.highlightFirstOption(); - }else if(!options.direction){ - this.dropDown.highlightLastOption(); - } - if(wasSelected){ - this._announceOption(this.dropDown.getHighlightedOption()); - } - }else if(this.autoComplete && !this._prev_key_backspace - // when the user clicks the arrow button to show the full list, - // startSearch looks for "*". - // it does not make sense to autocomplete - // if they are just previewing the options available. - && !/^[*]+$/.test(query[this.searchAttr].toString())){ - this._announceOption(this.dropDown.containerNode.firstChild.nextSibling); // 1st real item - } - }, - - _showResultList: function(){ - // summary: - // Display the drop down if not already displayed, or if it is displayed, then - // reposition it if necessary (reposition may be necessary if drop down's height changed). - this.closeDropDown(true); - this.openDropDown(); - this.domNode.setAttribute("aria-expanded", "true"); - }, - - loadDropDown: function(/*Function*/ /*===== callback =====*/){ - // Overrides _HasDropDown.loadDropDown(). - // This is called when user has pressed button icon or pressed the down arrow key - // to open the drop down. - this._startSearchAll(); - }, - - isLoaded: function(){ - // signal to _HasDropDown that it needs to call loadDropDown() to load the - // drop down asynchronously before displaying it - return false; - }, - - closeDropDown: function(){ - // Overrides _HasDropDown.closeDropDown(). Closes the drop down (assuming that it's open). - // This method is the callback when the user types ESC or clicking - // the button icon while the drop down is open. It's also called by other code. - this._abortQuery(); - if(this._opened){ - this.inherited(arguments); - this.domNode.setAttribute("aria-expanded", "false"); - this.focusNode.removeAttribute("aria-activedescendant"); - } - }, - - _setBlurValue: function(){ - // if the user clicks away from the textbox OR tabs away, set the - // value to the textbox value - // #4617: - // if value is now more choices or previous choices, revert - // the value - var newvalue = this.get('displayedValue'); - var pw = this.dropDown; - if(pw && ( - newvalue == pw._messages["previousMessage"] || - newvalue == pw._messages["nextMessage"] - ) - ){ - this._setValueAttr(this._lastValueReported, true); - }else if(typeof this.item == "undefined"){ - // Update 'value' (ex: KY) according to currently displayed text - this.item = null; - this.set('displayedValue', newvalue); - }else{ - if(this.value != this._lastValueReported){ - this._handleOnChange(this.value, true); - } - this._refreshState(); - } - }, - - _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){ - // summary: - // Set the displayed valued in the input box, and the hidden value - // that gets submitted, based on a dojo.data store item. - // description: - // Users shouldn't call this function; they should be calling - // set('item', value) - // tags: - // private - var value = ''; - if(item){ - if(!displayedValue){ - displayedValue = this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API) - this.store.getValue(item, this.searchAttr) : item[this.searchAttr]; - } - value = this._getValueField() != this.searchAttr ? this.store.getIdentity(item) : displayedValue; - } - this.set('value', value, priorityChange, displayedValue, item); - }, - - _announceOption: function(/*Node*/ node){ - // summary: - // a11y code that puts the highlighted option in the textbox. - // This way screen readers will know what is happening in the - // menu. - - if(!node){ - return; - } - // pull the text value from the item attached to the DOM node - var newValue; - if(node == this.dropDown.nextButton || - node == this.dropDown.previousButton){ - newValue = node.innerHTML; - this.item = undefined; - this.value = ''; - }else{ - var item = this.dropDown.items[node.getAttribute("item")]; - newValue = (this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API) - this.store.getValue(item, this.searchAttr) : item[this.searchAttr]).toString(); - this.set('item', item, false, newValue); - } - // get the text that the user manually entered (cut off autocompleted text) - this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length); - // set up ARIA activedescendant - this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id")); - // autocomplete the rest of the option to announce change - this._autoCompleteText(newValue); - }, - - _selectOption: function(/*DomNode*/ target){ - // summary: - // Menu callback function, called when an item in the menu is selected. - this.closeDropDown(); - if(target){ - this._announceOption(target); - } - this._setCaretPos(this.focusNode, this.focusNode.value.length); - this._handleOnChange(this.value, true); - }, - - _startSearchAll: function(){ - this._startSearch(''); - }, - - _startSearchFromInput: function(){ - this.item = undefined; // undefined means item needs to be set - this.inherited(arguments); - }, - - _startSearch: function(/*String*/ key){ - // summary: - // Starts a search for elements matching key (key=="" means to return all items), - // and calls _openResultList() when the search completes, to display the results. - if(!this.dropDown){ - var popupId = this.id + "_popup", - dropDownConstructor = lang.isString(this.dropDownClass) ? - lang.getObject(this.dropDownClass, false) : this.dropDownClass; - this.dropDown = new dropDownConstructor({ - onChange: lang.hitch(this, this._selectOption), - id: popupId, - dir: this.dir, - textDir: this.textDir - }); - this.focusNode.removeAttribute("aria-activedescendant"); - this.textbox.setAttribute("aria-owns",popupId); // associate popup with textbox - } - this._lastInput = key; // Store exactly what was entered by the user. - this.inherited(arguments); - }, - - _getValueField: function(){ - // summary: - // Helper for postMixInProperties() to set this.value based on data inlined into the markup. - // Returns the attribute name in the item (in dijit/form/_ComboBoxDataStore) to use as the value. - return this.searchAttr; - }, - - //////////// INITIALIZATION METHODS /////////////////////////////////////// - - postMixInProperties: function(){ - this.inherited(arguments); - if(!this.store){ - var srcNodeRef = this.srcNodeRef; - // if user didn't specify store, then assume there are option tags - this.store = new DataList({}, srcNodeRef); - - // if there is no value set and there is an option list, set - // the value to the first value to be consistent with native Select - // Firefox and Safari set value - // IE6 and Opera set selectedIndex, which is automatically set - // by the selected attribute of an option tag - // IE6 does not set value, Opera sets value = selectedIndex - if(!("value" in this.params)){ - var item = (this.item = this.store.fetchSelectedItem()); - if(item){ - var valueField = this._getValueField(); - // remove getValue() for 2.0 (old dojo.data API) - this.value = this.store._oldAPI ? this.store.getValue(item, valueField) : item[valueField]; - } - } - } - }, - - postCreate: function(){ - // summary: - // Subclasses must call this method from their postCreate() methods - // tags: - // protected - - // find any associated label element and add to ComboBox node. - var label=query('label[for="'+this.id+'"]'); - if(label.length){ - if(!label[0].id){ label[0].id = this.id + "_label"; } - this.domNode.setAttribute("aria-labelledby", label[0].id); - - } - this.inherited(arguments); - this.connect(this, "onSearch", "_openResultList"); - }, - - _getMenuLabelFromItem: function(/*Item*/ item){ - var label = this.labelFunc(item, this.store), - labelType = this.labelType; - // If labelType is not "text" we don't want to screw any markup ot whatever. - if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){ - label = this.doHighlight(label, this._lastInput); - labelType = "html"; - } - return {html: labelType == "html", label: label}; - }, - - doHighlight: function(/*String*/ label, /*String*/ find){ - // summary: - // Highlights the string entered by the user in the menu. By default this - // highlights the first occurrence found. Override this method - // to implement your custom highlighting. - // tags: - // protected - - var - // Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true - modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""), - i = this.queryExpr.indexOf("${0}"); - find = regexp.escapeString(find); // escape regexp special chars - //If < appears in label, and user presses t, we don't want to highlight the t in the escaped "<" - //first find out every occurences of "find", wrap each occurence in a pair of "\uFFFF" characters (which - //should not appear in any string). then html escape the whole string, and replace '\uFFFF" with the - //HTML highlight markup. - return this._escapeHtml(label.replace( - new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers), - '\uFFFF$1\uFFFF')).replace( - /\uFFFF([^\uFFFF]+)\uFFFF/g, '<span class="dijitComboBoxHighlightMatch">$1</span>' - ); // returns String, (almost) valid HTML (entities encoded) - }, - - _escapeHtml: function(/*String*/ str){ - // TODO Should become dojo.html.entities(), when exists use instead - // summary: - // Adds escape sequences for special characters in XML: `&<>"'` - str = String(str).replace(/&/gm, "&").replace(/</gm, "<") - .replace(/>/gm, ">").replace(/"/gm, """); //balance" - return str; // string - }, - - reset: function(){ - // Overrides the _FormWidget.reset(). - // Additionally reset the .item (to clean up). - this.item = null; - this.inherited(arguments); - }, - - labelFunc: function(item, store){ - // summary: - // Computes the label to display based on the dojo.data store item. - // item: Object - // The item from the store - // store: dojo/store/api/Store - // The store. - // returns: - // The label that the ComboBox should display - // tags: - // private - - // Use toString() because XMLStore returns an XMLItem whereas this - // method is expected to return a String (#9354). - // Remove getValue() for 2.0 (old dojo.data API) - return (store._oldAPI ? store.getValue(item, this.labelAttr || this.searchAttr) : - item[this.labelAttr || this.searchAttr]).toString(); // String - }, - - _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){ - // summary: - // Hook so set('value', value) works. - // description: - // Sets the value of the select. - this._set("item", item||null); // value not looked up in store - if(value == null /* or undefined */){ value = ''; } // null translates to blank - this.inherited(arguments); - }, - _setTextDirAttr: function(/*String*/ textDir){ - // summary: - // Setter for textDir, needed for the dropDown's textDir update. - // description: - // Users shouldn't call this function; they should be calling - // set('textDir', value) - // tags: - // private - this.inherited(arguments); - // update the drop down also (_ComboBoxMenuMixin) - if(this.dropDown){ - this.dropDown._set("textDir", textDir); - } - } - }); -}); - -}, -'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n", -'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\" class=\"dijitTabInnerDiv dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"focusNode\">\n\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n</div>", -'dijit/form/MappedTextBox':function(){ -define("dijit/form/MappedTextBox", [ - "dojo/_base/declare", // declare - "dojo/dom-construct", // domConstruct.place - "./ValidationTextBox" -], function(declare, domConstruct, ValidationTextBox){ - - // module: - // dijit/form/MappedTextBox - - return declare("dijit.form.MappedTextBox", ValidationTextBox, { - // summary: - // A dijit/form/ValidationTextBox subclass which provides a base class for widgets that have - // a visible formatted display value, and a serializable - // value in a hidden input field which is actually sent to the server. - // description: - // The visible display may - // be locale-dependent and interactive. The value sent to the server is stored in a hidden - // input field which uses the `name` attribute declared by the original widget. That value sent - // to the server is defined by the dijit/form/MappedTextBox.serialize() method and is typically - // locale-neutral. - // tags: - // protected - - postMixInProperties: function(){ - this.inherited(arguments); - - // we want the name attribute to go to the hidden <input>, not the displayed <input>, - // so override _FormWidget.postMixInProperties() setting of nameAttrSetting - this.nameAttrSetting = ""; - }, - - // Override default behavior to assign name to focusNode - _setNameAttr: null, - - serialize: function(val /*=====, options =====*/){ - // summary: - // Overridable function used to convert the get('value') result to a canonical - // (non-localized) string. For example, will print dates in ISO format, and - // numbers the same way as they are represented in javascript. - // val: anything - // options: Object? - // tags: - // protected extension - return val.toString ? val.toString() : ""; // String - }, - - toString: function(){ - // summary: - // Returns widget as a printable string using the widget's value - // tags: - // protected - var val = this.filter(this.get('value')); // call filter in case value is nonstring and filter has been customized - return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String - }, - - validate: function(){ - // Overrides `dijit/form/TextBox.validate` - this.valueNode.value = this.toString(); - return this.inherited(arguments); - }, - - buildRendering: function(){ - // Overrides `dijit/_TemplatedMixin/buildRendering` - - this.inherited(arguments); - - // Create a hidden <input> node with the serialized value used for submit - // (as opposed to the displayed value). - // Passing in name as markup rather than calling domConstruct.create() with an attrs argument - // to make query(input[name=...]) work on IE. (see #8660) - this.valueNode = domConstruct.place("<input type='hidden'" + (this.name ? ' name="' + this.name.replace(/"/g, """) + '"' : "") + "/>", this.textbox, "after"); - }, - - reset: function(){ - // Overrides `dijit/form/ValidationTextBox.reset` to - // reset the hidden textbox value to '' - this.valueNode.value = ''; - this.inherited(arguments); - } - }); -}); - -}, -'dijit/form/ComboBoxMixin':function(){ -require({cache:{ -'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"button presentation\" aria-hidden=\"true\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n"}}); -define("dijit/form/ComboBoxMixin", [ - "dojo/_base/declare", // declare - "dojo/_base/Deferred", - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.mixin - "dojo/store/util/QueryResults", - "./_AutoCompleterMixin", - "./_ComboBoxMenu", - "../_HasDropDown", - "dojo/text!./templates/DropDownBox.html" -], function(declare, Deferred, kernel, lang, QueryResults, _AutoCompleterMixin, _ComboBoxMenu, _HasDropDown, template){ - - - // module: - // dijit/form/ComboBoxMixin - - return declare("dijit.form.ComboBoxMixin", [_HasDropDown, _AutoCompleterMixin], { - // summary: - // Provides main functionality of ComboBox widget - - // dropDownClass: [protected extension] Function String - // Dropdown widget class used to select a date/time. - // Subclasses should specify this. - dropDownClass: _ComboBoxMenu, - - // hasDownArrow: Boolean - // Set this textbox to have a down arrow button, to display the drop down list. - // Defaults to true. - hasDownArrow: true, - - templateString: template, - - baseClass: "dijitTextBox dijitComboBox", - - /*===== - // store: [const] dojo/store/api/Store|dojo/data/api/Read - // Reference to data provider object used by this ComboBox. - // - // Should be dojo/store/api/Store, but dojo/data/api/Read supported - // for backwards compatibility. - store: null, - =====*/ - - // Set classes like dijitDownArrowButtonHover depending on - // mouse action over button node - cssStateNodes: { - "_buttonNode": "dijitDownArrowButton" - }, - - _setHasDownArrowAttr: function(/*Boolean*/ val){ - this._set("hasDownArrow", val); - this._buttonNode.style.display = val ? "" : "none"; - }, - - _showResultList: function(){ - // hide the tooltip - this.displayMessage(""); - this.inherited(arguments); - }, - - _setStoreAttr: function(store){ - // For backwards-compatibility, accept dojo.data store in addition to dojo/store/api/Store. Remove in 2.0. - if(!store.get){ - lang.mixin(store, { - _oldAPI: true, - get: function(id){ - // summary: - // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity. - // Like dojo/store/DataStore.get() except returns native item. - var deferred = new Deferred(); - this.fetchItemByIdentity({ - identity: id, - onItem: function(object){ - deferred.resolve(object); - }, - onError: function(error){ - deferred.reject(error); - } - }); - return deferred.promise; - }, - query: function(query, options){ - // summary: - // Queries the store for objects. Like dojo/store/DataStore.query() - // except returned Deferred contains array of native items. - var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); }); - deferred.total = new Deferred(); - var fetchHandle = this.fetch(lang.mixin({ - query: query, - onBegin: function(count){ - deferred.total.resolve(count); - }, - onComplete: function(results){ - deferred.resolve(results); - }, - onError: function(error){ - deferred.reject(error); - } - }, options)); - return QueryResults(deferred); - } - }); - } - this._set("store", store); - }, - - postMixInProperties: function(){ - // Since _setValueAttr() depends on this.store, _setStoreAttr() needs to execute first. - // Unfortunately, without special code, it ends up executing second. - var store = this.params.store || this.store; - if(store){ - this._setStoreAttr(store); - } - - this.inherited(arguments); - - // User may try to access this.store.getValue() etc. in a custom labelFunc() function. - // It's not available with the new data store for handling inline <option> tags, so add it. - if(!this.params.store && !this.store._oldAPI){ - var clazz = this.declaredClass; - lang.mixin(this.store, { - getValue: function(item, attr){ - kernel.deprecated(clazz + ".store.getValue(item, attr) is deprecated for builtin store. Use item.attr directly", "", "2.0"); - return item[attr]; - }, - getLabel: function(item){ - kernel.deprecated(clazz + ".store.getLabel(item) is deprecated for builtin store. Use item.label directly", "", "2.0"); - return item.name; - }, - fetch: function(args){ - kernel.deprecated(clazz + ".store.fetch() is deprecated for builtin store.", "Use store.query()", "2.0"); - var shim = ["dojo/data/ObjectStore"]; // indirection so it doesn't get rolled into a build - require(shim, lang.hitch(this, function(ObjectStore){ - new ObjectStore({objectStore: this}).fetch(args); - })); - } - }); - } - } - }); -}); - -}, -'dijit/form/_TextBoxMixin':function(){ -define("dijit/form/_TextBoxMixin", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom", // dom.byId - "dojo/_base/event", // event.stop - "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT - "dojo/_base/lang", // lang.mixin - "dojo/on", // on - "../main" // for exporting dijit._setSelectionRange, dijit.selectInputText -], function(array, declare, dom, event, keys, lang, on, dijit){ - -// module: -// dijit/form/_TextBoxMixin - -var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, { - // summary: - // A mixin for textbox form input widgets - - // trim: Boolean - // Removes leading and trailing whitespace if true. Default is false. - trim: false, - - // uppercase: Boolean - // Converts all characters to uppercase if true. Default is false. - uppercase: false, - - // lowercase: Boolean - // Converts all characters to lowercase if true. Default is false. - lowercase: false, - - // propercase: Boolean - // Converts the first character of each word to uppercase if true. - propercase: false, - - // maxLength: String - // HTML INPUT tag maxLength declaration. - maxLength: "", - - // selectOnClick: [const] Boolean - // If true, all text will be selected when focused with mouse - selectOnClick: false, - - // placeHolder: String - // Defines a hint to help users fill out the input field (as defined in HTML 5). - // This should only contain plain text (no html markup). - placeHolder: "", - - _getValueAttr: function(){ - // summary: - // Hook so get('value') works as we like. - // description: - // For `dijit/form/TextBox` this basically returns the value of the `<input>`. - // - // For `dijit/form/MappedTextBox` subclasses, which have both - // a "displayed value" and a separate "submit value", - // This treats the "displayed value" as the master value, computing the - // submit value from it via this.parse(). - return this.parse(this.get('displayedValue'), this.constraints); - }, - - _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ - // summary: - // Hook so set('value', ...) works. - // - // description: - // Sets the value of the widget to "value" which can be of - // any type as determined by the widget. - // - // value: - // The visual element value is also set to a corresponding, - // but not necessarily the same, value. - // - // formattedValue: - // If specified, used to set the visual element value, - // otherwise a computed visual value is used. - // - // priorityChange: - // If true, an onChange event is fired immediately instead of - // waiting for the next blur event. - - var filteredValue; - if(value !== undefined){ - // TODO: this is calling filter() on both the display value and the actual value. - // I added a comment to the filter() definition about this, but it should be changed. - filteredValue = this.filter(value); - if(typeof formattedValue != "string"){ - if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){ - formattedValue = this.filter(this.format(filteredValue, this.constraints)); - }else{ formattedValue = ''; } - } - } - if(formattedValue != null /* and !undefined */ && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){ - this.textbox.value = formattedValue; - this._set("displayedValue", this.get("displayedValue")); - } - - if(this.textDir == "auto"){ - this.applyTextDir(this.focusNode, formattedValue); - } - - this.inherited(arguments, [filteredValue, priorityChange]); - }, - - // displayedValue: String - // For subclasses like ComboBox where the displayed value - // (ex: Kentucky) and the serialized value (ex: KY) are different, - // this represents the displayed value. - // - // Setting 'displayedValue' through set('displayedValue', ...) - // updates 'value', and vice-versa. Otherwise 'value' is updated - // from 'displayedValue' periodically, like onBlur etc. - // - // TODO: move declaration to MappedTextBox? - // Problem is that ComboBox references displayedValue, - // for benefit of FilteringSelect. - displayedValue: "", - - _getDisplayedValueAttr: function(){ - // summary: - // Hook so get('displayedValue') works. - // description: - // Returns the displayed value (what the user sees on the screen), - // after filtering (ie, trimming spaces etc.). - // - // For some subclasses of TextBox (like ComboBox), the displayed value - // is different from the serialized value that's actually - // sent to the server (see `dijit/form/ValidationTextBox.serialize()`) - - // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need - // this method - // TODO: this isn't really the displayed value when the user is typing - return this.filter(this.textbox.value); - }, - - _setDisplayedValueAttr: function(/*String*/ value){ - // summary: - // Hook so set('displayedValue', ...) works. - // description: - // Sets the value of the visual element to the string "value". - // The widget value is also set to a corresponding, - // but not necessarily the same, value. - - if(value == null /* or undefined */){ value = '' } - else if(typeof value != "string"){ value = String(value) } - - this.textbox.value = value; - - // sets the serialized value to something corresponding to specified displayedValue - // (if possible), and also updates the textbox.value, for example converting "123" - // to "123.00" - this._setValueAttr(this.get('value'), undefined); - - this._set("displayedValue", this.get('displayedValue')); - - // textDir support - if(this.textDir == "auto"){ - this.applyTextDir(this.focusNode, value); - } - }, - - format: function(value /*=====, constraints =====*/){ - // summary: - // Replaceable function to convert a value to a properly formatted string. - // value: String - // constraints: Object - // tags: - // protected extension - return value == null /* or undefined */ ? "" : (value.toString ? value.toString() : value); - }, - - parse: function(value /*=====, constraints =====*/){ - // summary: - // Replaceable function to convert a formatted string to a value - // value: String - // constraints: Object - // tags: - // protected extension - - return value; // String - }, - - _refreshState: function(){ - // summary: - // After the user types some characters, etc., this method is - // called to check the field for validity etc. The base method - // in `dijit/form/TextBox` does nothing, but subclasses override. - // tags: - // protected - }, - - /*===== - onInput: function(event){ - // summary: - // Connect to this function to receive notifications of various user data-input events. - // Return false to cancel the event and prevent it from being processed. - // event: - // keydown | keypress | cut | paste | input - // tags: - // callback - }, - =====*/ - onInput: function(){}, - - __skipInputEvent: false, - _onInput: function(/*Event*/ evt){ - // summary: - // Called AFTER the input event has happened - - // set text direction according to textDir that was defined in creation - if(this.textDir == "auto"){ - this.applyTextDir(this.focusNode, this.focusNode.value); - } - - this._processInput(evt); - }, - - _processInput: function(/*Event*/ evt){ - // summary: - // Default action handler for user input events - - this._refreshState(); - - // In case someone is watch()'ing for changes to displayedValue - this._set("displayedValue", this.get("displayedValue")); - }, - - postCreate: function(){ - // setting the value here is needed since value="" in the template causes "undefined" - // and setting in the DOM (instead of the JS object) helps with form reset actions - this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same - - this.inherited(arguments); - - // normalize input events to reduce spurious event processing - // onkeydown: do not forward modifier keys - // set charOrCode to numeric keycode - // onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown) - // onpaste & oncut: set charOrCode to 229 (IME) - // oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward - var handleEvent = function(e){ - var charOrCode; - if(e.type == "keydown"){ - charOrCode = e.keyCode; - switch(charOrCode){ // ignore state keys - case keys.SHIFT: - case keys.ALT: - case keys.CTRL: - case keys.META: - case keys.CAPS_LOCK: - case keys.NUM_LOCK: - case keys.SCROLL_LOCK: - return; - } - if(!e.ctrlKey && !e.metaKey && !e.altKey){ // no modifiers - switch(charOrCode){ // ignore location keys - case keys.NUMPAD_0: - case keys.NUMPAD_1: - case keys.NUMPAD_2: - case keys.NUMPAD_3: - case keys.NUMPAD_4: - case keys.NUMPAD_5: - case keys.NUMPAD_6: - case keys.NUMPAD_7: - case keys.NUMPAD_8: - case keys.NUMPAD_9: - case keys.NUMPAD_MULTIPLY: - case keys.NUMPAD_PLUS: - case keys.NUMPAD_ENTER: - case keys.NUMPAD_MINUS: - case keys.NUMPAD_PERIOD: - case keys.NUMPAD_DIVIDE: - return; - } - if((charOrCode >= 65 && charOrCode <= 90) || (charOrCode >= 48 && charOrCode <= 57) || charOrCode == keys.SPACE){ - return; // keypress will handle simple non-modified printable keys - } - var named = false; - for(var i in keys){ - if(keys[i] === e.keyCode){ - named = true; - break; - } - } - if(!named){ return; } // only allow named ones through - } - } - charOrCode = e.charCode >= 32 ? String.fromCharCode(e.charCode) : e.charCode; - if(!charOrCode){ - charOrCode = (e.keyCode >= 65 && e.keyCode <= 90) || (e.keyCode >= 48 && e.keyCode <= 57) || e.keyCode == keys.SPACE ? String.fromCharCode(e.keyCode) : e.keyCode; - } - if(!charOrCode){ - charOrCode = 229; // IME - } - if(e.type == "keypress"){ - if(typeof charOrCode != "string"){ return; } - if((charOrCode >= 'a' && charOrCode <= 'z') || (charOrCode >= 'A' && charOrCode <= 'Z') || (charOrCode >= '0' && charOrCode <= '9') || (charOrCode === ' ')){ - if(e.ctrlKey || e.metaKey || e.altKey){ return; } // can only be stopped reliably in keydown - } - } - if(e.type == "input"){ - if(this.__skipInputEvent){ // duplicate event - this.__skipInputEvent = false; - return; - } - }else{ - this.__skipInputEvent = true; - } - // create fake event to set charOrCode and to know if preventDefault() was called - var faux = { faux: true }, attr; - for(attr in e){ - if(attr != "layerX" && attr != "layerY"){ // prevent WebKit warnings - var v = e[attr]; - if(typeof v != "function" && typeof v != "undefined"){ faux[attr] = v; } - } - } - lang.mixin(faux, { - charOrCode: charOrCode, - _wasConsumed: false, - preventDefault: function(){ - faux._wasConsumed = true; - e.preventDefault(); - }, - stopPropagation: function(){ e.stopPropagation(); } - }); - // give web page author a chance to consume the event - //console.log(faux.type + ', charOrCode = (' + (typeof charOrCode) + ') ' + charOrCode + ', ctrl ' + !!faux.ctrlKey + ', alt ' + !!faux.altKey + ', meta ' + !!faux.metaKey + ', shift ' + !!faux.shiftKey); - if(this.onInput(faux) === false){ // return false means stop - faux.preventDefault(); - faux.stopPropagation(); - } - if(faux._wasConsumed){ return; } // if preventDefault was called - this.defer(function(){ this._onInput(faux); }); // widget notification after key has posted - }; - this.own(on(this.textbox, "keydown, keypress, paste, cut, input, compositionend", lang.hitch(this, handleEvent))); - }, - - _blankValue: '', // if the textbox is blank, what value should be reported - filter: function(val){ - // summary: - // Auto-corrections (such as trimming) that are applied to textbox - // value on blur or form submit. - // description: - // For MappedTextBox subclasses, this is called twice - // - // - once with the display value - // - once the value as set/returned by set('value', ...) - // - // and get('value'), ex: a Number for NumberTextBox. - // - // In the latter case it does corrections like converting null to NaN. In - // the former case the NumberTextBox.filter() method calls this.inherited() - // to execute standard trimming code in TextBox.filter(). - // - // TODO: break this into two methods in 2.0 - // - // tags: - // protected extension - if(val === null){ return this._blankValue; } - if(typeof val != "string"){ return val; } - if(this.trim){ - val = lang.trim(val); - } - if(this.uppercase){ - val = val.toUpperCase(); - } - if(this.lowercase){ - val = val.toLowerCase(); - } - if(this.propercase){ - val = val.replace(/[^\s]+/g, function(word){ - return word.substring(0,1).toUpperCase() + word.substring(1); - }); - } - return val; - }, - - _setBlurValue: function(){ - this._setValueAttr(this.get('value'), true); - }, - - _onBlur: function(e){ - if(this.disabled){ return; } - this._setBlurValue(); - this.inherited(arguments); - }, - - _isTextSelected: function(){ - return this.textbox.selectionStart != this.textbox.selectionEnd; - }, - - _onFocus: function(/*String*/ by){ - if(this.disabled || this.readOnly){ return; } - - // Select all text on focus via click if nothing already selected. - // Since mouse-up will clear the selection, need to defer selection until after mouse-up. - // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event. - if(this.selectOnClick && by == "mouse"){ - this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){ - // Only select all text on first click; otherwise users would have no way to clear - // the selection. - this.disconnect(this._selectOnClickHandle); - this._selectOnClickHandle = null; - - // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up) - // and if not, then select all the text - if(!this._isTextSelected()){ - _TextBoxMixin.selectInputText(this.textbox); - } - }); - // in case the mouseup never comes - this.defer(function(){ - if(this._selectOnClickHandle){ - this.disconnect(this._selectOnClickHandle); - this._selectOnClickHandle = null; - } - }, 500); // if mouseup not received soon, then treat it as some gesture - } - // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport - // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip - this.inherited(arguments); - - this._refreshState(); - }, - - reset: function(){ - // Overrides `dijit/_FormWidget/reset()`. - // Additionally resets the displayed textbox value to '' - this.textbox.value = ''; - this.inherited(arguments); - }, - - _setTextDirAttr: function(/*String*/ textDir){ - // summary: - // Setter for textDir. - // description: - // Users shouldn't call this function; they should be calling - // set('textDir', value) - // tags: - // private - - // only if new textDir is different from the old one - // and on widgets creation. - if(!this._created - || this.textDir != textDir){ - this._set("textDir", textDir); - // so the change of the textDir will take place immediately. - this.applyTextDir(this.focusNode, this.focusNode.value); - } - } -}); - - -_TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ - if(element.setSelectionRange){ - element.setSelectionRange(start, stop); - } -}; - -_TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ - // summary: - // Select text in the input element argument, from start (default 0), to stop (default end). - - // TODO: use functions in _editor/selection.js? - element = dom.byId(element); - if(isNaN(start)){ start = 0; } - if(isNaN(stop)){ stop = element.value ? element.value.length : 0; } - try{ - element.focus(); - _TextBoxMixin._setSelectionRange(element, start, stop); - }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ } -}; - -return _TextBoxMixin; -}); - -}, -'dijit/form/SimpleTextarea':function(){ -define("dijit/form/SimpleTextarea", [ - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add - "dojo/sniff", // has("ie") has("opera") - "./TextBox" -], function(declare, domClass, has, TextBox){ - -// module: -// dijit/form/SimpleTextarea - - -return declare("dijit.form.SimpleTextarea", TextBox, { - // summary: - // A simple textarea that degrades, and responds to - // minimal LayoutContainer usage, and works with dijit/form/Form. - // Doesn't automatically size according to input, like Textarea. - // - // example: - // | <textarea data-dojo-type="dijit/form/SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea> - // - // example: - // | new SimpleTextarea({ rows:20, cols:30 }, "foo"); - - baseClass: "dijitTextBox dijitTextArea", - - // rows: Number - // The number of rows of text. - rows: "3", - - // rows: Number - // The number of characters per line. - cols: "20", - - templateString: "<textarea ${!nameAttrSetting} data-dojo-attach-point='focusNode,containerNode,textbox' autocomplete='off'></textarea>", - - postMixInProperties: function(){ - // Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef) - // TODO: parser will handle this in 2.0 - if(!this.value && this.srcNodeRef){ - this.value = this.srcNodeRef.value; - } - this.inherited(arguments); - }, - - buildRendering: function(){ - this.inherited(arguments); - if(has("ie") && this.cols){ // attribute selectors is not supported in IE6 - domClass.add(this.textbox, "dijitTextAreaCols"); - } - }, - - filter: function(/*String*/ value){ - // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines - // as \r\n instead of just \n - if(value){ - value = value.replace(/\r/g,""); - } - return this.inherited(arguments); - }, - - _onInput: function(/*Event?*/ e){ - // Override TextBox._onInput() to enforce maxLength restriction - if(this.maxLength){ - var maxLength = parseInt(this.maxLength); - var value = this.textbox.value.replace(/\r/g,''); - var overflow = value.length - maxLength; - if(overflow > 0){ - var textarea = this.textbox; - if(textarea.selectionStart){ - var pos = textarea.selectionStart; - var cr = 0; - if(has("opera")){ - cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length; - } - this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr); - textarea.setSelectionRange(pos-overflow, pos-overflow); - }else if(this.ownerDocument.selection){ //IE - textarea.focus(); - var range = this.ownerDocument.selection.createRange(); - // delete overflow characters - range.moveStart("character", -overflow); - range.text = ''; - // show cursor - range.select(); - } - } - } - this.inherited(arguments); - } -}); - -}); - -}, -'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode,innerDiv,tabContent\" class=\"dijitTabInner dijitTabContent\">\n\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode'/>\n\t<span data-dojo-attach-point='containerNode,focusNode' class='tabLabel'></span>\n\t<span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t role=\"presentation\">\n\t\t<span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t\t\t></span>\n</div>\n", -'dijit/_base/window':function(){ -define("dijit/_base/window", [ - "dojo/window", // windowUtils.get - "../main" // export symbol to dijit -], function(windowUtils, dijit){ - // module: - // dijit/_base/window - - /*===== - return { - // summary: - // Back compatibility module, new code should use windowUtils directly instead of using this module. - }; - =====*/ - - dijit.getDocumentWindow = function(doc){ - return windowUtils.get(doc); - }; -}); - -}, -'dijit/PopupMenuItem':function(){ -define("dijit/PopupMenuItem", [ - "dojo/_base/declare", // declare - "dojo/dom-style", // domStyle.set - "dojo/query", // query - "./registry", // registry.byNode - "./MenuItem", - "./hccss" -], function(declare, domStyle, query, registry, MenuItem){ - - // module: - // dijit/PopupMenuItem - - return declare("dijit.PopupMenuItem", MenuItem, { - // summary: - // An item in a Menu that spawn a drop down (usually a drop down menu) - - _fillContent: function(){ - // summary: - // When Menu is declared in markup, this code gets the menu label and - // the popup widget from the srcNodeRef. - // description: - // srcNodeRefinnerHTML contains both the menu item text and a popup widget - // The first part holds the menu item text and the second part is the popup - // example: - // | <div data-dojo-type="dijit/PopupMenuItem"> - // | <span>pick me</span> - // | <popup> ... </popup> - // | </div> - // tags: - // protected - - if(this.srcNodeRef){ - var nodes = query("*", this.srcNodeRef); - this.inherited(arguments, [nodes[0]]); - - // save pointer to srcNode so we can grab the drop down widget after it's instantiated - this.dropDownContainer = this.srcNodeRef; - } - }, - - startup: function(){ - if(this._started){ return; } - this.inherited(arguments); - - // we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's - // land now. move it to win.doc.body. - if(!this.popup){ - var node = query("[widgetId]", this.dropDownContainer)[0]; - this.popup = registry.byNode(node); - } - this.ownerDocumentBody.appendChild(this.popup.domNode); - this.popup.startup(); - - this.popup.domNode.style.display="none"; - if(this.arrowWrapper){ - domStyle.set(this.arrowWrapper, "visibility", ""); - } - this.focusNode.setAttribute("aria-haspopup", "true"); - }, - - destroyDescendants: function(/*Boolean*/ preserveDom){ - if(this.popup){ - // Destroy the popup, unless it's already been destroyed. This can happen because - // the popup is a direct child of <body> even though it's logically my child. - if(!this.popup._destroyed){ - this.popup.destroyRecursive(preserveDom); - } - delete this.popup; - } - this.inherited(arguments); - } - }); -}); - -}, -'dojo/hccss':function(){ -define("dojo/hccss", [ - "require", // require.toUrl - "./_base/config", // config.blankGif - "./dom-class", // domClass.add - "./dom-style", // domStyle.getComputedStyle - "./has", - "./ready", // ready - "./_base/window" // win.body -], function(require, config, domClass, domStyle, has, ready, win){ - - // module: - // dojo/hccss - - /*===== - return function(){ - // summary: - // Test if computer is in high contrast mode (i.e. if browser is not displaying background images). - // Defines `has("highcontrast")` and sets `dj_a11y` CSS class on `<body>` if machine is in high contrast mode. - // Returns `has()` method; - }; - =====*/ - - // Has() test for when background images aren't displayed. Don't call has("highcontrast") before dojo/domReady!. - has.add("highcontrast", function(){ - // note: if multiple documents, doesn't matter which one we use - var div = win.doc.createElement("div"); - div.style.cssText = "border: 1px solid; border-color:red green; position: absolute; height: 5px; top: -999px;" + - "background-image: url(" + (config.blankGif || require.toUrl("./resources/blank.gif")) + ");"; - win.body().appendChild(div); - - var cs = domStyle.getComputedStyle(div), - bkImg = cs.backgroundImage, - hc = (cs.borderTopColor == cs.borderRightColor) || - (bkImg && (bkImg == "none" || bkImg == "url(invalid-url:)" )); - - if(has("ie") <= 8){ - div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014 - }else{ - win.body().removeChild(div); - } - - return hc; - }); - - // Priority is 90 to run ahead of parser priority of 100. For 2.0, remove the ready() call and instead - // change this module to depend on dojo/domReady! - ready(90, function(){ - if(has("highcontrast")){ - domClass.add(win.body(), "dj_a11y"); - } - }); - - return has; -}); - -}, -'dijit/form/RadioButton':function(){ -define("dijit/form/RadioButton", [ - "dojo/_base/declare", // declare - "./CheckBox", - "./_RadioButtonMixin" -], function(declare, CheckBox, _RadioButtonMixin){ - - // module: - // dijit/form/RadioButton - - return declare("dijit.form.RadioButton", [CheckBox, _RadioButtonMixin], { - // summary: - // Same as an HTML radio, but with fancy styling. - - baseClass: "dijitRadio" - }); -}); - -}, -'dijit/main':function(){ -define("dijit/main", [ - "dojo/_base/kernel" -], function(dojo){ - // module: - // dijit/main - -/*===== -return { - // summary: - // The dijit package main module. - // Deprecated. Users should access individual modules (ex: dijit/registry) directly. -}; -=====*/ - - return dojo.dijit; -}); - -}, -'dijit/_OnDijitClickMixin':function(){ -define("dijit/_OnDijitClickMixin", [ - "dojo/on", - "dojo/_base/array", // array.forEach - "dojo/keys", // keys.ENTER keys.SPACE - "dojo/_base/declare", // declare - "dojo/has", // has("dom-addeventlistener") - "dojo/_base/unload", // unload.addOnWindowUnload - "dojo/_base/window", // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent - "./a11yclick" -], function(on, array, keys, declare, has, unload, win, a11yclick){ - - // module: - // dijit/_OnDijitClickMixin - - var ret = declare("dijit._OnDijitClickMixin", null, { - connect: function( - /*Object|null*/ obj, - /*String|Function*/ event, - /*String|Function*/ method){ - // summary: - // Connects specified obj/event to specified method of this object - // and registers for disconnect() on widget destroy. - // description: - // Provide widget-specific analog to connect.connect, except with the - // implicit use of this widget as the target object. - // This version of connect also provides a special "ondijitclick" - // event which triggers on a click or space or enter keyup. - // Events connected with `this.connect` are disconnected upon - // destruction. - // returns: - // A handle that can be passed to `disconnect` in order to disconnect before - // the widget is destroyed. - // example: - // | var btn = new Button(); - // | // when foo.bar() is called, call the listener we're going to - // | // provide in the scope of btn - // | btn.connect(foo, "bar", function(){ - // | console.debug(this.toString()); - // | }); - // tags: - // protected - - return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]); - } - }); - - ret.a11yclick = a11yclick; // back compat - - return ret; -}); - -}, -'dijit/InlineEditBox':function(){ -require({cache:{ -'url:dijit/templates/InlineEditBox.html':"<span data-dojo-attach-point=\"editNode\" role=\"presentation\" class=\"dijitReset dijitInline dijitOffScreen\"\n\tdata-dojo-attach-event=\"onkeypress: _onKeyPress\"\n\t><span data-dojo-attach-point=\"editorPlaceholder\"></span\n\t><span data-dojo-attach-point=\"buttonContainer\"\n\t\t><button data-dojo-type=\"dijit/form/Button\" data-dojo-props=\"label: '${buttonSave}', 'class': 'saveButton'\"\n\t\t\tdata-dojo-attach-point=\"saveButton\" data-dojo-attach-event=\"onClick:save\"></button\n\t\t><button data-dojo-type=\"dijit/form/Button\" data-dojo-props=\"label: '${buttonCancel}', 'class': 'cancelButton'\"\n\t\t\tdata-dojo-attach-point=\"cancelButton\" data-dojo-attach-event=\"onClick:cancel\"></button\n\t></span\n></span>\n"}}); -define("dijit/InlineEditBox", [ - "require", - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set domAttr.get - "dojo/dom-class", // domClass.add domClass.remove domClass.toggle - "dojo/dom-construct", // domConstruct.create domConstruct.destroy - "dojo/dom-style", // domStyle.getComputedStyle domStyle.set domStyle.get - "dojo/_base/event", // event.stop - "dojo/i18n", // i18n.getLocalization - "dojo/_base/kernel", // kernel.deprecated - "dojo/keys", // keys.ENTER keys.ESCAPE - "dojo/_base/lang", // lang.getObject - "dojo/sniff", // has("ie") - "dojo/when", - "./focus", - "./_Widget", - "./_TemplatedMixin", - "./_WidgetsInTemplateMixin", - "./_Container", - "./form/Button", - "./form/_TextBoxMixin", - "./form/TextBox", - "dojo/text!./templates/InlineEditBox.html", - "dojo/i18n!./nls/common" -], function(require, array, declare, domAttr, domClass, domConstruct, domStyle, event, i18n, kernel, keys, lang, has, when, - fm, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, Button, _TextBoxMixin, TextBox, template){ - - // module: - // dijit/InlineEditBox - - var InlineEditor = declare("dijit._InlineEditor", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], { - // summary: - // Internal widget used by InlineEditBox, displayed when in editing mode - // to display the editor and maybe save/cancel buttons. Calling code should - // connect to save/cancel methods to detect when editing is finished - // - // Has mainly the same parameters as InlineEditBox, plus these values: - // - // style: Object - // Set of CSS attributes of display node, to replicate in editor - // - // value: String - // Value as an HTML string or plain text string, depending on renderAsHTML flag - - templateString: template, - - postMixInProperties: function(){ - this.inherited(arguments); - this.messages = i18n.getLocalization("dijit", "common", this.lang); - array.forEach(["buttonSave", "buttonCancel"], function(prop){ - if(!this[prop]){ - this[prop] = this.messages[prop]; - } - }, this); - }, - - buildRendering: function(){ - this.inherited(arguments); - - // Create edit widget in place in the template - // TODO: remove getObject() for 2.0 - var Cls = typeof this.editor == "string" ? (lang.getObject(this.editor) || require(this.editor)) : this.editor; - - // Copy the style from the source - // Don't copy ALL properties though, just the necessary/applicable ones. - // wrapperStyle/destStyle code is to workaround IE bug where getComputedStyle().fontSize - // is a relative value like 200%, rather than an absolute value like 24px, and - // the 200% can refer *either* to a setting on the node or it's ancestor (see #11175) - var srcStyle = this.sourceStyle, - editStyle = "line-height:" + srcStyle.lineHeight + ";", - destStyle = domStyle.getComputedStyle(this.domNode); - array.forEach(["Weight", "Family", "Size", "Style"], function(prop){ - var textStyle = srcStyle["font" + prop], - wrapperStyle = destStyle["font" + prop]; - if(wrapperStyle != textStyle){ - editStyle += "font-" + prop + ":" + srcStyle["font" + prop] + ";"; - } - }, this); - array.forEach(["marginTop", "marginBottom", "marginLeft", "marginRight", "position", "left", "top", "right", "bottom", "float", "clear", "display"], function(prop){ - this.domNode.style[prop] = srcStyle[prop]; - }, this); - var width = this.inlineEditBox.width; - if(width == "100%"){ - // block mode - editStyle += "width:100%;"; - this.domNode.style.display = "block"; - }else{ - // inline-block mode - editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";"; - } - var editorParams = lang.delegate(this.inlineEditBox.editorParams, { - style: editStyle, - dir: this.dir, - lang: this.lang, - textDir: this.textDir - }); - editorParams[ "displayedValue" in Cls.prototype ? "displayedValue" : "value"] = this.value; - this.editWidget = new Cls(editorParams, this.editorPlaceholder); - - if(this.inlineEditBox.autoSave){ - // Remove the save/cancel buttons since saving is done by simply tabbing away or - // selecting a value from the drop down list - domConstruct.destroy(this.buttonContainer); - } - }, - - postCreate: function(){ - this.inherited(arguments); - - var ew = this.editWidget; - - if(this.inlineEditBox.autoSave){ - // Selecting a value from a drop down list causes an onChange event and then we save - this.connect(ew, "onChange", "_onChange"); - - // ESC and TAB should cancel and save. Note that edit widgets do a stopEvent() on ESC key (to - // prevent Dialog from closing when the user just wants to revert the value in the edit widget), - // so this is the only way we can see the key press event. - this.connect(ew, "onKeyPress", "_onKeyPress"); - }else{ - // If possible, enable/disable save button based on whether the user has changed the value - if("intermediateChanges" in ew){ - ew.set("intermediateChanges", true); - this.connect(ew, "onChange", "_onIntermediateChange"); - this.saveButton.set("disabled", true); - } - } - }, - - startup: function(){ - this.editWidget.startup(); - this.inherited(arguments); - }, - - _onIntermediateChange: function(/*===== val =====*/){ - // summary: - // Called for editor widgets that support the intermediateChanges=true flag as a way - // to detect when to enable/disabled the save button - this.saveButton.set("disabled", (this.getValue() == this._resetValue) || !this.enableSave()); - }, - - destroy: function(){ - this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM - this.inherited(arguments); - }, - - getValue: function(){ - // summary: - // Return the [display] value of the edit widget - var ew = this.editWidget; - return String(ew.get("displayedValue" in ew ? "displayedValue" : "value")); - }, - - _onKeyPress: function(e){ - // summary: - // Handler for keypress in the edit box in autoSave mode. - // description: - // For autoSave widgets, if Esc/Enter, call cancel/save. - // tags: - // private - - if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){ - if(e.altKey || e.ctrlKey){ - return; - } - // If Enter/Esc pressed, treat as save/cancel. - if(e.charOrCode == keys.ESCAPE){ - event.stop(e); - this.cancel(true); // sets editing=false which short-circuits _onBlur processing - }else if(e.charOrCode == keys.ENTER && e.target.tagName == "INPUT"){ - event.stop(e); - this._onChange(); // fire _onBlur and then save - } - - // _onBlur will handle TAB automatically by allowing - // the TAB to change focus before we mess with the DOM: #6227 - // Expounding by request: - // The current focus is on the edit widget input field. - // save() will hide and destroy this widget. - // We want the focus to jump from the currently hidden - // displayNode, but since it's hidden, it's impossible to - // unhide it, focus it, and then have the browser focus - // away from it to the next focusable element since each - // of these events is asynchronous and the focus-to-next-element - // is already queued. - // So we allow the browser time to unqueue the move-focus event - // before we do all the hide/show stuff. - } - }, - - _onBlur: function(){ - // summary: - // Called when focus moves outside the editor - // tags: - // private - - this.inherited(arguments); - if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){ - if(this.getValue() == this._resetValue){ - this.cancel(false); - }else if(this.enableSave()){ - this.save(false); - } - } - }, - - _onChange: function(){ - // summary: - // Called when the underlying widget fires an onChange event, - // such as when the user selects a value from the drop down list of a ComboBox, - // which means that the user has finished entering the value and we should save. - // tags: - // private - - if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){ - fm.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value - } - }, - - enableSave: function(){ - // summary: - // User overridable function returning a Boolean to indicate - // if the Save button should be enabled or not - usually due to invalid conditions - // tags: - // extension - return this.editWidget.isValid ? this.editWidget.isValid() : true; - }, - - focus: function(){ - // summary: - // Focus the edit widget. - // tags: - // protected - - this.editWidget.focus(); - - if(this.editWidget.focusNode){ - // IE can take 30ms to report the focus event, but focus manager needs to know before a 0ms timeout. - fm._onFocusNode(this.editWidget.focusNode); - - if(this.editWidget.focusNode.tagName == "INPUT"){ - this.defer(function(){ - _TextBoxMixin.selectInputText(this.editWidget.focusNode); - }); - } - } - } - }); - - - var InlineEditBox = declare("dijit.InlineEditBox", _Widget, { - // summary: - // An element with in-line edit capabilities - // - // description: - // Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that - // when you click it, an editor shows up in place of the original - // text. Optionally, Save and Cancel button are displayed below the edit widget. - // When Save is clicked, the text is pulled from the edit - // widget and redisplayed and the edit widget is again hidden. - // By default a plain Textarea widget is used as the editor (or for - // inline values a TextBox), but you can specify an editor such as - // dijit.Editor (for editing HTML) or a Slider (for adjusting a number). - // An edit widget must support the following API to be used: - // - // - displayedValue or value as initialization parameter, - // and available through set('displayedValue') / set('value') - // - void focus() - // - DOM-node focusNode = node containing editable text - - // editing: [readonly] Boolean - // Is the node currently in edit mode? - editing: false, - - // autoSave: Boolean - // Changing the value automatically saves it; don't have to push save button - // (and save button isn't even displayed) - autoSave: true, - - // buttonSave: String - // Save button label - buttonSave: "", - - // buttonCancel: String - // Cancel button label - buttonCancel: "", - - // renderAsHtml: Boolean - // Set this to true if the specified Editor's value should be interpreted as HTML - // rather than plain text (ex: `dijit.Editor`) - renderAsHtml: false, - - // editor: String|Function - // MID (ex: "dijit/form/TextBox") or constructor for editor widget - editor: TextBox, - - // editorWrapper: String|Function - // Class name (or reference to the Class) for widget that wraps the editor widget, displaying save/cancel - // buttons. - editorWrapper: InlineEditor, - - // editorParams: Object - // Set of parameters for editor, like {required: true} - editorParams: {}, - - // disabled: Boolean - // If true, clicking the InlineEditBox to edit it will have no effect. - disabled: false, - - onChange: function(/*===== value =====*/){ - // summary: - // Set this handler to be notified of changes to value. - // tags: - // callback - }, - - onCancel: function(){ - // summary: - // Set this handler to be notified when editing is cancelled. - // tags: - // callback - }, - - // width: String - // Width of editor. By default it's width=100% (ie, block mode). - width: "100%", - - // value: String - // The display value of the widget in read-only mode - value: "", - - // noValueIndicator: [const] String - // The text that gets displayed when there is no value (so that the user has a place to click to edit) - noValueIndicator: has("ie") <= 6 ? // font-family needed on IE6 but it messes up IE8 - "<span style='font-family: wingdings; text-decoration: underline;'>    ✍    </span>" : - "<span style='text-decoration: underline;'>    ✍    </span>", //   == - - constructor: function(/*===== params, srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified: - // - // - use srcNodeRef.innerHTML as my value - // - replace srcNodeRef with my generated DOM tree - - this.editorParams = {}; - }, - - postMixInProperties: function(){ - this.inherited(arguments); - - // save pointer to original source node, since Widget nulls-out srcNodeRef - this.displayNode = this.srcNodeRef; - - // connect handlers to the display node - var events = { - ondijitclick: "_onClick", - onmouseover: "_onMouseOver", - onmouseout: "_onMouseOut", - onfocus: "_onMouseOver", - onblur: "_onMouseOut" - }; - for(var name in events){ - this.connect(this.displayNode, name, events[name]); - } - this.displayNode.setAttribute("role", "button"); - if(!this.displayNode.getAttribute("tabIndex")){ - this.displayNode.setAttribute("tabIndex", 0); - } - - if(!this.value && !("value" in this.params)){ // "" is a good value if specified directly so check params){ - this.value = lang.trim(this.renderAsHtml ? this.displayNode.innerHTML : - (this.displayNode.innerText || this.displayNode.textContent || "")); - } - if(!this.value){ - this.displayNode.innerHTML = this.noValueIndicator; - } - - domClass.add(this.displayNode, 'dijitInlineEditBoxDisplayMode'); - }, - - setDisabled: function(/*Boolean*/ disabled){ - // summary: - // Deprecated. Use set('disabled', ...) instead. - // tags: - // deprecated - kernel.deprecated("dijit.InlineEditBox.setDisabled() is deprecated. Use set('disabled', bool) instead.", "", "2.0"); - this.set('disabled', disabled); - }, - - _setDisabledAttr: function(/*Boolean*/ disabled){ - // summary: - // Hook to make set("disabled", ...) work. - // Set disabled state of widget. - this.domNode.setAttribute("aria-disabled", disabled ? "true" : "false"); - if(disabled){ - this.displayNode.removeAttribute("tabIndex"); - }else{ - this.displayNode.setAttribute("tabIndex", 0); - } - domClass.toggle(this.displayNode, "dijitInlineEditBoxDisplayModeDisabled", disabled); - this._set("disabled", disabled); - }, - - _onMouseOver: function(){ - // summary: - // Handler for onmouseover and onfocus event. - // tags: - // private - if(!this.disabled){ - domClass.add(this.displayNode, "dijitInlineEditBoxDisplayModeHover"); - } - }, - - _onMouseOut: function(){ - // summary: - // Handler for onmouseout and onblur event. - // tags: - // private - domClass.remove(this.displayNode, "dijitInlineEditBoxDisplayModeHover"); - }, - - _onClick: function(/*Event*/ e){ - // summary: - // Handler for onclick event. - // tags: - // private - if(this.disabled){ - return; - } - if(e){ - event.stop(e); - } - this._onMouseOut(); - - // Since FF gets upset if you move a node while in an event handler for that node... - this.defer("edit"); - }, - - edit: function(){ - // summary: - // Display the editor widget in place of the original (read only) markup. - // tags: - // private - - if(this.disabled || this.editing){ - return; - } - this._set('editing', true); - - // save some display node values that can be restored later - this._savedTabIndex = domAttr.get(this.displayNode, "tabIndex") || "0"; - - if(this.wrapperWidget){ - var ew = this.wrapperWidget.editWidget; - ew.set("displayedValue" in ew ? "displayedValue" : "value", this.value); - }else{ - // Placeholder for edit widget - // Put place holder (and eventually editWidget) before the display node so that it's positioned correctly - // when Calendar dropdown appears, which happens automatically on focus. - var placeholder = domConstruct.create("span", null, this.domNode, "before"); - - // Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons) - var Ewc = typeof this.editorWrapper == "string" ? lang.getObject(this.editorWrapper) : this.editorWrapper; - this.wrapperWidget = new Ewc({ - value: this.value, - buttonSave: this.buttonSave, - buttonCancel: this.buttonCancel, - dir: this.dir, - lang: this.lang, - tabIndex: this._savedTabIndex, - editor: this.editor, - inlineEditBox: this, - sourceStyle: domStyle.getComputedStyle(this.displayNode), - save: lang.hitch(this, "save"), - cancel: lang.hitch(this, "cancel"), - textDir: this.textDir - }, placeholder); - if(!this.wrapperWidget._started){ - this.wrapperWidget.startup(); - } - if(!this._started){ - this.startup(); - } - } - var ww = this.wrapperWidget; - - // to avoid screen jitter, we first create the editor with position: absolute, visibility: hidden, - // and then when it's finished rendering, we switch from display mode to editor - // position: absolute releases screen space allocated to the display node - // opacity:0 is the same as visibility: hidden but is still focusable - // visibility: hidden removes focus outline - - domClass.add(this.displayNode, "dijitOffScreen"); - domClass.remove(ww.domNode, "dijitOffScreen"); - domStyle.set(ww.domNode, { visibility: "visible" }); - domAttr.set(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode - - // After edit widget has finished initializing (in particular need to wait for dijit.Editor), - // or immediately if there is no onLoadDeferred Deferred, - // replace the display widget with edit widget, leaving them both displayed for a brief time so that - // focus can be shifted without incident. - when(ww.editWidget.onLoadDeferred, lang.hitch(ww, function(){ - this.defer(function(){ // defer needed so that the change of focus doesn't happen on mousedown which also sets focus - this.focus(); // both nodes are showing, so we can switch focus safely - this._resetValue = this.getValue(); - }); - })); - }, - - _onBlur: function(){ - // summary: - // Called when focus moves outside the InlineEditBox. - // Performs garbage collection. - // tags: - // private - - this.inherited(arguments); - if(!this.editing){ - /* causes IE focus problems, see TooltipDialog_a11y.html... - this.defer(function(){ - if(this.wrapperWidget){ - this.wrapperWidget.destroy(); - delete this.wrapperWidget; - } - }); - */ - } - }, - - destroy: function(){ - if(this.wrapperWidget && !this.wrapperWidget._destroyed){ - this.wrapperWidget.destroy(); - delete this.wrapperWidget; - } - this.inherited(arguments); - }, - - _showText: function(/*Boolean*/ focus){ - // summary: - // Revert to display mode, and optionally focus on display node - // tags: - // private - - var ww = this.wrapperWidget; - domStyle.set(ww.domNode, { visibility: "hidden" }); // hide the editor from mouse/keyboard events - domClass.add(ww.domNode, "dijitOffScreen"); - domClass.remove(this.displayNode, "dijitOffScreen"); - domAttr.set(this.displayNode, "tabIndex", this._savedTabIndex); - if(focus){ - fm.focus(this.displayNode); - } - }, - - save: function(/*Boolean*/ focus){ - // summary: - // Save the contents of the editor and revert to display mode. - // focus: Boolean - // Focus on the display mode text - // tags: - // private - - if(this.disabled || !this.editing){ - return; - } - this._set('editing', false); - - var ww = this.wrapperWidget; - var value = ww.getValue(); - this.set('value', value); // display changed, formatted value - - this._showText(focus); // set focus as needed - }, - - setValue: function(/*String*/ val){ - // summary: - // Deprecated. Use set('value', ...) instead. - // tags: - // deprecated - kernel.deprecated("dijit.InlineEditBox.setValue() is deprecated. Use set('value', ...) instead.", "", "2.0"); - return this.set("value", val); - }, - - _setValueAttr: function(/*String*/ val){ - // summary: - // Hook to make set("value", ...) work. - // Inserts specified HTML value into this node, or an "input needed" character if node is blank. - - val = lang.trim(val); - var renderVal = this.renderAsHtml ? val : val.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """).replace(/\n/g, "<br>"); - this.displayNode.innerHTML = renderVal || this.noValueIndicator; - this._set("value", val); - - if(this._started){ - // tell the world that we have changed - this.defer(function(){ - this.onChange(val); - }); // defer prevents browser freeze for long-running event handlers - } - // contextual (auto) text direction depends on the text value - if(this.textDir == "auto"){ - this.applyTextDir(this.displayNode, this.displayNode.innerText); - } - }, - - getValue: function(){ - // summary: - // Deprecated. Use get('value') instead. - // tags: - // deprecated - kernel.deprecated("dijit.InlineEditBox.getValue() is deprecated. Use get('value') instead.", "", "2.0"); - return this.get("value"); - }, - - cancel: function(/*Boolean*/ focus){ - // summary: - // Revert to display mode, discarding any changes made in the editor - // tags: - // private - - if(this.disabled || !this.editing){ - return; - } - this._set('editing', false); - - // tell the world that we have no changes - this.defer("onCancel"); // defer prevents browser freeze for long-running event handlers - - this._showText(focus); - }, - - _setTextDirAttr: function(/*String*/ textDir){ - // summary: - // Setter for textDir. - // description: - // Users shouldn't call this function; they should be calling - // set('textDir', value) - // tags: - // private - if(!this._created || this.textDir != textDir){ - this._set("textDir", textDir); - this.applyTextDir(this.displayNode, this.displayNode.innerText); - this.displayNode.align = this.dir == "rtl" ? "right" : "left"; //fix the text alignment - } - } - }); - - InlineEditBox._InlineEditor = InlineEditor; // for monkey patching - - return InlineEditBox; -}); -}, -'dojo/selector/acme':function(){ -define("dojo/selector/acme", [ - "../dom", "../sniff", "../_base/array", "../_base/lang", "../_base/window" -], function(dom, has, array, lang, win){ - - // module: - // dojo/selector/acme - -/* - acme architectural overview: - - acme is a relatively full-featured CSS3 query library. It is - designed to take any valid CSS3 selector and return the nodes matching - the selector. To do this quickly, it processes queries in several - steps, applying caching where profitable. - - The steps (roughly in reverse order of the way they appear in the code): - 1.) check to see if we already have a "query dispatcher" - - if so, use that with the given parameterization. Skip to step 4. - 2.) attempt to determine which branch to dispatch the query to: - - JS (optimized DOM iteration) - - native (FF3.1+, Safari 3.1+, IE 8+) - 3.) tokenize and convert to executable "query dispatcher" - - this is where the lion's share of the complexity in the - system lies. In the DOM version, the query dispatcher is - assembled as a chain of "yes/no" test functions pertaining to - a section of a simple query statement (".blah:nth-child(odd)" - but not "div div", which is 2 simple statements). Individual - statement dispatchers are cached (to prevent re-definition) - as are entire dispatch chains (to make re-execution of the - same query fast) - 4.) the resulting query dispatcher is called in the passed scope - (by default the top-level document) - - for DOM queries, this results in a recursive, top-down - evaluation of nodes based on each simple query section - - for native implementations, this may mean working around spec - bugs. So be it. - 5.) matched nodes are pruned to ensure they are unique (if necessary) -*/ - - - //////////////////////////////////////////////////////////////////////// - // Toolkit aliases - //////////////////////////////////////////////////////////////////////// - - // if you are extracting acme for use in your own system, you will - // need to provide these methods and properties. No other porting should be - // necessary, save for configuring the system to use a class other than - // dojo/NodeList as the return instance instantiator - var trim = lang.trim; - var each = array.forEach; - - var getDoc = function(){ return win.doc; }; - // NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo - var cssCaseBug = (getDoc().compatMode) == "BackCompat"; - - //////////////////////////////////////////////////////////////////////// - // Global utilities - //////////////////////////////////////////////////////////////////////// - - - var specials = ">~+"; - - // global thunk to determine whether we should treat the current query as - // case sensitive or not. This switch is flipped by the query evaluator - // based on the document passed as the context to search. - var caseSensitive = false; - - // how high? - var yesman = function(){ return true; }; - - //////////////////////////////////////////////////////////////////////// - // Tokenizer - //////////////////////////////////////////////////////////////////////// - - var getQueryParts = function(query){ - // summary: - // state machine for query tokenization - // description: - // instead of using a brittle and slow regex-based CSS parser, - // acme implements an AST-style query representation. This - // representation is only generated once per query. For example, - // the same query run multiple times or under different root nodes - // does not re-parse the selector expression but instead uses the - // cached data structure. The state machine implemented here - // terminates on the last " " (space) character and returns an - // ordered array of query component structures (or "parts"). Each - // part represents an operator or a simple CSS filtering - // expression. The structure for parts is documented in the code - // below. - - - // NOTE: - // this code is designed to run fast and compress well. Sacrifices - // to readability and maintainability have been made. Your best - // bet when hacking the tokenizer is to put The Donnas on *really* - // loud (may we recommend their "Spend The Night" release?) and - // just assume you're gonna make mistakes. Keep the unit tests - // open and run them frequently. Knowing is half the battle ;-) - if(specials.indexOf(query.slice(-1)) >= 0){ - // if we end with a ">", "+", or "~", that means we're implicitly - // searching all children, so make it explicit - query += " * "; - }else{ - // if you have not provided a terminator, one will be provided for - // you... - query += " "; - } - - var ts = function(/*Integer*/ s, /*Integer*/ e){ - // trim and slice. - - // take an index to start a string slice from and an end position - // and return a trimmed copy of that sub-string - return trim(query.slice(s, e)); - }; - - // the overall data graph of the full query, as represented by queryPart objects - var queryParts = []; - - - // state keeping vars - var inBrackets = -1, inParens = -1, inMatchFor = -1, - inPseudo = -1, inClass = -1, inId = -1, inTag = -1, currentQuoteChar, - lc = "", cc = "", pStart; - - // iteration vars - var x = 0, // index in the query - ql = query.length, - currentPart = null, // data structure representing the entire clause - _cp = null; // the current pseudo or attr matcher - - // several temporary variables are assigned to this structure during a - // potential sub-expression match: - // attr: - // a string representing the current full attribute match in a - // bracket expression - // type: - // if there's an operator in a bracket expression, this is - // used to keep track of it - // value: - // the internals of parenthetical expression for a pseudo. for - // :nth-child(2n+1), value might be "2n+1" - - var endTag = function(){ - // called when the tokenizer hits the end of a particular tag name. - // Re-sets state variables for tag matching and sets up the matcher - // to handle the next type of token (tag or operator). - if(inTag >= 0){ - var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase(); - currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv; - inTag = -1; - } - }; - - var endId = function(){ - // called when the tokenizer might be at the end of an ID portion of a match - if(inId >= 0){ - currentPart.id = ts(inId, x).replace(/\\/g, ""); - inId = -1; - } - }; - - var endClass = function(){ - // called when the tokenizer might be at the end of a class name - // match. CSS allows for multiple classes, so we augment the - // current item with another class in its list - if(inClass >= 0){ - currentPart.classes.push(ts(inClass + 1, x).replace(/\\/g, "")); - inClass = -1; - } - }; - - var endAll = function(){ - // at the end of a simple fragment, so wall off the matches - endId(); - endTag(); - endClass(); - }; - - var endPart = function(){ - endAll(); - if(inPseudo >= 0){ - currentPart.pseudos.push({ name: ts(inPseudo + 1, x) }); - } - // hint to the selector engine to tell it whether or not it - // needs to do any iteration. Many simple selectors don't, and - // we can avoid significant construction-time work by advising - // the system to skip them - currentPart.loops = ( - currentPart.pseudos.length || - currentPart.attrs.length || - currentPart.classes.length ); - - currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string - - - // otag/tag are hints to suggest to the system whether or not - // it's an operator or a tag. We save a copy of otag since the - // tag name is cast to upper-case in regular HTML matches. The - // system has a global switch to figure out if the current - // expression needs to be case sensitive or not and it will use - // otag or tag accordingly - currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*"); - - if(currentPart.tag){ - // if we're in a case-insensitive HTML doc, we likely want - // the toUpperCase when matching on element.tagName. If we - // do it here, we can skip the string op per node - // comparison - currentPart.tag = currentPart.tag.toUpperCase(); - } - - // add the part to the list - if(queryParts.length && (queryParts[queryParts.length-1].oper)){ - // operators are always infix, so we remove them from the - // list and attach them to the next match. The evaluator is - // responsible for sorting out how to handle them. - currentPart.infixOper = queryParts.pop(); - currentPart.query = currentPart.infixOper.query + " " + currentPart.query; - /* - console.debug( "swapping out the infix", - currentPart.infixOper, - "and attaching it to", - currentPart); - */ - } - queryParts.push(currentPart); - - currentPart = null; - }; - - // iterate over the query, character by character, building up a - // list of query part objects - for(; lc=cc, cc=query.charAt(x), x < ql; x++){ - // cc: the current character in the match - // lc: the last character (if any) - - // someone is trying to escape something, so don't try to match any - // fragments. We assume we're inside a literal. - if(lc == "\\"){ continue; } - if(!currentPart){ // a part was just ended or none has yet been created - // NOTE: I hate all this alloc, but it's shorter than writing tons of if's - pStart = x; - // rules describe full CSS sub-expressions, like: - // #someId - // .className:first-child - // but not: - // thinger > div.howdy[type=thinger] - // the indidual components of the previous query would be - // split into 3 parts that would be represented a structure like: - // [ - // { - // query: "thinger", - // tag: "thinger", - // }, - // { - // query: "div.howdy[type=thinger]", - // classes: ["howdy"], - // infixOper: { - // query: ">", - // oper: ">", - // } - // }, - // ] - currentPart = { - query: null, // the full text of the part's rule - pseudos: [], // CSS supports multiple pseud-class matches in a single rule - attrs: [], // CSS supports multi-attribute match, so we need an array - classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy - tag: null, // only one tag... - oper: null, // ...or operator per component. Note that these wind up being exclusive. - id: null, // the id component of a rule - getTag: function(){ - return caseSensitive ? this.otag : this.tag; - } - }; - - // if we don't have a part, we assume we're going to start at - // the beginning of a match, which should be a tag name. This - // might fault a little later on, but we detect that and this - // iteration will still be fine. - inTag = x; - } - - // Skip processing all quoted characters. - // If we are inside quoted text then currentQuoteChar stores the character that began the quote, - // thus that character that will end it. - if(currentQuoteChar){ - if(cc == currentQuoteChar){ - currentQuoteChar = null; - } - continue; - }else if (cc == "'" || cc == '"'){ - currentQuoteChar = cc; - continue; - } - - if(inBrackets >= 0){ - // look for a the close first - if(cc == "]"){ // if we're in a [...] clause and we end, do assignment - if(!_cp.attr){ - // no attribute match was previously begun, so we - // assume this is an attribute existence match in the - // form of [someAttributeName] - _cp.attr = ts(inBrackets+1, x); - }else{ - // we had an attribute already, so we know that we're - // matching some sort of value, as in [attrName=howdy] - _cp.matchFor = ts((inMatchFor||inBrackets+1), x); - } - var cmf = _cp.matchFor; - if(cmf){ - // try to strip quotes from the matchFor value. We want - // [attrName=howdy] to match the same - // as [attrName = 'howdy' ] - if( (cmf.charAt(0) == '"') || (cmf.charAt(0) == "'") ){ - _cp.matchFor = cmf.slice(1, -1); - } - } - // remove backslash escapes from an attribute match, since DOM - // querying will get attribute values without backslashes - if(_cp.matchFor){ - _cp.matchFor = _cp.matchFor.replace(/\\/g, ""); - } - - // end the attribute by adding it to the list of attributes. - currentPart.attrs.push(_cp); - _cp = null; // necessary? - inBrackets = inMatchFor = -1; - }else if(cc == "="){ - // if the last char was an operator prefix, make sure we - // record it along with the "=" operator. - var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : ""; - _cp.type = addToCc+cc; - _cp.attr = ts(inBrackets+1, x-addToCc.length); - inMatchFor = x+1; - } - // now look for other clause parts - }else if(inParens >= 0){ - // if we're in a parenthetical expression, we need to figure - // out if it's attached to a pseudo-selector rule like - // :nth-child(1) - if(cc == ")"){ - if(inPseudo >= 0){ - _cp.value = ts(inParens+1, x); - } - inPseudo = inParens = -1; - } - }else if(cc == "#"){ - // start of an ID match - endAll(); - inId = x+1; - }else if(cc == "."){ - // start of a class match - endAll(); - inClass = x; - }else if(cc == ":"){ - // start of a pseudo-selector match - endAll(); - inPseudo = x; - }else if(cc == "["){ - // start of an attribute match. - endAll(); - inBrackets = x; - // provide a new structure for the attribute match to fill-in - _cp = { - /*===== - attr: null, type: null, matchFor: null - =====*/ - }; - }else if(cc == "("){ - // we really only care if we've entered a parenthetical - // expression if we're already inside a pseudo-selector match - if(inPseudo >= 0){ - // provide a new structure for the pseudo match to fill-in - _cp = { - name: ts(inPseudo+1, x), - value: null - }; - currentPart.pseudos.push(_cp); - } - inParens = x; - }else if( - (cc == " ") && - // if it's a space char and the last char is too, consume the - // current one without doing more work - (lc != cc) - ){ - endPart(); - } - } - return queryParts; - }; - - - //////////////////////////////////////////////////////////////////////// - // DOM query infrastructure - //////////////////////////////////////////////////////////////////////// - - var agree = function(first, second){ - // the basic building block of the yes/no chaining system. agree(f1, - // f2) generates a new function which returns the boolean results of - // both of the passed functions to a single logical-anded result. If - // either are not passed, the other is used exclusively. - if(!first){ return second; } - if(!second){ return first; } - - return function(){ - return first.apply(window, arguments) && second.apply(window, arguments); - }; - }; - - var getArr = function(i, arr){ - // helps us avoid array alloc when we don't need it - var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ? - if(i){ r.push(i); } - return r; - }; - - var _isElement = function(n){ return (1 == n.nodeType); }; - - // FIXME: need to coalesce _getAttr with defaultGetter - var blank = ""; - var _getAttr = function(elem, attr){ - if(!elem){ return blank; } - if(attr == "class"){ - return elem.className || blank; - } - if(attr == "for"){ - return elem.htmlFor || blank; - } - if(attr == "style"){ - return elem.style.cssText || blank; - } - return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank; - }; - - var attrs = { - "*=": function(attr, value){ - return function(elem){ - // E[foo*="bar"] - // an E element whose "foo" attribute value contains - // the substring "bar" - return (_getAttr(elem, attr).indexOf(value)>=0); - }; - }, - "^=": function(attr, value){ - // E[foo^="bar"] - // an E element whose "foo" attribute value begins exactly - // with the string "bar" - return function(elem){ - return (_getAttr(elem, attr).indexOf(value)==0); - }; - }, - "$=": function(attr, value){ - // E[foo$="bar"] - // an E element whose "foo" attribute value ends exactly - // with the string "bar" - return function(elem){ - var ea = " "+_getAttr(elem, attr); - var lastIndex = ea.lastIndexOf(value); - return lastIndex > -1 && (lastIndex==(ea.length-value.length)); - }; - }, - "~=": function(attr, value){ - // E[foo~="bar"] - // an E element whose "foo" attribute value is a list of - // space-separated values, one of which is exactly equal - // to "bar" - - // return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]"; - var tval = " "+value+" "; - return function(elem){ - var ea = " "+_getAttr(elem, attr)+" "; - return (ea.indexOf(tval)>=0); - }; - }, - "|=": function(attr, value){ - // E[hreflang|="en"] - // an E element whose "hreflang" attribute has a - // hyphen-separated list of values beginning (from the - // left) with "en" - var valueDash = value+"-"; - return function(elem){ - var ea = _getAttr(elem, attr); - return ( - (ea == value) || - (ea.indexOf(valueDash)==0) - ); - }; - }, - "=": function(attr, value){ - return function(elem){ - return (_getAttr(elem, attr) == value); - }; - } - }; - - // avoid testing for node type if we can. Defining this in the negative - // here to avoid negation in the fast path. - var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined"); - var _ns = !_noNES ? "nextElementSibling" : "nextSibling"; - var _ps = !_noNES ? "previousElementSibling" : "previousSibling"; - var _simpleNodeTest = (_noNES ? _isElement : yesman); - - var _lookLeft = function(node){ - // look left - while(node = node[_ps]){ - if(_simpleNodeTest(node)){ return false; } - } - return true; - }; - - var _lookRight = function(node){ - // look right - while(node = node[_ns]){ - if(_simpleNodeTest(node)){ return false; } - } - return true; - }; - - var getNodeIndex = function(node){ - var root = node.parentNode; - root = root.nodeType != 7 ? root : root.nextSibling; // PROCESSING_INSTRUCTION_NODE - var i = 0, - tret = root.children || root.childNodes, - ci = (node["_i"]||node.getAttribute("_i")||-1), - cl = (root["_l"]|| (typeof root.getAttribute !== "undefined" ? root.getAttribute("_l") : -1)); - - if(!tret){ return -1; } - var l = tret.length; - - // we calculate the parent length as a cheap way to invalidate the - // cache. It's not 100% accurate, but it's much more honest than what - // other libraries do - if( cl == l && ci >= 0 && cl >= 0 ){ - // if it's legit, tag and release - return ci; - } - - // else re-key things - if(has("ie") && typeof root.setAttribute !== "undefined"){ - root.setAttribute("_l", l); - }else{ - root["_l"] = l; - } - ci = -1; - for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){ - if(_simpleNodeTest(te)){ - if(has("ie")){ - te.setAttribute("_i", ++i); - }else{ - te["_i"] = ++i; - } - if(node === te){ - // NOTE: - // shortcutting the return at this step in indexing works - // very well for benchmarking but we avoid it here since - // it leads to potential O(n^2) behavior in sequential - // getNodexIndex operations on a previously un-indexed - // parent. We may revisit this at a later time, but for - // now we just want to get the right answer more often - // than not. - ci = i; - } - } - } - return ci; - }; - - var isEven = function(elem){ - return !((getNodeIndex(elem)) % 2); - }; - - var isOdd = function(elem){ - return ((getNodeIndex(elem)) % 2); - }; - - var pseudos = { - "checked": function(name, condition){ - return function(elem){ - return !!("checked" in elem ? elem.checked : elem.selected); - }; - }, - "disabled": function(name, condition){ - return function(elem){ - return elem.disabled; - }; - }, - "enabled": function(name, condition){ - return function(elem){ - return !elem.disabled; - }; - }, - "first-child": function(){ return _lookLeft; }, - "last-child": function(){ return _lookRight; }, - "only-child": function(name, condition){ - return function(node){ - return _lookLeft(node) && _lookRight(node); - }; - }, - "empty": function(name, condition){ - return function(elem){ - // DomQuery and jQuery get this wrong, oddly enough. - // The CSS 3 selectors spec is pretty explicit about it, too. - var cn = elem.childNodes; - var cnl = elem.childNodes.length; - // if(!cnl){ return true; } - for(var x=cnl-1; x >= 0; x--){ - var nt = cn[x].nodeType; - if((nt === 1)||(nt == 3)){ return false; } - } - return true; - }; - }, - "contains": function(name, condition){ - var cz = condition.charAt(0); - if( cz == '"' || cz == "'" ){ //remove quote - condition = condition.slice(1, -1); - } - return function(elem){ - return (elem.innerHTML.indexOf(condition) >= 0); - }; - }, - "not": function(name, condition){ - var p = getQueryParts(condition)[0]; - var ignores = { el: 1 }; - if(p.tag != "*"){ - ignores.tag = 1; - } - if(!p.classes.length){ - ignores.classes = 1; - } - var ntf = getSimpleFilterFunc(p, ignores); - return function(elem){ - return (!ntf(elem)); - }; - }, - "nth-child": function(name, condition){ - var pi = parseInt; - // avoid re-defining function objects if we can - if(condition == "odd"){ - return isOdd; - }else if(condition == "even"){ - return isEven; - } - // FIXME: can we shorten this? - if(condition.indexOf("n") != -1){ - var tparts = condition.split("n", 2); - var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1; - var idx = tparts[1] ? pi(tparts[1]) : 0; - var lb = 0, ub = -1; - if(pred > 0){ - if(idx < 0){ - idx = (idx % pred) && (pred + (idx % pred)); - }else if(idx>0){ - if(idx >= pred){ - lb = idx - idx % pred; - } - idx = idx % pred; - } - }else if(pred<0){ - pred *= -1; - // idx has to be greater than 0 when pred is negative; - // shall we throw an error here? - if(idx > 0){ - ub = idx; - idx = idx % pred; - } - } - if(pred > 0){ - return function(elem){ - var i = getNodeIndex(elem); - return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx); - }; - }else{ - condition = idx; - } - } - var ncount = pi(condition); - return function(elem){ - return (getNodeIndex(elem) == ncount); - }; - } - }; - - var defaultGetter = (has("ie") < 9 || has("ie") == 9 && has("quirks")) ? function(cond){ - var clc = cond.toLowerCase(); - if(clc == "class"){ cond = "className"; } - return function(elem){ - return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]); - }; - } : function(cond){ - return function(elem){ - return (elem && elem.getAttribute && elem.hasAttribute(cond)); - }; - }; - - var getSimpleFilterFunc = function(query, ignores){ - // generates a node tester function based on the passed query part. The - // query part is one of the structures generated by the query parser - // when it creates the query AST. The "ignores" object specifies which - // (if any) tests to skip, allowing the system to avoid duplicating - // work where it may have already been taken into account by other - // factors such as how the nodes to test were fetched in the first - // place - if(!query){ return yesman; } - ignores = ignores||{}; - - var ff = null; - - if(!("el" in ignores)){ - ff = agree(ff, _isElement); - } - - if(!("tag" in ignores)){ - if(query.tag != "*"){ - ff = agree(ff, function(elem){ - return (elem && ((caseSensitive ? elem.tagName : elem.tagName.toUpperCase()) == query.getTag())); - }); - } - } - - if(!("classes" in ignores)){ - each(query.classes, function(cname, idx, arr){ - // get the class name - /* - var isWildcard = cname.charAt(cname.length-1) == "*"; - if(isWildcard){ - cname = cname.substr(0, cname.length-1); - } - // I dislike the regex thing, even if memoized in a cache, but it's VERY short - var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)"); - */ - var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)"); - ff = agree(ff, function(elem){ - return re.test(elem.className); - }); - ff.count = idx; - }); - } - - if(!("pseudos" in ignores)){ - each(query.pseudos, function(pseudo){ - var pn = pseudo.name; - if(pseudos[pn]){ - ff = agree(ff, pseudos[pn](pn, pseudo.value)); - } - }); - } - - if(!("attrs" in ignores)){ - each(query.attrs, function(attr){ - var matcher; - var a = attr.attr; - // type, attr, matchFor - if(attr.type && attrs[attr.type]){ - matcher = attrs[attr.type](a, attr.matchFor); - }else if(a.length){ - matcher = defaultGetter(a); - } - if(matcher){ - ff = agree(ff, matcher); - } - }); - } - - if(!("id" in ignores)){ - if(query.id){ - ff = agree(ff, function(elem){ - return (!!elem && (elem.id == query.id)); - }); - } - } - - if(!ff){ - if(!("default" in ignores)){ - ff = yesman; - } - } - return ff; - }; - - var _nextSibling = function(filterFunc){ - return function(node, ret, bag){ - while(node = node[_ns]){ - if(_noNES && (!_isElement(node))){ continue; } - if( - (!bag || _isUnique(node, bag)) && - filterFunc(node) - ){ - ret.push(node); - } - break; - } - return ret; - }; - }; - - var _nextSiblings = function(filterFunc){ - return function(root, ret, bag){ - var te = root[_ns]; - while(te){ - if(_simpleNodeTest(te)){ - if(bag && !_isUnique(te, bag)){ - break; - } - if(filterFunc(te)){ - ret.push(te); - } - } - te = te[_ns]; - } - return ret; - }; - }; - - // get an array of child *elements*, skipping text and comment nodes - var _childElements = function(filterFunc){ - filterFunc = filterFunc||yesman; - return function(root, ret, bag){ - // get an array of child elements, skipping text and comment nodes - var te, x = 0, tret = root.children || root.childNodes; - while(te = tret[x++]){ - if( - _simpleNodeTest(te) && - (!bag || _isUnique(te, bag)) && - (filterFunc(te, x)) - ){ - ret.push(te); - } - } - return ret; - }; - }; - - // test to see if node is below root - var _isDescendant = function(node, root){ - var pn = node.parentNode; - while(pn){ - if(pn == root){ - break; - } - pn = pn.parentNode; - } - return !!pn; - }; - - var _getElementsFuncCache = {}; - - var getElementsFunc = function(query){ - var retFunc = _getElementsFuncCache[query.query]; - // if we've got a cached dispatcher, just use that - if(retFunc){ return retFunc; } - // else, generate a new on - - // NOTE: - // this function returns a function that searches for nodes and - // filters them. The search may be specialized by infix operators - // (">", "~", or "+") else it will default to searching all - // descendants (the " " selector). Once a group of children is - // found, a test function is applied to weed out the ones we - // don't want. Many common cases can be fast-pathed. We spend a - // lot of cycles to create a dispatcher that doesn't do more work - // than necessary at any point since, unlike this function, the - // dispatchers will be called every time. The logic of generating - // efficient dispatchers looks like this in pseudo code: - // - // # if it's a purely descendant query (no ">", "+", or "~" modifiers) - // if infixOperator == " ": - // if only(id): - // return def(root): - // return d.byId(id, root); - // - // elif id: - // return def(root): - // return filter(d.byId(id, root)); - // - // elif cssClass && getElementsByClassName: - // return def(root): - // return filter(root.getElementsByClassName(cssClass)); - // - // elif only(tag): - // return def(root): - // return root.getElementsByTagName(tagName); - // - // else: - // # search by tag name, then filter - // return def(root): - // return filter(root.getElementsByTagName(tagName||"*")); - // - // elif infixOperator == ">": - // # search direct children - // return def(root): - // return filter(root.children); - // - // elif infixOperator == "+": - // # search next sibling - // return def(root): - // return filter(root.nextElementSibling); - // - // elif infixOperator == "~": - // # search rightward siblings - // return def(root): - // return filter(nextSiblings(root)); - - var io = query.infixOper; - var oper = (io ? io.oper : ""); - // the default filter func which tests for all conditions in the query - // part. This is potentially inefficient, so some optimized paths may - // re-define it to test fewer things. - var filterFunc = getSimpleFilterFunc(query, { el: 1 }); - var qt = query.tag; - var wildcardTag = ("*" == qt); - var ecs = getDoc()["getElementsByClassName"]; - - if(!oper){ - // if there's no infix operator, then it's a descendant query. ID - // and "elements by class name" variants can be accelerated so we - // call them out explicitly: - if(query.id){ - // testing shows that the overhead of yesman() is acceptable - // and can save us some bytes vs. re-defining the function - // everywhere. - filterFunc = (!query.loops && wildcardTag) ? - yesman : - getSimpleFilterFunc(query, { el: 1, id: 1 }); - - retFunc = function(root, arr){ - var te = dom.byId(query.id, (root.ownerDocument||root)); - if(!te || !filterFunc(te)){ return; } - if(9 == root.nodeType){ // if root's a doc, we just return directly - return getArr(te, arr); - }else{ // otherwise check ancestry - if(_isDescendant(te, root)){ - return getArr(te, arr); - } - } - }; - }else if( - ecs && - // isAlien check. Workaround for Prototype.js being totally evil/dumb. - /\{\s*\[native code\]\s*\}/.test(String(ecs)) && - query.classes.length && - !cssCaseBug - ){ - // it's a class-based query and we've got a fast way to run it. - - // ignore class and ID filters since we will have handled both - filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 }); - var classesString = query.classes.join(" "); - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - var tret = root.getElementsByClassName(classesString); - while((te = tret[x++])){ - if(filterFunc(te, root) && _isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; - - }else if(!wildcardTag && !query.loops){ - // it's tag only. Fast-path it. - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - var tag = query.getTag(), - tret = tag ? root.getElementsByTagName(tag) : []; - while((te = tret[x++])){ - if(_isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; - }else{ - // the common case: - // a descendant selector without a fast path. By now it's got - // to have a tag selector, even if it's just "*" so we query - // by that and filter - filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 }); - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - // we use getTag() to avoid case sensitivity issues - var tag = query.getTag(), - tret = tag ? root.getElementsByTagName(tag) : []; - while((te = tret[x++])){ - if(filterFunc(te, root) && _isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; - } - }else{ - // the query is scoped in some way. Instead of querying by tag we - // use some other collection to find candidate nodes - var skipFilters = { el: 1 }; - if(wildcardTag){ - skipFilters.tag = 1; - } - filterFunc = getSimpleFilterFunc(query, skipFilters); - if("+" == oper){ - retFunc = _nextSibling(filterFunc); - }else if("~" == oper){ - retFunc = _nextSiblings(filterFunc); - }else if(">" == oper){ - retFunc = _childElements(filterFunc); - } - } - // cache it and return - return _getElementsFuncCache[query.query] = retFunc; - }; - - var filterDown = function(root, queryParts){ - // NOTE: - // this is the guts of the DOM query system. It takes a list of - // parsed query parts and a root and finds children which match - // the selector represented by the parts - var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret; - - for(var i = 0; i < qpl; i++){ - ret = []; - qp = queryParts[i]; - x = candidates.length - 1; - if(x > 0){ - // if we have more than one root at this level, provide a new - // hash to use for checking group membership but tell the - // system not to post-filter us since we will already have been - // guaranteed to be unique - bag = {}; - ret.nozip = true; - } - var gef = getElementsFunc(qp); - for(var j = 0; (te = candidates[j]); j++){ - // for every root, get the elements that match the descendant - // selector, adding them to the "ret" array and filtering them - // via membership in this level's bag. If there are more query - // parts, then this level's return will be used as the next - // level's candidates - gef(te, ret, bag); - } - if(!ret.length){ break; } - candidates = ret; - } - return ret; - }; - - //////////////////////////////////////////////////////////////////////// - // the query runner - //////////////////////////////////////////////////////////////////////// - - // these are the primary caches for full-query results. The query - // dispatcher functions are generated then stored here for hash lookup in - // the future - var _queryFuncCacheDOM = {}, - _queryFuncCacheQSA = {}; - - // this is the second level of splitting, from full-length queries (e.g., - // "div.foo .bar") into simple query expressions (e.g., ["div.foo", - // ".bar"]) - var getStepQueryFunc = function(query){ - var qparts = getQueryParts(trim(query)); - - // if it's trivial, avoid iteration and zipping costs - if(qparts.length == 1){ - // we optimize this case here to prevent dispatch further down the - // chain, potentially slowing things down. We could more elegantly - // handle this in filterDown(), but it's slower for simple things - // that need to be fast (e.g., "#someId"). - var tef = getElementsFunc(qparts[0]); - return function(root){ - var r = tef(root, []); - if(r){ r.nozip = true; } - return r; - }; - } - - // otherwise, break it up and return a runner that iterates over the parts recursively - return function(root){ - return filterDown(root, qparts); - }; - }; - - // NOTES: - // * we can't trust QSA for anything but document-rooted queries, so - // caching is split into DOM query evaluators and QSA query evaluators - // * caching query results is dirty and leak-prone (or, at a minimum, - // prone to unbounded growth). Other toolkits may go this route, but - // they totally destroy their own ability to manage their memory - // footprint. If we implement it, it should only ever be with a fixed - // total element reference # limit and an LRU-style algorithm since JS - // has no weakref support. Caching compiled query evaluators is also - // potentially problematic, but even on large documents the size of the - // query evaluators is often < 100 function objects per evaluator (and - // LRU can be applied if it's ever shown to be an issue). - // * since IE's QSA support is currently only for HTML documents and even - // then only in IE 8's "standards mode", we have to detect our dispatch - // route at query time and keep 2 separate caches. Ugg. - - // we need to determine if we think we can run a given query via - // querySelectorAll or if we'll need to fall back on DOM queries to get - // there. We need a lot of information about the environment and the query - // to make the determination (e.g. does it support QSA, does the query in - // question work in the native QSA impl, etc.). - - // IE QSA queries may incorrectly include comment nodes, so we throw the - // zipping function into "remove" comments mode instead of the normal "skip - // it" which every other QSA-clued browser enjoys - var noZip = has("ie") ? "commentStrip" : "nozip"; - - var qsa = "querySelectorAll"; - var qsaAvail = !!getDoc()[qsa]; - - //Don't bother with n+3 type of matches, IE complains if we modify those. - var infixSpaceRe = /\\[>~+]|n\+\d|([^ \\])?([>~+])([^ =])?/g; - var infixSpaceFunc = function(match, pre, ch, post){ - return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match; - }; - - //Don't apply the infixSpaceRe to attribute value selectors - var attRe = /([^[]*)([^\]]*])?/g; - var attFunc = function(match, nonAtt, att){ - return nonAtt.replace(infixSpaceRe, infixSpaceFunc) + (att||""); - }; - var getQueryFunc = function(query, forceDOM){ - //Normalize query. The CSS3 selectors spec allows for omitting spaces around - //infix operators, >, ~ and + - //Do the work here since detection for spaces is used as a simple "not use QSA" - //test below. - query = query.replace(attRe, attFunc); - - if(qsaAvail){ - // if we've got a cached variant and we think we can do it, run it! - var qsaCached = _queryFuncCacheQSA[query]; - if(qsaCached && !forceDOM){ return qsaCached; } - } - - // else if we've got a DOM cached variant, assume that we already know - // all we need to and use it - var domCached = _queryFuncCacheDOM[query]; - if(domCached){ return domCached; } - - // TODO: - // today we're caching DOM and QSA branches separately so we - // recalc useQSA every time. If we had a way to tag root+query - // efficiently, we'd be in good shape to do a global cache. - - var qcz = query.charAt(0); - var nospace = (-1 == query.indexOf(" ")); - - // byId searches are wicked fast compared to QSA, even when filtering - // is required - if( (query.indexOf("#") >= 0) && (nospace) ){ - forceDOM = true; - } - - var useQSA = ( - qsaAvail && (!forceDOM) && - // as per CSS 3, we can't currently start w/ combinator: - // http://www.w3.org/TR/css3-selectors/#w3cselgrammar - (specials.indexOf(qcz) == -1) && - // IE's QSA impl sucks on pseudos - (!has("ie") || (query.indexOf(":") == -1)) && - - (!(cssCaseBug && (query.indexOf(".") >= 0))) && - - // FIXME: - // need to tighten up browser rules on ":contains" and "|=" to - // figure out which aren't good - // Latest webkit (around 531.21.8) does not seem to do well with :checked on option - // elements, even though according to spec, selected options should - // match :checked. So go nonQSA for it: - // http://bugs.dojotoolkit.org/ticket/5179 - (query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) && - (query.indexOf("|=") == -1) // some browsers don't grok it - ); - - // TODO: - // if we've got a descendant query (e.g., "> .thinger" instead of - // just ".thinger") in a QSA-able doc, but are passed a child as a - // root, it should be possible to give the item a synthetic ID and - // trivially rewrite the query to the form "#synid > .thinger" to - // use the QSA branch - - - if(useQSA){ - var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ? - (query + " *") : query; - return _queryFuncCacheQSA[query] = function(root){ - try{ - // the QSA system contains an egregious spec bug which - // limits us, effectively, to only running QSA queries over - // entire documents. See: - // http://ejohn.org/blog/thoughts-on-queryselectorall/ - // despite this, we can also handle QSA runs on simple - // selectors, but we don't want detection to be expensive - // so we're just checking for the presence of a space char - // right now. Not elegant, but it's cheaper than running - // the query parser when we might not need to - if(!((9 == root.nodeType) || nospace)){ throw ""; } - var r = root[qsa](tq); - // skip expensive duplication checks and just wrap in a NodeList - r[noZip] = true; - return r; - }catch(e){ - // else run the DOM branch on this query, ensuring that we - // default that way in the future - return getQueryFunc(query, true)(root); - } - }; - }else{ - // DOM branch - var parts = query.match(/([^\s,](?:"(?:\\.|[^"])+"|'(?:\\.|[^'])+'|[^,])*)/g); - return _queryFuncCacheDOM[query] = ((parts.length < 2) ? - // if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher - getStepQueryFunc(query) : - // if it *is* a complex query, break it up into its - // constituent parts and return a dispatcher that will - // merge the parts when run - function(root){ - var pindex = 0, // avoid array alloc for every invocation - ret = [], - tp; - while((tp = parts[pindex++])){ - ret = ret.concat(getStepQueryFunc(tp)(root)); - } - return ret; - } - ); - } - }; - - var _zipIdx = 0; - - // NOTE: - // this function is Moo inspired, but our own impl to deal correctly - // with XML in IE - var _nodeUID = has("ie") ? function(node){ - if(caseSensitive){ - // XML docs don't have uniqueID on their nodes - return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx); - - }else{ - return node.uniqueID; - } - } : - function(node){ - return (node._uid || (node._uid = ++_zipIdx)); - }; - - // determine if a node in is unique in a "bag". In this case we don't want - // to flatten a list of unique items, but rather just tell if the item in - // question is already in the bag. Normally we'd just use hash lookup to do - // this for us but IE's DOM is busted so we can't really count on that. On - // the upside, it gives us a built in unique ID function. - var _isUnique = function(node, bag){ - if(!bag){ return 1; } - var id = _nodeUID(node); - if(!bag[id]){ return bag[id] = 1; } - return 0; - }; - - // attempt to efficiently determine if an item in a list is a dupe, - // returning a list of "uniques", hopefully in document order - var _zipIdxName = "_zipIdx"; - var _zip = function(arr){ - if(arr && arr.nozip){ - return arr; - } - var ret = []; - if(!arr || !arr.length){ return ret; } - if(arr[0]){ - ret.push(arr[0]); - } - if(arr.length < 2){ return ret; } - - _zipIdx++; - - // we have to fork here for IE and XML docs because we can't set - // expandos on their nodes (apparently). *sigh* - var x, te; - if(has("ie") && caseSensitive){ - var szidx = _zipIdx+""; - arr[0].setAttribute(_zipIdxName, szidx); - for(x = 1; te = arr[x]; x++){ - if(arr[x].getAttribute(_zipIdxName) != szidx){ - ret.push(te); - } - te.setAttribute(_zipIdxName, szidx); - } - }else if(has("ie") && arr.commentStrip){ - try{ - for(x = 1; te = arr[x]; x++){ - if(_isElement(te)){ - ret.push(te); - } - } - }catch(e){ /* squelch */ } - }else{ - if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; } - for(x = 1; te = arr[x]; x++){ - if(arr[x][_zipIdxName] != _zipIdx){ - ret.push(te); - } - te[_zipIdxName] = _zipIdx; - } - } - return ret; - }; - - // the main executor - var query = function(/*String*/ query, /*String|DOMNode?*/ root){ - // summary: - // Returns nodes which match the given CSS3 selector, searching the - // entire document by default but optionally taking a node to scope - // the search by. Returns an array. - // description: - // dojo.query() is the swiss army knife of DOM node manipulation in - // Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's - // "$" function, dojo.query provides robust, high-performance - // CSS-based node selector support with the option of scoping searches - // to a particular sub-tree of a document. - // - // Supported Selectors: - // -------------------- - // - // acme supports a rich set of CSS3 selectors, including: - // - // - class selectors (e.g., `.foo`) - // - node type selectors like `span` - // - ` ` descendant selectors - // - `>` child element selectors - // - `#foo` style ID selectors - // - `*` universal selector - // - `~`, the preceded-by sibling selector - // - `+`, the immediately preceded-by sibling selector - // - attribute queries: - // - `[foo]` attribute presence selector - // - `[foo='bar']` attribute value exact match - // - `[foo~='bar']` attribute value list item match - // - `[foo^='bar']` attribute start match - // - `[foo$='bar']` attribute end match - // - `[foo*='bar']` attribute substring match - // - `:first-child`, `:last-child`, and `:only-child` positional selectors - // - `:empty` content emtpy selector - // - `:checked` pseudo selector - // - `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations - // - `:nth-child(even)`, `:nth-child(odd)` positional selectors - // - `:not(...)` negation pseudo selectors - // - // Any legal combination of these selectors will work with - // `dojo.query()`, including compound selectors ("," delimited). - // Very complex and useful searches can be constructed with this - // palette of selectors and when combined with functions for - // manipulation presented by dojo/NodeList, many types of DOM - // manipulation operations become very straightforward. - // - // Unsupported Selectors: - // ---------------------- - // - // While dojo.query handles many CSS3 selectors, some fall outside of - // what's reasonable for a programmatic node querying engine to - // handle. Currently unsupported selectors include: - // - // - namespace-differentiated selectors of any form - // - all `::` pseduo-element selectors - // - certain pseudo-selectors which don't get a lot of day-to-day use: - // - `:root`, `:lang()`, `:target`, `:focus` - // - all visual and state selectors: - // - `:root`, `:active`, `:hover`, `:visited`, `:link`, - // `:enabled`, `:disabled` - // - `:*-of-type` pseudo selectors - // - // dojo.query and XML Documents: - // ----------------------------- - // - // `dojo.query` (as of dojo 1.2) supports searching XML documents - // in a case-sensitive manner. If an HTML document is served with - // a doctype that forces case-sensitivity (e.g., XHTML 1.1 - // Strict), dojo.query() will detect this and "do the right - // thing". Case sensitivity is dependent upon the document being - // searched and not the query used. It is therefore possible to - // use case-sensitive queries on strict sub-documents (iframes, - // etc.) or XML documents while still assuming case-insensitivity - // for a host/root document. - // - // Non-selector Queries: - // --------------------- - // - // If something other than a String is passed for the query, - // `dojo.query` will return a new `dojo/NodeList` instance - // constructed from that parameter alone and all further - // processing will stop. This means that if you have a reference - // to a node or NodeList, you can quickly construct a new NodeList - // from the original by calling `dojo.query(node)` or - // `dojo.query(list)`. - // - // query: - // The CSS3 expression to match against. For details on the syntax of - // CSS3 selectors, see <http://www.w3.org/TR/css3-selectors/#selectors> - // root: - // A DOMNode (or node id) to scope the search from. Optional. - // returns: Array - // example: - // search the entire document for elements with the class "foo": - // | dojo.query(".foo"); - // these elements will match: - // | <span class="foo"></span> - // | <span class="foo bar"></span> - // | <p class="thud foo"></p> - // example: - // search the entire document for elements with the classes "foo" *and* "bar": - // | dojo.query(".foo.bar"); - // these elements will match: - // | <span class="foo bar"></span> - // while these will not: - // | <span class="foo"></span> - // | <p class="thud foo"></p> - // example: - // find `<span>` elements which are descendants of paragraphs and - // which have a "highlighted" class: - // | dojo.query("p span.highlighted"); - // the innermost span in this fragment matches: - // | <p class="foo"> - // | <span>... - // | <span class="highlighted foo bar">...</span> - // | </span> - // | </p> - // example: - // set an "odd" class on all odd table rows inside of the table - // `#tabular_data`, using the `>` (direct child) selector to avoid - // affecting any nested tables: - // | dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd"); - // example: - // remove all elements with the class "error" from the document - // and store them in a list: - // | var errors = dojo.query(".error").orphan(); - // example: - // add an onclick handler to every submit button in the document - // which causes the form to be sent via Ajax instead: - // | dojo.query("input[type='submit']").onclick(function(e){ - // | dojo.stopEvent(e); // prevent sending the form - // | var btn = e.target; - // | dojo.xhrPost({ - // | form: btn.form, - // | load: function(data){ - // | // replace the form with the response - // | var div = dojo.doc.createElement("div"); - // | dojo.place(div, btn.form, "after"); - // | div.innerHTML = data; - // | dojo.style(btn.form, "display", "none"); - // | } - // | }); - // | }); - - root = root || getDoc(); - - // throw the big case sensitivity switch - var od = root.ownerDocument || root; // root is either Document or a node inside the document - caseSensitive = (od.createElement("div").tagName === "div"); - - // NOTE: - // adding "true" as the 2nd argument to getQueryFunc is useful for - // testing the DOM branch without worrying about the - // behavior/performance of the QSA branch. - var r = getQueryFunc(query)(root); - - // FIXME: - // need to investigate this branch WRT #8074 and #8075 - if(r && r.nozip){ - return r; - } - return _zip(r); // dojo/NodeList - }; - query.filter = function(/*Node[]*/ nodeList, /*String*/ filter, /*String|DOMNode?*/ root){ - // summary: - // function for filtering a NodeList based on a selector, optimized for simple selectors - var tmpNodeList = [], - parts = getQueryParts(filter), - filterFunc = - (parts.length == 1 && !/[^\w#\.]/.test(filter)) ? - getSimpleFilterFunc(parts[0]) : - function(node){ - return array.indexOf(query(filter, dom.byId(root)), node) != -1; - }; - for(var x = 0, te; te = nodeList[x]; x++){ - if(filterFunc(te)){ tmpNodeList.push(te); } - } - return tmpNodeList; - }; - return query; -}); - -}, -'dojo/dnd/autoscroll':function(){ -define("dojo/dnd/autoscroll", ["../_base/lang", "../sniff", "../_base/window", "../dom-geometry", "../dom-style", "../window"], - function(lang, has, win, domGeom, domStyle, winUtils){ - -// module: -// dojo/dnd/autoscroll - -var exports = { - // summary: - // Used by dojo/dnd/Manager to scroll document or internal node when the user - // drags near the edge of the viewport or a scrollable node -}; -lang.setObject("dojo.dnd.autoscroll", exports); - -exports.getViewport = winUtils.getBox; - -exports.V_TRIGGER_AUTOSCROLL = 32; -exports.H_TRIGGER_AUTOSCROLL = 32; - -exports.V_AUTOSCROLL_VALUE = 16; -exports.H_AUTOSCROLL_VALUE = 16; - -// These are set by autoScrollStart(). -// Set to default values in case autoScrollStart() isn't called. (back-compat, remove for 2.0) -var viewport, - doc = win.doc, - maxScrollTop = Infinity, - maxScrollLeft = Infinity; - -exports.autoScrollStart = function(d){ - // summary: - // Called at the start of a drag. - // d: Document - // The document of the node being dragged. - - doc = d; - viewport = winUtils.getBox(doc); - - // Save height/width of document at start of drag, before it gets distorted by a user dragging an avatar past - // the document's edge - var html = win.body(doc).parentNode; - maxScrollTop = Math.max(html.scrollHeight - viewport.h, 0); - maxScrollLeft = Math.max(html.scrollWidth - viewport.w, 0); // usually 0 -}; - -exports.autoScroll = function(e){ - // summary: - // a handler for mousemove and touchmove events, which scrolls the window, if - // necessary - // e: Event - // mousemove/touchmove event - - // FIXME: needs more docs! - var v = viewport || winUtils.getBox(doc), // getBox() call for back-compat, in case autoScrollStart() wasn't called - html = win.body(doc).parentNode, - dx = 0, dy = 0; - if(e.clientX < exports.H_TRIGGER_AUTOSCROLL){ - dx = -exports.H_AUTOSCROLL_VALUE; - }else if(e.clientX > v.w - exports.H_TRIGGER_AUTOSCROLL){ - dx = Math.min(exports.H_AUTOSCROLL_VALUE, maxScrollLeft - html.scrollLeft); // don't scroll past edge of doc - } - if(e.clientY < exports.V_TRIGGER_AUTOSCROLL){ - dy = -exports.V_AUTOSCROLL_VALUE; - }else if(e.clientY > v.h - exports.V_TRIGGER_AUTOSCROLL){ - dy = Math.min(exports.V_AUTOSCROLL_VALUE, maxScrollTop - html.scrollTop); // don't scroll past edge of doc - } - window.scrollBy(dx, dy); -}; - -exports._validNodes = {"div": 1, "p": 1, "td": 1}; -exports._validOverflow = {"auto": 1, "scroll": 1}; - -exports.autoScrollNodes = function(e){ - // summary: - // a handler for mousemove and touchmove events, which scrolls the first available - // Dom element, it falls back to exports.autoScroll() - // e: Event - // mousemove/touchmove event - - // FIXME: needs more docs! - - var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop; - - for(var n = e.target; n;){ - if(n.nodeType == 1 && (n.tagName.toLowerCase() in exports._validNodes)){ - var s = domStyle.getComputedStyle(n), - overflow = (s.overflow.toLowerCase() in exports._validOverflow), - overflowX = (s.overflowX.toLowerCase() in exports._validOverflow), - overflowY = (s.overflowY.toLowerCase() in exports._validOverflow); - if(overflow || overflowX || overflowY){ - b = domGeom.getContentBox(n, s); - t = domGeom.position(n, true); - } - // overflow-x - if(overflow || overflowX){ - w = Math.min(exports.H_TRIGGER_AUTOSCROLL, b.w / 2); - rx = e.pageX - t.x; - if(has("webkit") || has("opera")){ - // FIXME: this code should not be here, it should be taken into account - // either by the event fixing code, or the domGeom.position() - // FIXME: this code doesn't work on Opera 9.5 Beta - rx += win.body().scrollLeft; - } - dx = 0; - if(rx > 0 && rx < b.w){ - if(rx < w){ - dx = -w; - }else if(rx > b.w - w){ - dx = w; - } - oldLeft = n.scrollLeft; - n.scrollLeft = n.scrollLeft + dx; - } - } - // overflow-y - if(overflow || overflowY){ - //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop); - h = Math.min(exports.V_TRIGGER_AUTOSCROLL, b.h / 2); - ry = e.pageY - t.y; - if(has("webkit") || has("opera")){ - // FIXME: this code should not be here, it should be taken into account - // either by the event fixing code, or the domGeom.position() - // FIXME: this code doesn't work on Opera 9.5 Beta - ry += win.body().scrollTop; - } - dy = 0; - if(ry > 0 && ry < b.h){ - if(ry < h){ - dy = -h; - }else if(ry > b.h - h){ - dy = h; - } - oldTop = n.scrollTop; - n.scrollTop = n.scrollTop + dy; - } - } - if(dx || dy){ return; } - } - try{ - n = n.parentNode; - }catch(x){ - n = null; - } - } - exports.autoScroll(e); -}; - -return exports; - -}); - -}, -'dijit/form/_RadioButtonMixin':function(){ -define("dijit/form/_RadioButtonMixin", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/_base/event", // event.stop - "dojo/_base/lang", // lang.hitch - "dojo/query", // query - "../registry" // registry.getEnclosingWidget -], function(array, declare, domAttr, event, lang, query, registry){ - - // module: - // dijit/form/_RadioButtonMixin - - return declare("dijit.form._RadioButtonMixin", null, { - // summary: - // Mixin to provide widget functionality for an HTML radio button - - // type: [private] String - // type attribute on `<input>` node. - // Users should not change this value. - type: "radio", - - _getRelatedWidgets: function(){ - // Private function needed to help iterate over all radio buttons in a group. - var ary = []; - query("input[type=radio]", this.focusNode.form || this.ownerDocument).forEach( // can't use name= since query doesn't support [] in the name - lang.hitch(this, function(inputNode){ - if(inputNode.name == this.name && inputNode.form == this.focusNode.form){ - var widget = registry.getEnclosingWidget(inputNode); - if(widget){ - ary.push(widget); - } - } - }) - ); - return ary; - }, - - _setCheckedAttr: function(/*Boolean*/ value){ - // If I am being checked then have to deselect currently checked radio button - this.inherited(arguments); - if(!this._created){ return; } - if(value){ - array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){ - if(widget != this && widget.checked){ - widget.set('checked', false); - } - })); - } - }, - - _getSubmitValue: function(/*String*/ value){ - return value === null ? "on" : value; - }, - - _onClick: function(/*Event*/ e){ - if(this.checked || this.disabled){ // nothing to do - event.stop(e); - return false; - } - if(this.readOnly){ // ignored by some browsers so we have to resync the DOM elements with widget values - event.stop(e); - array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){ - domAttr.set(this.focusNode || this.domNode, 'checked', widget.checked); - })); - return false; - } - return this.inherited(arguments); - } - }); -}); - -}, -'dojo/data/ItemFileWriteStore':function(){ -define("dojo/data/ItemFileWriteStore", ["../_base/lang", "../_base/declare", "../_base/array", "../_base/json", "../_base/kernel", - "./ItemFileReadStore", "../date/stamp" -], function(lang, declare, arrayUtil, jsonUtil, kernel, ItemFileReadStore, dateStamp){ - -// module: -// dojo/data/ItemFileWriteStore - -return declare("dojo.data.ItemFileWriteStore", ItemFileReadStore, { - // summary: - // TODOC - - constructor: function(/* object */ keywordParameters){ - // keywordParameters: - // The structure of the typeMap object is as follows: - // | { - // | type0: function || object, - // | type1: function || object, - // | ... - // | typeN: function || object - // | } - // Where if it is a function, it is assumed to be an object constructor that takes the - // value of _value as the initialization parameters. It is serialized assuming object.toString() - // serialization. If it is an object, then it is assumed - // to be an object of general form: - // | { - // | type: function, //constructor. - // | deserialize: function(value) //The function that parses the value and constructs the object defined by type appropriately. - // | serialize: function(object) //The function that converts the object back into the proper file format form. - // | } - - // ItemFileWriteStore extends ItemFileReadStore to implement these additional dojo.data APIs - this._features['dojo.data.api.Write'] = true; - this._features['dojo.data.api.Notification'] = true; - - // For keeping track of changes so that we can implement isDirty and revert - this._pending = { - _newItems:{}, - _modifiedItems:{}, - _deletedItems:{} - }; - - if(!this._datatypeMap['Date'].serialize){ - this._datatypeMap['Date'].serialize = function(obj){ - return dateStamp.toISOString(obj, {zulu:true}); - }; - } - //Disable only if explicitly set to false. - if(keywordParameters && (keywordParameters.referenceIntegrity === false)){ - this.referenceIntegrity = false; - } - - // this._saveInProgress is set to true, briefly, from when save() is first called to when it completes - this._saveInProgress = false; - }, - - referenceIntegrity: true, //Flag that defaultly enabled reference integrity tracking. This way it can also be disabled pogrammatially or declaratively. - - _assert: function(/* boolean */ condition){ - if(!condition){ - throw new Error("assertion failed in ItemFileWriteStore"); - } - }, - - _getIdentifierAttribute: function(){ - // this._assert((identifierAttribute === Number) || (dojo.isString(identifierAttribute))); - return this.getFeatures()['dojo.data.api.Identity']; - }, - - -/* dojo/data/api/Write */ - - newItem: function(/* Object? */ keywordArgs, /* Object? */ parentInfo){ - // summary: - // See dojo/data/api/Write.newItem() - - this._assert(!this._saveInProgress); - - if(!this._loadFinished){ - // We need to do this here so that we'll be able to find out what - // identifierAttribute was specified in the data file. - this._forceLoad(); - } - - if(typeof keywordArgs != "object" && typeof keywordArgs != "undefined"){ - throw new Error("newItem() was passed something other than an object"); - } - var newIdentity = null; - var identifierAttribute = this._getIdentifierAttribute(); - if(identifierAttribute === Number){ - newIdentity = this._arrayOfAllItems.length; - }else{ - newIdentity = keywordArgs[identifierAttribute]; - if(typeof newIdentity === "undefined"){ - throw new Error("newItem() was not passed an identity for the new item"); - } - if(lang.isArray(newIdentity)){ - throw new Error("newItem() was not passed an single-valued identity"); - } - } - - // make sure this identity is not already in use by another item, if identifiers were - // defined in the file. Otherwise it would be the item count, - // which should always be unique in this case. - if(this._itemsByIdentity){ - this._assert(typeof this._itemsByIdentity[newIdentity] === "undefined"); - } - this._assert(typeof this._pending._newItems[newIdentity] === "undefined"); - this._assert(typeof this._pending._deletedItems[newIdentity] === "undefined"); - - var newItem = {}; - newItem[this._storeRefPropName] = this; - newItem[this._itemNumPropName] = this._arrayOfAllItems.length; - if(this._itemsByIdentity){ - this._itemsByIdentity[newIdentity] = newItem; - //We have to set the identifier now, otherwise we can't look it - //up at calls to setValueorValues in parentInfo handling. - newItem[identifierAttribute] = [newIdentity]; - } - this._arrayOfAllItems.push(newItem); - - //We need to construct some data for the onNew call too... - var pInfo = null; - - // Now we need to check to see where we want to assign this thingm if any. - if(parentInfo && parentInfo.parent && parentInfo.attribute){ - pInfo = { - item: parentInfo.parent, - attribute: parentInfo.attribute, - oldValue: undefined - }; - - //See if it is multi-valued or not and handle appropriately - //Generally, all attributes are multi-valued for this store - //So, we only need to append if there are already values present. - var values = this.getValues(parentInfo.parent, parentInfo.attribute); - if(values && values.length > 0){ - var tempValues = values.slice(0, values.length); - if(values.length === 1){ - pInfo.oldValue = values[0]; - }else{ - pInfo.oldValue = values.slice(0, values.length); - } - tempValues.push(newItem); - this._setValueOrValues(parentInfo.parent, parentInfo.attribute, tempValues, false); - pInfo.newValue = this.getValues(parentInfo.parent, parentInfo.attribute); - }else{ - this._setValueOrValues(parentInfo.parent, parentInfo.attribute, newItem, false); - pInfo.newValue = newItem; - } - }else{ - //Toplevel item, add to both top list as well as all list. - newItem[this._rootItemPropName]=true; - this._arrayOfTopLevelItems.push(newItem); - } - - this._pending._newItems[newIdentity] = newItem; - - //Clone over the properties to the new item - for(var key in keywordArgs){ - if(key === this._storeRefPropName || key === this._itemNumPropName){ - // Bummer, the user is trying to do something like - // newItem({_S:"foo"}). Unfortunately, our superclass, - // ItemFileReadStore, is already using _S in each of our items - // to hold private info. To avoid a naming collision, we - // need to move all our private info to some other property - // of all the items/objects. So, we need to iterate over all - // the items and do something like: - // item.__S = item._S; - // item._S = undefined; - // But first we have to make sure the new "__S" variable is - // not in use, which means we have to iterate over all the - // items checking for that. - throw new Error("encountered bug in ItemFileWriteStore.newItem"); - } - var value = keywordArgs[key]; - if(!lang.isArray(value)){ - value = [value]; - } - newItem[key] = value; - if(this.referenceIntegrity){ - for(var i = 0; i < value.length; i++){ - var val = value[i]; - if(this.isItem(val)){ - this._addReferenceToMap(val, newItem, key); - } - } - } - } - this.onNew(newItem, pInfo); // dojo/data/api/Notification call - return newItem; // item - }, - - _removeArrayElement: function(/* Array */ array, /* anything */ element){ - var index = arrayUtil.indexOf(array, element); - if(index != -1){ - array.splice(index, 1); - return true; - } - return false; - }, - - deleteItem: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Write.deleteItem() - this._assert(!this._saveInProgress); - this._assertIsItem(item); - - // Remove this item from the _arrayOfAllItems, but leave a null value in place - // of the item, so as not to change the length of the array, so that in newItem() - // we can still safely do: newIdentity = this._arrayOfAllItems.length; - var indexInArrayOfAllItems = item[this._itemNumPropName]; - var identity = this.getIdentity(item); - - //If we have reference integrity on, we need to do reference cleanup for the deleted item - if(this.referenceIntegrity){ - //First scan all the attributes of this items for references and clean them up in the map - //As this item is going away, no need to track its references anymore. - - //Get the attributes list before we generate the backup so it - //doesn't pollute the attributes list. - var attributes = this.getAttributes(item); - - //Backup the map, we'll have to restore it potentially, in a revert. - if(item[this._reverseRefMap]){ - item["backup_" + this._reverseRefMap] = lang.clone(item[this._reverseRefMap]); - } - - //TODO: This causes a reversion problem. This list won't be restored on revert since it is - //attached to the 'value'. item, not ours. Need to back tese up somehow too. - //Maybe build a map of the backup of the entries and attach it to the deleted item to be restored - //later. Or just record them and call _addReferenceToMap on them in revert. - arrayUtil.forEach(attributes, function(attribute){ - arrayUtil.forEach(this.getValues(item, attribute), function(value){ - if(this.isItem(value)){ - //We have to back up all the references we had to others so they can be restored on a revert. - if(!item["backupRefs_" + this._reverseRefMap]){ - item["backupRefs_" + this._reverseRefMap] = []; - } - item["backupRefs_" + this._reverseRefMap].push({id: this.getIdentity(value), attr: attribute}); - this._removeReferenceFromMap(value, item, attribute); - } - }, this); - }, this); - - //Next, see if we have references to this item, if we do, we have to clean them up too. - var references = item[this._reverseRefMap]; - if(references){ - //Look through all the items noted as references to clean them up. - for(var itemId in references){ - var containingItem = null; - if(this._itemsByIdentity){ - containingItem = this._itemsByIdentity[itemId]; - }else{ - containingItem = this._arrayOfAllItems[itemId]; - } - //We have a reference to a containing item, now we have to process the - //attributes and clear all references to the item being deleted. - if(containingItem){ - for(var attribute in references[itemId]){ - var oldValues = this.getValues(containingItem, attribute) || []; - var newValues = arrayUtil.filter(oldValues, function(possibleItem){ - return !(this.isItem(possibleItem) && this.getIdentity(possibleItem) == identity); - }, this); - //Remove the note of the reference to the item and set the values on the modified attribute. - this._removeReferenceFromMap(item, containingItem, attribute); - if(newValues.length < oldValues.length){ - this._setValueOrValues(containingItem, attribute, newValues, true); - } - } - } - } - } - } - - this._arrayOfAllItems[indexInArrayOfAllItems] = null; - - item[this._storeRefPropName] = null; - if(this._itemsByIdentity){ - delete this._itemsByIdentity[identity]; - } - this._pending._deletedItems[identity] = item; - - //Remove from the toplevel items, if necessary... - if(item[this._rootItemPropName]){ - this._removeArrayElement(this._arrayOfTopLevelItems, item); - } - this.onDelete(item); // dojo/data/api/Notification call - return true; - }, - - setValue: function(/* dojo/data/api/Item */ item, /* attribute-name-string */ attribute, /* almost anything */ value){ - // summary: - // See dojo/data/api/Write.set() - return this._setValueOrValues(item, attribute, value, true); // boolean - }, - - setValues: function(/* dojo/data/api/Item */ item, /* attribute-name-string */ attribute, /* array */ values){ - // summary: - // See dojo/data/api/Write.setValues() - return this._setValueOrValues(item, attribute, values, true); // boolean - }, - - unsetAttribute: function(/* dojo/data/api/Item */ item, /* attribute-name-string */ attribute){ - // summary: - // See dojo/data/api/Write.unsetAttribute() - return this._setValueOrValues(item, attribute, [], true); - }, - - _setValueOrValues: function(/* dojo/data/api/Item */ item, /* attribute-name-string */ attribute, /* anything */ newValueOrValues, /*boolean?*/ callOnSet){ - this._assert(!this._saveInProgress); - - // Check for valid arguments - this._assertIsItem(item); - this._assert(lang.isString(attribute)); - this._assert(typeof newValueOrValues !== "undefined"); - - // Make sure the user isn't trying to change the item's identity - var identifierAttribute = this._getIdentifierAttribute(); - if(attribute == identifierAttribute){ - throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier."); - } - - // To implement the Notification API, we need to make a note of what - // the old attribute value was, so that we can pass that info when - // we call the onSet method. - var oldValueOrValues = this._getValueOrValues(item, attribute); - - var identity = this.getIdentity(item); - if(!this._pending._modifiedItems[identity]){ - // Before we actually change the item, we make a copy of it to - // record the original state, so that we'll be able to revert if - // the revert method gets called. If the item has already been - // modified then there's no need to do this now, since we already - // have a record of the original state. - var copyOfItemState = {}; - for(var key in item){ - if((key === this._storeRefPropName) || (key === this._itemNumPropName) || (key === this._rootItemPropName)){ - copyOfItemState[key] = item[key]; - }else if(key === this._reverseRefMap){ - copyOfItemState[key] = lang.clone(item[key]); - }else{ - copyOfItemState[key] = item[key].slice(0, item[key].length); - } - } - // Now mark the item as dirty, and save the copy of the original state - this._pending._modifiedItems[identity] = copyOfItemState; - } - - // Okay, now we can actually change this attribute on the item - var success = false; - - if(lang.isArray(newValueOrValues) && newValueOrValues.length === 0){ - - // If we were passed an empty array as the value, that counts - // as "unsetting" the attribute, so we need to remove this - // attribute from the item. - success = delete item[attribute]; - newValueOrValues = undefined; // used in the onSet Notification call below - - if(this.referenceIntegrity && oldValueOrValues){ - var oldValues = oldValueOrValues; - if(!lang.isArray(oldValues)){ - oldValues = [oldValues]; - } - for(var i = 0; i < oldValues.length; i++){ - var value = oldValues[i]; - if(this.isItem(value)){ - this._removeReferenceFromMap(value, item, attribute); - } - } - } - }else{ - var newValueArray; - if(lang.isArray(newValueOrValues)){ - // Unfortunately, it's not safe to just do this: - // newValueArray = newValueOrValues; - // Instead, we need to copy the array, which slice() does very nicely. - // This is so that our internal data structure won't - // get corrupted if the user mucks with the values array *after* - // calling setValues(). - newValueArray = newValueOrValues.slice(0, newValueOrValues.length); - }else{ - newValueArray = [newValueOrValues]; - } - - //We need to handle reference integrity if this is on. - //In the case of set, we need to see if references were added or removed - //and update the reference tracking map accordingly. - if(this.referenceIntegrity){ - if(oldValueOrValues){ - var oldValues = oldValueOrValues; - if(!lang.isArray(oldValues)){ - oldValues = [oldValues]; - } - //Use an associative map to determine what was added/removed from the list. - //Should be O(n) performant. First look at all the old values and make a list of them - //Then for any item not in the old list, we add it. If it was already present, we remove it. - //Then we pass over the map and any references left it it need to be removed (IE, no match in - //the new values list). - var map = {}; - arrayUtil.forEach(oldValues, function(possibleItem){ - if(this.isItem(possibleItem)){ - var id = this.getIdentity(possibleItem); - map[id.toString()] = true; - } - }, this); - arrayUtil.forEach(newValueArray, function(possibleItem){ - if(this.isItem(possibleItem)){ - var id = this.getIdentity(possibleItem); - if(map[id.toString()]){ - delete map[id.toString()]; - }else{ - this._addReferenceToMap(possibleItem, item, attribute); - } - } - }, this); - for(var rId in map){ - var removedItem; - if(this._itemsByIdentity){ - removedItem = this._itemsByIdentity[rId]; - }else{ - removedItem = this._arrayOfAllItems[rId]; - } - this._removeReferenceFromMap(removedItem, item, attribute); - } - }else{ - //Everything is new (no old values) so we have to just - //insert all the references, if any. - for(var i = 0; i < newValueArray.length; i++){ - var value = newValueArray[i]; - if(this.isItem(value)){ - this._addReferenceToMap(value, item, attribute); - } - } - } - } - item[attribute] = newValueArray; - success = true; - } - - // Now we make the dojo/data/api/Notification call - if(callOnSet){ - this.onSet(item, attribute, oldValueOrValues, newValueOrValues); - } - return success; // boolean - }, - - _addReferenceToMap: function(/* dojo/data/api/Item */ refItem, /* dojo/data/api/Item */ parentItem, /* string */ attribute){ - // summary: - // Method to add an reference map entry for an item and attribute. - // description: - // Method to add an reference map entry for an item and attribute. - // refItem: - // The item that is referenced. - // parentItem: - // The item that holds the new reference to refItem. - // attribute: - // The attribute on parentItem that contains the new reference. - - var parentId = this.getIdentity(parentItem); - var references = refItem[this._reverseRefMap]; - - if(!references){ - references = refItem[this._reverseRefMap] = {}; - } - var itemRef = references[parentId]; - if(!itemRef){ - itemRef = references[parentId] = {}; - } - itemRef[attribute] = true; - }, - - _removeReferenceFromMap: function(/* dojo/data/api/Item */ refItem, /* dojo/data/api/Item */ parentItem, /* string */ attribute){ - // summary: - // Method to remove an reference map entry for an item and attribute. - // description: - // Method to remove an reference map entry for an item and attribute. This will - // also perform cleanup on the map such that if there are no more references at all to - // the item, its reference object and entry are removed. - // refItem: - // The item that is referenced. - // parentItem: - // The item holding a reference to refItem. - // attribute: - // The attribute on parentItem that contains the reference. - var identity = this.getIdentity(parentItem); - var references = refItem[this._reverseRefMap]; - var itemId; - if(references){ - for(itemId in references){ - if(itemId == identity){ - delete references[itemId][attribute]; - if(this._isEmpty(references[itemId])){ - delete references[itemId]; - } - } - } - if(this._isEmpty(references)){ - delete refItem[this._reverseRefMap]; - } - } - }, - - _dumpReferenceMap: function(){ - // summary: - // Function to dump the reverse reference map of all items in the store for debug purposes. - // description: - // Function to dump the reverse reference map of all items in the store for debug purposes. - var i; - for(i = 0; i < this._arrayOfAllItems.length; i++){ - var item = this._arrayOfAllItems[i]; - if(item && item[this._reverseRefMap]){ - console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + jsonUtil.toJson(item[this._reverseRefMap])); - } - } - }, - - _getValueOrValues: function(/* dojo/data/api/Item */ item, /* attribute-name-string */ attribute){ - var valueOrValues = undefined; - if(this.hasAttribute(item, attribute)){ - var valueArray = this.getValues(item, attribute); - if(valueArray.length == 1){ - valueOrValues = valueArray[0]; - }else{ - valueOrValues = valueArray; - } - } - return valueOrValues; - }, - - _flatten: function(/* anything */ value){ - if(this.isItem(value)){ - // Given an item, return an serializable object that provides a - // reference to the item. - // For example, given kermit: - // var kermit = store.newItem({id:2, name:"Kermit"}); - // we want to return - // {_reference:2} - return {_reference: this.getIdentity(value)}; - }else{ - if(typeof value === "object"){ - for(var type in this._datatypeMap){ - var typeMap = this._datatypeMap[type]; - if(lang.isObject(typeMap) && !lang.isFunction(typeMap)){ - if(value instanceof typeMap.type){ - if(!typeMap.serialize){ - throw new Error("ItemFileWriteStore: No serializer defined for type mapping: [" + type + "]"); - } - return {_type: type, _value: typeMap.serialize(value)}; - } - }else if(value instanceof typeMap){ - //SImple mapping, therefore, return as a toString serialization. - return {_type: type, _value: value.toString()}; - } - } - } - return value; - } - }, - - _getNewFileContentString: function(){ - // summary: - // Generate a string that can be saved to a file. - // The result should look similar to: - // http://trac.dojotoolkit.org/browser/dojo/trunk/tests/data/countries.json - var serializableStructure = {}; - - var identifierAttribute = this._getIdentifierAttribute(); - if(identifierAttribute !== Number){ - serializableStructure.identifier = identifierAttribute; - } - if(this._labelAttr){ - serializableStructure.label = this._labelAttr; - } - serializableStructure.items = []; - for(var i = 0; i < this._arrayOfAllItems.length; ++i){ - var item = this._arrayOfAllItems[i]; - if(item !== null){ - var serializableItem = {}; - for(var key in item){ - if(key !== this._storeRefPropName && key !== this._itemNumPropName && key !== this._reverseRefMap && key !== this._rootItemPropName){ - var valueArray = this.getValues(item, key); - if(valueArray.length == 1){ - serializableItem[key] = this._flatten(valueArray[0]); - }else{ - var serializableArray = []; - for(var j = 0; j < valueArray.length; ++j){ - serializableArray.push(this._flatten(valueArray[j])); - serializableItem[key] = serializableArray; - } - } - } - } - serializableStructure.items.push(serializableItem); - } - } - var prettyPrint = true; - return jsonUtil.toJson(serializableStructure, prettyPrint); - }, - - _isEmpty: function(something){ - // summary: - // Function to determine if an array or object has no properties or values. - // something: - // The array or object to examine. - var empty = true; - if(lang.isObject(something)){ - var i; - for(i in something){ - empty = false; - break; - } - }else if(lang.isArray(something)){ - if(something.length > 0){ - empty = false; - } - } - return empty; //boolean - }, - - save: function(/* object */ keywordArgs){ - // summary: - // See dojo/data/api/Write.save() - this._assert(!this._saveInProgress); - - // this._saveInProgress is set to true, briefly, from when save is first called to when it completes - this._saveInProgress = true; - - var self = this; - var saveCompleteCallback = function(){ - self._pending = { - _newItems:{}, - _modifiedItems:{}, - _deletedItems:{} - }; - - self._saveInProgress = false; // must come after this._pending is cleared, but before any callbacks - if(keywordArgs && keywordArgs.onComplete){ - var scope = keywordArgs.scope || kernel.global; - keywordArgs.onComplete.call(scope); - } - }; - var saveFailedCallback = function(err){ - self._saveInProgress = false; - if(keywordArgs && keywordArgs.onError){ - var scope = keywordArgs.scope || kernel.global; - keywordArgs.onError.call(scope, err); - } - }; - - if(this._saveEverything){ - var newFileContentString = this._getNewFileContentString(); - this._saveEverything(saveCompleteCallback, saveFailedCallback, newFileContentString); - } - if(this._saveCustom){ - this._saveCustom(saveCompleteCallback, saveFailedCallback); - } - if(!this._saveEverything && !this._saveCustom){ - // Looks like there is no user-defined save-handler function. - // That's fine, it just means the datastore is acting as a "mock-write" - // store -- changes get saved in memory but don't get saved to disk. - saveCompleteCallback(); - } - }, - - revert: function(){ - // summary: - // See dojo/data/api/Write.revert() - this._assert(!this._saveInProgress); - - var identity; - for(identity in this._pending._modifiedItems){ - // find the original item and the modified item that replaced it - var copyOfItemState = this._pending._modifiedItems[identity]; - var modifiedItem = null; - if(this._itemsByIdentity){ - modifiedItem = this._itemsByIdentity[identity]; - }else{ - modifiedItem = this._arrayOfAllItems[identity]; - } - - // Restore the original item into a full-fledged item again, we want to try to - // keep the same object instance as if we don't it, causes bugs like #9022. - copyOfItemState[this._storeRefPropName] = this; - for(var key in modifiedItem){ - delete modifiedItem[key]; - } - lang.mixin(modifiedItem, copyOfItemState); - } - var deletedItem; - for(identity in this._pending._deletedItems){ - deletedItem = this._pending._deletedItems[identity]; - deletedItem[this._storeRefPropName] = this; - var index = deletedItem[this._itemNumPropName]; - - //Restore the reverse refererence map, if any. - if(deletedItem["backup_" + this._reverseRefMap]){ - deletedItem[this._reverseRefMap] = deletedItem["backup_" + this._reverseRefMap]; - delete deletedItem["backup_" + this._reverseRefMap]; - } - this._arrayOfAllItems[index] = deletedItem; - if(this._itemsByIdentity){ - this._itemsByIdentity[identity] = deletedItem; - } - if(deletedItem[this._rootItemPropName]){ - this._arrayOfTopLevelItems.push(deletedItem); - } - } - //We have to pass through it again and restore the reference maps after all the - //undeletes have occurred. - for(identity in this._pending._deletedItems){ - deletedItem = this._pending._deletedItems[identity]; - if(deletedItem["backupRefs_" + this._reverseRefMap]){ - arrayUtil.forEach(deletedItem["backupRefs_" + this._reverseRefMap], function(reference){ - var refItem; - if(this._itemsByIdentity){ - refItem = this._itemsByIdentity[reference.id]; - }else{ - refItem = this._arrayOfAllItems[reference.id]; - } - this._addReferenceToMap(refItem, deletedItem, reference.attr); - }, this); - delete deletedItem["backupRefs_" + this._reverseRefMap]; - } - } - - for(identity in this._pending._newItems){ - var newItem = this._pending._newItems[identity]; - newItem[this._storeRefPropName] = null; - // null out the new item, but don't change the array index so - // so we can keep using _arrayOfAllItems.length. - this._arrayOfAllItems[newItem[this._itemNumPropName]] = null; - if(newItem[this._rootItemPropName]){ - this._removeArrayElement(this._arrayOfTopLevelItems, newItem); - } - if(this._itemsByIdentity){ - delete this._itemsByIdentity[identity]; - } - } - - this._pending = { - _newItems:{}, - _modifiedItems:{}, - _deletedItems:{} - }; - return true; // boolean - }, - - isDirty: function(/* item? */ item){ - // summary: - // See dojo/data/api/Write.isDirty() - if(item){ - // return true if the item is dirty - var identity = this.getIdentity(item); - return new Boolean(this._pending._newItems[identity] || - this._pending._modifiedItems[identity] || - this._pending._deletedItems[identity]).valueOf(); // boolean - }else{ - // return true if the store is dirty -- which means return true - // if there are any new items, dirty items, or modified items - return !this._isEmpty(this._pending._newItems) || - !this._isEmpty(this._pending._modifiedItems) || - !this._isEmpty(this._pending._deletedItems); // boolean - } - }, - -/* dojo/data/api/Notification */ - - onSet: function(/* dojo/data/api/Item */ item, - /*attribute-name-string*/ attribute, - /*object|array*/ oldValue, - /*object|array*/ newValue){ - // summary: - // See dojo/data/api/Notification.onSet() - - // No need to do anything. This method is here just so that the - // client code can connect observers to it. - }, - - onNew: function(/* dojo/data/api/Item */ newItem, /*object?*/ parentInfo){ - // summary: - // See dojo/data/api/Notification.onNew() - - // No need to do anything. This method is here just so that the - // client code can connect observers to it. - }, - - onDelete: function(/* dojo/data/api/Item */ deletedItem){ - // summary: - // See dojo/data/api/Notification.onDelete() - - // No need to do anything. This method is here just so that the - // client code can connect observers to it. - }, - - close: function(/* object? */ request){ - // summary: - // Over-ride of base close function of ItemFileReadStore to add in check for store state. - // description: - // Over-ride of base close function of ItemFileReadStore to add in check for store state. - // If the store is still dirty (unsaved changes), then an error will be thrown instead of - // clearing the internal state for reload from the url. - - //Clear if not dirty ... or throw an error - if(this.clearOnClose){ - if(!this.isDirty()){ - this.inherited(arguments); - }else{ - //Only throw an error if the store was dirty and we were loading from a url (cannot reload from url until state is saved). - throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store. Please save or revert the changes before invoking close."); - } - } - } -}); - -}); - -}, -'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow dijitInline\" role=\"presentation\"\n\t\t><div data-dojo-attach-point=\"indentNode\" class=\"dijitInline\"></div\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n", -'dojo/dnd/TimedMoveable':function(){ -define("dojo/dnd/TimedMoveable", ["../_base/declare", "./Moveable" /*=====, "./Mover" =====*/], function(declare, Moveable /*=====, Mover =====*/){ - // module: - // dojo/dnd/TimedMoveable - - /*===== - var __TimedMoveableArgs = declare([Moveable.__MoveableArgs], { - // timeout: Number - // delay move by this number of ms, - // accumulating position changes during the timeout - timeout: 0 - }); - =====*/ - - // precalculate long expressions - var oldOnMove = Moveable.prototype.onMove; - - return declare("dojo.dnd.TimedMoveable", Moveable, { - // summary: - // A specialized version of Moveable to support an FPS throttling. - // This class puts an upper restriction on FPS, which may reduce - // the CPU load. The additional parameter "timeout" regulates - // the delay before actually moving the moveable object. - - // object attributes (for markup) - timeout: 40, // in ms, 40ms corresponds to 25 fps - - constructor: function(node, params){ - // summary: - // an object that makes a node moveable with a timer - // node: Node||String - // a node (or node's id) to be moved - // params: __TimedMoveableArgs - // object with additional parameters. - - // sanitize parameters - if(!params){ params = {}; } - if(params.timeout && typeof params.timeout == "number" && params.timeout >= 0){ - this.timeout = params.timeout; - } - }, - - onMoveStop: function(/*Mover*/ mover){ - if(mover._timer){ - // stop timer - clearTimeout(mover._timer); - // reflect the last received position - oldOnMove.call(this, mover, mover._leftTop); - } - Moveable.prototype.onMoveStop.apply(this, arguments); - }, - onMove: function(/*Mover*/ mover, /*Object*/ leftTop){ - mover._leftTop = leftTop; - if(!mover._timer){ - var _t = this; // to avoid using dojo.hitch() - mover._timer = setTimeout(function(){ - // we don't have any pending requests - mover._timer = null; - // reflect the last received position - oldOnMove.call(_t, mover, mover._leftTop); - }, this.timeout); - } - } - }); -}); - -}, -'dojo/NodeList-fx':function(){ -define("dojo/NodeList-fx", ["./query", "./_base/lang", "./_base/connect", "./_base/fx", "./fx"], -function(query, lang, connectLib, baseFx, coreFx){ - -// module: -// dojo/NodeList-fx - -/*===== -return function(){ - // summary: - // Adds dojo.fx animation support to dojo.query() by extending the NodeList class - // with additional FX functions. NodeList is the array-like object used to hold query results. -}; -=====*/ - -var NodeList = query.NodeList; - -lang.extend(NodeList, { - _anim: function(obj, method, args){ - args = args||{}; - var a = coreFx.combine( - this.map(function(item){ - var tmpArgs = { node: item }; - lang.mixin(tmpArgs, args); - return obj[method](tmpArgs); - }) - ); - return args.auto ? a.play() && this : a; // dojo/_base/fx.Animation|dojo/NodeList - }, - - wipeIn: function(args){ - // summary: - // wipe in all elements of this NodeList via `dojo/fx.wipeIn()` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // Fade in all tables with class "blah": - // | dojo.query("table.blah").wipeIn().play(); - // - // example: - // Utilizing `auto` to get the NodeList back: - // | dojo.query(".titles").wipeIn({ auto:true }).onclick(someFunction); - // - return this._anim(coreFx, "wipeIn", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - wipeOut: function(args){ - // summary: - // wipe out all elements of this NodeList via `dojo/fx.wipeOut()` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // Wipe out all tables with class "blah": - // | dojo.query("table.blah").wipeOut().play(); - return this._anim(coreFx, "wipeOut", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - slideTo: function(args){ - // summary: - // slide all elements of the node list to the specified place via `dojo/fx.slideTo()` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // | Move all tables with class "blah" to 300/300: - // | dojo.query("table.blah").slideTo({ - // | left: 40, - // | top: 50 - // | }).play(); - return this._anim(coreFx, "slideTo", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - - fadeIn: function(args){ - // summary: - // fade in all elements of this NodeList via `dojo.fadeIn` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // Fade in all tables with class "blah": - // | dojo.query("table.blah").fadeIn().play(); - return this._anim(baseFx, "fadeIn", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - fadeOut: function(args){ - // summary: - // fade out all elements of this NodeList via `dojo.fadeOut` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // Fade out all elements with class "zork": - // | dojo.query(".zork").fadeOut().play(); - // example: - // Fade them on a delay and do something at the end: - // | var fo = dojo.query(".zork").fadeOut(); - // | dojo.connect(fo, "onEnd", function(){ /*...*/ }); - // | fo.play(); - // example: - // Using `auto`: - // | dojo.query("li").fadeOut({ auto:true }).filter(filterFn).forEach(doit); - // - return this._anim(baseFx, "fadeOut", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - animateProperty: function(args){ - // summary: - // Animate all elements of this NodeList across the properties specified. - // syntax identical to `dojo.animateProperty` - // - // args: Object? - // Additional dojo/_base/fx.Animation arguments to mix into this set with the addition of - // an `auto` parameter. - // - // returns: dojo/_base/fx.Animation|dojo/NodeList - // A special args member `auto` can be passed to automatically play the animation. - // If args.auto is present, the original dojo/NodeList will be returned for further - // chaining. Otherwise the dojo/_base/fx.Animation instance is returned and must be .play()'ed - // - // example: - // | dojo.query(".zork").animateProperty({ - // | duration: 500, - // | properties: { - // | color: { start: "black", end: "white" }, - // | left: { end: 300 } - // | } - // | }).play(); - // - // example: - // | dojo.query(".grue").animateProperty({ - // | auto:true, - // | properties: { - // | height:240 - // | } - // | }).onclick(handler); - return this._anim(baseFx, "animateProperty", args); // dojo/_base/fx.Animation|dojo/NodeList - }, - - anim: function( /*Object*/ properties, - /*Integer?*/ duration, - /*Function?*/ easing, - /*Function?*/ onEnd, - /*Integer?*/ delay){ - // summary: - // Animate one or more CSS properties for all nodes in this list. - // The returned animation object will already be playing when it - // is returned. See the docs for `dojo.anim` for full details. - // properties: Object - // the properties to animate. does NOT support the `auto` parameter like other - // NodeList-fx methods. - // duration: Integer? - // Optional. The time to run the animations for - // easing: Function? - // Optional. The easing function to use. - // onEnd: Function? - // A function to be called when the animation ends - // delay: - // how long to delay playing the returned animation - // example: - // Another way to fade out: - // | dojo.query(".thinger").anim({ opacity: 0 }); - // example: - // animate all elements with the "thigner" class to a width of 500 - // pixels over half a second - // | dojo.query(".thinger").anim({ width: 500 }, 700); - var canim = coreFx.combine( - this.map(function(item){ - return baseFx.animateProperty({ - node: item, - properties: properties, - duration: duration||350, - easing: easing - }); - }) - ); - if(onEnd){ - connectLib.connect(canim, "onEnd", onEnd); - } - return canim.play(delay||0); // dojo/_base/fx.Animation - } -}); - -return NodeList; -}); - -}, -'dijit/form/_ListMouseMixin':function(){ -define("dijit/form/_ListMouseMixin", [ - "dojo/_base/declare", // declare - "dojo/mouse", - "dojo/on", - "dojo/touch", - "./_ListBase" -], function(declare, mouse, on, touch, _ListBase){ - -// module: -// dijit/form/_ListMouseMixin - -return declare( "dijit.form._ListMouseMixin", _ListBase, { - // summary: - // a Mixin to handle mouse or touch events for a focus-less menu - // Abstract methods that must be defined externally: - // - // - onClick: item was chosen (mousedown somewhere on the menu and mouseup somewhere on the menu) - // tags: - // private - - postCreate: function(){ - this.inherited(arguments); - - this.own(on(this.domNode, touch.press, function(evt){ evt.preventDefault(); })); // prevent focus shift on list scrollbar press - - this._listConnect(touch.press, "_onMouseDown"); - this._listConnect(touch.release, "_onMouseUp"); - this._listConnect(mouse.enter, "_onMouseOver"); - this._listConnect(mouse.leave, "_onMouseOut"); - }, - - _onMouseDown: function(/*Event*/ evt, /*DomNode*/ target){ - if(this._hoveredNode){ - this.onUnhover(this._hoveredNode); - this._hoveredNode = null; - } - this._isDragging = true; - this._setSelectedAttr(target); - }, - - _onMouseUp: function(/*Event*/ evt, /*DomNode*/ target){ - this._isDragging = false; - var selectedNode = this.selected; - var hoveredNode = this._hoveredNode; - if(selectedNode && target == selectedNode){ - this.onClick(selectedNode); - }else if(hoveredNode && target == hoveredNode){ // drag to select - this._setSelectedAttr(hoveredNode); - this.onClick(hoveredNode); - } - }, - - _onMouseOut: function(/*Event*/ evt, /*DomNode*/ target){ - if(this._hoveredNode){ - this.onUnhover(this._hoveredNode); - this._hoveredNode = null; - } - if(this._isDragging){ - this._cancelDrag = (new Date()).getTime() + 1000; // cancel in 1 second if no _onMouseOver fires - } - }, - - _onMouseOver: function(/*Event*/ evt, /*DomNode*/ target){ - if(this._cancelDrag){ - var time = (new Date()).getTime(); - if(time > this._cancelDrag){ - this._isDragging = false; - } - this._cancelDrag = null; - } - this._hoveredNode = target; - this.onHover(target); - if(this._isDragging){ - this._setSelectedAttr(target); - } - } -}); - -}); - -}, -'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n", -'dojo/cookie':function(){ -define("dojo/cookie", ["./_base/kernel", "./regexp"], function(dojo, regexp){ - -// module: -// dojo/cookie - -/*===== -var __cookieProps = { - // expires: Date|String|Number? - // If a number, the number of days from today at which the cookie - // will expire. If a date, the date past which the cookie will expire. - // If expires is in the past, the cookie will be deleted. - // If expires is omitted or is 0, the cookie will expire when the browser closes. - // path: String? - // The path to use for the cookie. - // domain: String? - // The domain to use for the cookie. - // secure: Boolean? - // Whether to only send the cookie on secure connections -}; -=====*/ - - -dojo.cookie = function(/*String*/name, /*String?*/ value, /*__cookieProps?*/ props){ - // summary: - // Get or set a cookie. - // description: - // If one argument is passed, returns the value of the cookie - // For two or more arguments, acts as a setter. - // name: - // Name of the cookie - // value: - // Value for the cookie - // props: - // Properties for the cookie - // example: - // set a cookie with the JSON-serialized contents of an object which - // will expire 5 days from now: - // | require(["dojo/cookie", "dojo/json"], function(cookie, json){ - // | cookie("configObj", json.stringify(config, {expires: 5 })); - // | }); - // - // example: - // de-serialize a cookie back into a JavaScript object: - // | require(["dojo/cookie", "dojo/json"], function(cookie, json){ - // | config = json.parse(cookie("configObj")); - // | }); - // - // example: - // delete a cookie: - // | require(["dojo/cookie"], function(cookie){ - // | cookie("configObj", null, {expires: -1}); - // | }); - var c = document.cookie, ret; - if(arguments.length == 1){ - var matches = c.match(new RegExp("(?:^|; )" + regexp.escapeString(name) + "=([^;]*)")); - ret = matches ? decodeURIComponent(matches[1]) : undefined; - }else{ - props = props || {}; -// FIXME: expires=0 seems to disappear right away, not on close? (FF3) Change docs? - var exp = props.expires; - if(typeof exp == "number"){ - var d = new Date(); - d.setTime(d.getTime() + exp*24*60*60*1000); - exp = props.expires = d; - } - if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); } - - value = encodeURIComponent(value); - var updatedCookie = name + "=" + value, propName; - for(propName in props){ - updatedCookie += "; " + propName; - var propValue = props[propName]; - if(propValue !== true){ updatedCookie += "=" + propValue; } - } - document.cookie = updatedCookie; - } - return ret; // String|undefined -}; - -dojo.cookie.isSupported = function(){ - // summary: - // Use to determine if the current browser supports cookies or not. - // - // Returns true if user allows cookies. - // Returns false if user doesn't allow cookies. - - if(!("cookieEnabled" in navigator)){ - this("__djCookieTest__", "CookiesAllowed"); - navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed"; - if(navigator.cookieEnabled){ - this("__djCookieTest__", "", {expires: -1}); - } - } - return navigator.cookieEnabled; -}; - -return dojo.cookie; -}); - -}, -'dojo/cache':function(){ -define("dojo/cache", ["./_base/kernel", "./text"], function(dojo){ - // module: - // dojo/cache - - // dojo.cache is defined in dojo/text - return dojo.cache; -}); - -}, -'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"button presentation\" aria-hidden=\"true\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n", -'dijit/ProgressBar':function(){ -require({cache:{ -'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\n\t><div data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\n/></div>\n"}}); -define("dijit/ProgressBar", [ - "require", // require.toUrl - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.toggle - "dojo/_base/lang", // lang.mixin - "dojo/number", // number.format - "./_Widget", - "./_TemplatedMixin", - "dojo/text!./templates/ProgressBar.html" -], function(require, declare, domClass, lang, number, _Widget, _TemplatedMixin, template){ - -// module: -// dijit/ProgressBar - - -return declare("dijit.ProgressBar", [_Widget, _TemplatedMixin], { - // summary: - // A progress indication widget, showing the amount completed - // (often the percentage completed) of a task. - // - // example: - // | <div data-dojo-type="ProgressBar" - // | places="0" - // | value="..." maximum="..."> - // | </div> - - // progress: [const] String (Percentage or Number) - // Number or percentage indicating amount of task completed. - // Deprecated. Use "value" instead. - progress: "0", - - // value: String (Percentage or Number) - // Number or percentage indicating amount of task completed. - // With "%": percentage value, 0% <= progress <= 100%, or - // without "%": absolute value, 0 <= progress <= maximum. - // Infinity means that the progress bar is indeterminate. - value: "", - - // maximum: [const] Float - // Max sample number - maximum: 100, - - // places: [const] Number - // Number of places to show in values; 0 by default - places: 0, - - // indeterminate: [const] Boolean - // If false: show progress value (number or percentage). - // If true: show that a process is underway but that the amount completed is unknown. - // Deprecated. Use "value" instead. - indeterminate: false, - - // label: String? - // Label on progress bar. Defaults to percentage for determinate progress bar and - // blank for indeterminate progress bar. - label:"", - - // name: String - // this is the field name (for a form) if set. This needs to be set if you want to use - // this widget in a dijit/form/Form widget (such as dijit/Dialog) - name: '', - - templateString: template, - - // _indeterminateHighContrastImagePath: [private] URL - // URL to image to use for indeterminate progress bar when display is in high contrast mode - _indeterminateHighContrastImagePath: - require.toUrl("./themes/a11y/indeterminate_progress.gif"), - - postMixInProperties: function(){ - this.inherited(arguments); - - // Back-compat for when constructor specifies indeterminate or progress, rather than value. Remove for 2.0. - if(!(this.params && "value" in this.params)){ - this.value = this.indeterminate ? Infinity : this.progress; - } - }, - - buildRendering: function(){ - this.inherited(arguments); - this.indeterminateHighContrastImage.setAttribute("src", - this._indeterminateHighContrastImagePath.toString()); - this.update(); - }, - - update: function(/*Object?*/attributes){ - // summary: - // Internal method to change attributes of ProgressBar, similar to set(hash). Users should call - // set("value", ...) rather than calling this method directly. - // attributes: - // May provide progress and/or maximum properties on this parameter; - // see attribute specs for details. - // example: - // | myProgressBar.update({'indeterminate': true}); - // | myProgressBar.update({'progress': 80}); - // | myProgressBar.update({'indeterminate': true, label:"Loading ..." }) - // tags: - // private - - // TODO: deprecate this method and use set() instead - - lang.mixin(this, attributes || {}); - var tip = this.internalProgress, ap = this.domNode; - var percent = 1; - if(this.indeterminate){ - ap.removeAttribute("aria-valuenow"); - }else{ - if(String(this.progress).indexOf("%") != -1){ - percent = Math.min(parseFloat(this.progress)/100, 1); - this.progress = percent * this.maximum; - }else{ - this.progress = Math.min(this.progress, this.maximum); - percent = this.maximum ? this.progress / this.maximum : 0; - } - ap.setAttribute("aria-valuenow", this.progress); - } - - // Even indeterminate ProgressBars should have these attributes - ap.setAttribute("aria-describedby", this.labelNode.id); - ap.setAttribute("aria-valuemin", 0); - ap.setAttribute("aria-valuemax", this.maximum); - - this.labelNode.innerHTML = this.report(percent); - - domClass.toggle(this.domNode, "dijitProgressBarIndeterminate", this.indeterminate); - tip.style.width = (percent * 100) + "%"; - this.onChange(); - }, - - _setValueAttr: function(v){ - this._set("value", v); - if(v == Infinity){ - this.update({indeterminate:true}); - }else{ - this.update({indeterminate:false, progress:v}); - } - }, - - _setLabelAttr: function(label){ - this._set("label", label); - this.update(); - }, - - _setIndeterminateAttr: function(indeterminate){ - // Deprecated, use set("value", ...) instead - this.indeterminate = indeterminate; - this.update(); - }, - - report: function(/*float*/percent){ - // summary: - // Generates message to show inside progress bar (normally indicating amount of task completed). - // May be overridden. - // tags: - // extension - - return this.label ? this.label : - (this.indeterminate ? " " : number.format(percent, { type: "percent", places: this.places, locale: this.lang })); - }, - - onChange: function(){ - // summary: - // Callback fired when progress updates. - // tags: - // extension - } -}); - -}); - -}, -'dijit/_base/popup':function(){ -define("dijit/_base/popup", [ - "dojo/dom-class", // domClass.contains - "dojo/_base/window", - "../popup", - "../BackgroundIframe" // just loading for back-compat, in case client code is referencing it -], function(domClass, win, popup){ - -// module: -// dijit/_base/popup - -/*===== -return { - // summary: - // Deprecated. Old module for popups, new code should use dijit/popup directly. -}; -=====*/ - - -// Hack support for old API passing in node instead of a widget (to various methods) -var origCreateWrapper = popup._createWrapper; -popup._createWrapper = function(widget){ - if(!widget.declaredClass){ - // make fake widget to pass to new API - widget = { - _popupWrapper: (widget.parentNode && domClass.contains(widget.parentNode, "dijitPopup")) ? - widget.parentNode : null, - domNode: widget, - destroy: function(){}, - ownerDocument: widget.ownerDocument, - ownerDocumentBody: win.body(widget.ownerDocument) - }; - } - return origCreateWrapper.call(this, widget); -}; - -// Support old format of orient parameter -var origOpen = popup.open; -popup.open = function(/*__OpenArgs*/ args){ - // Convert old hash structure (ex: {"BL": "TL", ...}) of orient to format compatible w/new popup.open() API. - // Don't do conversion for: - // - null parameter (that means to use the default positioning) - // - "R" or "L" strings used to indicate positioning for context menus (when there is no around node) - // - new format, ex: ["below", "above"] - // - return value from deprecated dijit.getPopupAroundAlignment() method, - // ex: ["below", "above"] - if(args.orient && typeof args.orient != "string" && !("length" in args.orient)){ - var ary = []; - for(var key in args.orient){ - ary.push({aroundCorner: key, corner: args.orient[key]}); - } - args.orient = ary; - } - - return origOpen.call(this, args); -}; - -return popup; -}); - -}, -'dijit/ColorPalette':function(){ -require({cache:{ -'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n"}}); -define("dijit/ColorPalette", [ - "require", // require.toUrl - "dojo/text!./templates/ColorPalette.html", - "./_Widget", // used also to load dijit/hccss for setting has("highcontrast") - "./_TemplatedMixin", - "./_PaletteMixin", - "./hccss", // has("highcontrast") - "dojo/i18n", // i18n.getLocalization - "dojo/_base/Color", // dojo.Color dojo.Color.named - "dojo/_base/declare", // declare - "dojo/dom-construct", // domConstruct.place - "dojo/string", // string.substitute - "dojo/i18n!dojo/nls/colors", // translations - "dojo/colors" // extend dojo.Color w/names of other colors -], function(require, template, _Widget, _TemplatedMixin, _PaletteMixin, has, i18n, Color, - declare, domConstruct, string){ - -// module: -// dijit/ColorPalette - -var ColorPalette = declare("dijit.ColorPalette", [_Widget, _TemplatedMixin, _PaletteMixin], { - // summary: - // A keyboard accessible color-picking widget - // description: - // Grid showing various colors, so the user can pick a certain color. - // Can be used standalone, or as a popup. - // - // example: - // | <div data-dojo-type="dijit/ColorPalette"></div> - // - // example: - // | var picker = new dijit.ColorPalette({ },srcNode); - // | picker.startup(); - - - // palette: [const] String - // Size of grid, either "7x10" or "3x4". - palette: "7x10", - - // _palettes: [protected] Map - // This represents the value of the colors. - // The first level is a hashmap of the different palettes available. - // The next two dimensions represent the columns and rows of colors. - _palettes: { - "7x10": [["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan", "lavender", "plum"], - ["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"], - ["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise", "skyblue", "mediumslateblue","orchid"], - ["gray", "red", "orangered", "darkorange", "yellow", "limegreen", "darkseagreen", "royalblue", "slateblue", "mediumorchid"], - ["dimgray", "crimson", "chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"], - ["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ], - ["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo", "purple"]], - - "3x4": [["white", "lime", "green", "blue"], - ["silver", "yellow", "fuchsia", "navy"], - ["gray", "red", "purple", "black"]] - }, - - // templateString: String - // The template of this widget. - templateString: template, - - baseClass: "dijitColorPalette", - - _dyeFactory: function(value, row, col, title){ - // Overrides _PaletteMixin._dyeFactory(). - return new this._dyeClass(value, row, col, title); - }, - - buildRendering: function(){ - // Instantiate the template, which makes a skeleton into which we'll insert a bunch of - // <img> nodes - this.inherited(arguments); - - // Creates customized constructor for dye class (color of a single cell) for - // specified palette and high-contrast vs. normal mode. Used in _getDye(). - this._dyeClass = declare(ColorPalette._Color, { - palette: this.palette - }); - - // Creates <img> nodes in each cell of the template. - this._preparePalette( - this._palettes[this.palette], - i18n.getLocalization("dojo", "colors", this.lang)); - } -}); - -ColorPalette._Color = declare("dijit._Color", Color, { - // summary: - // Object associated with each cell in a ColorPalette palette. - // Implements dijit/Dye. - - // Template for each cell in normal (non-high-contrast mode). Each cell contains a wrapper - // node for showing the border (called dijitPaletteImg for back-compat), and dijitColorPaletteSwatch - // for showing the color. - template: - "<span class='dijitInline dijitPaletteImg'>" + - "<img src='${blankGif}' alt='${alt}' title='${title}' class='dijitColorPaletteSwatch' style='background-color: ${color}'/>" + - "</span>", - - // Template for each cell in high contrast mode. Each cell contains an image with the whole palette, - // but scrolled and clipped to show the correct color only - hcTemplate: - "<span class='dijitInline dijitPaletteImg' style='position: relative; overflow: hidden; height: 12px; width: 14px;'>" + - "<img src='${image}' alt='${alt}' title='${title}' style='position: absolute; left: ${left}px; top: ${top}px; ${size}'/>" + - "</span>", - - // _imagePaths: [protected] Map - // This is stores the path to the palette images used for high-contrast mode display - _imagePaths: { - "7x10": require.toUrl("./themes/a11y/colors7x10.png"), - "3x4": require.toUrl("./themes/a11y/colors3x4.png") - }, - - constructor: function(alias, row, col, title){ - // summary: - // Constructor for ColorPalette._Color - // alias: String - // English name of the color. - // row: Number - // Vertical position in grid. - // column: Number - // Horizontal position in grid. - // title: String - // Localized name of the color. - this._title = title; - this._row = row; - this._col = col; - this.setColor(Color.named[alias]); - }, - - getValue: function(){ - // summary: - // Note that although dijit._Color is initialized with a value like "white" getValue() always - // returns a hex value - return this.toHex(); - }, - - fillCell: function(/*DOMNode*/ cell, /*String*/ blankGif){ - var html = string.substitute(has("highcontrast") ? this.hcTemplate : this.template, { - // substitution variables for normal mode - color: this.toHex(), - blankGif: blankGif, - alt: this._title, - title: this._title, - - // variables used for high contrast mode - image: this._imagePaths[this.palette].toString(), - left: this._col * -20 - 5, - top: this._row * -20 - 5, - size: this.palette == "7x10" ? "height: 145px; width: 206px" : "height: 64px; width: 86px" - }); - - domConstruct.place(html, cell); - } -}); - - -return ColorPalette; -}); - -}, -'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n", -'dojo/_base/url':function(){ -define("dojo/_base/url", ["./kernel"], function(dojo){ - // module: - // dojo/url - - var - ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"), - ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"), - _Url = function(){ - var n = null, - _a = arguments, - uri = [_a[0]]; - // resolve uri components relative to each other - for(var i = 1; i<_a.length; i++){ - if(!_a[i]){ continue; } - - // Safari doesn't support this.constructor so we have to be explicit - // FIXME: Tracked (and fixed) in Webkit bug 3537. - // http://bugs.webkit.org/show_bug.cgi?id=3537 - var relobj = new _Url(_a[i]+""), - uriobj = new _Url(uri[0]+""); - - if( - relobj.path == "" && - !relobj.scheme && - !relobj.authority && - !relobj.query - ){ - if(relobj.fragment != n){ - uriobj.fragment = relobj.fragment; - } - relobj = uriobj; - }else if(!relobj.scheme){ - relobj.scheme = uriobj.scheme; - - if(!relobj.authority){ - relobj.authority = uriobj.authority; - - if(relobj.path.charAt(0) != "/"){ - var path = uriobj.path.substring(0, - uriobj.path.lastIndexOf("/") + 1) + relobj.path; - - var segs = path.split("/"); - for(var j = 0; j < segs.length; j++){ - if(segs[j] == "."){ - // flatten "./" references - if(j == segs.length - 1){ - segs[j] = ""; - }else{ - segs.splice(j, 1); - j--; - } - }else if(j > 0 && !(j == 1 && segs[0] == "") && - segs[j] == ".." && segs[j-1] != ".."){ - // flatten "../" references - if(j == (segs.length - 1)){ - segs.splice(j, 1); - segs[j - 1] = ""; - }else{ - segs.splice(j - 1, 2); - j -= 2; - } - } - } - relobj.path = segs.join("/"); - } - } - } - - uri = []; - if(relobj.scheme){ - uri.push(relobj.scheme, ":"); - } - if(relobj.authority){ - uri.push("//", relobj.authority); - } - uri.push(relobj.path); - if(relobj.query){ - uri.push("?", relobj.query); - } - if(relobj.fragment){ - uri.push("#", relobj.fragment); - } - } - - this.uri = uri.join(""); - - // break the uri into its main components - var r = this.uri.match(ore); - - this.scheme = r[2] || (r[1] ? "" : n); - this.authority = r[4] || (r[3] ? "" : n); - this.path = r[5]; // can never be undefined - this.query = r[7] || (r[6] ? "" : n); - this.fragment = r[9] || (r[8] ? "" : n); - - if(this.authority != n){ - // server based naming authority - r = this.authority.match(ire); - - this.user = r[3] || n; - this.password = r[4] || n; - this.host = r[6] || r[7]; // ipv6 || ipv4 - this.port = r[9] || n; - } - }; - _Url.prototype.toString = function(){ return this.uri; }; - - return dojo._Url = _Url; -}); - -}, -'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n", -'dojo/text':function(){ -define("dojo/text", ["./_base/kernel", "require", "./has", "./_base/xhr"], function(dojo, require, has, xhr){ - // module: - // dojo/text - - var getText; - if( 1 ){ - getText= function(url, sync, load){ - xhr("GET", {url: url, sync:!!sync, load: load, headers: dojo.config.textPluginHeaders || {}}); - }; - }else{ - // TODOC: only works for dojo AMD loader - if(require.getText){ - getText= require.getText; - }else{ - console.error("dojo/text plugin failed to load because loader does not support getText"); - } - } - - var - theCache = {}, - - strip= function(text){ - //Strips <?xml ...?> declarations so that external SVG and XML - //documents can be added to a document without worry. Also, if the string - //is an HTML document, only the part inside the body tag is returned. - if(text){ - text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, ""); - var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); - if(matches){ - text= matches[1]; - } - }else{ - text = ""; - } - return text; - }, - - notFound = {}, - - pending = {}; - - dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){ - // summary: - // A getter and setter for storing the string content associated with the - // module and url arguments. - // description: - // If module is a string that contains slashes, then it is interpretted as a fully - // resolved path (typically a result returned by require.toUrl), and url should not be - // provided. This is the preferred signature. If module is a string that does not - // contain slashes, then url must also be provided and module and url are used to - // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated. - // If value is specified, the cache value for the moduleUrl will be set to - // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it - // in its internal cache and return that cached value for the URL. To clear - // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the - // the URL contents, only modules on the same domain of the page can use this capability. - // The build system can inline the cache values though, to allow for xdomain hosting. - // module: String||Object - // If a String with slashes, a fully resolved path; if a String without slashes, the - // module name to use for the base part of the URL, similar to module argument - // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that - // generates a valid path for the cache item. For example, a dojo._Url object. - // url: String - // The rest of the path to append to the path derived from the module argument. If - // module is an object, then this second argument should be the "value" argument instead. - // value: String||Object? - // If a String, the value to use in the cache for the module/url combination. - // If an Object, it can have two properties: value and sanitize. The value property - // should be the value to use in the cache, and sanitize can be set to true or false, - // to indicate if XML declarations should be removed from the value and if the HTML - // inside a body tag in the value should be extracted as the real value. The value argument - // or the value property on the value argument are usually only used by the build system - // as it inlines cache content. - // example: - // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style - // of call is used to avoid an issue with the build system erroneously trying to intern - // this example. To get the build system to intern your dojo.cache calls, use the - // "dojo.cache" style of call): - // | //If template.html contains "<h1>Hello</h1>" that will be - // | //the value for the text variable. - // | var text = dojo["cache"]("my.module", "template.html"); - // example: - // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input - // (the dojo["cache"] style of call is used to avoid an issue with the build system - // erroneously trying to intern this example. To get the build system to intern your - // dojo.cache calls, use the "dojo.cache" style of call): - // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the - // | //text variable will contain just "<h1>Hello</h1>". - // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true}); - // example: - // Same example as previous, but demonstrates how an object can be passed in as - // the first argument, then the value argument can then be the second argument. - // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the - // | //text variable will contain just "<h1>Hello</h1>". - // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true}); - - // * (string string [value]) => (module, url, value) - // * (object [value]) => (module, value), url defaults to "" - // - // * if module is an object, then it must be convertable to a string - // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl - // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize" - var key; - if(typeof module=="string"){ - if(/\//.test(module)){ - // module is a version 1.7+ resolved path - key = module; - value = url; - }else{ - // module is a version 1.6- argument to dojo.moduleUrl - key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "")); - } - }else{ - key = module + ""; - value = url; - } - var - val = (value != undefined && typeof value != "string") ? value.value : value, - sanitize = value && value.sanitize; - - if(typeof val == "string"){ - //We have a string, set cache value - theCache[key] = val; - return sanitize ? strip(val) : val; - }else if(val === null){ - //Remove cached value - delete theCache[key]; - return null; - }else{ - //Allow cache values to be empty strings. If key property does - //not exist, fetch it. - if(!(key in theCache)){ - getText(key, true, function(text){ - theCache[key]= text; - }); - } - return sanitize ? strip(theCache[key]) : theCache[key]; - } - }; - - return { - // summary: - // This module implements the dojo/text! plugin and the dojo.cache API. - // description: - // We choose to include our own plugin to leverage functionality already contained in dojo - // and thereby reduce the size of the plugin compared to various foreign loader implementations. - // Also, this allows foreign AMD loaders to be used without their plugins. - // - // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous - // loader. This feature is outside the scope of the CommonJS plugins specification. - - // the dojo/text caches it's own resources because of dojo.cache - dynamic: true, - - normalize: function(id, toAbsMid){ - // id is something like (path may be relative): - // - // "path/to/text.html" - // "path/to/text.html!strip" - var parts= id.split("!"), - url= parts[0]; - return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : ""); - }, - - load: function(id, require, load){ - // id: String - // Path to the resource. - // require: Function - // Object that include the function toUrl with given id returns a valid URL from which to load the text. - // load: Function - // Callback function which will be called, when the loading finished. - - // id is something like (path is always absolute): - // - // "path/to/text.html" - // "path/to/text.html!strip" - var - parts= id.split("!"), - stripFlag= parts.length>1, - absMid= parts[0], - url = require.toUrl(parts[0]), - requireCacheUrl = "url:" + url, - text = notFound, - finish = function(text){ - load(stripFlag ? strip(text) : text); - }; - if(absMid in theCache){ - text = theCache[absMid]; - }else if(requireCacheUrl in require.cache){ - text = require.cache[requireCacheUrl]; - }else if(url in theCache){ - text = theCache[url]; - } - if(text===notFound){ - if(pending[url]){ - pending[url].push(finish); - }else{ - var pendingList = pending[url] = [finish]; - getText(url, !require.async, function(text){ - theCache[absMid]= theCache[url]= text; - for(var i = 0; i<pendingList.length;){ - pendingList[i++](text); - } - delete pending[url]; - }); - } - }else{ - finish(text); - } - } - }; - -}); - - -}, -'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" role=\"${type}\" aria-checked=\"false\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n", -'dojo/uacss':function(){ -define("dojo/uacss", ["./dom-geometry", "./_base/lang", "./ready", "./sniff", "./_base/window"], - function(geometry, lang, ready, has, baseWindow){ - - // module: - // dojo/uacss - - /*===== - return { - // summary: - // Applies pre-set CSS classes to the top-level HTML node, based on: - // - // - browser (ex: dj_ie) - // - browser version (ex: dj_ie6) - // - box model (ex: dj_contentBox) - // - text direction (ex: dijitRtl) - // - // In addition, browser, browser version, and box model are - // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl. - // - // Returns the has() method. - }; - =====*/ - - var - html = baseWindow.doc.documentElement, - ie = has("ie"), - opera = has("opera"), - maj = Math.floor, - ff = has("ff"), - boxModel = geometry.boxModel.replace(/-/,''), - - classes = { - "dj_quirks": has("quirks"), - - // NOTE: Opera not supported by dijit - "dj_opera": opera, - - "dj_khtml": has("khtml"), - - "dj_webkit": has("webkit"), - "dj_safari": has("safari"), - "dj_chrome": has("chrome"), - - "dj_gecko": has("mozilla") - }; // no dojo unsupported browsers - - if(ie){ - classes["dj_ie"] = true; - classes["dj_ie" + maj(ie)] = true; - classes["dj_iequirks"] = has("quirks"); - } - if(ff){ - classes["dj_ff" + maj(ff)] = true; - } - - classes["dj_" + boxModel] = true; - - // apply browser, browser version, and box model class names - var classStr = ""; - for(var clz in classes){ - if(classes[clz]){ - classStr += clz + " "; - } - } - html.className = lang.trim(html.className + " " + classStr); - - // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension. - // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl). - // priority is 90 to run ahead of parser priority of 100 - ready(90, function(){ - if(!geometry.isBodyLtr()){ - var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "); - html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")); - } - }); - return has; -}); - -}, -'dijit/Tooltip':function(){ -require({cache:{ -'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n"}}); -define("dijit/Tooltip", [ - "dojo/_base/array", // array.forEach array.indexOf array.map - "dojo/_base/declare", // declare - "dojo/_base/fx", // fx.fadeIn fx.fadeOut - "dojo/dom", // dom.byId - "dojo/dom-class", // domClass.add - "dojo/dom-geometry", // domGeometry.position - "dojo/dom-style", // domStyle.set, domStyle.get - "dojo/_base/lang", // lang.hitch lang.isArrayLike - "dojo/mouse", - "dojo/on", - "dojo/sniff", // has("ie") - "./_base/manager", // manager.defaultDuration - "./place", - "./_Widget", - "./_TemplatedMixin", - "./BackgroundIframe", - "dojo/text!./templates/Tooltip.html", - "./main" // sets dijit.showTooltip etc. for back-compat -], function(array, declare, fx, dom, domClass, domGeometry, domStyle, lang, mouse, on, has, - manager, place, _Widget, _TemplatedMixin, BackgroundIframe, template, dijit){ - - // module: - // dijit/Tooltip - - - // TODO: Tooltip should really share more positioning code with TooltipDialog, like: - // - the orient() method - // - the connector positioning code in show() - // - the dijitTooltip[Dialog] class - // - // The problem is that Tooltip's implementation supplies it's own <iframe> and interacts directly - // with dijit/place, rather than going through dijit/popup like TooltipDialog and other popups (ex: Menu). - - var MasterTooltip = declare("dijit._MasterTooltip", [_Widget, _TemplatedMixin], { - // summary: - // Internal widget that holds the actual tooltip markup, - // which occurs once per page. - // Called by Tooltip widgets which are just containers to hold - // the markup - // tags: - // protected - - // duration: Integer - // Milliseconds to fade in/fade out - duration: manager.defaultDuration, - - templateString: template, - - postCreate: function(){ - this.ownerDocumentBody.appendChild(this.domNode); - - this.bgIframe = new BackgroundIframe(this.domNode); - - // Setup fade-in and fade-out functions. - this.fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onShow") }); - this.fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onHide") }); - }, - - show: function(innerHTML, aroundNode, position, rtl, textDir){ - // summary: - // Display tooltip w/specified contents to right of specified node - // (To left if there's no space on the right, or if rtl == true) - // innerHTML: String - // Contents of the tooltip - // aroundNode: DomNode|dijit/place.__Rectangle - // Specifies that tooltip should be next to this node / area - // position: String[]? - // List of positions to try to position tooltip (ex: ["right", "above"]) - // rtl: Boolean? - // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true - // means "rtl"; specifies GUI direction, not text direction. - // textDir: String? - // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text. - - - if(this.aroundNode && this.aroundNode === aroundNode && this.containerNode.innerHTML == innerHTML){ - return; - } - - if(this.fadeOut.status() == "playing"){ - // previous tooltip is being hidden; wait until the hide completes then show new one - this._onDeck=arguments; - return; - } - this.containerNode.innerHTML=innerHTML; - - if(textDir){ - this.set("textDir", textDir); - } - - this.containerNode.align = rtl? "right" : "left"; //fix the text alignment - - var pos = place.around(this.domNode, aroundNode, - position && position.length ? position : Tooltip.defaultPosition, !rtl, lang.hitch(this, "orient")); - - // Position the tooltip connector for middle alignment. - // This could not have been done in orient() since the tooltip wasn't positioned at that time. - var aroundNodeCoords = pos.aroundNodePos; - if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){ - this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px"; - this.connectorNode.style.left = ""; - }else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){ - this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px"; - }else{ - // Not *-centered, but just above/below/after/before - this.connectorNode.style.left = ""; - this.connectorNode.style.top = ""; - } - - // show it - domStyle.set(this.domNode, "opacity", 0); - this.fadeIn.play(); - this.isShowingNow = true; - this.aroundNode = aroundNode; - }, - - orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner, /*Object*/ spaceAvailable, /*Object*/ aroundNodeCoords){ - // summary: - // Private function to set CSS for tooltip node based on which position it's in. - // This is called by the dijit popup code. It will also reduce the tooltip's - // width to whatever width is available - // tags: - // protected - - this.connectorNode.style.top = ""; //reset to default - - var heightAvailable = spaceAvailable.h, - widthAvailable = spaceAvailable.w; - - node.className = "dijitTooltip " + - { - "MR-ML": "dijitTooltipRight", - "ML-MR": "dijitTooltipLeft", - "TM-BM": "dijitTooltipAbove", - "BM-TM": "dijitTooltipBelow", - "BL-TL": "dijitTooltipBelow dijitTooltipABLeft", - "TL-BL": "dijitTooltipAbove dijitTooltipABLeft", - "BR-TR": "dijitTooltipBelow dijitTooltipABRight", - "TR-BR": "dijitTooltipAbove dijitTooltipABRight", - "BR-BL": "dijitTooltipRight", - "BL-BR": "dijitTooltipLeft" - }[aroundCorner + "-" + tooltipCorner]; - - // reset width; it may have been set by orient() on a previous tooltip show() - this.domNode.style.width = "auto"; - - // Reduce tooltip's width to the amount of width available, so that it doesn't overflow screen. - // Note that sometimes widthAvailable is negative, but we guard against setting style.width to a - // negative number since that causes an exception on IE. - var size = domGeometry.position(this.domNode); - if(has("ie") == 9){ - // workaround strange IE9 bug where setting width to offsetWidth causes words to wrap - size.w += 2; - } - - var width = Math.min((Math.max(widthAvailable,1)), size.w); - - domGeometry.setMarginBox(this.domNode, {w: width}); - - // Reposition the tooltip connector. - if(tooltipCorner.charAt(0) == 'B' && aroundCorner.charAt(0) == 'B'){ - var bb = domGeometry.position(node); - var tooltipConnectorHeight = this.connectorNode.offsetHeight; - if(bb.h > heightAvailable){ - // The tooltip starts at the top of the page and will extend past the aroundNode - var aroundNodePlacement = heightAvailable - ((aroundNodeCoords.h + tooltipConnectorHeight) >> 1); - this.connectorNode.style.top = aroundNodePlacement + "px"; - this.connectorNode.style.bottom = ""; - }else{ - // Align center of connector with center of aroundNode, except don't let bottom - // of connector extend below bottom of tooltip content, or top of connector - // extend past top of tooltip content - this.connectorNode.style.bottom = Math.min( - Math.max(aroundNodeCoords.h/2 - tooltipConnectorHeight/2, 0), - bb.h - tooltipConnectorHeight) + "px"; - this.connectorNode.style.top = ""; - } - }else{ - // reset the tooltip back to the defaults - this.connectorNode.style.top = ""; - this.connectorNode.style.bottom = ""; - } - - return Math.max(0, size.w - widthAvailable); - }, - - _onShow: function(){ - // summary: - // Called at end of fade-in operation - // tags: - // protected - if(has("ie")){ - // the arrow won't show up on a node w/an opacity filter - this.domNode.style.filter=""; - } - }, - - hide: function(aroundNode){ - // summary: - // Hide the tooltip - - if(this._onDeck && this._onDeck[1] == aroundNode){ - // this hide request is for a show() that hasn't even started yet; - // just cancel the pending show() - this._onDeck=null; - }else if(this.aroundNode === aroundNode){ - // this hide request is for the currently displayed tooltip - this.fadeIn.stop(); - this.isShowingNow = false; - this.aroundNode = null; - this.fadeOut.play(); - }else{ - // just ignore the call, it's for a tooltip that has already been erased - } - }, - - _onHide: function(){ - // summary: - // Called at end of fade-out operation - // tags: - // protected - - this.domNode.style.cssText=""; // to position offscreen again - this.containerNode.innerHTML=""; - if(this._onDeck){ - // a show request has been queued up; do it now - this.show.apply(this, this._onDeck); - this._onDeck=null; - } - }, - - _setAutoTextDir: function(/*Object*/node){ - // summary: - // Resolve "auto" text direction for children nodes - // tags: - // private - - this.applyTextDir(node, has("ie") ? node.outerText : node.textContent); - array.forEach(node.children, function(child){this._setAutoTextDir(child); }, this); - }, - - _setTextDirAttr: function(/*String*/ textDir){ - // summary: - // Setter for textDir. - // description: - // Users shouldn't call this function; they should be calling - // set('textDir', value) - // tags: - // private - - this._set("textDir", textDir); - - if (textDir == "auto"){ - this._setAutoTextDir(this.containerNode); - }else{ - this.containerNode.dir = this.textDir; - } - } - }); - - dijit.showTooltip = function(innerHTML, aroundNode, position, rtl, textDir){ - // summary: - // Static method to display tooltip w/specified contents in specified position. - // See description of dijit/Tooltip.defaultPosition for details on position parameter. - // If position is not specified then dijit/Tooltip.defaultPosition is used. - // innerHTML: String - // Contents of the tooltip - // aroundNode: place.__Rectangle - // Specifies that tooltip should be next to this node / area - // position: String[]? - // List of positions to try to position tooltip (ex: ["right", "above"]) - // rtl: Boolean? - // Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true - // means "rtl"; specifies GUI direction, not text direction. - // textDir: String? - // Corresponds to `WidgetBase.textdir` attribute; specifies direction of text. - - // After/before don't work, but for back-compat convert them to the working after-centered, before-centered. - // Possibly remove this in 2.0. Alternately, get before/after to work. - if(position){ - position = array.map(position, function(val){ - return {after: "after-centered", before: "before-centered"}[val] || val; - }); - } - - if(!Tooltip._masterTT){ dijit._masterTT = Tooltip._masterTT = new MasterTooltip(); } - return Tooltip._masterTT.show(innerHTML, aroundNode, position, rtl, textDir); - }; - - dijit.hideTooltip = function(aroundNode){ - // summary: - // Static method to hide the tooltip displayed via showTooltip() - return Tooltip._masterTT && Tooltip._masterTT.hide(aroundNode); - }; - - var Tooltip = declare("dijit.Tooltip", _Widget, { - // summary: - // Pops up a tooltip (a help message) when you hover over a node. - // Also provides static show() and hide() methods that can be used without instantiating a dijit/Tooltip. - - // label: String - // Text to display in the tooltip. - // Specified as innerHTML when creating the widget from markup. - label: "", - - // showDelay: Integer - // Number of milliseconds to wait after hovering over/focusing on the object, before - // the tooltip is displayed. - showDelay: 400, - - // connectId: String|String[]|DomNode|DomNode[] - // Id of domNode(s) to attach the tooltip to. - // When user hovers over specified dom node(s), the tooltip will appear. - connectId: [], - - // position: String[] - // See description of `dijit/Tooltip.defaultPosition` for details on position parameter. - position: [], - - // selector: String? - // CSS expression to apply this Tooltip to descendants of connectIds, rather than to - // the nodes specified by connectIds themselves. Useful for applying a Tooltip to - // a range of rows in a table, tree, etc. Use in conjunction with getContent() parameter. - // Ex: connectId: myTable, selector: "tr", getContent: function(node){ return ...; } - // - // The application must require() an appropriate level of dojo/query to handle the selector. - selector: "", - - // TODO: in 2.0 remove support for multiple connectIds. selector gives the same effect. - // So, change connectId to a "", remove addTarget()/removeTarget(), etc. - - _setConnectIdAttr: function(/*String|String[]}DomNode|DomNode[]*/ newId){ - // summary: - // Connect to specified node(s) - - // Remove connections to old nodes (if there are any) - array.forEach(this._connections || [], function(nested){ - array.forEach(nested, function(handle){ handle.remove(); }); - }, this); - - // Make array of id's to connect to, excluding entries for nodes that don't exist yet, see startup() - this._connectIds = array.filter(lang.isArrayLike(newId) ? newId : (newId ? [newId] : []), - function(id){ return dom.byId(id, this.ownerDocument); }, this); - - // Make connections - this._connections = array.map(this._connectIds, function(id){ - var node = dom.byId(id, this.ownerDocument), - selector = this.selector, - delegatedEvent = selector ? - function(eventType){ return on.selector(selector, eventType); } : - function(eventType){ return eventType; }, - self = this; - return [ - on(node, delegatedEvent(mouse.enter), function(){ - self._onHover(this); - }), - on(node, delegatedEvent("focusin"), function(){ - self._onHover(this); - }), - on(node, delegatedEvent(mouse.leave), lang.hitch(self, "_onUnHover")), - on(node, delegatedEvent("focusout"), lang.hitch(self, "_onUnHover")) - ]; - }, this); - - this._set("connectId", newId); - }, - - addTarget: function(/*OomNode|String*/ node){ - // summary: - // Attach tooltip to specified node if it's not already connected - - // TODO: remove in 2.0 and just use set("connectId", ...) interface - - var id = node.id || node; - if(array.indexOf(this._connectIds, id) == -1){ - this.set("connectId", this._connectIds.concat(id)); - } - }, - - removeTarget: function(/*DomNode|String*/ node){ - // summary: - // Detach tooltip from specified node - - // TODO: remove in 2.0 and just use set("connectId", ...) interface - - var id = node.id || node, // map from DOMNode back to plain id string - idx = array.indexOf(this._connectIds, id); - if(idx >= 0){ - // remove id (modifies original this._connectIds but that's OK in this case) - this._connectIds.splice(idx, 1); - this.set("connectId", this._connectIds); - } - }, - - buildRendering: function(){ - this.inherited(arguments); - domClass.add(this.domNode,"dijitTooltipData"); - }, - - startup: function(){ - this.inherited(arguments); - - // If this tooltip was created in a template, or for some other reason the specified connectId[s] - // didn't exist during the widget's initialization, then connect now. - var ids = this.connectId; - array.forEach(lang.isArrayLike(ids) ? ids : [ids], this.addTarget, this); - }, - - getContent: function(/*DomNode*/ node){ - // summary: - // User overridable function that return the text to display in the tooltip. - // tags: - // extension - return this.label || this.domNode.innerHTML; - }, - - _onHover: function(/*DomNode*/ target){ - // summary: - // Despite the name of this method, it actually handles both hover and focus - // events on the target node, setting a timer to show the tooltip. - // tags: - // private - if(!this._showTimer){ - this._showTimer = this.defer(function(){ this.open(target); }, this.showDelay); - } - }, - - _onUnHover: function(){ - // summary: - // Despite the name of this method, it actually handles both mouseleave and blur - // events on the target node, hiding the tooltip. - // tags: - // private - - if(this._showTimer){ - this._showTimer.remove(); - delete this._showTimer; - } - this.close(); - }, - - open: function(/*DomNode*/ target){ - // summary: - // Display the tooltip; usually not called directly. - // tags: - // private - - if(this._showTimer){ - this._showTimer.remove(); - delete this._showTimer; - } - - var content = this.getContent(target); - if(!content){ - return; - } - Tooltip.show(content, target, this.position, !this.isLeftToRight(), this.textDir); - - this._connectNode = target; // _connectNode means "tooltip currently displayed for this node" - this.onShow(target, this.position); - }, - - close: function(){ - // summary: - // Hide the tooltip or cancel timer for show of tooltip - // tags: - // private - - if(this._connectNode){ - // if tooltip is currently shown - Tooltip.hide(this._connectNode); - delete this._connectNode; - this.onHide(); - } - if(this._showTimer){ - // if tooltip is scheduled to be shown (after a brief delay) - this._showTimer.remove(); - delete this._showTimer; - } - }, - - onShow: function(/*===== target, position =====*/){ - // summary: - // Called when the tooltip is shown - // tags: - // callback - }, - - onHide: function(){ - // summary: - // Called when the tooltip is hidden - // tags: - // callback - }, - - destroy: function(){ - this.close(); - - // Remove connections manually since they aren't registered to be removed by _WidgetBase - array.forEach(this._connections || [], function(nested){ - array.forEach(nested, function(handle){ handle.remove(); }); - }, this); - - this.inherited(arguments); - } - }); - - Tooltip._MasterTooltip = MasterTooltip; // for monkey patching - Tooltip.show = dijit.showTooltip; // export function through module return value - Tooltip.hide = dijit.hideTooltip; // export function through module return value - - Tooltip.defaultPosition = ["after-centered", "before-centered"]; - - /*===== - lang.mixin(Tooltip, { - // defaultPosition: String[] - // This variable controls the position of tooltips, if the position is not specified to - // the Tooltip widget or *TextBox widget itself. It's an array of strings with the values - // possible for `dijit/place.around()`. The recommended values are: - // - // - before-centered: centers tooltip to the left of the anchor node/widget, or to the right - // in the case of RTL scripts like Hebrew and Arabic - // - after-centered: centers tooltip to the right of the anchor node/widget, or to the left - // in the case of RTL scripts like Hebrew and Arabic - // - above-centered: tooltip is centered above anchor node - // - below-centered: tooltip is centered above anchor node - // - // The list is positions is tried, in order, until a position is found where the tooltip fits - // within the viewport. - // - // Be careful setting this parameter. A value of "above-centered" may work fine until the user scrolls - // the screen so that there's no room above the target node. Nodes with drop downs, like - // DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure - // that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there - // is only room below (or above) the target node, but not both. - }); - =====*/ - return Tooltip; -}); - -}, -'dojo/string':function(){ -define("dojo/string", [ - "./_base/kernel", // kernel.global - "./_base/lang" -], function(kernel, lang){ - -// module: -// dojo/string - -var string = { - // summary: - // String utilities for Dojo -}; -lang.setObject("dojo.string", string); - -string.rep = function(/*String*/str, /*Integer*/num){ - // summary: - // Efficiently replicate a string `n` times. - // str: - // the string to replicate - // num: - // number of times to replicate the string - - if(num <= 0 || !str){ return ""; } - - var buf = []; - for(;;){ - if(num & 1){ - buf.push(str); - } - if(!(num >>= 1)){ break; } - str += str; - } - return buf.join(""); // String -}; - -string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){ - // summary: - // Pad a string to guarantee that it is at least `size` length by - // filling with the character `ch` at either the start or end of the - // string. Pads at the start, by default. - // text: - // the string to pad - // size: - // length to provide padding - // ch: - // character to pad, defaults to '0' - // end: - // adds padding at the end if true, otherwise pads at start - // example: - // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++". - // | string.pad("Dojo", 10, "+", true); - - if(!ch){ - ch = '0'; - } - var out = String(text), - pad = string.rep(ch, Math.ceil((size - out.length) / ch.length)); - return end ? out + pad : pad + out; // String -}; - -string.substitute = function( /*String*/ template, - /*Object|Array*/map, - /*Function?*/ transform, - /*Object?*/ thisObject){ - // summary: - // Performs parameterized substitutions on a string. Throws an - // exception if any parameter is unmatched. - // template: - // a string with expressions in the form `${key}` to be replaced or - // `${key:format}` which specifies a format function. keys are case-sensitive. - // map: - // hash to search for substitutions - // transform: - // a function to process all parameters before substitution takes - // place, e.g. mylib.encodeXML - // thisObject: - // where to look for optional format function; default to the global - // namespace - // example: - // Substitutes two expressions in a string from an Array or Object - // | // returns "File 'foo.html' is not found in directory '/temp'." - // | // by providing substitution data in an Array - // | string.substitute( - // | "File '${0}' is not found in directory '${1}'.", - // | ["foo.html","/temp"] - // | ); - // | - // | // also returns "File 'foo.html' is not found in directory '/temp'." - // | // but provides substitution data in an Object structure. Dotted - // | // notation may be used to traverse the structure. - // | string.substitute( - // | "File '${name}' is not found in directory '${info.dir}'.", - // | { name: "foo.html", info: { dir: "/temp" } } - // | ); - // example: - // Use a transform function to modify the values: - // | // returns "file 'foo.html' is not found in directory '/temp'." - // | string.substitute( - // | "${0} is not found in ${1}.", - // | ["foo.html","/temp"], - // | function(str){ - // | // try to figure out the type - // | var prefix = (str.charAt(0) == "/") ? "directory": "file"; - // | return prefix + " '" + str + "'"; - // | } - // | ); - // example: - // Use a formatter - // | // returns "thinger -- howdy" - // | string.substitute( - // | "${0:postfix}", ["thinger"], null, { - // | postfix: function(value, key){ - // | return value + " -- howdy"; - // | } - // | } - // | ); - - thisObject = thisObject || kernel.global; - transform = transform ? - lang.hitch(thisObject, transform) : function(v){ return v; }; - - return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, - function(match, key, format){ - var value = lang.getObject(key, false, map); - if(format){ - value = lang.getObject(format, false, thisObject).call(thisObject, value, key); - } - return transform(value, key).toString(); - }); // String -}; - -string.trim = String.prototype.trim ? - lang.trim : // aliasing to the native function - function(str){ - str = str.replace(/^\s+/, ''); - for(var i = str.length - 1; i >= 0; i--){ - if(/\S/.test(str.charAt(i))){ - str = str.substring(0, i + 1); - break; - } - } - return str; - }; - -/*===== - string.trim = function(str){ - // summary: - // Trims whitespace from both sides of the string - // str: String - // String to be trimmed - // returns: String - // Returns the trimmed string - // description: - // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript). - // The short yet performant version of this function is dojo.trim(), - // which is part of Dojo base. Uses String.prototype.trim instead, if available. - return ""; // String - }; - =====*/ - - return string; -}); - -}, -'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>", -'dijit/layout/AccordionPane':function(){ -define("dijit/layout/AccordionPane", [ - "dojo/_base/declare", // declare - "dojo/_base/kernel", // kernel.deprecated - "./ContentPane" -], function(declare, kernel, ContentPane){ - - // module: - // dijit/layout/AccordionPane - - return declare("dijit.layout.AccordionPane", ContentPane, { - // summary: - // Deprecated widget. Use `dijit/layout/ContentPane` instead. - // tags: - // deprecated - - constructor: function(){ - kernel.deprecated("dijit.layout.AccordionPane deprecated, use ContentPane instead", "", "2.0"); - }, - - onSelected: function(){ - // summary: - // called when this pane is selected - } - }); -}); - -}, -'dijit/dijit':function(){ -define("dijit/dijit", [ - "./main", - "./_base", - "dojo/parser", - "./_Widget", - "./_TemplatedMixin", - "./_Container", - "./layout/_LayoutWidget", - "./form/_FormWidget", - "./form/_FormValueWidget" -], function(dijit){ - - // module: - // dijit/dijit - - /*===== - return { - // summary: - // A roll-up for common dijit methods - // All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require) - // And some other stuff that we tend to pull in all the time anyway - }; - =====*/ - - return dijit; -}); - -}, -'dijit/form/DropDownButton':function(){ -require({cache:{ -'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">▼</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\" role=\"presentation\"\n/></span>\n"}}); -define("dijit/form/DropDownButton", [ - "dojo/_base/declare", // declare - "dojo/_base/lang", // hitch - "dojo/query", // query - "../registry", // registry.byNode - "../popup", // dijit.popup2.hide - "./Button", - "../_Container", - "../_HasDropDown", - "dojo/text!./templates/DropDownButton.html" -], function(declare, lang, query, registry, popup, Button, _Container, _HasDropDown, template){ - -// module: -// dijit/form/DropDownButton - - -return declare("dijit.form.DropDownButton", [Button, _Container, _HasDropDown], { - // summary: - // A button with a drop down - // - // example: - // | <button data-dojo-type="dijit/form/DropDownButton"> - // | Hello world - // | <div data-dojo-type="dijit/Menu">...</div> - // | </button> - // - // example: - // | var button1 = new DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) }); - // | win.body().appendChild(button1); - // - - baseClass : "dijitDropDownButton", - - templateString: template, - - _fillContent: function(){ - // Overrides Button._fillContent(). - // - // My inner HTML contains both the button contents and a drop down widget, like - // <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton> - // The first node is assumed to be the button content. The widget is the popup. - - if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef - //FIXME: figure out how to filter out the widget and use all remaining nodes as button - // content, not just nodes[0] - var nodes = query("*", this.srcNodeRef); - this.inherited(arguments, [nodes[0]]); - - // save pointer to srcNode so we can grab the drop down widget after it's instantiated - this.dropDownContainer = this.srcNodeRef; - } - }, - - startup: function(){ - if(this._started){ return; } - - // the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM, - // make it invisible, and store a reference to pass to the popup code. - if(!this.dropDown && this.dropDownContainer){ - var dropDownNode = query("[widgetId]", this.dropDownContainer)[0]; - this.dropDown = registry.byNode(dropDownNode); - delete this.dropDownContainer; - } - if(this.dropDown){ - popup.hide(this.dropDown); - } - - this.inherited(arguments); - }, - - isLoaded: function(){ - // Returns whether or not we are loaded - if our dropdown has an href, - // then we want to check that. - var dropDown = this.dropDown; - return (!!dropDown && (!dropDown.href || dropDown.isLoaded)); - }, - - loadDropDown: function(/*Function*/ callback){ - // Default implementation assumes that drop down already exists, - // but hasn't loaded it's data (ex: ContentPane w/href). - // App must override if the drop down is lazy-created. - var dropDown = this.dropDown; - var handler = dropDown.on("load", lang.hitch(this, function(){ - handler.remove(); - callback(); - })); - dropDown.refresh(); // tell it to load - }, - - isFocusable: function(){ - // Overridden so that focus is handled by the _HasDropDown mixin, not by - // the _FormWidget mixin. - return this.inherited(arguments) && !this._mouseDown; - } -}); - -}); - -}, -'dijit/form/_FormValueMixin':function(){ -define("dijit/form/_FormValueMixin", [ - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/keys", // keys.ESCAPE - "dojo/sniff", // has("ie"), has("quirks") - "./_FormWidgetMixin" -], function(declare, domAttr, keys, has, _FormWidgetMixin){ - - // module: - // dijit/form/_FormValueMixin - - return declare("dijit.form._FormValueMixin", _FormWidgetMixin, { - // summary: - // Mixin for widgets corresponding to native HTML elements such as `<input>` or `<select>` - // that have user changeable values. - // description: - // Each _FormValueMixin represents a single input value, and has a (possibly hidden) `<input>` element, - // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?) - // works as expected. - - // readOnly: Boolean - // Should this widget respond to user input? - // In markup, this is specified as "readOnly". - // Similar to disabled except readOnly form values are submitted. - readOnly: false, - - _setReadOnlyAttr: function(/*Boolean*/ value){ - domAttr.set(this.focusNode, 'readOnly', value); - this._set("readOnly", value); - }, - - postCreate: function(){ - this.inherited(arguments); - - if(has("ie")){ // IE won't stop the event with keypress - this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown); - } - // Update our reset value if it hasn't yet been set (because this.set() - // is only called when there *is* a value) - if(this._resetValue === undefined){ - this._lastValueReported = this._resetValue = this.value; - } - }, - - _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ - // summary: - // Hook so set('value', value) works. - // description: - // Sets the value of the widget. - // If the value has changed, then fire onChange event, unless priorityChange - // is specified as null (or false?) - this._handleOnChange(newValue, priorityChange); - }, - - _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ - // summary: - // Called when the value of the widget has changed. Saves the new value in this.value, - // and calls onChange() if appropriate. See _FormWidget._handleOnChange() for details. - this._set("value", newValue); - this.inherited(arguments); - }, - - undo: function(){ - // summary: - // Restore the value to the last value passed to onChange - this._setValueAttr(this._lastValueReported, false); - }, - - reset: function(){ - // summary: - // Reset the widget's value to what it was at initialization time - this._hasBeenBlurred = false; - this._setValueAttr(this._resetValue, true); - }, - - _onKeyDown: function(e){ - if(e.keyCode == keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){ - if(has("ie") < 9 || (has("ie") && has("quirks"))){ - e.preventDefault(); // default behavior needs to be stopped here since keypress is too late - var node = e.srcElement, - te = node.ownerDocument.createEventObject(); - te.keyCode = keys.ESCAPE; - te.shiftKey = e.shiftKey; - node.fireEvent('onkeypress', te); - } - } - } - }); -}); - -}, -'dijit/form/_FormWidgetMixin':function(){ -define("dijit/form/_FormWidgetMixin", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/dom-style", // domStyle.get - "dojo/_base/lang", // lang.hitch lang.isArray - "dojo/mouse", // mouse.isLeft - "dojo/sniff", // has("webkit") - "dojo/window", // winUtils.scrollIntoView - "../a11y" // a11y.hasDefaultTabStop -], function(array, declare, domAttr, domStyle, lang, mouse, has, winUtils, a11y){ - -// module: -// dijit/form/_FormWidgetMixin - -return declare("dijit.form._FormWidgetMixin", null, { - // summary: - // Mixin for widgets corresponding to native HTML elements such as `<checkbox>` or `<button>`, - // which can be children of a `<form>` node or a `dijit/form/Form` widget. - // - // description: - // Represents a single HTML element. - // All these widgets should have these attributes just like native HTML input elements. - // You can set them during widget construction or afterwards, via `dijit/_WidgetBase.set()`. - // - // They also share some common methods. - - // name: [const] String - // Name used when submitting form; same as "name" attribute or plain HTML elements - name: "", - - // alt: String - // Corresponds to the native HTML `<input>` element's attribute. - alt: "", - - // value: String - // Corresponds to the native HTML `<input>` element's attribute. - value: "", - - // type: [const] String - // Corresponds to the native HTML `<input>` element's attribute. - type: "text", - - // type: String - // Apply aria-label in markup to the widget's focusNode - "aria-label": "focusNode", - - // tabIndex: String - // Order fields are traversed when user hits the tab key - tabIndex: "0", - _setTabIndexAttr: "focusNode", // force copy even when tabIndex default value, needed since Button is <span> - - // disabled: Boolean - // Should this widget respond to user input? - // In markup, this is specified as "disabled='disabled'", or just "disabled". - disabled: false, - - // intermediateChanges: Boolean - // Fires onChange for each value change or only on demand - intermediateChanges: false, - - // scrollOnFocus: Boolean - // On focus, should this widget scroll into view? - scrollOnFocus: true, - - // Override _WidgetBase mapping id to this.domNode, needs to be on focusNode so <label> etc. - // works with screen reader - _setIdAttr: "focusNode", - - _setDisabledAttr: function(/*Boolean*/ value){ - this._set("disabled", value); - domAttr.set(this.focusNode, 'disabled', value); - if(this.valueNode){ - domAttr.set(this.valueNode, 'disabled', value); - } - this.focusNode.setAttribute("aria-disabled", value ? "true" : "false"); - - if(value){ - // reset these, because after the domNode is disabled, we can no longer receive - // mouse related events, see #4200 - this._set("hovering", false); - this._set("active", false); - - // clear tab stop(s) on this widget's focusable node(s) (ComboBox has two focusable nodes) - var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex : - ("_setTabIndexAttr" in this) ? this._setTabIndexAttr : "focusNode"; - array.forEach(lang.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){ - var node = this[attachPointName]; - // complex code because tabIndex=-1 on a <div> doesn't work on FF - if(has("webkit") || a11y.hasDefaultTabStop(node)){ // see #11064 about webkit bug - node.setAttribute('tabIndex', "-1"); - }else{ - node.removeAttribute('tabIndex'); - } - }, this); - }else{ - if(this.tabIndex != ""){ - this.set('tabIndex', this.tabIndex); - } - } - }, - - _onFocus: function(/*String*/ by){ - // If user clicks on the widget, even if the mouse is released outside of it, - // this widget's focusNode should get focus (to mimic native browser hehavior). - // Browsers often need help to make sure the focus via mouse actually gets to the focusNode. - if(by == "mouse" && this.isFocusable()){ - // IE exhibits strange scrolling behavior when refocusing a node so only do it when !focused. - var focusConnector = this.connect(this.focusNode, "onfocus", function(){ - this.disconnect(mouseUpConnector); - this.disconnect(focusConnector); - }); - // Set a global event to handle mouseup, so it fires properly - // even if the cursor leaves this.domNode before the mouse up event. - var mouseUpConnector = this.connect(this.ownerDocumentBody, "onmouseup", function(){ - this.disconnect(mouseUpConnector); - this.disconnect(focusConnector); - // if here, then the mousedown did not focus the focusNode as the default action - if(this.focused){ - this.focus(); - } - }); - } - if(this.scrollOnFocus){ - this.defer(function(){ winUtils.scrollIntoView(this.domNode); }); // without defer, the input caret position can change on mouse click - } - this.inherited(arguments); - }, - - isFocusable: function(){ - // summary: - // Tells if this widget is focusable or not. Used internally by dijit. - // tags: - // protected - return !this.disabled && this.focusNode && (domStyle.get(this.domNode, "display") != "none"); - }, - - focus: function(){ - // summary: - // Put focus on this widget - if(!this.disabled && this.focusNode.focus){ - try{ this.focusNode.focus(); }catch(e){}/*squelch errors from hidden nodes*/ - } - }, - - compare: function(/*anything*/ val1, /*anything*/ val2){ - // summary: - // Compare 2 values (as returned by get('value') for this widget). - // tags: - // protected - if(typeof val1 == "number" && typeof val2 == "number"){ - return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2; - }else if(val1 > val2){ - return 1; - }else if(val1 < val2){ - return -1; - }else{ - return 0; - } - }, - - onChange: function(/*===== newValue =====*/){ - // summary: - // Callback when this widget's value is changed. - // tags: - // callback - }, - - // _onChangeActive: [private] Boolean - // Indicates that changes to the value should call onChange() callback. - // This is false during widget initialization, to avoid calling onChange() - // when the initial value is set. - _onChangeActive: false, - - _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ - // summary: - // Called when the value of the widget is set. Calls onChange() if appropriate - // newValue: - // the new value - // priorityChange: - // For a slider, for example, dragging the slider is priorityChange==false, - // but on mouse up, it's priorityChange==true. If intermediateChanges==false, - // onChange is only called form priorityChange=true events. - // tags: - // private - if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){ - // this block executes not for a change, but during initialization, - // and is used to store away the original value (or for ToggleButton, the original checked state) - this._resetValue = this._lastValueReported = newValue; - } - this._pendingOnChange = this._pendingOnChange - || (typeof newValue != typeof this._lastValueReported) - || (this.compare(newValue, this._lastValueReported) != 0); - if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){ - this._lastValueReported = newValue; - this._pendingOnChange = false; - if(this._onChangeActive){ - if(this._onChangeHandle){ - this._onChangeHandle.remove(); - } - // defer allows hidden value processing to run and - // also the onChange handler can safely adjust focus, etc - this._onChangeHandle = this.defer( - function(){ - this._onChangeHandle = null; - this.onChange(newValue); - }); // try to collapse multiple onChange's fired faster than can be processed - } - } - }, - - create: function(){ - // Overrides _Widget.create() - this.inherited(arguments); - this._onChangeActive = true; - }, - - destroy: function(){ - if(this._onChangeHandle){ // destroy called before last onChange has fired - this._onChangeHandle.remove(); - this.onChange(this._lastValueReported); - } - this.inherited(arguments); - } -}); - -}); - -}, -'dijit/a11yclick':function(){ -define("dijit/a11yclick", [ - "dojo/on", - "dojo/_base/array", // array.forEach - "dojo/keys", // keys.ENTER keys.SPACE - "dojo/_base/declare", // declare - "dojo/has", // has("dom-addeventlistener") - "dojo/_base/unload", // unload.addOnWindowUnload - "dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent -], function(on, array, keys, declare, has, unload, win){ - - // module: - // dijit/a11yclick - - // Keep track of where the last keydown event was, to help avoid generating - // spurious ondijitclick events when: - // 1. focus is on a <button> or <a> - // 2. user presses then releases the ENTER key - // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler - // 4. onkeyup event fires, causing the ondijitclick handler to fire - var lastKeyDownNode = null; - if(has("dom-addeventlistener")){ - win.doc.addEventListener('keydown', function(evt){ - lastKeyDownNode = evt.target; - }, true); - }else{ - // Fallback path for IE6-8 - (function(){ - var keydownCallback = function(evt){ - lastKeyDownNode = evt.srcElement; - }; - win.doc.attachEvent('onkeydown', keydownCallback); - unload.addOnWindowUnload(function(){ - win.doc.detachEvent('onkeydown', keydownCallback); - }); - })(); - } - - function clickKey(/*Event*/ e){ - return (e.keyCode === keys.ENTER || e.keyCode === keys.SPACE) && - !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey; - } - - return function(node, listener){ - // summary: - // Custom a11yclick (a.k.a. ondijitclick) event - // which triggers on a mouse click, touch, or space/enter keyup. - - if(/input|button/i.test(node.nodeName)){ - // pass through, the browser already generates click event on SPACE/ENTER key - return on(node, "click", listener); - }else{ - // Don't fire the click event unless both the keydown and keyup occur on this node. - // Avoids problems where focus shifted to this node or away from the node on keydown, - // either causing this node to process a stray keyup event, or causing another node - // to get a stray keyup event. - - var handles = [ - on(node, "keydown", function(e){ - //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode)); - if(clickKey(e)){ - // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work - lastKeyDownNode = e.target; - - // Prevent viewport scrolling on space key in IE<9. - // (Reproducible on test_Button.html on any of the first dijit/form/Button examples) - e.preventDefault(); - } - }), - - on(node, "keyup", function(e){ - //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode)); - if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey - //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert - lastKeyDownNode = null; - on.emit(e.target, "click", { - cancelable: true, - bubbles: true - }); - } - }), - - on(node, "click", function(e){ - // catch mouse clicks, plus the on.emit() calls from above and below - listener.call(this, e); - }) - ]; - - if(has("touch")){ - // touchstart-->touchend will automatically generate a click event, but there are problems - // on iOS after focus has been programatically shifted (#14604, #14918), so setup a failsafe - // if click doesn't fire naturally. - - var clickTimer; - handles.push( - on(node, "touchend", function(e){ - var target = e.target; - clickTimer = setTimeout(function(){ - clickTimer = null; - on.emit(target, "click", { - cancelable: true, - bubbles: true - }); - }, 600); - }), - on(node, "click", function(e){ - // If browser generates a click naturally, clear the timer to fire a synthetic click event - if(clickTimer){ - clearTimeout(clickTimer); - } - }) - // TODO: if the touchstart and touchend were <100ms apart, and then there's another touchstart - // event <300ms after the touchend event, then clear the synthetic click timer, because user - // is doing a zoom. Alternately monitor screen.deviceXDPI (or something similar) to see if - // zoom level has changed. - ); - } - - return { - remove: function(){ - array.forEach(handles, function(h){ h.remove(); }); - if(clickTimer){ - clearTimeout(clickTimer); - clickTimer = null; - } - } - }; - } - }; - - return ret; -}); - -}, -'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\n\t><div data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\n/></div>\n", -'dijit/Destroyable':function(){ -define("dijit/Destroyable", [ - "dojo/_base/array", // array.forEach array.map - "dojo/aspect", - "dojo/_base/declare" -], function(array, aspect, declare){ - -// module: -// dijit/Destroyable - -return declare("dijit.Destroyable", null, { - // summary: - // Mixin to track handles and release them when instance is destroyed. - // description: - // Call this.own(...) on list of handles (returned from dojo/aspect, dojo/on, - // dojo/Stateful::watch, or any class (including widgets) with a destroyRecursive() or destroy() method. - // Then call destroy() later to destroy this instance and release the resources. - - destroy: function(/*Boolean*/ preserveDom){ - // summary: - // Destroy this class, releasing any resources registered via own(). - this._destroyed = true; - }, - - own: function(){ - // summary: - // Track specified handles and remove/destroy them when this instance is destroyed, unless they were - // already removed/destroyed manually. - // tags: - // protected - // returns: - // The array of specified handles, so you can do for example: - // | var handle = this.own(on(...))[0]; - - array.forEach(arguments, function(handle){ - var destroyMethodName = - "destroyRecursive" in handle ? "destroyRecursive" : // remove "destroyRecursive" for 2.0 - "destroy" in handle ? "destroy" : - "remove"; - - // When this.destroy() is called, destroy handle. Since I'm using aspect.before(), - // the handle will be destroyed before a subclass's destroy() method starts running, before it calls - // this.inherited() or even if it doesn't call this.inherited() at all. If that's an issue, make an - // onDestroy() method and connect to that instead. - var odh = aspect.before(this, "destroy", function(preserveDom){ - handle[destroyMethodName](preserveDom); - }); - - // If handle is destroyed manually before this.destroy() is called, remove the listener set directly above. - var hdh = aspect.after(handle, destroyMethodName, function(){ - odh.remove(); - hdh.remove(); - }, true); - }, this); - - return arguments; // handle - } -}); - -}); - -}, -'dijit/layout/_ContentPaneResizeMixin':function(){ -define("dijit/layout/_ContentPaneResizeMixin", [ - "dojo/_base/array", // array.filter array.forEach - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.contains domClass.toggle - "dojo/dom-geometry",// domGeometry.contentBox domGeometry.marginBox - "dojo/dom-style", - "dojo/_base/lang", // lang.mixin - "dojo/query", // query - "dojo/sniff", // has("ie") - "../registry", // registry.byId - "../Viewport", - "./utils" // marginBox2contextBox -], function(array, declare, domClass, domGeometry, domStyle, lang, query, has, - registry, Viewport, layoutUtils){ - -// module: -// dijit/layout/_ContentPaneResizeMixin - - -return declare("dijit.layout._ContentPaneResizeMixin", null, { - // summary: - // Resize() functionality of ContentPane. If there's a single layout widget - // child then it will call resize() with the same dimensions as the ContentPane. - // Otherwise just calls resize on each child. - // - // Also implements basic startup() functionality, where starting the parent - // will start the children - - // doLayout: Boolean - // - false - don't adjust size of children - // - true - if there is a single visible child widget, set it's size to however big the ContentPane is - doLayout: true, - - // isLayoutContainer: [protected] Boolean - // Indicates that this widget will call resize() on it's child widgets - // when they become visible. - isLayoutContainer: true, - - startup: function(){ - // summary: - // See `dijit/layout/_LayoutWidget.startup()` for description. - // Although ContentPane doesn't extend _LayoutWidget, it does implement - // the same API. - - if(this._started){ return; } - - var parent = this.getParent(); - this._childOfLayoutWidget = parent && parent.isLayoutContainer; - - // I need to call resize() on my child/children (when I become visible), unless - // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then. - this._needLayout = !this._childOfLayoutWidget; - - this.inherited(arguments); - - if(this._isShown()){ - this._onShow(); - } - - if(!this._childOfLayoutWidget){ - // Since my parent isn't a layout container, and my style *may be* width=height=100% - // or something similar (either set directly or via a CSS class), - // monitor when viewport size changes so that I can re-layout. - // This is more for subclasses of ContentPane than ContentPane itself, although it - // could be useful for a ContentPane if it has a single child widget inheriting ContentPane's size. - this.own(Viewport.on("resize", lang.hitch(this, "resize"))); - } - }, - - _checkIfSingleChild: function(){ - // summary: - // Test if we have exactly one visible widget as a child, - // and if so assume that we are a container for that widget, - // and should propagate startup() and resize() calls to it. - // Skips over things like data stores since they aren't visible. - - var candidateWidgets = [], - otherVisibleNodes = false; - - query("> *", this.containerNode).some(function(node){ - var widget = registry.byNode(node); - if(widget && widget.resize){ - candidateWidgets.push(widget); - }else if(node.offsetHeight){ - otherVisibleNodes = true; - } - }); - - this._singleChild = candidateWidgets.length == 1 && !otherVisibleNodes ? - candidateWidgets[0] : null; - - // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449) - domClass.toggle(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild); - }, - - resize: function(changeSize, resultSize){ - // summary: - // See `dijit/layout/_LayoutWidget.resize()` for description. - // Although ContentPane doesn't extend _LayoutWidget, it does implement - // the same API. - - this._resizeCalled = true; - - this._scheduleLayout(changeSize, resultSize); - }, - - _scheduleLayout: function(changeSize, resultSize){ - // summary: - // Resize myself, and call resize() on each of my child layout widgets, either now - // (if I'm currently visible) or when I become visible - if(this._isShown()){ - this._layout(changeSize, resultSize); - }else{ - this._needLayout = true; - this._changeSize = changeSize; - this._resultSize = resultSize; - } - }, - - _layout: function(changeSize, resultSize){ - // summary: - // Resize myself according to optional changeSize/resultSize parameters, like a layout widget. - // Also, since I am an isLayoutContainer widget, each of my children expects me to - // call resize() or layout() on it. - // - // Should be called on initialization and also whenever we get new content - // (from an href, or from set('content', ...))... but deferred until - // the ContentPane is visible - - delete this._needLayout; - - // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is - // never called directly, so resize() is our trigger to do the initial href download (see [20099]). - // However, don't load href for closed TitlePanes. - if(!this._wasShown && this.open !== false){ - this._onShow(); - } - - // Set margin box size, unless it wasn't specified, in which case use current size. - if(changeSize){ - domGeometry.setMarginBox(this.domNode, changeSize); - } - - // Compute content box size of containerNode in case we [later] need to size our single child. - var cn = this.containerNode; - if(cn === this.domNode){ - // If changeSize or resultSize was passed to this method and this.containerNode == - // this.domNode then we can compute the content-box size without querying the node, - // which is more reliable (similar to LayoutWidget.resize) (see for example #9449). - var mb = resultSize || {}; - lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize - if(!("h" in mb) || !("w" in mb)){ - mb = lang.mixin(domGeometry.getMarginBox(cn), mb); // just use domGeometry.setMarginBox() to fill in missing values - } - this._contentBox = layoutUtils.marginBox2contentBox(cn, mb); - }else{ - this._contentBox = domGeometry.getContentBox(cn); - } - - this._layoutChildren(); - }, - - _layoutChildren: function(){ - // Call _checkIfSingleChild() again in case app has manually mucked w/the content - // of the ContentPane (rather than changing it through the set("content", ...) API. - if(this.doLayout){ - this._checkIfSingleChild(); - } - - if(this._singleChild && this._singleChild.resize){ - var cb = this._contentBox || domGeometry.getContentBox(this.containerNode); - - // note: if widget has padding this._contentBox will have l and t set, - // but don't pass them to resize() or it will doubly-offset the child - this._singleChild.resize({w: cb.w, h: cb.h}); - }else{ - // All my child widgets are independently sized (rather than matching my size), - // but I still need to call resize() on each child to make it layout. - array.forEach(this.getChildren(), function(widget){ - if(widget.resize){ - widget.resize(); - } - }); - } - }, - - _isShown: function(){ - // summary: - // Returns true if the content is currently shown. - // description: - // If I am a child of a layout widget then it actually returns true if I've ever been visible, - // not whether I'm currently visible, since that's much faster than tracing up the DOM/widget - // tree every call, and at least solves the performance problem on page load by deferring loading - // hidden ContentPanes until they are first shown - - if(this._childOfLayoutWidget){ - // If we are TitlePane, etc - we return that only *IF* we've been resized - if(this._resizeCalled && "open" in this){ - return this.open; - } - return this._resizeCalled; - }else if("open" in this){ - return this.open; // for TitlePane, etc. - }else{ - var node = this.domNode, parent = this.domNode.parentNode; - return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !domClass.contains(node, "dijitHidden") && - parent && parent.style && (parent.style.display != 'none'); - } - }, - - _onShow: function(){ - // summary: - // Called when the ContentPane is made visible - // description: - // For a plain ContentPane, this is called on initialization, from startup(). - // If the ContentPane is a hidden pane of a TabContainer etc., then it's - // called whenever the pane is made visible. - // - // Does layout/resize of child widget(s) - - // Need to keep track of whether ContentPane has been shown (which is different than - // whether or not it's currently visible). - this._wasShown = true; - - if(this._needLayout){ - // If a layout has been scheduled for when we become visible, do it now - this._layout(this._changeSize, this._resultSize); - } - - this.inherited(arguments); - } -}); - -}); - -}, -'dijit/WidgetSet':function(){ -define("dijit/WidgetSet", [ - "dojo/_base/array", // array.forEach array.map - "dojo/_base/declare", // declare - "dojo/_base/kernel", // kernel.global - "./registry" // to add functions to dijit.registry -], function(array, declare, kernel, registry){ - - // module: - // dijit/WidgetSet - - var WidgetSet = declare("dijit.WidgetSet", null, { - // summary: - // A set of widgets indexed by id. - // Deprecated, will be removed in 2.0. - // - // example: - // Create a small list of widgets: - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | var ws = new WidgetSet(); - // | ws.add(registry.byId("one")); - // | ws.add(registry.byId("two")); - // | // destroy both: - // | ws.forEach(function(w){ w.destroy(); }); - // | }); - - constructor: function(){ - this._hash = {}; - this.length = 0; - }, - - add: function(/*dijit/_WidgetBase*/ widget){ - // summary: - // Add a widget to this list. If a duplicate ID is detected, a error is thrown. - // - // widget: dijit/_WidgetBase - // Any dijit/_WidgetBase subclass. - if(this._hash[widget.id]){ - throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); - } - this._hash[widget.id] = widget; - this.length++; - }, - - remove: function(/*String*/ id){ - // summary: - // Remove a widget from this WidgetSet. Does not destroy the widget; simply - // removes the reference. - if(this._hash[id]){ - delete this._hash[id]; - this.length--; - } - }, - - forEach: function(/*Function*/ func, /* Object? */thisObj){ - // summary: - // Call specified function for each widget in this set. - // - // func: - // A callback function to run for each item. Is passed the widget, the index - // in the iteration, and the full hash, similar to `array.forEach`. - // - // thisObj: - // An optional scope parameter - // - // example: - // Using the default `dijit.registry` instance: - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | registry.forEach(function(widget){ - // | console.log(widget.declaredClass); - // | }); - // | }); - // - // returns: - // Returns self, in order to allow for further chaining. - - thisObj = thisObj || kernel.global; - var i = 0, id; - for(id in this._hash){ - func.call(thisObj, this._hash[id], i++, this._hash); - } - return this; // dijit/WidgetSet - }, - - filter: function(/*Function*/ filter, /* Object? */thisObj){ - // summary: - // Filter down this WidgetSet to a smaller new WidgetSet - // Works the same as `array.filter` and `NodeList.filter` - // - // filter: - // Callback function to test truthiness. Is passed the widget - // reference and the pseudo-index in the object. - // - // thisObj: Object? - // Option scope to use for the filter function. - // - // example: - // Arbitrary: select the odd widgets in this list - // | - // | - // | - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | registry.filter(function(w, i){ - // | return i % 2 == 0; - // | }).forEach(function(w){ /* odd ones */ }); - // | }); - - thisObj = thisObj || kernel.global; - var res = new WidgetSet(), i = 0, id; - for(id in this._hash){ - var w = this._hash[id]; - if(filter.call(thisObj, w, i++, this._hash)){ - res.add(w); - } - } - return res; // dijit/WidgetSet - }, - - byId: function(/*String*/ id){ - // summary: - // Find a widget in this list by it's id. - // example: - // Test if an id is in a particular WidgetSet - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | var ws = new WidgetSet(); - // | ws.add(registry.byId("bar")); - // | var t = ws.byId("bar") // returns a widget - // | var x = ws.byId("foo"); // returns undefined - // | }); - - return this._hash[id]; // dijit/_WidgetBase - }, - - byClass: function(/*String*/ cls){ - // summary: - // Reduce this widgetset to a new WidgetSet of a particular `declaredClass` - // - // cls: String - // The Class to scan for. Full dot-notated string. - // - // example: - // Find all `dijit.TitlePane`s in a page: - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); }); - // | }); - - var res = new WidgetSet(), id, widget; - for(id in this._hash){ - widget = this._hash[id]; - if(widget.declaredClass == cls){ - res.add(widget); - } - } - return res; // dijit/WidgetSet - }, - - toArray: function(){ - // summary: - // Convert this WidgetSet into a true Array - // - // example: - // Work with the widget .domNodes in a real Array - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | array.map(registry.toArray(), function(w){ return w.domNode; }); - // | }); - - - var ar = []; - for(var id in this._hash){ - ar.push(this._hash[id]); - } - return ar; // dijit/_WidgetBase[] - }, - - map: function(/* Function */func, /* Object? */thisObj){ - // summary: - // Create a new Array from this WidgetSet, following the same rules as `array.map` - // example: - // | require(["dijit/WidgetSet", "dijit/registry"], - // | function(WidgetSet, registry){ - // | var nodes = registry.map(function(w){ return w.domNode; }); - // | }); - // - // returns: - // A new array of the returned values. - return array.map(this.toArray(), func, thisObj); // Array - }, - - every: function(func, thisObj){ - // summary: - // A synthetic clone of `array.every` acting explicitly on this WidgetSet - // - // func: Function - // A callback function run for every widget in this list. Exits loop - // when the first false return is encountered. - // - // thisObj: Object? - // Optional scope parameter to use for the callback - - thisObj = thisObj || kernel.global; - var x = 0, i; - for(i in this._hash){ - if(!func.call(thisObj, this._hash[i], x++, this._hash)){ - return false; // Boolean - } - } - return true; // Boolean - }, - - some: function(func, thisObj){ - // summary: - // A synthetic clone of `array.some` acting explicitly on this WidgetSet - // - // func: Function - // A callback function run for every widget in this list. Exits loop - // when the first true return is encountered. - // - // thisObj: Object? - // Optional scope parameter to use for the callback - - thisObj = thisObj || kernel.global; - var x = 0, i; - for(i in this._hash){ - if(func.call(thisObj, this._hash[i], x++, this._hash)){ - return true; // Boolean - } - } - return false; // Boolean - } - - }); - - // Add in 1.x compatibility methods to dijit/registry. - // These functions won't show up in the API doc but since they are deprecated anyway, - // that's probably for the best. - array.forEach(["forEach", "filter", "byClass", "map", "every", "some"], function(func){ - registry[func] = WidgetSet.prototype[func]; - }); - - - return WidgetSet; -}); - -}, -'dojo/dnd/Moveable':function(){ -define("dojo/dnd/Moveable", [ - "../_base/array", "../_base/declare", "../_base/event", "../_base/lang", - "../dom", "../dom-class", "../Evented", "../on", "../topic", "../touch", "./common", "./Mover", "../_base/window" -], function(array, declare, event, lang, dom, domClass, Evented, on, topic, touch, dnd, Mover, win){ - -// module: -// dojo/dnd/Moveable - - -var Moveable = declare("dojo.dnd.Moveable", [Evented], { - // summary: - // an object, which makes a node movable - - // object attributes (for markup) - handle: "", - delay: 0, - skip: false, - - constructor: function(node, params){ - // node: Node - // a node (or node's id) to be moved - // params: Moveable.__MoveableArgs? - // optional parameters - this.node = dom.byId(node); - if(!params){ params = {}; } - this.handle = params.handle ? dom.byId(params.handle) : null; - if(!this.handle){ this.handle = this.node; } - this.delay = params.delay > 0 ? params.delay : 0; - this.skip = params.skip; - this.mover = params.mover ? params.mover : Mover; - this.events = [ - on(this.handle, touch.press, lang.hitch(this, "onMouseDown")), - // cancel text selection and text dragging - on(this.handle, "dragstart", lang.hitch(this, "onSelectStart")), - on(this.handle, "selectstart", lang.hitch(this, "onSelectStart")) - ]; - }, - - // markup methods - markupFactory: function(params, node, Ctor){ - return new Ctor(node, params); - }, - - // methods - destroy: function(){ - // summary: - // stops watching for possible move, deletes all references, so the object can be garbage-collected - array.forEach(this.events, function(handle){ handle.remove(); }); - this.events = this.node = this.handle = null; - }, - - // mouse event processors - onMouseDown: function(e){ - // summary: - // event processor for onmousedown/ontouchstart, creates a Mover for the node - // e: Event - // mouse/touch event - if(this.skip && dnd.isFormElement(e)){ return; } - if(this.delay){ - this.events.push( - on(this.handle, touch.move, lang.hitch(this, "onMouseMove")), - on(this.handle, touch.release, lang.hitch(this, "onMouseUp")) - ); - this._lastX = e.pageX; - this._lastY = e.pageY; - }else{ - this.onDragDetected(e); - } - event.stop(e); - }, - onMouseMove: function(e){ - // summary: - // event processor for onmousemove/ontouchmove, used only for delayed drags - // e: Event - // mouse/touch event - if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){ - this.onMouseUp(e); - this.onDragDetected(e); - } - event.stop(e); - }, - onMouseUp: function(e){ - // summary: - // event processor for onmouseup, used only for delayed drags - // e: Event - // mouse event - for(var i = 0; i < 2; ++i){ - this.events.pop().remove(); - } - event.stop(e); - }, - onSelectStart: function(e){ - // summary: - // event processor for onselectevent and ondragevent - // e: Event - // mouse event - if(!this.skip || !dnd.isFormElement(e)){ - event.stop(e); - } - }, - - // local events - onDragDetected: function(/*Event*/ e){ - // summary: - // called when the drag is detected; - // responsible for creation of the mover - new this.mover(this.node, e, this); - }, - onMoveStart: function(/*Mover*/ mover){ - // summary: - // called before every move operation - topic.publish("/dnd/move/start", mover); - domClass.add(win.body(), "dojoMove"); - domClass.add(this.node, "dojoMoveItem"); - }, - onMoveStop: function(/*Mover*/ mover){ - // summary: - // called after every move operation - topic.publish("/dnd/move/stop", mover); - domClass.remove(win.body(), "dojoMove"); - domClass.remove(this.node, "dojoMoveItem"); - }, - onFirstMove: function(/*===== mover, e =====*/){ - // summary: - // called during the very first move notification; - // can be used to initialize coordinates, can be overwritten. - // mover: Mover - // e: Event - - // default implementation does nothing - }, - onMove: function(mover, leftTop /*=====, e =====*/){ - // summary: - // called during every move notification; - // should actually move the node; can be overwritten. - // mover: Mover - // leftTop: Object - // e: Event - this.onMoving(mover, leftTop); - var s = mover.node.style; - s.left = leftTop.l + "px"; - s.top = leftTop.t + "px"; - this.onMoved(mover, leftTop); - }, - onMoving: function(/*===== mover, leftTop =====*/){ - // summary: - // called before every incremental move; can be overwritten. - // mover: Mover - // leftTop: Object - - // default implementation does nothing - }, - onMoved: function(/*===== mover, leftTop =====*/){ - // summary: - // called after every incremental move; can be overwritten. - // mover: Mover - // leftTop: Object - - // default implementation does nothing - } -}); - -/*===== -Moveable.__MoveableArgs = declare([], { - // handle: Node||String - // A node (or node's id), which is used as a mouse handle. - // If omitted, the node itself is used as a handle. - handle: null, - - // delay: Number - // delay move by this number of pixels - delay: 0, - - // skip: Boolean - // skip move of form elements - skip: false, - - // mover: Object - // a constructor of custom Mover - mover: dnd.Mover -}); -=====*/ - -return Moveable; -}); - -}, -'dijit/TooltipDialog':function(){ -require({cache:{ -'url:dijit/templates/TooltipDialog.html':"<div role=\"presentation\" tabIndex=\"-1\">\n\t<div class=\"dijitTooltipContainer\" role=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" data-dojo-attach-point=\"containerNode\" role=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" role=\"presentation\" data-dojo-attach-point=\"connectorNode\"></div>\n</div>\n"}}); -define("dijit/TooltipDialog", [ - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.replace - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "dojo/_base/lang", // lang.hitch - "./focus", - "./layout/ContentPane", - "./_DialogMixin", - "./form/_FormMixin", - "./_TemplatedMixin", - "dojo/text!./templates/TooltipDialog.html", - "./main" // exports methods to dijit global -], function(declare, domClass, event, keys, lang, - focus, ContentPane, _DialogMixin, _FormMixin, _TemplatedMixin, template, dijit){ - - // module: - // dijit/TooltipDialog - - - return declare("dijit.TooltipDialog", - [ContentPane, _TemplatedMixin, _FormMixin, _DialogMixin], { - // summary: - // Pops up a dialog that appears like a Tooltip - - // title: String - // Description of tooltip dialog (required for a11y) - title: "", - - // doLayout: [protected] Boolean - // Don't change this parameter from the default value. - // This ContentPane parameter doesn't make sense for TooltipDialog, since TooltipDialog - // is never a child of a layout container, nor can you specify the size of - // TooltipDialog in order to control the size of an inner widget. - doLayout: false, - - // autofocus: Boolean - // A Toggle to modify the default focus behavior of a Dialog, which - // is to focus on the first dialog element after opening the dialog. - // False will disable autofocusing. Default: true. - autofocus: true, - - // baseClass: [protected] String - // The root className to use for the various states of this widget - baseClass: "dijitTooltipDialog", - - // _firstFocusItem: [private readonly] DomNode - // The pointer to the first focusable node in the dialog. - // Set by `dijit/_DialogMixin._getFocusItems()`. - _firstFocusItem: null, - - // _lastFocusItem: [private readonly] DomNode - // The pointer to which node has focus prior to our dialog. - // Set by `dijit/_DialogMixin._getFocusItems()`. - _lastFocusItem: null, - - templateString: template, - - _setTitleAttr: function(/*String*/ title){ - this.containerNode.title = title; - this._set("title", title); - }, - - postCreate: function(){ - this.inherited(arguments); - this.connect(this.containerNode, "onkeypress", "_onKey"); - }, - - orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner){ - // summary: - // Configure widget to be displayed in given position relative to the button. - // This is called from the dijit.popup code, and should not be called - // directly. - // tags: - // protected - - // Note: intentionally not using dijitTooltip class since that sets position:absolute, which - // confuses dijit/popup trying to get the size of the tooltip. - var newC = { - "MR-ML": "dijitTooltipRight", - "ML-MR": "dijitTooltipLeft", - "TM-BM": "dijitTooltipAbove", - "BM-TM": "dijitTooltipBelow", - "BL-TL": "dijitTooltipBelow dijitTooltipABLeft", - "TL-BL": "dijitTooltipAbove dijitTooltipABLeft", - "BR-TR": "dijitTooltipBelow dijitTooltipABRight", - "TR-BR": "dijitTooltipAbove dijitTooltipABRight", - "BR-BL": "dijitTooltipRight", - "BL-BR": "dijitTooltipLeft" - }[aroundCorner + "-" + tooltipCorner]; - - domClass.replace(this.domNode, newC, this._currentOrientClass || ""); - this._currentOrientClass = newC; - - // Tooltip.orient() has code to reposition connector for when Tooltip is before/after anchor. - // Not putting here to avoid code bloat, and since TooltipDialogs are generally above/below. - // Should combine code from Tooltip and TooltipDialog. - }, - - focus: function(){ - // summary: - // Focus on first field - this._getFocusItems(this.containerNode); - focus.focus(this._firstFocusItem); - }, - - onOpen: function(/*Object*/ pos){ - // summary: - // Called when dialog is displayed. - // This is called from the dijit.popup code, and should not be called directly. - // tags: - // protected - - this.orient(this.domNode,pos.aroundCorner, pos.corner); - - // Position the tooltip connector for middle alignment. - // This could not have been done in orient() since the tooltip wasn't positioned at that time. - var aroundNodeCoords = pos.aroundNodePos; - if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){ - this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px"; - this.connectorNode.style.left = ""; - }else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){ - this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px"; - } - - this._onShow(); // lazy load trigger (TODO: shouldn't we load before positioning?) - }, - - onClose: function(){ - // summary: - // Called when dialog is hidden. - // This is called from the dijit.popup code, and should not be called directly. - // tags: - // protected - this.onHide(); - }, - - _onKey: function(/*Event*/ evt){ - // summary: - // Handler for keyboard events - // description: - // Keep keyboard focus in dialog; close dialog on escape key - // tags: - // private - - var node = evt.target; - if(evt.charOrCode === keys.TAB){ - this._getFocusItems(this.containerNode); - } - var singleFocusItem = (this._firstFocusItem == this._lastFocusItem); - if(evt.charOrCode == keys.ESCAPE){ - // Use defer to avoid crash on IE, see #10396. - this.defer("onCancel"); - event.stop(evt); - }else if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){ - if(!singleFocusItem){ - focus.focus(this._lastFocusItem); // send focus to last item in dialog - } - event.stop(evt); - }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){ - if(!singleFocusItem){ - focus.focus(this._firstFocusItem); // send focus to first item in dialog - } - event.stop(evt); - }else if(evt.charOrCode === keys.TAB){ - // we want the browser's default tab handling to move focus - // but we don't want the tab to propagate upwards - evt.stopPropagation(); - } - } - }); -}); - -}, -'dojo/store/util/SimpleQueryEngine':function(){ -define("dojo/store/util/SimpleQueryEngine", ["../../_base/array" /*=====, "../api/Store" =====*/], function(arrayUtil /*=====, Store =====*/){ - -// module: -// dojo/store/util/SimpleQueryEngine - -return function(query, options){ - // summary: - // Simple query engine that matches using filter functions, named filter - // functions or objects by name-value on a query object hash - // - // description: - // The SimpleQueryEngine provides a way of getting a QueryResults through - // the use of a simple object hash as a filter. The hash will be used to - // match properties on data objects with the corresponding value given. In - // other words, only exact matches will be returned. - // - // This function can be used as a template for more complex query engines; - // for example, an engine can be created that accepts an object hash that - // contains filtering functions, or a string that gets evaluated, etc. - // - // When creating a new dojo.store, simply set the store's queryEngine - // field as a reference to this function. - // - // query: Object - // An object hash with fields that may match fields of items in the store. - // Values in the hash will be compared by normal == operator, but regular expressions - // or any object that provides a test() method are also supported and can be - // used to match strings by more complex expressions - // (and then the regex's or object's test() method will be used to match values). - // - // options: dojo/store/api/Store.QueryOptions? - // An object that contains optional information such as sort, start, and count. - // - // returns: Function - // A function that caches the passed query under the field "matches". See any - // of the "query" methods on dojo.stores. - // - // example: - // Define a store with a reference to this engine, and set up a query method. - // - // | var myStore = function(options){ - // | // ...more properties here - // | this.queryEngine = SimpleQueryEngine; - // | // define our query method - // | this.query = function(query, options){ - // | return QueryResults(this.queryEngine(query, options)(this.data)); - // | }; - // | }; - - // create our matching query function - switch(typeof query){ - default: - throw new Error("Can not query with a " + typeof query); - case "object": case "undefined": - var queryObject = query; - query = function(object){ - for(var key in queryObject){ - var required = queryObject[key]; - if(required && required.test){ - // an object can provide a test method, which makes it work with regex - if(!required.test(object[key], object)){ - return false; - } - }else if(required != object[key]){ - return false; - } - } - return true; - }; - break; - case "string": - // named query - if(!this[query]){ - throw new Error("No filter function " + query + " was found in store"); - } - query = this[query]; - // fall through - case "function": - // fall through - } - function execute(array){ - // execute the whole query, first we filter - var results = arrayUtil.filter(array, query); - // next we sort - var sortSet = options && options.sort; - if(sortSet){ - results.sort(typeof sortSet == "function" ? sortSet : function(a, b){ - for(var sort, i=0; sort = sortSet[i]; i++){ - var aValue = a[sort.attribute]; - var bValue = b[sort.attribute]; - if (aValue != bValue){ - return !!sort.descending == (aValue == null || aValue > bValue) ? -1 : 1; - } - } - return 0; - }); - } - // now we paginate - if(options && (options.start || options.count)){ - var total = results.length; - results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity)); - results.total = total; - } - return results; - } - execute.matches = query; - return execute; -}; - -}); - -}, -'dijit/typematic':function(){ -define("dijit/typematic", [ - "dojo/_base/array", // array.forEach - "dojo/_base/connect", // connect.connect - "dojo/_base/event", // event.stop - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.mixin, lang.hitch - "dojo/on", - "dojo/sniff", // has("ie") - "./main" // setting dijit.typematic global -], function(array, connect, event, kernel, lang, on, has, dijit){ - -// module: -// dijit/typematic - -var typematic = (dijit.typematic = { - // summary: - // These functions are used to repetitively call a user specified callback - // method when a specific key or mouse click over a specific DOM node is - // held down for a specific amount of time. - // Only 1 such event is allowed to occur on the browser page at 1 time. - - _fireEventAndReload: function(){ - this._timer = null; - this._callback(++this._count, this._node, this._evt); - - // Schedule next event, timer is at most minDelay (default 10ms) to avoid - // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup) - this._currentTimeout = Math.max( - this._currentTimeout < 0 ? this._initialDelay : - (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)), - this._minDelay); - this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout); - }, - - trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number?*/ subsequentDelay, /*Number?*/ initialDelay, /*Number?*/ minDelay){ - // summary: - // Start a timed, repeating callback sequence. - // If already started, the function call is ignored. - // This method is not normally called by the user but can be - // when the normal listener code is insufficient. - // evt: - // key or mouse event object to pass to the user callback - // _this: - // pointer to the user's widget space. - // node: - // the DOM node object to pass the the callback function - // callback: - // function to call until the sequence is stopped called with 3 parameters: - // count: - // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped - // node: - // the DOM node object passed in - // evt: - // key or mouse event object - // obj: - // user space object used to uniquely identify each typematic sequence - // subsequentDelay: - // if > 1, the number of milliseconds until the 3->n events occur - // or else the fractional time multiplier for the next event's delay, default=0.9 - // initialDelay: - // the number of milliseconds until the 2nd event occurs, default=500ms - // minDelay: - // the maximum delay in milliseconds for event to fire, default=10ms - if(obj != this._obj){ - this.stop(); - this._initialDelay = initialDelay || 500; - this._subsequentDelay = subsequentDelay || 0.90; - this._minDelay = minDelay || 10; - this._obj = obj; - this._node = node; - this._currentTimeout = -1; - this._count = -1; - this._callback = lang.hitch(_this, callback); - this._evt = { faux: true }; - for(var attr in evt){ - if(attr != "layerX" && attr != "layerY"){ // prevent WebKit warnings - var v = evt[attr]; - if(typeof v != "function" && typeof v != "undefined"){ this._evt[attr] = v } - } - } - this._fireEventAndReload(); - } - }, - - stop: function(){ - // summary: - // Stop an ongoing timed, repeating callback sequence. - if(this._timer){ - clearTimeout(this._timer); - this._timer = null; - } - if(this._obj){ - this._callback(-1, this._node, this._evt); - this._obj = null; - } - }, - - addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ - // summary: - // Start listening for a specific typematic key. - // See also the trigger method for other parameters. - // keyObject: - // an object defining the key to listen for: - // - // - charOrCode: the printable character (string) or keyCode (number) to listen for. - // - keyCode: (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0). - // - charCode: (deprecated - use charOrCode) the charCode (number) to listen for. - // - ctrlKey: desired ctrl key state to initiate the callback sequence: - // - pressed (true) - // - released (false) - // - either (unspecified) - // - altKey: same as ctrlKey but for the alt key - // - shiftKey: same as ctrlKey but for the shift key - // returns: - // a connection handle - - if(keyObject.keyCode){ - keyObject.charOrCode = keyObject.keyCode; - kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0"); - }else if(keyObject.charCode){ - keyObject.charOrCode = String.fromCharCode(keyObject.charCode); - kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0"); - } - var handles = [ - on(node, connect._keypress, lang.hitch(this, function(evt){ - if(evt.charOrCode == keyObject.charOrCode && - (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) && - (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) && - (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey - (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){ - event.stop(evt); - typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay); - }else if(typematic._obj == keyObject){ - typematic.stop(); - } - })), - on(node, "keyup", lang.hitch(this, function(){ - if(typematic._obj == keyObject){ - typematic.stop(); - } - })) - ]; - return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; - }, - - addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ - // summary: - // Start listening for a typematic mouse click. - // See the trigger method for other parameters. - // returns: - // a connection handle - var handles = [ - on(node, "mousedown", lang.hitch(this, function(evt){ - evt.preventDefault(); - typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); - })), - on(node, "mouseup", lang.hitch(this, function(evt){ - if(this._obj){ - evt.preventDefault(); - } - typematic.stop(); - })), - on(node, "mouseout", lang.hitch(this, function(evt){ - if(this._obj){ - evt.preventDefault(); - } - typematic.stop(); - })), - on(node, "dblclick", lang.hitch(this, function(evt){ - evt.preventDefault(); - if(has("ie") < 9){ - typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); - setTimeout(lang.hitch(this, typematic.stop), 50); - } - })) - ]; - return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; - }, - - addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){ - // summary: - // Start listening for a specific typematic key and mouseclick. - // This is a thin wrapper to addKeyListener and addMouseListener. - // See the addMouseListener and addKeyListener methods for other parameters. - // mouseNode: - // the DOM node object to listen on for mouse events. - // keyNode: - // the DOM node object to listen on for key events. - // returns: - // a connection handle - var handles = [ - this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay), - this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay) - ]; - return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } }; - } -}); - -return typematic; - -}); - -}, -'dijit/MenuItem':function(){ -require({cache:{ -'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n"}}); -define("dijit/MenuItem", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "dojo/dom-attr", // domAttr.set - "dojo/dom-class", // domClass.toggle - "dojo/_base/kernel", // kernel.deprecated - "dojo/sniff", // has("ie") - "./_Widget", - "./_TemplatedMixin", - "./_Contained", - "./_CssStateMixin", - "dojo/text!./templates/MenuItem.html" -], function(declare, dom, domAttr, domClass, kernel, has, - _Widget, _TemplatedMixin, _Contained, _CssStateMixin, template){ - - // module: - // dijit/MenuItem - - return declare("dijit.MenuItem", - [_Widget, _TemplatedMixin, _Contained, _CssStateMixin], - { - // summary: - // A line item in a Menu Widget - - // Make 3 columns - // icon, label, and expand arrow (BiDi-dependent) indicating sub-menu - templateString: template, - - baseClass: "dijitMenuItem", - - // label: String - // Menu text - label: "", - _setLabelAttr: function(val){ - this.containerNode.innerHTML = val; - this._set("label", val); - if(this.textDir === "auto"){ - this.applyTextDir(this.focusNode, this.label); - } - }, - - // iconClass: String - // Class to apply to DOMNode to make it display an icon. - iconClass: "dijitNoIcon", - _setIconClassAttr: { node: "iconNode", type: "class" }, - - // accelKey: String - // Text for the accelerator (shortcut) key combination. - // Note that although Menu can display accelerator keys there - // is no infrastructure to actually catch and execute these - // accelerators. - accelKey: "", - - // disabled: Boolean - // If true, the menu item is disabled. - // If false, the menu item is enabled. - disabled: false, - - _fillContent: function(/*DomNode*/ source){ - // If button label is specified as srcNodeRef.innerHTML rather than - // this.params.label, handle it here. - if(source && !("label" in this.params)){ - this.set('label', source.innerHTML); - } - }, - - buildRendering: function(){ - this.inherited(arguments); - var label = this.id+"_text"; - domAttr.set(this.containerNode, "id", label); - if(this.accelKeyNode){ - domAttr.set(this.accelKeyNode, "id", this.id + "_accel"); - label += " " + this.id + "_accel"; - } - this.domNode.setAttribute("aria-labelledby", label); - dom.setSelectable(this.domNode, false); - }, - - onClick: function(/*Event*/){ - // summary: - // User defined function to handle clicks - // tags: - // callback - }, - - focus: function(){ - // summary: - // Focus on this MenuItem - try{ - if(has("ie") == 8){ - // needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275) - this.containerNode.focus(); - } - this.focusNode.focus(); - }catch(e){ - // this throws on IE (at least) in some scenarios - } - }, - - _onFocus: function(){ - // summary: - // This is called by the focus manager when focus - // goes to this MenuItem or a child menu. - // tags: - // protected - this._setSelected(true); - this.getParent()._onItemFocus(this); - - this.inherited(arguments); - }, - - _setSelected: function(selected){ - // summary: - // Indicate that this node is the currently selected one - // tags: - // private - - /*** - * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem. - * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu. - * That's not supposed to happen, but the problem is: - * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent - * points to the parent Menu, bypassing the parent MenuItem... thus the - * MenuItem is not in the chain of active widgets and gets a premature call to - * _onBlur() - */ - - domClass.toggle(this.domNode, "dijitMenuItemSelected", selected); - }, - - setLabel: function(/*String*/ content){ - // summary: - // Deprecated. Use set('label', ...) instead. - // tags: - // deprecated - kernel.deprecated("dijit.MenuItem.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0"); - this.set("label", content); - }, - - setDisabled: function(/*Boolean*/ disabled){ - // summary: - // Deprecated. Use set('disabled', bool) instead. - // tags: - // deprecated - kernel.deprecated("dijit.Menu.setDisabled() is deprecated. Use set('disabled', bool) instead.", "", "2.0"); - this.set('disabled', disabled); - }, - _setDisabledAttr: function(/*Boolean*/ value){ - // summary: - // Hook for attr('disabled', ...) to work. - // Enable or disable this menu item. - - this.focusNode.setAttribute('aria-disabled', value ? 'true' : 'false'); - this._set("disabled", value); - }, - _setAccelKeyAttr: function(/*String*/ value){ - // summary: - // Hook for attr('accelKey', ...) to work. - // Set accelKey on this menu item. - - this.accelKeyNode.style.display=value?"":"none"; - this.accelKeyNode.innerHTML=value; - //have to use colSpan to make it work in IE - domAttr.set(this.containerNode,'colSpan',value?"1":"2"); - - this._set("accelKey", value); - }, - _setTextDirAttr: function(/*String*/ textDir){ - // summary: - // Setter for textDir. - // description: - // Users shouldn't call this function; they should be calling - // set('textDir', value) - // tags: - // private - - // only if new textDir is different from the old one - // and on widgets creation. - if(!this._created || this.textDir != textDir){ - this._set("textDir", textDir); - this.applyTextDir(this.focusNode, this.label); - } - } - }); -}); - -}, -'dijit/layout/TabController':function(){ -require({cache:{ -'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode,innerDiv,tabContent\" class=\"dijitTabInner dijitTabContent\">\n\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode'/>\n\t<span data-dojo-attach-point='containerNode,focusNode' class='tabLabel'></span>\n\t<span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t role=\"presentation\">\n\t\t<span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t\t\t></span>\n</div>\n"}}); -define("dijit/layout/TabController", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "dojo/dom-attr", // domAttr.attr - "dojo/dom-class", // domClass.toggle - "dojo/i18n", // i18n.getLocalization - "dojo/_base/lang", // lang.hitch lang.trim - "./StackController", - "../registry", - "../Menu", - "../MenuItem", - "dojo/text!./templates/_TabButton.html", - "dojo/i18n!../nls/common" -], function(declare, dom, domAttr, domClass, i18n, lang, StackController, registry, Menu, MenuItem, template){ - - // module: - // dijit/layout/TabController - - var TabButton = declare("dijit.layout._TabButton", StackController.StackButton, { - // summary: - // A tab (the thing you click to select a pane). - // description: - // Contains the title of the pane, and optionally a close-button to destroy the pane. - // This is an internal widget and should not be instantiated directly. - // tags: - // private - - // baseClass: String - // The CSS class applied to the domNode. - baseClass: "dijitTab", - - // Apply dijitTabCloseButtonHover when close button is hovered - cssStateNodes: { - closeNode: "dijitTabCloseButton" - }, - - templateString: template, - - // Override _FormWidget.scrollOnFocus. - // Don't scroll the whole tab container into view when the button is focused. - scrollOnFocus: false, - - buildRendering: function(){ - this.inherited(arguments); - - dom.setSelectable(this.containerNode, false); - }, - - startup: function(){ - this.inherited(arguments); - var n = this.domNode; - - // Required to give IE6 a kick, as it initially hides the - // tabs until they are focused on. - this.defer(function(){ - n.className = n.className; - }, 1); - }, - - _setCloseButtonAttr: function(/*Boolean*/ disp){ - // summary: - // Hide/show close button - this._set("closeButton", disp); - domClass.toggle(this.domNode, "dijitClosable", disp); - this.closeNode.style.display = disp ? "" : "none"; - if(disp){ - var _nlsResources = i18n.getLocalization("dijit", "common"); - if(this.closeNode){ - domAttr.set(this.closeNode, "title", _nlsResources.itemClose); - } - } - }, - - _setDisabledAttr: function(/*Boolean*/ disabled){ - // summary: - // Make tab selected/unselectable - - this.inherited(arguments); - - // Don't show tooltip for close button when tab is disabled - if(this.closeNode){ - if(disabled){ - domAttr.remove(this.closeNode, "title"); - }else{ - var _nlsResources = i18n.getLocalization("dijit", "common"); - domAttr.set(this.closeNode, "title", _nlsResources.itemClose); - } - } - }, - - _setLabelAttr: function(/*String*/ content){ - // summary: - // Hook for set('label', ...) to work. - // description: - // takes an HTML string. - // Inherited ToggleButton implementation will Set the label (text) of the button; - // Need to set the alt attribute of icon on tab buttons if no label displayed - this.inherited(arguments); - if(!this.showLabel && !this.params.title){ - this.iconNode.alt = lang.trim(this.containerNode.innerText || this.containerNode.textContent || ''); - } - } - }); - - var TabController = declare("dijit.layout.TabController", StackController, { - // summary: - // Set of tabs (the things with titles and a close button, that you click to show a tab panel). - // Used internally by `dijit/layout/TabContainer`. - // description: - // Lets the user select the currently shown pane in a TabContainer or StackContainer. - // TabController also monitors the TabContainer, and whenever a pane is - // added or deleted updates itself accordingly. - // tags: - // private - - baseClass: "dijitTabController", - - templateString: "<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'></div>", - - // tabPosition: String - // Defines where tabs go relative to the content. - // "top", "bottom", "left-h", "right-h" - tabPosition: "top", - - // buttonWidget: Constructor - // The tab widget to create to correspond to each page - buttonWidget: TabButton, - - // buttonWidgetCloseClass: String - // Class of [x] close icon, used by event delegation code to tell when close button was clicked - buttonWidgetCloseClass: "dijitTabCloseButton", - - postCreate: function(){ - this.inherited(arguments); - - // Setup a close menu to be shared between all the closable tabs (excluding disabled tabs) - var closeMenu = new Menu({ - id: this.id+"_Menu", - ownerDocument: this.ownerDocument, - dir: this.dir, - lang: this.lang, - textDir: this.textDir, - targetNodeIds: [this.domNode], - selector: function(node){ - return domClass.contains(node, "dijitClosable") && !domClass.contains(node, "dijitTabDisabled"); - } - }); - this.own(closeMenu); - - var _nlsResources = i18n.getLocalization("dijit", "common"), - controller = this; - closeMenu.addChild(new MenuItem({ - label: _nlsResources.itemClose, - ownerDocument: this.ownerDocument, - dir: this.dir, - lang: this.lang, - textDir: this.textDir, - onClick: function(evt){ - var button = registry.byNode(this.getParent().currentTarget); - controller.onCloseButtonClick(button.page); - } - })); - } - }); - - TabController.TabButton = TabButton; // for monkey patching - - return TabController; -}); - -}, -'dijit/ToolbarSeparator':function(){ -define("dijit/ToolbarSeparator", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "./_Widget", - "./_TemplatedMixin" -], function(declare, dom, _Widget, _TemplatedMixin){ - - // module: - // dijit/ToolbarSeparator - - - return declare("dijit.ToolbarSeparator", [_Widget, _TemplatedMixin], { - // summary: - // A spacer between two `dijit.Toolbar` items - - templateString: '<div class="dijitToolbarSeparator dijitInline" role="presentation"></div>', - - buildRendering: function(){ - this.inherited(arguments); - dom.setSelectable(this.domNode, false); - }, - - isFocusable: function(){ - // summary: - // This widget isn't focusable, so pass along that fact. - // tags: - // protected - return false; - } - }); -}); - -}, -'dijit/layout/_LayoutWidget':function(){ -define("dijit/layout/_LayoutWidget", [ - "dojo/_base/lang", // lang.mixin - "../_Widget", - "../_Container", - "../_Contained", - "../Viewport", - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.remove - "dojo/dom-geometry", // domGeometry.marginBox - "dojo/dom-style" // domStyle.getComputedStyle -], function(lang, _Widget, _Container, _Contained, Viewport, - declare, domClass, domGeometry, domStyle){ - - // module: - // dijit/layout/_LayoutWidget - - - return declare("dijit.layout._LayoutWidget", [_Widget, _Container, _Contained], { - // summary: - // Base class for a _Container widget which is responsible for laying out its children. - // Widgets which mixin this code must define layout() to manage placement and sizing of the children. - - // baseClass: [protected extension] String - // This class name is applied to the widget's domNode - // and also may be used to generate names for sub nodes, - // for example dijitTabContainer-content. - baseClass: "dijitLayoutContainer", - - // isLayoutContainer: [protected] Boolean - // Indicates that this widget is going to call resize() on its - // children widgets, setting their size, when they become visible. - isLayoutContainer: true, - - buildRendering: function(){ - this.inherited(arguments); - domClass.add(this.domNode, "dijitContainer"); - }, - - startup: function(){ - // summary: - // Called after all the widgets have been instantiated and their - // dom nodes have been inserted somewhere under win.doc.body. - // - // Widgets should override this method to do any initialization - // dependent on other widgets existing, and then call - // this superclass method to finish things off. - // - // startup() in subclasses shouldn't do anything - // size related because the size of the widget hasn't been set yet. - - if(this._started){ return; } - - // Need to call inherited first - so that child widgets get started - // up correctly - this.inherited(arguments); - - // If I am a not being controlled by a parent layout widget... - var parent = this.getParent && this.getParent(); - if(!(parent && parent.isLayoutContainer)){ - // Do recursive sizing and layout of all my descendants - // (passing in no argument to resize means that it has to glean the size itself) - this.resize(); - - // Since my parent isn't a layout container, and my style *may be* width=height=100% - // or something similar (either set directly or via a CSS class), - // monitor when viewport size changes so that I can re-layout. - this.own(Viewport.on("resize", lang.hitch(this, "resize"))); - } - }, - - resize: function(changeSize, resultSize){ - // summary: - // Call this to resize a widget, or after its size has changed. - // description: - // ####Change size mode: - // - // When changeSize is specified, changes the marginBox of this widget - // and forces it to re-layout its contents accordingly. - // changeSize may specify height, width, or both. - // - // If resultSize is specified it indicates the size the widget will - // become after changeSize has been applied. - // - // ####Notification mode: - // - // When changeSize is null, indicates that the caller has already changed - // the size of the widget, or perhaps it changed because the browser - // window was resized. Tells widget to re-layout its contents accordingly. - // - // If resultSize is also specified it indicates the size the widget has - // become. - // - // In either mode, this method also: - // - // 1. Sets this._borderBox and this._contentBox to the new size of - // the widget. Queries the current domNode size if necessary. - // 2. Calls layout() to resize contents (and maybe adjust child widgets). - // changeSize: Object? - // Sets the widget to this margin-box size and position. - // May include any/all of the following properties: - // | {w: int, h: int, l: int, t: int} - // resultSize: Object? - // The margin-box size of this widget after applying changeSize (if - // changeSize is specified). If caller knows this size and - // passes it in, we don't need to query the browser to get the size. - // | {w: int, h: int} - - var node = this.domNode; - - // set margin box size, unless it wasn't specified, in which case use current size - if(changeSize){ - domGeometry.setMarginBox(node, changeSize); - } - - // If either height or width wasn't specified by the user, then query node for it. - // But note that setting the margin box and then immediately querying dimensions may return - // inaccurate results, so try not to depend on it. - var mb = resultSize || {}; - lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize - if( !("h" in mb) || !("w" in mb) ){ - mb = lang.mixin(domGeometry.getMarginBox(node), mb); // just use domGeometry.marginBox() to fill in missing values - } - - // Compute and save the size of my border box and content box - // (w/out calling domGeometry.getContentBox() since that may fail if size was recently set) - var cs = domStyle.getComputedStyle(node); - var me = domGeometry.getMarginExtents(node, cs); - var be = domGeometry.getBorderExtents(node, cs); - var bb = (this._borderBox = { - w: mb.w - (me.w + be.w), - h: mb.h - (me.h + be.h) - }); - var pe = domGeometry.getPadExtents(node, cs); - this._contentBox = { - l: domStyle.toPixelValue(node, cs.paddingLeft), - t: domStyle.toPixelValue(node, cs.paddingTop), - w: bb.w - pe.w, - h: bb.h - pe.h - }; - - // Callback for widget to adjust size of its children - this.layout(); - }, - - layout: function(){ - // summary: - // Widgets override this method to size and position their contents/children. - // When this is called this._contentBox is guaranteed to be set (see resize()). - // - // This is called after startup(), and also when the widget's size has been - // changed. - // tags: - // protected extension - }, - - _setupChild: function(/*dijit/_WidgetBase*/child){ - // summary: - // Common setup for initial children and children which are added after startup - // tags: - // protected extension - - var cls = this.baseClass + "-child " - + (child.baseClass ? this.baseClass + "-" + child.baseClass : ""); - domClass.add(child.domNode, cls); - }, - - addChild: function(/*dijit/_WidgetBase*/ child, /*Integer?*/ insertIndex){ - // Overrides _Container.addChild() to call _setupChild() - this.inherited(arguments); - if(this._started){ - this._setupChild(child); - } - }, - - removeChild: function(/*dijit/_WidgetBase*/ child){ - // Overrides _Container.removeChild() to remove class added by _setupChild() - var cls = this.baseClass + "-child" - + (child.baseClass ? - " " + this.baseClass + "-" + child.baseClass : ""); - domClass.remove(child.domNode, cls); - - this.inherited(arguments); - } - }); -}); - -}, -'dijit/popup':function(){ -define("dijit/popup", [ - "dojo/_base/array", // array.forEach array.some - "dojo/aspect", - "dojo/_base/connect", // connect._keypress - "dojo/_base/declare", // declare - "dojo/dom", // dom.isDescendant - "dojo/dom-attr", // domAttr.set - "dojo/dom-construct", // domConstruct.create domConstruct.destroy - "dojo/dom-geometry", // domGeometry.isBodyLtr - "dojo/dom-style", // domStyle.set - "dojo/_base/event", // event.stop - "dojo/keys", - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/sniff", // has("ie") has("mozilla") - "./place", - "./BackgroundIframe", - "./main" // dijit (defining dijit.popup to match API doc) -], function(array, aspect, connect, declare, dom, domAttr, domConstruct, domGeometry, domStyle, event, keys, lang, on, has, - place, BackgroundIframe, dijit){ - - // module: - // dijit/popup - - /*===== - var __OpenArgs = { - // popup: Widget - // widget to display - // parent: Widget - // the button etc. that is displaying this popup - // around: DomNode - // DOM node (typically a button); place popup relative to this node. (Specify this *or* "x" and "y" parameters.) - // x: Integer - // Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.) - // y: Integer - // Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.) - // orient: Object|String - // When the around parameter is specified, orient should be a list of positions to try, ex: - // | [ "below", "above" ] - // For backwards compatibility it can also be an (ordered) hash of tuples of the form - // (around-node-corner, popup-node-corner), ex: - // | { "BL": "TL", "TL": "BL" } - // where BL means "bottom left" and "TL" means "top left", etc. - // - // dijit/popup.open() tries to position the popup according to each specified position, in order, - // until the popup appears fully within the viewport. - // - // The default value is ["below", "above"] - // - // When an (x,y) position is specified rather than an around node, orient is either - // "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse, - // specifically positioning the popup's top-right corner at the mouse position, and if that doesn't - // fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner, - // and the top-right corner. - // onCancel: Function - // callback when user has canceled the popup by: - // - // 1. hitting ESC or - // 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog); - // i.e. whenever popupWidget.onCancel() is called, args.onCancel is called - // onClose: Function - // callback whenever this popup is closed - // onExecute: Function - // callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only) - // padding: place.__Position - // adding a buffer around the opening position. This is only useful when around is not set. - }; - =====*/ - - function destroyWrapper(){ - // summary: - // Function to destroy wrapper when popup widget is destroyed. - // Left in this scope to avoid memory leak on IE8 on refresh page, see #15206. - if(this._popupWrapper){ - domConstruct.destroy(this._popupWrapper); - delete this._popupWrapper; - } - } - - var PopupManager = declare(null, { - // summary: - // Used to show drop downs (ex: the select list of a ComboBox) - // or popups (ex: right-click context menus). - - // _stack: dijit/_WidgetBase[] - // Stack of currently popped up widgets. - // (someone opened _stack[0], and then it opened _stack[1], etc.) - _stack: [], - - // _beginZIndex: Number - // Z-index of the first popup. (If first popup opens other - // popups they get a higher z-index.) - _beginZIndex: 1000, - - _idGen: 1, - - _createWrapper: function(/*Widget*/ widget){ - // summary: - // Initialization for widgets that will be used as popups. - // Puts widget inside a wrapper DIV (if not already in one), - // and returns pointer to that wrapper DIV. - - var wrapper = widget._popupWrapper, - node = widget.domNode; - - if(!wrapper){ - // Create wrapper <div> for when this widget [in the future] will be used as a popup. - // This is done early because of IE bugs where creating/moving DOM nodes causes focus - // to go wonky, see tests/robot/Toolbar.html to reproduce - wrapper = domConstruct.create("div", { - "class":"dijitPopup", - style:{ display: "none"}, - role: "presentation" - }, widget.ownerDocumentBody); - wrapper.appendChild(node); - - var s = node.style; - s.display = ""; - s.visibility = ""; - s.position = ""; - s.top = "0px"; - - widget._popupWrapper = wrapper; - aspect.after(widget, "destroy", destroyWrapper, true); - } - - return wrapper; - }, - - moveOffScreen: function(/*Widget*/ widget){ - // summary: - // Moves the popup widget off-screen. - // Do not use this method to hide popups when not in use, because - // that will create an accessibility issue: the offscreen popup is - // still in the tabbing order. - - // Create wrapper if not already there - var wrapper = this._createWrapper(widget); - - domStyle.set(wrapper, { - visibility: "hidden", - top: "-9999px", // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111) - display: "" - }); - }, - - hide: function(/*Widget*/ widget){ - // summary: - // Hide this popup widget (until it is ready to be shown). - // Initialization for widgets that will be used as popups - // - // Also puts widget inside a wrapper DIV (if not already in one) - // - // If popup widget needs to layout it should - // do so when it is made visible, and popup._onShow() is called. - - // Create wrapper if not already there - var wrapper = this._createWrapper(widget); - - domStyle.set(wrapper, "display", "none"); - }, - - getTopPopup: function(){ - // summary: - // Compute the closest ancestor popup that's *not* a child of another popup. - // Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button. - var stack = this._stack; - for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){ - /* do nothing, just trying to get right value for pi */ - } - return stack[pi]; - }, - - open: function(/*__OpenArgs*/ args){ - // summary: - // Popup the widget at the specified position - // - // example: - // opening at the mouse position - // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY}); - // - // example: - // opening the widget as a dropdown - // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}}); - // - // Note that whatever widget called dijit/popup.open() should also listen to its own _onBlur callback - // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed. - - var stack = this._stack, - widget = args.popup, - orient = args.orient || ["below", "below-alt", "above", "above-alt"], - ltr = args.parent ? args.parent.isLeftToRight() : domGeometry.isBodyLtr(widget.ownerDocument), - around = args.around, - id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++); - - // If we are opening a new popup that isn't a child of a currently opened popup, then - // close currently opened popup(s). This should happen automatically when the old popups - // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198]. - while(stack.length && (!args.parent || !dom.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){ - this.close(stack[stack.length-1].widget); - } - - // Get pointer to popup wrapper, and create wrapper if it doesn't exist - var wrapper = this._createWrapper(widget); - - - domAttr.set(wrapper, { - id: id, - style: { - zIndex: this._beginZIndex + stack.length - }, - "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup", - dijitPopupParent: args.parent ? args.parent.id : "" - }); - - if(has("ie") || has("mozilla")){ - if(!widget.bgIframe){ - // setting widget.bgIframe triggers cleanup in _Widget.destroy() - widget.bgIframe = new BackgroundIframe(wrapper); - } - } - - // position the wrapper node and make it visible - var best = around ? - place.around(wrapper, around, orient, ltr, widget.orient ? lang.hitch(widget, "orient") : null) : - place.at(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding); - - wrapper.style.display = ""; - wrapper.style.visibility = "visible"; - widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown - - var handlers = []; - - // provide default escape and tab key handling - // (this will work for any widget, not just menu) - handlers.push(on(wrapper, connect._keypress, lang.hitch(this, function(evt){ - if(evt.charOrCode == keys.ESCAPE && args.onCancel){ - event.stop(evt); - args.onCancel(); - }else if(evt.charOrCode === keys.TAB){ - event.stop(evt); - var topPopup = this.getTopPopup(); - if(topPopup && topPopup.onCancel){ - topPopup.onCancel(); - } - } - }))); - - // watch for cancel/execute events on the popup and notify the caller - // (for a menu, "execute" means clicking an item) - if(widget.onCancel && args.onCancel){ - handlers.push(widget.on("cancel", args.onCancel)); - } - - handlers.push(widget.on(widget.onExecute ? "execute" : "change", lang.hitch(this, function(){ - var topPopup = this.getTopPopup(); - if(topPopup && topPopup.onExecute){ - topPopup.onExecute(); - } - }))); - - stack.push({ - widget: widget, - parent: args.parent, - onExecute: args.onExecute, - onCancel: args.onCancel, - onClose: args.onClose, - handlers: handlers - }); - - if(widget.onOpen){ - // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here) - widget.onOpen(best); - } - - return best; - }, - - close: function(/*Widget?*/ popup){ - // summary: - // Close specified popup and any popups that it parented. - // If no popup is specified, closes all popups. - - var stack = this._stack; - - // Basically work backwards from the top of the stack closing popups - // until we hit the specified popup, but IIRC there was some issue where closing - // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C] - // closing C might close B indirectly and then the while() condition will run where stack==[A]... - // so the while condition is constructed defensively. - while((popup && array.some(stack, function(elem){return elem.widget == popup;})) || - (!popup && stack.length)){ - var top = stack.pop(), - widget = top.widget, - onClose = top.onClose; - - if(widget.onClose){ - // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here) - widget.onClose(); - } - - var h; - while(h = top.handlers.pop()){ h.remove(); } - - // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc. - if(widget && widget.domNode){ - this.hide(widget); - } - - if(onClose){ - onClose(); - } - } - } - }); - - return (dijit.popup = new PopupManager()); -}); - -}, -'dijit/_base/manager':function(){ -define("dijit/_base/manager", [ - "dojo/_base/array", - "dojo/_base/config", // defaultDuration - "dojo/_base/lang", - "../registry", - "../main" // for setting exports to dijit namespace -], function(array, config, lang, registry, dijit){ - - // module: - // dijit/_base/manager - - var exports = { - // summary: - // Deprecated. Shim to methods on registry, plus a few other declarations. - // New code should access dijit/registry directly when possible. - }; - - array.forEach(["byId", "getUniqueId", "findWidgets", "_destroyAll", "byNode", "getEnclosingWidget"], function(name){ - exports[name] = registry[name]; - }); - - lang.mixin(exports, { - // defaultDuration: Integer - // The default fx.animation speed (in ms) to use for all Dijit - // transitional fx.animations, unless otherwise specified - // on a per-instance basis. Defaults to 200, overrided by - // `djConfig.defaultDuration` - defaultDuration: config["defaultDuration"] || 200 - }); - - lang.mixin(dijit, exports); - - /*===== return exports; =====*/ - return dijit; // for back compat :-( -}); - -}, -'dijit/layout/StackController':function(){ -define("dijit/layout/StackController", [ - "dojo/_base/array", // array.forEach array.indexOf array.map - "dojo/_base/declare", // declare - "dojo/dom-class", - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "dojo/_base/lang", // lang.getObject - "dojo/on", - "../focus", // focus.focus() - "../registry", // registry.byId - "../_Widget", - "../_TemplatedMixin", - "../_Container", - "../form/ToggleButton", - "dojo/i18n!../nls/common" -], function(array, declare, domClass, event, keys, lang, on, - focus, registry, _Widget, _TemplatedMixin, _Container, ToggleButton){ - - // module: - // dijit/layout/StackController - - var StackButton = declare("dijit.layout._StackButton", ToggleButton, { - // summary: - // Internal widget used by StackContainer. - // description: - // The button-like or tab-like object you click to select or delete a page - // tags: - // private - - // Override _FormWidget.tabIndex. - // StackContainer buttons are not in the tab order by default. - // Probably we should be calling this.startupKeyNavChildren() instead. - tabIndex: "-1", - - // closeButton: Boolean - // When true, display close button for this tab - closeButton: false, - - _aria_attr: "aria-selected", - - buildRendering: function(/*Event*/ evt){ - this.inherited(arguments); - (this.focusNode || this.domNode).setAttribute("role", "tab"); - } - }); - - - var StackController = declare("dijit.layout.StackController", [_Widget, _TemplatedMixin, _Container], { - // summary: - // Set of buttons to select a page in a `dijit/layout/StackContainer` - // description: - // Monitors the specified StackContainer, and whenever a page is - // added, deleted, or selected, updates itself accordingly. - - baseClass: "dijitStackController", - - templateString: "<span role='tablist' data-dojo-attach-event='onkeypress'></span>", - - // containerId: [const] String - // The id of the page container that I point to - containerId: "", - - // buttonWidget: [const] Constructor - // The button widget to create to correspond to each page - buttonWidget: StackButton, - - // buttonWidgetCloseClass: String - // CSS class of [x] close icon, used by event delegation code to tell when close button was clicked - buttonWidgetCloseClass: "dijitStackCloseButton", - - constructor: function(params /*===== , srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree - - this.pane2button = {}; // mapping from pane id to buttons - }, - - postCreate: function(){ - this.inherited(arguments); - - // Listen to notifications from StackContainer. - // TODO: do this through bubbled events instead of topics - this.subscribe(this.containerId+"-startup", "onStartup"); - this.subscribe(this.containerId+"-addChild", "onAddChild"); - this.subscribe(this.containerId+"-removeChild", "onRemoveChild"); - this.subscribe(this.containerId+"-selectChild", "onSelectChild"); - this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress"); - - // Listen for click events to select or close tabs. - // No need to worry about ENTER/SPACE key handling: tabs are selected via left/right arrow keys, - // and closed via shift-F10 (to show the close menu). - this.connect(this.containerNode, 'click', function(evt){ - var button = registry.getEnclosingWidget(evt.target); - if(button != this.containerNode && !button.disabled && button.page){ - for(var target = evt.target; target !== this.containerNode; target = target.parentNode){ - if(domClass.contains(target, this.buttonWidgetCloseClass)){ - this.onCloseButtonClick(button.page); - break; - }else if(target == button.domNode){ - this.onButtonClick(button.page); - break; - } - } - } - }); - }, - - onStartup: function(/*Object*/ info){ - // summary: - // Called after StackContainer has finished initializing - // tags: - // private - array.forEach(info.children, this.onAddChild, this); - if(info.selected){ - // Show button corresponding to selected pane (unless selected - // is null because there are no panes) - this.onSelectChild(info.selected); - } - - // Reflect events like page title changes to tab buttons - var containerNode = registry.byId(this.containerId).containerNode, - pane2button = this.pane2button, - paneToButtonAttr = { - "title": "label", - "showtitle": "showLabel", - "iconclass": "iconClass", - "closable": "closeButton", - "tooltip": "title", - "disabled": "disabled" - }, - connectFunc = function(attr, buttonAttr){ - return on(containerNode, "attrmodified-" + attr, function(evt){ - var button = pane2button[evt.detail && evt.detail.widget && evt.detail.widget.id]; - if(button){ - button.set(buttonAttr, evt.detail.newValue); - } - }); - }; - for(var attr in paneToButtonAttr){ - this.own(connectFunc(attr, paneToButtonAttr[attr])); - } - }, - - destroy: function(){ - // Since the buttons are internal to the StackController widget, destroy() should remove them, which is - // done by calling onRemoveChild(). - for(var pane in this.pane2button){ - this.onRemoveChild(registry.byId(pane)); - } - - // TODO: destroyRecursive() will call destroy() on each child button twice. Once from the above code, - // and once because _WidgetBase.destroyDescendants() deletes anything inside of this.containerNode. - // Probably shouldn't attach that DOMNode as this.containerNode. - - this.inherited(arguments); - }, - - onAddChild: function(/*dijit/_WidgetBase*/ page, /*Integer?*/ insertIndex){ - // summary: - // Called whenever a page is added to the container. - // Create button corresponding to the page. - // tags: - // private - - // create an instance of the button widget - // (remove typeof buttonWidget == string support in 2.0) - var Cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget; - var button = new Cls({ - id: this.id + "_" + page.id, - name: this.id + "_" + page.id, - label: page.title, - disabled: page.disabled, - ownerDocument: this.ownerDocument, - dir: page.dir, - lang: page.lang, - textDir: page.textDir, - showLabel: page.showTitle, - iconClass: page.iconClass, - closeButton: page.closable, - title: page.tooltip, - page: page - }); - - this.addChild(button, insertIndex); - this.pane2button[page.id] = button; - page.controlButton = button; // this value might be overwritten if two tabs point to same container - if(!this._currentChild){ - // If this is the first child then StackContainer will soon publish that it's selected, - // but before that StackContainer calls layout(), and before layout() is called the - // StackController needs to have the proper height... which means that the button needs - // to be marked as selected now. See test_TabContainer_CSS.html for test. - this.onSelectChild(page); - } - }, - - onRemoveChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Called whenever a page is removed from the container. - // Remove the button corresponding to the page. - // tags: - // private - - if(this._currentChild === page){ this._currentChild = null; } - - var button = this.pane2button[page.id]; - if(button){ - this.removeChild(button); - delete this.pane2button[page.id]; - button.destroy(); - } - delete page.controlButton; - }, - - onSelectChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Called when a page has been selected in the StackContainer, either by me or by another StackController - // tags: - // private - - if(!page){ return; } - - if(this._currentChild){ - var oldButton=this.pane2button[this._currentChild.id]; - oldButton.set('checked', false); - oldButton.focusNode.setAttribute("tabIndex", "-1"); - } - - var newButton=this.pane2button[page.id]; - newButton.set('checked', true); - this._currentChild = page; - newButton.focusNode.setAttribute("tabIndex", "0"); - var container = registry.byId(this.containerId); - container.containerNode.setAttribute("aria-labelledby", newButton.id); - }, - - onButtonClick: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Called whenever one of my child buttons is pressed in an attempt to select a page - // tags: - // private - - var button = this.pane2button[page.id]; - - // For TabContainer where the tabs are <span>, need to set focus explicitly when left/right arrow - focus.focus(button.focusNode); - - if(this._currentChild && this._currentChild.id === page.id) { - //In case the user clicked the checked button, keep it in the checked state because it remains to be the selected stack page. - button.set('checked', true); - } - var container = registry.byId(this.containerId); - container.selectChild(page); - }, - - onCloseButtonClick: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Called whenever one of my child buttons [X] is pressed in an attempt to close a page - // tags: - // private - - var container = registry.byId(this.containerId); - container.closeChild(page); - if(this._currentChild){ - var b = this.pane2button[this._currentChild.id]; - if(b){ - focus.focus(b.focusNode || b.domNode); - } - } - }, - - // TODO: this is a bit redundant with forward, back api in StackContainer - adjacent: function(/*Boolean*/ forward){ - // summary: - // Helper for onkeypress to find next/previous button - // tags: - // private - - if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; } - // find currently focused button in children array - var children = this.getChildren(); - var idx = array.indexOf(children, this.pane2button[this._currentChild.id]), - current = children[idx]; - - // Pick next/previous non-disabled button to focus on. If we get back to the original button it means - // that all buttons must be disabled, so return current child to avoid an infinite loop. - var child; - do{ - idx = (idx + (forward ? 1 : children.length - 1)) % children.length; - child = children[idx]; - }while(child.disabled && child != current); - - return child; // dijit/_WidgetBase - }, - - onkeypress: function(/*Event*/ e){ - // summary: - // Handle keystrokes on the page list, for advancing to next/previous button - // and closing the current page if the page is closable. - // tags: - // private - - if(this.disabled || e.altKey ){ return; } - var forward = null; - if(e.ctrlKey || !e._djpage){ - switch(e.charOrCode){ - case keys.LEFT_ARROW: - case keys.UP_ARROW: - if(!e._djpage){ forward = false; } - break; - case keys.PAGE_UP: - if(e.ctrlKey){ forward = false; } - break; - case keys.RIGHT_ARROW: - case keys.DOWN_ARROW: - if(!e._djpage){ forward = true; } - break; - case keys.PAGE_DOWN: - if(e.ctrlKey){ forward = true; } - break; - case keys.HOME: - // Navigate to first non-disabled child - var children = this.getChildren(); - for(var idx = 0; idx < children.length; idx++){ - var child = children[idx]; - if(!child.disabled){ - this.onButtonClick(child.page); - break; - } - } - event.stop(e); - break; - case keys.END: - // Navigate to last non-disabled child - var children = this.getChildren(); - for(var idx = children.length-1; idx >= 0; idx--){ - var child = children[idx]; - if(!child.disabled){ - this.onButtonClick(child.page); - break; - } - } - event.stop(e); - break; - case keys.DELETE: - if(this._currentChild.closable){ - this.onCloseButtonClick(this._currentChild); - } - event.stop(e); - break; - default: - if(e.ctrlKey){ - if(e.charOrCode === keys.TAB){ - this.onButtonClick(this.adjacent(!e.shiftKey).page); - event.stop(e); - }else if(e.charOrCode == "w"){ - if(this._currentChild.closable){ - this.onCloseButtonClick(this._currentChild); - } - event.stop(e); // avoid browser tab closing. - } - } - } - // handle next/previous page navigation (left/right arrow, etc.) - if(forward !== null){ - this.onButtonClick(this.adjacent(forward).page); - event.stop(e); - } - } - }, - - onContainerKeyPress: function(/*Object*/ info){ - // summary: - // Called when there was a keypress on the container - // tags: - // private - info.e._djpage = info.page; - this.onkeypress(info.e); - } - }); - - StackController.StackButton = StackButton; // for monkey patching - - return StackController; -}); - -}, -'url:dijit/templates/TooltipDialog.html':"<div role=\"presentation\" tabIndex=\"-1\">\n\t<div class=\"dijitTooltipContainer\" role=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" data-dojo-attach-point=\"containerNode\" role=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" role=\"presentation\" data-dojo-attach-point=\"connectorNode\"></div>\n</div>\n", -'dojo/dnd/Mover':function(){ -define("dojo/dnd/Mover", [ - "../_base/array", "../_base/declare", "../_base/event", "../_base/lang", "../sniff", "../_base/window", - "../dom", "../dom-geometry", "../dom-style", "../Evented", "../on", "../touch", "./common", "./autoscroll" -], function(array, declare, event, lang, has, win, dom, domGeom, domStyle, Evented, on, touch, dnd, autoscroll){ - -// module: -// dojo/dnd/Mover - -return declare("dojo.dnd.Mover", [Evented], { - // summary: - // an object which makes a node follow the mouse, or touch-drag on touch devices. - // Used as a default mover, and as a base class for custom movers. - - constructor: function(node, e, host){ - // node: Node - // a node (or node's id) to be moved - // e: Event - // a mouse event, which started the move; - // only pageX and pageY properties are used - // host: Object? - // object which implements the functionality of the move, - // and defines proper events (onMoveStart and onMoveStop) - this.node = dom.byId(node); - this.marginBox = {l: e.pageX, t: e.pageY}; - this.mouseButton = e.button; - var h = (this.host = host), d = node.ownerDocument; - this.events = [ - // At the start of a drag, onFirstMove is called, and then the following - // listener is disconnected. - on(d, touch.move, lang.hitch(this, "onFirstMove")), - - // These are called continually during the drag - on(d, touch.move, lang.hitch(this, "onMouseMove")), - - // And these are called at the end of the drag - on(d, touch.release, lang.hitch(this, "onMouseUp")), - - // cancel text selection and text dragging - on(d, "dragstart", event.stop), - on(d.body, "selectstart", event.stop) - ]; - - // Tell autoscroll that a drag is starting - autoscroll.autoScrollStart(d); - - // notify that the move has started - if(h && h.onMoveStart){ - h.onMoveStart(this); - } - }, - // mouse event processors - onMouseMove: function(e){ - // summary: - // event processor for onmousemove/ontouchmove - // e: Event - // mouse/touch event - autoscroll.autoScroll(e); - var m = this.marginBox; - this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e); - event.stop(e); - }, - onMouseUp: function(e){ - if(has("webkit") && has("mac") && this.mouseButton == 2 ? - e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too? - this.destroy(); - } - event.stop(e); - }, - // utilities - onFirstMove: function(e){ - // summary: - // makes the node absolute; it is meant to be called only once. - // relative and absolutely positioned nodes are assumed to use pixel units - var s = this.node.style, l, t, h = this.host; - switch(s.position){ - case "relative": - case "absolute": - // assume that left and top values are in pixels already - l = Math.round(parseFloat(s.left)) || 0; - t = Math.round(parseFloat(s.top)) || 0; - break; - default: - s.position = "absolute"; // enforcing the absolute mode - var m = domGeom.getMarginBox(this.node); - // event.pageX/pageY (which we used to generate the initial - // margin box) includes padding and margin set on the body. - // However, setting the node's position to absolute and then - // doing domGeom.marginBox on it *doesn't* take that additional - // space into account - so we need to subtract the combined - // padding and margin. We use getComputedStyle and - // _getMarginBox/_getContentBox to avoid the extra lookup of - // the computed style. - var b = win.doc.body; - var bs = domStyle.getComputedStyle(b); - var bm = domGeom.getMarginBox(b, bs); - var bc = domGeom.getContentBox(b, bs); - l = m.l - (bc.l - bm.l); - t = m.t - (bc.t - bm.t); - break; - } - this.marginBox.l = l - this.marginBox.l; - this.marginBox.t = t - this.marginBox.t; - if(h && h.onFirstMove){ - h.onFirstMove(this, e); - } - - // Disconnect touch.move that call this function - this.events.shift().remove(); - }, - destroy: function(){ - // summary: - // stops the move, deletes all references, so the object can be garbage-collected - array.forEach(this.events, function(handle){ handle.remove(); }); - // undo global settings - var h = this.host; - if(h && h.onMoveStop){ - h.onMoveStop(this); - } - // destroy objects - this.events = this.node = this.host = null; - } -}); - -}); - -}, -'dijit/layout/TabContainer':function(){ -define("dijit/layout/TabContainer", [ - "dojo/_base/lang", // lang.getObject - "dojo/_base/declare", // declare - "./_TabContainerBase", - "./TabController", - "./ScrollingTabController" -], function(lang, declare, _TabContainerBase, TabController, ScrollingTabController){ - - // module: - // dijit/layout/TabContainer - - - return declare("dijit.layout.TabContainer", _TabContainerBase, { - // summary: - // A Container with tabs to select each child (only one of which is displayed at a time). - // description: - // A TabContainer is a container that has multiple panes, but shows only - // one pane at a time. There are a set of tabs corresponding to each pane, - // where each tab has the name (aka title) of the pane, and optionally a close button. - // - // See `StackContainer.ChildWidgetProperties` for details on the properties that can be set on - // children of a `TabContainer`. - - // useMenu: [const] Boolean - // True if a menu should be used to select tabs when they are too - // wide to fit the TabContainer, false otherwise. - useMenu: true, - - // useSlider: [const] Boolean - // True if a slider should be used to select tabs when they are too - // wide to fit the TabContainer, false otherwise. - useSlider: true, - - // controllerWidget: Class - // An optional parameter to override the widget used to display the tab labels - controllerWidget: "", - - _makeController: function(/*DomNode*/ srcNode){ - // summary: - // Instantiate tablist controller widget and return reference to it. - // Callback from _TabContainerBase.postCreate(). - // tags: - // protected extension - - // "string" branch for back-compat, remove for 2.0 - var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"), - TabController = typeof this.controllerWidget == "string" ? lang.getObject(this.controllerWidget) : - this.controllerWidget; - - return new TabController({ - id: this.id + "_tablist", - ownerDocument: this.ownerDocument, - dir: this.dir, - lang: this.lang, - textDir: this.textDir, - tabPosition: this.tabPosition, - doLayout: this.doLayout, - containerId: this.id, - "class": cls, - nested: this.nested, - useMenu: this.useMenu, - useSlider: this.useSlider, - tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null - }, srcNode); - }, - - postMixInProperties: function(){ - this.inherited(arguments); - - // Scrolling controller only works for horizontal non-nested tabs - if(!this.controllerWidget){ - this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ? - ScrollingTabController : TabController; - } - } - }); -}); - -}, -'dijit/BackgroundIframe':function(){ -define("dijit/BackgroundIframe", [ - "require", // require.toUrl - "./main", // to export dijit.BackgroundIframe - "dojo/_base/config", - "dojo/dom-construct", // domConstruct.create - "dojo/dom-style", // domStyle.set - "dojo/_base/lang", // lang.extend lang.hitch - "dojo/on", - "dojo/sniff", // has("ie"), has("mozilla"), has("quirks") - "dojo/_base/window" // win.doc.createElement -], function(require, dijit, config, domConstruct, domStyle, lang, on, has, win){ - - // module: - // dijit/BackgroundIFrame - - // TODO: remove _frames, it isn't being used much, since popups never release their - // iframes (see [22236]) - var _frames = new function(){ - // summary: - // cache of iframes - - var queue = []; - - this.pop = function(){ - var iframe; - if(queue.length){ - iframe = queue.pop(); - iframe.style.display=""; - }else{ - if(has("ie") < 9){ - var burl = config["dojoBlankHtmlUrl"] || require.toUrl("dojo/resources/blank.html") || "javascript:\"\""; - var html="<iframe src='" + burl + "' role='presentation'" - + " style='position: absolute; left: 0px; top: 0px;" - + "z-index: -1; filter:Alpha(Opacity=\"0\");'>"; - iframe = win.doc.createElement(html); - }else{ - iframe = domConstruct.create("iframe"); - iframe.src = 'javascript:""'; - iframe.className = "dijitBackgroundIframe"; - iframe.setAttribute("role", "presentation"); - domStyle.set(iframe, "opacity", 0.1); - } - iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work. - } - return iframe; - }; - - this.push = function(iframe){ - iframe.style.display="none"; - queue.push(iframe); - } - }(); - - - dijit.BackgroundIframe = function(/*DomNode*/ node){ - // summary: - // For IE/FF z-index schenanigans. id attribute is required. - // - // description: - // new dijit.BackgroundIframe(node). - // - // Makes a background iframe as a child of node, that fills - // area (and position) of node - - if(!node.id){ throw new Error("no id"); } - if(has("ie") || has("mozilla")){ - var iframe = (this.iframe = _frames.pop()); - node.appendChild(iframe); - if(has("ie")<7 || has("quirks")){ - this.resize(node); - this._conn = on(node, 'resize', lang.hitch(this, function(){ - this.resize(node); - })); - }else{ - domStyle.set(iframe, { - width: '100%', - height: '100%' - }); - } - } - }; - - lang.extend(dijit.BackgroundIframe, { - resize: function(node){ - // summary: - // Resize the iframe so it's the same size as node. - // Needed on IE6 and IE/quirks because height:100% doesn't work right. - if(this.iframe){ - domStyle.set(this.iframe, { - width: node.offsetWidth + 'px', - height: node.offsetHeight + 'px' - }); - } - }, - destroy: function(){ - // summary: - // destroy the iframe - if(this._conn){ - this._conn.remove(); - this._conn = null; - } - if(this.iframe){ - _frames.push(this.iframe); - delete this.iframe; - } - } - }); - - return dijit.BackgroundIframe; -}); - -}, -'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\"\n\t data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n", -'dojo/dnd/Avatar':function(){ -define("dojo/dnd/Avatar", [ - "../_base/declare", - "../_base/window", - "../dom", - "../dom-attr", - "../dom-class", - "../dom-construct", - "../hccss", - "../query" -], function(declare, win, dom, domAttr, domClass, domConstruct, has, query){ - -// module: -// dojo/dnd/Avatar - -return declare("dojo.dnd.Avatar", null, { - // summary: - // Object that represents transferred DnD items visually - // manager: Object - // a DnD manager object - - constructor: function(manager){ - this.manager = manager; - this.construct(); - }, - - // methods - construct: function(){ - // summary: - // constructor function; - // it is separate so it can be (dynamically) overwritten in case of need - - var a = domConstruct.create("table", { - "class": "dojoDndAvatar", - style: { - position: "absolute", - zIndex: "1999", - margin: "0px" - } - }), - source = this.manager.source, node, - b = domConstruct.create("tbody", null, a), - tr = domConstruct.create("tr", null, b), - td = domConstruct.create("td", null, tr), - k = Math.min(5, this.manager.nodes.length), i = 0; - - if(has("highcontrast")){ - domConstruct.create("span", { - id : "a11yIcon", - innerHTML : this.manager.copy ? '+' : "<" - }, td) - } - domConstruct.create("span", { - innerHTML: source.generateText ? this._generateText() : "" - }, td); - - // we have to set the opacity on IE only after the node is live - domAttr.set(tr, { - "class": "dojoDndAvatarHeader", - style: {opacity: 0.9} - }); - for(; i < k; ++i){ - if(source.creator){ - // create an avatar representation of the node - node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node; - }else{ - // or just clone the node and hope it works - node = this.manager.nodes[i].cloneNode(true); - if(node.tagName.toLowerCase() == "tr"){ - // insert extra table nodes - var table = domConstruct.create("table"), - tbody = domConstruct.create("tbody", null, table); - tbody.appendChild(node); - node = table; - } - } - node.id = ""; - tr = domConstruct.create("tr", null, b); - td = domConstruct.create("td", null, tr); - td.appendChild(node); - domAttr.set(tr, { - "class": "dojoDndAvatarItem", - style: {opacity: (9 - i) / 10} - }); - } - this.node = a; - }, - destroy: function(){ - // summary: - // destructor for the avatar; called to remove all references so it can be garbage-collected - domConstruct.destroy(this.node); - this.node = false; - }, - update: function(){ - // summary: - // updates the avatar to reflect the current DnD state - domClass.toggle(this.node, "dojoDndAvatarCanDrop", this.manager.canDropFlag); - if(has("highcontrast")){ - var icon = dom.byId("a11yIcon"); - var text = '+'; // assume canDrop && copy - if (this.manager.canDropFlag && !this.manager.copy){ - text = '< '; // canDrop && move - }else if (!this.manager.canDropFlag && !this.manager.copy){ - text = "o"; //!canDrop && move - }else if(!this.manager.canDropFlag){ - text = 'x'; // !canDrop && copy - } - icon.innerHTML=text; - } - // replace text - query(("tr.dojoDndAvatarHeader td span" +(has("highcontrast") ? " span" : "")), this.node).forEach( - function(node){ - node.innerHTML = this.manager.source.generateText ? this._generateText() : ""; - }, this); - }, - _generateText: function(){ - // summary: - // generates a proper text to reflect copying or moving of items - return this.manager.nodes.length.toString(); - } -}); - -}); - -}, -'dijit/form/Button':function(){ -require({cache:{ -'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">●</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n"}}); -define("dijit/form/Button", [ - "require", - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.toggle - "dojo/has", // has("dijit-legacy-requires") - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.trim - "dojo/ready", - "./_FormWidget", - "./_ButtonMixin", - "dojo/text!./templates/Button.html" -], function(require, declare, domClass, has, kernel, lang, ready, _FormWidget, _ButtonMixin, template){ - -// module: -// dijit/form/Button - -// Back compat w/1.6, remove for 2.0 -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/form/DropDownButton", "dijit/form/ComboButton", "dijit/form/ToggleButton"]; - require(requires); // use indirection so modules not rolled into a build - }); -} - -return declare("dijit.form.Button", [_FormWidget, _ButtonMixin], { - // summary: - // Basically the same thing as a normal HTML button, but with special styling. - // description: - // Buttons can display a label, an icon, or both. - // A label should always be specified (through innerHTML) or the label - // attribute. It can be hidden via showLabel=false. - // example: - // | <button data-dojo-type="dijit/form/Button" onClick="...">Hello world</button> - // - // example: - // | var button1 = new Button({label: "hello world", onClick: foo}); - // | dojo.body().appendChild(button1.domNode); - - // showLabel: Boolean - // Set this to true to hide the label text and display only the icon. - // (If showLabel=false then iconClass must be specified.) - // Especially useful for toolbars. - // If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon. - // - // The exception case is for computers in high-contrast mode, where the label - // will still be displayed, since the icon doesn't appear. - showLabel: true, - - // iconClass: String - // Class to apply to DOMNode in button to make it display an icon - iconClass: "dijitNoIcon", - _setIconClassAttr: { node: "iconNode", type: "class" }, - - baseClass: "dijitButton", - - templateString: template, - - // Map widget attributes to DOMNode attributes. - _setValueAttr: "valueNode", - - _onClick: function(/*Event*/ e){ - // summary: - // Internal function to handle click actions - var ok = this.inherited(arguments); - if(ok){ - if(this.valueNode){ - this.valueNode.click(); - e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click - e.stopPropagation(); // avoid two events bubbling from Button widget - // leave ok = true so that subclasses can do what they need to do - } - } - return ok; - }, - - _fillContent: function(/*DomNode*/ source){ - // Overrides _Templated._fillContent(). - // If button label is specified as srcNodeRef.innerHTML rather than - // this.params.label, handle it here. - // TODO: remove the method in 2.0, parser will do it all for me - if(source && (!this.params || !("label" in this.params))){ - var sourceLabel = lang.trim(source.innerHTML); - if(sourceLabel){ - this.label = sourceLabel; // _applyAttributes will be called after buildRendering completes to update the DOM - } - } - }, - - _setShowLabelAttr: function(val){ - if(this.containerNode){ - domClass.toggle(this.containerNode, "dijitDisplayNone", !val); - } - this._set("showLabel", val); - }, - - setLabel: function(/*String*/ content){ - // summary: - // Deprecated. Use set('label', ...) instead. - kernel.deprecated("dijit.form.Button.setLabel() is deprecated. Use set('label', ...) instead.", "", "2.0"); - this.set("label", content); - }, - - _setLabelAttr: function(/*String*/ content){ - // summary: - // Hook for set('label', ...) to work. - // description: - // Set the label (text) of the button; takes an HTML string. - // If the label is hidden (showLabel=false) then and no title has - // been specified, then label is also set as title attribute of icon. - this.inherited(arguments); - if(!this.showLabel && !("title" in this.params)){ - this.titleNode.title = lang.trim(this.containerNode.innerText || this.containerNode.textContent || ''); - } - } -}); - - -}); - - -}, -'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n", -'dojo/dnd/move':function(){ -define("dojo/dnd/move", [ - "../_base/declare", - "../dom-geometry", "../dom-style", - "./common", "./Mover", "./Moveable" -], function(declare, domGeom, domStyle, dnd, Mover, Moveable){ - -// module: -// dojo/dnd/move - -/*===== -var __constrainedMoveableArgs = declare([Moveable.__MoveableArgs], { - // constraints: Function - // Calculates a constraint box. - // It is called in a context of the moveable object. - constraints: function(){}, - - // within: Boolean - // restrict move within boundaries. - within: false -}); -=====*/ - -var constrainedMoveable = declare("dojo.dnd.move.constrainedMoveable", Moveable, { - // object attributes (for markup) - constraints: function(){}, - within: false, - - constructor: function(node, params){ - // summary: - // an object that makes a node moveable - // node: Node - // a node (or node's id) to be moved - // params: __constrainedMoveableArgs? - // an optional object with additional parameters; - // the rest is passed to the base class - if(!params){ params = {}; } - this.constraints = params.constraints; - this.within = params.within; - }, - onFirstMove: function(/*Mover*/ mover){ - // summary: - // called during the very first move notification; - // can be used to initialize coordinates, can be overwritten. - var c = this.constraintBox = this.constraints.call(this, mover); - c.r = c.l + c.w; - c.b = c.t + c.h; - if(this.within){ - var mb = domGeom.getMarginSize(mover.node); - c.r -= mb.w; - c.b -= mb.h; - } - }, - onMove: function(/*Mover*/ mover, /*Object*/ leftTop){ - // summary: - // called during every move notification; - // should actually move the node; can be overwritten. - var c = this.constraintBox, s = mover.node.style; - this.onMoving(mover, leftTop); - leftTop.l = leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l; - leftTop.t = leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t; - s.left = leftTop.l + "px"; - s.top = leftTop.t + "px"; - this.onMoved(mover, leftTop); - } -}); - -/*===== -var __boxConstrainedMoveableArgs = declare([__constrainedMoveableArgs], { - // box: Object - // a constraint box - box: {} -}); -=====*/ - -var boxConstrainedMoveable = declare("dojo.dnd.move.boxConstrainedMoveable", constrainedMoveable, { - // box: - // object attributes (for markup) - box: {}, - - constructor: function(node, params){ - // summary: - // an object, which makes a node moveable - // node: Node - // a node (or node's id) to be moved - // params: __boxConstrainedMoveableArgs? - // an optional object with parameters - var box = params && params.box; - this.constraints = function(){ return box; }; - } -}); - -/*===== -var __parentConstrainedMoveableArgs = declare( [__constrainedMoveableArgs], { - // area: String - // A parent's area to restrict the move. - // Can be "margin", "border", "padding", or "content". - area: "" -}); -=====*/ - -var parentConstrainedMoveable = declare("dojo.dnd.move.parentConstrainedMoveable", constrainedMoveable, { - // area: - // object attributes (for markup) - area: "content", - - constructor: function(node, params){ - // summary: - // an object, which makes a node moveable - // node: Node - // a node (or node's id) to be moved - // params: __parentConstrainedMoveableArgs? - // an optional object with parameters - var area = params && params.area; - this.constraints = function(){ - var n = this.node.parentNode, - s = domStyle.getComputedStyle(n), - mb = domGeom.getMarginBox(n, s); - if(area == "margin"){ - return mb; // Object - } - var t = domGeom.getMarginExtents(n, s); - mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h; - if(area == "border"){ - return mb; // Object - } - t = domGeom.getBorderExtents(n, s); - mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h; - if(area == "padding"){ - return mb; // Object - } - t = domGeom.getPadExtents(n, s); - mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h; - return mb; // Object - }; - } -}); - - -return { - // summary: - // TODOC - constrainedMoveable: constrainedMoveable, - boxConstrainedMoveable: boxConstrainedMoveable, - parentConstrainedMoveable: parentConstrainedMoveable -}; - -}); - -}, -'dijit/_WidgetBase':function(){ -define("dijit/_WidgetBase", [ - "require", // require.toUrl - "dojo/_base/array", // array.forEach array.map - "dojo/aspect", - "dojo/_base/config", // config.blankGif - "dojo/_base/connect", // connect.connect - "dojo/_base/declare", // declare - "dojo/dom", // dom.byId - "dojo/dom-attr", // domAttr.set domAttr.remove - "dojo/dom-class", // domClass.add domClass.replace - "dojo/dom-construct", // domConstruct.destroy domConstruct.place - "dojo/dom-geometry", // isBodyLtr - "dojo/dom-style", // domStyle.set, domStyle.get - "dojo/has", - "dojo/_base/kernel", - "dojo/_base/lang", // mixin(), isArray(), etc. - "dojo/on", - "dojo/ready", - "dojo/Stateful", // Stateful - "dojo/topic", - "dojo/_base/window", // win.doc, win.body() - "./Destroyable", - "./registry" // registry.getUniqueId(), registry.findWidgets() -], function(require, array, aspect, config, connect, declare, - dom, domAttr, domClass, domConstruct, domGeometry, domStyle, has, kernel, - lang, on, ready, Stateful, topic, win, Destroyable, registry){ - -// module: -// dijit/_WidgetBase - -// Flag to make dijit load modules the app didn't explicitly request, for backwards compatibility -has.add("dijit-legacy-requires", !kernel.isAsync); - -// For back-compat, remove in 2.0. -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/_base/manager"]; - require(requires); // use indirection so modules not rolled into a build - }); -} - -// Nested hash listing attributes for each tag, all strings in lowercase. -// ex: {"div": {"style": true, "tabindex" true}, "form": { ... -var tagAttrs = {}; -function getAttrs(obj){ - var ret = {}; - for(var attr in obj){ - ret[attr.toLowerCase()] = true; - } - return ret; -} - -function nonEmptyAttrToDom(attr){ - // summary: - // Returns a setter function that copies the attribute to this.domNode, - // or removes the attribute from this.domNode, depending on whether the - // value is defined or not. - return function(val){ - domAttr[val ? "set" : "remove"](this.domNode, attr, val); - this._set(attr, val); - }; -} - -return declare("dijit._WidgetBase", [Stateful, Destroyable], { - // summary: - // Future base class for all Dijit widgets. - // description: - // Future base class for all Dijit widgets. - // _Widget extends this class adding support for various features needed by desktop. - // - // Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(), - // postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch(). - // - // Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value). - // For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr(). - // - // _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes: - // - // - DOM node attribute - // | _setFocusAttr: {node: "focusNode", type: "attribute"} - // | _setFocusAttr: "focusNode" (shorthand) - // | _setFocusAttr: "" (shorthand, maps to this.domNode) - // Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus - // - // - DOM node innerHTML - // | _setTitleAttr: { node: "titleNode", type: "innerHTML" } - // Maps this.title to this.titleNode.innerHTML - // - // - DOM node innerText - // | _setTitleAttr: { node: "titleNode", type: "innerText" } - // Maps this.title to this.titleNode.innerText - // - // - DOM node CSS class - // | _setMyClassAttr: { node: "domNode", type: "class" } - // Maps this.myClass to this.domNode.className - // - // If the value of _setXXXAttr is an array, then each element in the array matches one of the - // formats of the above list. - // - // If the custom setter is null, no action is performed other than saving the new value - // in the widget (in this). - // - // If no custom setter is defined for an attribute, then it will be copied - // to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise. - // That's only done though for attributes that match DOMNode attributes (title, - // alt, aria-labelledby, etc.) - - // id: [const] String - // A unique, opaque ID string that can be assigned by users or by the - // system. If the developer passes an ID which is known not to be - // unique, the specified ID is ignored and the system-generated ID is - // used instead. - id: "", - _setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's - - // lang: [const] String - // Rarely used. Overrides the default Dojo locale used to render this widget, - // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute. - // Value must be among the list of locales specified during by the Dojo bootstrap, - // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us). - lang: "", - // set on domNode even when there's a focus node. but don't set lang="", since that's invalid. - _setLangAttr: nonEmptyAttrToDom("lang"), - - // dir: [const] String - // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir) - // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's - // default direction. - dir: "", - // set on domNode even when there's a focus node. but don't set dir="", since that's invalid. - _setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node - - // textDir: String - // Bi-directional support, the main variable which is responsible for the direction of the text. - // The text direction can be different than the GUI direction by using this parameter in creation - // of a widget. - // - // Allowed values: - // - // 1. "ltr" - // 2. "rtl" - // 3. "auto" - contextual the direction of a text defined by first strong letter. - // - // By default is as the page direction. - textDir: "", - - // class: String - // HTML class attribute - "class": "", - _setClassAttr: { node: "domNode", type: "class" }, - - // style: String||Object - // HTML style attributes as cssText string or name/value hash - style: "", - - // title: String - // HTML title attribute. - // - // For form widgets this specifies a tooltip to display when hovering over - // the widget (just like the native HTML title attribute). - // - // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer, - // etc., it's used to specify the tab label, accordion pane title, etc. - title: "", - - // tooltip: String - // When this widget's title attribute is used to for a tab label, accordion pane title, etc., - // this specifies the tooltip to appear when the mouse is hovered over that text. - tooltip: "", - - // baseClass: [protected] String - // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate - // widget state. - baseClass: "", - - // srcNodeRef: [readonly] DomNode - // pointer to original DOM node - srcNodeRef: null, - - // domNode: [readonly] DomNode - // This is our visible representation of the widget! Other DOM - // Nodes may by assigned to other properties, usually through the - // template system's data-dojo-attach-point syntax, but the domNode - // property is the canonical "top level" node in widget UI. - domNode: null, - - // containerNode: [readonly] DomNode - // Designates where children of the source DOM node will be placed. - // "Children" in this case refers to both DOM nodes and widgets. - // For example, for myWidget: - // - // | <div data-dojo-type=myWidget> - // | <b> here's a plain DOM node - // | <span data-dojo-type=subWidget>and a widget</span> - // | <i> and another plain DOM node </i> - // | </div> - // - // containerNode would point to: - // - // | <b> here's a plain DOM node - // | <span data-dojo-type=subWidget>and a widget</span> - // | <i> and another plain DOM node </i> - // - // In templated widgets, "containerNode" is set via a - // data-dojo-attach-point assignment. - // - // containerNode must be defined for any widget that accepts innerHTML - // (like ContentPane or BorderContainer or even Button), and conversely - // is null for widgets that don't, like TextBox. - containerNode: null, - - // ownerDocument: [const] Document? - // The document this widget belongs to. If not specified to constructor, will default to - // srcNodeRef.ownerDocument, or if no sourceRef specified, then to dojo/_base/window::doc - ownerDocument: null, - _setOwnerDocumentAttr: function(val){ - // this setter is merely to avoid automatically trying to set this.domNode.ownerDocument - this._set("ownerDocument", val); - }, - -/*===== - // _started: [readonly] Boolean - // startup() has completed. - _started: false, -=====*/ - - // attributeMap: [protected] Object - // Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute - // for each XXX attribute to be mapped to the DOM. - // - // attributeMap sets up a "binding" between attributes (aka properties) - // of the widget and the widget's DOM. - // Changes to widget attributes listed in attributeMap will be - // reflected into the DOM. - // - // For example, calling set('title', 'hello') - // on a TitlePane will automatically cause the TitlePane's DOM to update - // with the new title. - // - // attributeMap is a hash where the key is an attribute of the widget, - // and the value reflects a binding to a: - // - // - DOM node attribute - // | focus: {node: "focusNode", type: "attribute"} - // Maps this.focus to this.focusNode.focus - // - // - DOM node innerHTML - // | title: { node: "titleNode", type: "innerHTML" } - // Maps this.title to this.titleNode.innerHTML - // - // - DOM node innerText - // | title: { node: "titleNode", type: "innerText" } - // Maps this.title to this.titleNode.innerText - // - // - DOM node CSS class - // | myClass: { node: "domNode", type: "class" } - // Maps this.myClass to this.domNode.className - // - // If the value is an array, then each element in the array matches one of the - // formats of the above list. - // - // There are also some shorthands for backwards compatibility: - // - // - string --> { node: string, type: "attribute" }, for example: - // - // | "focusNode" ---> { node: "focusNode", type: "attribute" } - // - // - "" --> { node: "domNode", type: "attribute" } - attributeMap: {}, - - // _blankGif: [protected] String - // Path to a blank 1x1 image. - // Used by `<img>` nodes in templates that really get their image via CSS background-image. - _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"), - - //////////// INITIALIZATION METHODS /////////////////////////////////////// - - /*===== - constructor: function(params, srcNodeRef){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified: - // - // - use srcNodeRef.innerHTML as my contents - // - if this is a behavioral widget then apply behavior to that srcNodeRef - // - otherwise, replace srcNodeRef with my generated DOM tree - }, - =====*/ - - postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){ - // summary: - // Kicks off widget instantiation. See create() for details. - // tags: - // private - this.create(params, srcNodeRef); - }, - - create: function(params, srcNodeRef){ - // summary: - // Kick off the life-cycle of a widget - // description: - // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate, - // etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html - // for a discussion of the widget creation lifecycle. - // - // Of course, adventurous developers could override create entirely, but this should - // only be done as a last resort. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified: - // - // - use srcNodeRef.innerHTML as my contents - // - if this is a behavioral widget then apply behavior to that srcNodeRef - // - otherwise, replace srcNodeRef with my generated DOM tree - // tags: - // private - - // store pointer to original DOM tree - this.srcNodeRef = dom.byId(srcNodeRef); - - // No longer used, remove for 2.0. - this._connects = []; - this._supportingWidgets = []; - - // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test) - if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; } - - // mix in our passed parameters - if(params){ - this.params = params; - lang.mixin(this, params); - } - this.postMixInProperties(); - - // Generate an id for the widget if one wasn't specified, or it was specified as id: undefined. - // Do this before buildRendering() because it might expect the id to be there. - if(!this.id){ - this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_")); - if(this.params){ - // if params contains {id: undefined}, prevent _applyAttributes() from processing it - delete this.params.id; - } - } - - // The document and <body> node this widget is associated with - this.ownerDocument = this.ownerDocument || (this.srcNodeRef ? this.srcNodeRef.ownerDocument : win.doc); - this.ownerDocumentBody = win.body(this.ownerDocument); - - registry.add(this); - - this.buildRendering(); - - var deleteSrcNodeRef; - - if(this.domNode){ - // Copy attributes listed in attributeMap into the [newly created] DOM for the widget. - // Also calls custom setters for all attributes with custom setters. - this._applyAttributes(); - - // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree. - // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the - // widget being attached to the DOM since it isn't when a widget is created programmatically like - // new MyWidget({}). See #11635. - var source = this.srcNodeRef; - if(source && source.parentNode && this.domNode !== source){ - source.parentNode.replaceChild(this.domNode, source); - deleteSrcNodeRef = true; - } - - // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId", - // assuming that dojo._scopeName even exists in 2.0 - this.domNode.setAttribute("widgetId", this.id); - } - this.postCreate(); - - // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC. - // I think for back-compatibility it isn't deleting srcNodeRef until after postCreate() has run. - if(deleteSrcNodeRef){ - delete this.srcNodeRef; - } - - this._created = true; - }, - - _applyAttributes: function(){ - // summary: - // Step during widget creation to copy widget attributes to the - // DOM according to attributeMap and _setXXXAttr objects, and also to call - // custom _setXXXAttr() methods. - // - // Skips over blank/false attribute values, unless they were explicitly specified - // as parameters to the widget, since those are the default anyway, - // and setting tabIndex="" is different than not setting tabIndex at all. - // - // For backwards-compatibility reasons attributeMap overrides _setXXXAttr when - // _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap. - // tags: - // private - - // Get list of attributes where this.set(name, value) will do something beyond - // setting this[name] = value. Specifically, attributes that have: - // - associated _setXXXAttr() method/hash/string/array - // - entries in attributeMap (remove this for 2.0); - var ctor = this.constructor, - list = ctor._setterAttrs; - if(!list){ - list = (ctor._setterAttrs = []); - for(var attr in this.attributeMap){ - list.push(attr); - } - - var proto = ctor.prototype; - for(var fxName in proto){ - if(fxName in this.attributeMap){ continue; } - var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr"; - if(setterName in proto){ - list.push(fxName); - } - } - } - - // Call this.set() for each property that was either specified as parameter to constructor, - // or is in the list found above. For correlated properties like value and displayedValue, the one - // specified as a parameter should take precedence. - // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is - // NaN and thus is not ignored like a default value of "". - - // Step 1: Save the current values of the widget properties that were specified as parameters to the constructor. - // Generally this.foo == this.params.foo, except if postMixInProperties() changed the value of this.foo. - var params = {}; - for(var key in this.params || {}){ - params[key] = this[key]; - } - - // Step 2: Call set() for each property that wasn't passed as a parameter to the constructor - array.forEach(list, function(attr){ - if(attr in params){ - // skip this one, do it below - }else if(this[attr]){ - this.set(attr, this[attr]); - } - }, this); - - // Step 3: Call set() for each property that was specified as parameter to constructor. - // Use params hash created above to ignore side effects from step #2 above. - for(key in params){ - this.set(key, params[key]); - } - }, - - postMixInProperties: function(){ - // summary: - // Called after the parameters to the widget have been read-in, - // but before the widget template is instantiated. Especially - // useful to set properties that are referenced in the widget - // template. - // tags: - // protected - }, - - buildRendering: function(){ - // summary: - // Construct the UI for this widget, setting this.domNode. - // Most widgets will mixin `dijit._TemplatedMixin`, which implements this method. - // tags: - // protected - - if(!this.domNode){ - // Create root node if it wasn't created by _Templated - this.domNode = this.srcNodeRef || this.ownerDocument.createElement("div"); - } - - // baseClass is a single class name or occasionally a space-separated list of names. - // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix. - // TODO: make baseClass custom setter - if(this.baseClass){ - var classes = this.baseClass.split(" "); - if(!this.isLeftToRight()){ - classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; })); - } - domClass.add(this.domNode, classes); - } - }, - - postCreate: function(){ - // summary: - // Processing after the DOM fragment is created - // description: - // Called after the DOM fragment has been created, but not necessarily - // added to the document. Do not include any operations which rely on - // node dimensions or placement. - // tags: - // protected - }, - - startup: function(){ - // summary: - // Processing after the DOM fragment is added to the document - // description: - // Called after a widget and its children have been created and added to the page, - // and all related widgets have finished their create() cycle, up through postCreate(). - // This is useful for composite widgets that need to control or layout sub-widgets. - // Many layout widgets can use this as a wiring phase. - if(this._started){ return; } - this._started = true; - array.forEach(this.getChildren(), function(obj){ - if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ - obj.startup(); - obj._started = true; - } - }); - }, - - //////////// DESTROY FUNCTIONS //////////////////////////////// - - destroyRecursive: function(/*Boolean?*/ preserveDom){ - // summary: - // Destroy this widget and its descendants - // description: - // This is the generic "destructor" function that all widget users - // should call to cleanly discard with a widget. Once a widget is - // destroyed, it is removed from the manager object. - // preserveDom: - // If true, this method will leave the original DOM structure - // alone of descendant Widgets. Note: This will NOT work with - // dijit._Templated widgets. - - this._beingDestroyed = true; - this.destroyDescendants(preserveDom); - this.destroy(preserveDom); - }, - - destroy: function(/*Boolean*/ preserveDom){ - // summary: - // Destroy this widget, but not its descendants. - // This method will, however, destroy internal widgets such as those used within a template. - // preserveDom: Boolean - // If true, this method will leave the original DOM structure alone. - // Note: This will not yet work with _Templated widgets - - this._beingDestroyed = true; - this.uninitialize(); - - function destroy(w){ - if(w.destroyRecursive){ - w.destroyRecursive(preserveDom); - }else if(w.destroy){ - w.destroy(preserveDom); - } - } - - // Back-compat, remove for 2.0 - array.forEach(this._connects, lang.hitch(this, "disconnect")); - array.forEach(this._supportingWidgets, destroy); - - // Destroy supporting widgets, but not child widgets under this.containerNode (for 2.0, destroy child widgets - // here too). if() statement is to guard against exception if destroy() called multiple times (see #15815). - if(this.domNode){ - array.forEach(registry.findWidgets(this.domNode, this.containerNode), destroy); - } - - this.destroyRendering(preserveDom); - registry.remove(this.id); - this._destroyed = true; - }, - - destroyRendering: function(/*Boolean?*/ preserveDom){ - // summary: - // Destroys the DOM nodes associated with this widget - // preserveDom: - // If true, this method will leave the original DOM structure alone - // during tear-down. Note: this will not work with _Templated - // widgets yet. - // tags: - // protected - - if(this.bgIframe){ - this.bgIframe.destroy(preserveDom); - delete this.bgIframe; - } - - if(this.domNode){ - if(preserveDom){ - domAttr.remove(this.domNode, "widgetId"); - }else{ - domConstruct.destroy(this.domNode); - } - delete this.domNode; - } - - if(this.srcNodeRef){ - if(!preserveDom){ - domConstruct.destroy(this.srcNodeRef); - } - delete this.srcNodeRef; - } - }, - - destroyDescendants: function(/*Boolean?*/ preserveDom){ - // summary: - // Recursively destroy the children of this widget and their - // descendants. - // preserveDom: - // If true, the preserveDom attribute is passed to all descendant - // widget's .destroy() method. Not for use with _Templated - // widgets. - - // get all direct descendants and destroy them recursively - array.forEach(this.getChildren(), function(widget){ - if(widget.destroyRecursive){ - widget.destroyRecursive(preserveDom); - } - }); - }, - - uninitialize: function(){ - // summary: - // Deprecated. Override destroy() instead to implement custom widget tear-down - // behavior. - // tags: - // protected - return false; - }, - - ////////////////// GET/SET, CUSTOM SETTERS, ETC. /////////////////// - - _setStyleAttr: function(/*String||Object*/ value){ - // summary: - // Sets the style attribute of the widget according to value, - // which is either a hash like {height: "5px", width: "3px"} - // or a plain string - // description: - // Determines which node to set the style on based on style setting - // in attributeMap. - // tags: - // protected - - var mapNode = this.domNode; - - // Note: technically we should revert any style setting made in a previous call - // to his method, but that's difficult to keep track of. - - if(lang.isObject(value)){ - domStyle.set(mapNode, value); - }else{ - if(mapNode.style.cssText){ - mapNode.style.cssText += "; " + value; - }else{ - mapNode.style.cssText = value; - } - } - - this._set("style", value); - }, - - _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){ - // summary: - // Reflect a widget attribute (title, tabIndex, duration etc.) to - // the widget DOM, as specified by commands parameter. - // If commands isn't specified then it's looked up from attributeMap. - // Note some attributes like "type" - // cannot be processed this way as they are not mutable. - // attr: - // Name of member variable (ex: "focusNode" maps to this.focusNode) pointing - // to DOMNode inside the widget, or alternately pointing to a subwidget - // tags: - // private - - commands = arguments.length >= 3 ? commands : this.attributeMap[attr]; - - array.forEach(lang.isArray(commands) ? commands : [commands], function(command){ - - // Get target node and what we are doing to that node - var mapNode = this[command.node || command || "domNode"]; // DOM node - var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute - - switch(type){ - case "attribute": - if(lang.isFunction(value)){ // functions execute in the context of the widget - value = lang.hitch(this, value); - } - - // Get the name of the DOM node attribute; usually it's the same - // as the name of the attribute in the widget (attr), but can be overridden. - // Also maps handler names to lowercase, like onSubmit --> onsubmit - var attrName = command.attribute ? command.attribute : - (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr); - - if(mapNode.tagName){ - // Normal case, mapping to a DOMNode. Note that modern browsers will have a mapNode.set() - // method, but for consistency we still call domAttr - domAttr.set(mapNode, attrName, value); - }else{ - // mapping to a sub-widget - mapNode.set(attrName, value); - } - break; - case "innerText": - mapNode.innerHTML = ""; - mapNode.appendChild(this.ownerDocument.createTextNode(value)); - break; - case "innerHTML": - mapNode.innerHTML = value; - break; - case "class": - domClass.replace(mapNode, value, this[attr]); - break; - } - }, this); - }, - - get: function(name){ - // summary: - // Get a property from a widget. - // name: - // The property to get. - // description: - // Get a named property from a widget. The property may - // potentially be retrieved via a getter method. If no getter is defined, this - // just retrieves the object's property. - // - // For example, if the widget has properties `foo` and `bar` - // and a method named `_getFooAttr()`, calling: - // `myWidget.get("foo")` would be equivalent to calling - // `widget._getFooAttr()` and `myWidget.get("bar")` - // would be equivalent to the expression - // `widget.bar2` - var names = this._getAttrNames(name); - return this[names.g] ? this[names.g]() : this[name]; - }, - - set: function(name, value){ - // summary: - // Set a property on a widget - // name: - // The property to set. - // value: - // The value to set in the property. - // description: - // Sets named properties on a widget which may potentially be handled by a - // setter in the widget. - // - // For example, if the widget has properties `foo` and `bar` - // and a method named `_setFooAttr()`, calling - // `myWidget.set("foo", "Howdy!")` would be equivalent to calling - // `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)` - // would be equivalent to the statement `widget.bar = 3;` - // - // set() may also be called with a hash of name/value pairs, ex: - // - // | myWidget.set({ - // | foo: "Howdy", - // | bar: 3 - // | }); - // - // This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)` - - if(typeof name === "object"){ - for(var x in name){ - this.set(x, name[x]); - } - return this; - } - var names = this._getAttrNames(name), - setter = this[names.s]; - if(lang.isFunction(setter)){ - // use the explicit setter - var result = setter.apply(this, Array.prototype.slice.call(arguments, 1)); - }else{ - // Mapping from widget attribute to DOMNode/subwidget attribute/value/etc. - // Map according to: - // 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0) - // 2. _setFooAttr: {...} type attribute in the widget (if one exists) - // 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick. - // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar - // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset). - // Note also that Tree.focusNode() is a function not a DOMNode, so test for that. - var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode", - tag = this[defaultNode].tagName, - attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])), - map = name in this.attributeMap ? this.attributeMap[name] : - names.s in this ? this[names.s] : - ((names.l in attrsForTag && typeof value != "function") || - /^aria-|^data-|^role$/.test(name)) ? defaultNode : null; - if(map != null){ - this._attrToDom(name, value, map); - } - this._set(name, value); - } - return result || this; - }, - - _attrPairNames: {}, // shared between all widgets - _getAttrNames: function(name){ - // summary: - // Helper function for get() and set(). - // Caches attribute name values so we don't do the string ops every time. - // tags: - // private - - var apn = this._attrPairNames; - if(apn[name]){ return apn[name]; } - var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }); - return (apn[name] = { - n: name+"Node", - s: "_set"+uc+"Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr - g: "_get"+uc+"Attr", - l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset - }); - }, - - _set: function(/*String*/ name, /*anything*/ value){ - // summary: - // Helper function to set new value for specified attribute, and call handlers - // registered with watch() if the value has changed. - var oldValue = this[name]; - this[name] = value; - if(this._created && value !== oldValue){ - if(this._watchCallbacks){ - this._watchCallbacks(name, oldValue, value); - } - this.emit("attrmodified-" + name, { - detail: { - prevValue: oldValue, - newValue: value - } - }); - } - }, - - emit: function(/*String*/ type, /*Object?*/ eventObj, /*Array?*/ callbackArgs){ - // summary: - // Used by widgets to signal that a synthetic event occurred, ex: - // | myWidget.emit("attrmodified-selectedChildWidget", {}). - // - // Emits an event on this.domNode named type.toLowerCase(), based on eventObj. - // Also calls onType() method, if present, and returns value from that method. - // By default passes eventObj to callback, but will pass callbackArgs instead, if specified. - // Modifies eventObj by adding missing parameters (bubbles, cancelable, widget). - // tags: - // protected - - // Specify fallback values for bubbles, cancelable in case they are not set in eventObj. - // Also set pointer to widget, although since we can't add a pointer to the widget for native events - // (see #14729), maybe we shouldn't do it here? - eventObj = eventObj || {}; - if(eventObj.bubbles === undefined){ eventObj.bubbles = true; } - if(eventObj.cancelable === undefined){ eventObj.cancelable = true; } - if(!eventObj.detail){ eventObj.detail = {}; } - eventObj.detail.widget = this; - - var ret, callback = this["on"+type]; - if(callback){ - ret = callback.apply(this, callbackArgs ? callbackArgs : [eventObj]); - } - - // Emit event, but avoid spurious emit()'s as parent sets properties on child during startup/destroy - if(this._started && !this._beingDestroyed){ - on.emit(this.domNode, type.toLowerCase(), eventObj); - } - - return ret; - }, - - on: function(/*String|Function*/ type, /*Function*/ func){ - // summary: - // Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }). - // type: - // Name of event (ex: "click") or extension event like touch.press. - // description: - // Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`. - // Note that the function is not run in any particular scope, so if (for example) you want it to run in the - // widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`. - - // For backwards compatibility, if there's an onType() method in the widget then connect to that. - // Remove in 2.0. - var widgetMethod = this._onMap(type); - if(widgetMethod){ - return aspect.after(this, widgetMethod, func, true); - } - - // Otherwise, just listen for the event on this.domNode. - return this.own(on(this.domNode, type, func))[0]; - }, - - _onMap: function(/*String|Function*/ type){ - // summary: - // Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove"). - // If type is a synthetic event like touch.press then returns undefined. - var ctor = this.constructor, map = ctor._onMap; - if(!map){ - map = (ctor._onMap = {}); - for(var attr in ctor.prototype){ - if(/^on/.test(attr)){ - map[attr.replace(/^on/, "").toLowerCase()] = attr; - } - } - } - return map[typeof type == "string" && type.toLowerCase()]; // String - }, - - toString: function(){ - // summary: - // Returns a string that represents the widget - // description: - // When a widget is cast to a string, this method will be used to generate the - // output. Currently, it does not implement any sort of reversible - // serialization. - return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String - }, - - getChildren: function(){ - // summary: - // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode. - // Does not return nested widgets, nor widgets that are part of this widget's template. - return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit/_WidgetBase[] - }, - - getParent: function(){ - // summary: - // Returns the parent widget of this widget - return registry.getEnclosingWidget(this.domNode.parentNode); - }, - - connect: function( - /*Object|null*/ obj, - /*String|Function*/ event, - /*String|Function*/ method){ - // summary: - // Deprecated, will be removed in 2.0, use this.own(on(...)) or this.own(aspect.after(...)) instead. - // - // Connects specified obj/event to specified method of this object - // and registers for disconnect() on widget destroy. - // - // Provide widget-specific analog to dojo.connect, except with the - // implicit use of this widget as the target object. - // Events connected with `this.connect` are disconnected upon - // destruction. - // returns: - // A handle that can be passed to `disconnect` in order to disconnect before - // the widget is destroyed. - // example: - // | var btn = new Button(); - // | // when foo.bar() is called, call the listener we're going to - // | // provide in the scope of btn - // | btn.connect(foo, "bar", function(){ - // | console.debug(this.toString()); - // | }); - // tags: - // protected - - return this.own(connect.connect(obj, event, this, method))[0]; // handle - }, - - disconnect: function(handle){ - // summary: - // Deprecated, will be removed in 2.0, use handle.remove() instead. - // - // Disconnects handle created by `connect`. - // tags: - // protected - - handle.remove(); - }, - - subscribe: function(t, method){ - // summary: - // Deprecated, will be removed in 2.0, use this.own(topic.subscribe()) instead. - // - // Subscribes to the specified topic and calls the specified method - // of this object and registers for unsubscribe() on widget destroy. - // - // Provide widget-specific analog to dojo.subscribe, except with the - // implicit use of this widget as the target object. - // t: String - // The topic - // method: Function - // The callback - // example: - // | var btn = new Button(); - // | // when /my/topic is published, this button changes its label to - // | // be the parameter of the topic. - // | btn.subscribe("/my/topic", function(v){ - // | this.set("label", v); - // | }); - // tags: - // protected - return this.own(topic.subscribe(t, lang.hitch(this, method)))[0]; // handle - }, - - unsubscribe: function(/*Object*/ handle){ - // summary: - // Deprecated, will be removed in 2.0, use handle.remove() instead. - // - // Unsubscribes handle created by this.subscribe. - // Also removes handle from this widget's list of subscriptions - // tags: - // protected - - handle.remove(); - }, - - isLeftToRight: function(){ - // summary: - // Return this widget's explicit or implicit orientation (true for LTR, false for RTL) - // tags: - // protected - return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(this.ownerDocument); //Boolean - }, - - isFocusable: function(){ - // summary: - // Return true if this widget can currently be focused - // and false if not - return this.focus && (domStyle.get(this.domNode, "display") != "none"); - }, - - placeAt: function(/* String|DomNode|_Widget */ reference, /* String|Int? */ position){ - // summary: - // Place this widget somewhere in the DOM based - // on standard domConstruct.place() conventions. - // description: - // A convenience function provided in all _Widgets, providing a simple - // shorthand mechanism to put an existing (or newly created) Widget - // somewhere in the dom, and allow chaining. - // reference: - // Widget, DOMNode, or id of widget or DOMNode - // position: - // If reference is a widget (or id of widget), and that widget has an ".addChild" method, - // it will be called passing this widget instance into that method, supplying the optional - // position index passed. In this case position (if specified) should be an integer. - // - // If reference is a DOMNode (or id matching a DOMNode but not a widget), - // the position argument can be a numeric index or a string - // "first", "last", "before", or "after", same as dojo/dom-construct::place(). - // returns: dijit/_WidgetBase - // Provides a useful return of the newly created dijit._Widget instance so you - // can "chain" this function by instantiating, placing, then saving the return value - // to a variable. - // example: - // | // create a Button with no srcNodeRef, and place it in the body: - // | var button = new Button({ label:"click" }).placeAt(win.body()); - // | // now, 'button' is still the widget reference to the newly created button - // | button.on("click", function(e){ console.log('click'); })); - // example: - // | // create a button out of a node with id="src" and append it to id="wrapper": - // | var button = new Button({},"src").placeAt("wrapper"); - // example: - // | // place a new button as the first element of some div - // | var button = new Button({ label:"click" }).placeAt("wrapper","first"); - // example: - // | // create a contentpane and add it to a TabContainer - // | var tc = dijit.byId("myTabs"); - // | new ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc) - - var refWidget = !reference.tagName && registry.byId(reference); - if(refWidget && refWidget.addChild && (!position || typeof position === "number")){ - // Adding this to refWidget and can use refWidget.addChild() to handle everything. - refWidget.addChild(this, position); - }else{ - // "reference" is a plain DOMNode, or we can't use refWidget.addChild(). Use domConstruct.place() and - // target refWidget.containerNode for nested placement (position==number, "first", "last", "only"), and - // refWidget.domNode otherwise ("after"/"before"/"replace"). (But not supported officially, see #14946.) - var ref = refWidget ? - (refWidget.containerNode && !/after|before|replace/.test(position||"") ? - refWidget.containerNode : refWidget.domNode) : dom.byId(reference, this.ownerDocument); - domConstruct.place(this.domNode, ref, position); - - // Start this iff it has a parent widget that's already started. - if(!this._started && (this.getParent() || {})._started){ - this.startup(); - } - } - return this; - }, - - getTextDir: function(/*String*/ text,/*String*/ originalDir){ - // summary: - // Return direction of the text. - // The function overridden in the _BidiSupport module, - // its main purpose is to calculate the direction of the - // text, if was defined by the programmer through textDir. - // tags: - // protected. - return originalDir; - }, - - applyTextDir: function(/*===== element, text =====*/){ - // summary: - // The function overridden in the _BidiSupport module, - // originally used for setting element.dir according to this.textDir. - // In this case does nothing. - // element: DOMNode - // text: String - // tags: - // protected. - }, - - defer: function(fcn, delay){ - // summary: - // Wrapper to setTimeout to avoid deferred functions executing - // after the originating widget has been destroyed. - // Returns an object handle with a remove method (that returns null) (replaces clearTimeout). - // fcn: function reference - // delay: Optional number (defaults to 0) - // tags: - // protected. - var timer = setTimeout(lang.hitch(this, - function(){ - timer = null; - if(!this._destroyed){ - lang.hitch(this, fcn)(); - } - }), - delay || 0 - ); - return { - remove: function(){ - if(timer){ - clearTimeout(timer); - timer = null; - } - return null; // so this works well: handle = handle.remove(); - } - }; - } -}); - -}); - -}, -'dijit/layout/_TabContainerBase':function(){ -require({cache:{ -'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n"}}); -define("dijit/layout/_TabContainerBase", [ - "dojo/text!./templates/TabContainer.html", - "./StackContainer", - "./utils", // marginBox2contextBox, layoutChildren - "../_TemplatedMixin", - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add - "dojo/dom-geometry", // domGeometry.contentBox - "dojo/dom-style" // domStyle.style -], function(template, StackContainer, layoutUtils, _TemplatedMixin, declare, domClass, domGeometry, domStyle){ - -// module: -// dijit/layout/_TabContainerBase - - -return declare("dijit.layout._TabContainerBase", [StackContainer, _TemplatedMixin], { - // summary: - // Abstract base class for TabContainer. Must define _makeController() to instantiate - // and return the widget that displays the tab labels - // description: - // A TabContainer is a container that has multiple panes, but shows only - // one pane at a time. There are a set of tabs corresponding to each pane, - // where each tab has the name (aka title) of the pane, and optionally a close button. - - // tabPosition: String - // Defines where tabs go relative to tab content. - // "top", "bottom", "left-h", "right-h" - tabPosition: "top", - - baseClass: "dijitTabContainer", - - // tabStrip: [const] Boolean - // Defines whether the tablist gets an extra class for layouting, putting a border/shading - // around the set of tabs. Not supported by claro theme. - tabStrip: false, - - // nested: [const] Boolean - // If true, use styling for a TabContainer nested inside another TabContainer. - // For tundra etc., makes tabs look like links, and hides the outer - // border since the outer TabContainer already has a border. - nested: false, - - templateString: template, - - postMixInProperties: function(){ - // set class name according to tab position, ex: dijitTabContainerTop - this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, ""); - - this.srcNodeRef && domStyle.set(this.srcNodeRef, "visibility", "hidden"); - - this.inherited(arguments); - }, - - buildRendering: function(){ - this.inherited(arguments); - - // Create the tab list that will have a tab (a.k.a. tab button) for each tab panel - this.tablist = this._makeController(this.tablistNode); - - if(!this.doLayout){ domClass.add(this.domNode, "dijitTabContainerNoLayout"); } - - if(this.nested){ - /* workaround IE's lack of support for "a > b" selectors by - * tagging each node in the template. - */ - domClass.add(this.domNode, "dijitTabContainerNested"); - domClass.add(this.tablist.containerNode, "dijitTabContainerTabListNested"); - domClass.add(this.tablistSpacer, "dijitTabContainerSpacerNested"); - domClass.add(this.containerNode, "dijitTabPaneWrapperNested"); - }else{ - domClass.add(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled")); - } - }, - - _setupChild: function(/*dijit/_WidgetBase*/ tab){ - // Overrides StackContainer._setupChild(). - domClass.add(tab.domNode, "dijitTabPane"); - this.inherited(arguments); - }, - - startup: function(){ - if(this._started){ return; } - - // wire up the tablist and its tabs - this.tablist.startup(); - - this.inherited(arguments); - }, - - layout: function(){ - // Overrides StackContainer.layout(). - // Configure the content pane to take up all the space except for where the tabs are - - if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;} - - var sc = this.selectedChildWidget; - - if(this.doLayout){ - // position and size the titles and the container node - var titleAlign = this.tabPosition.replace(/-h/, ""); - this.tablist.layoutAlign = titleAlign; - var children = [this.tablist, { - domNode: this.tablistSpacer, - layoutAlign: titleAlign - }, { - domNode: this.containerNode, - layoutAlign: "client" - }]; - layoutUtils.layoutChildren(this.domNode, this._contentBox, children); - - // Compute size to make each of my children. - // children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above - this._containerContentBox = layoutUtils.marginBox2contentBox(this.containerNode, children[2]); - - if(sc && sc.resize){ - sc.resize(this._containerContentBox); - } - }else{ - // just layout the tab controller, so it can position left/right buttons etc. - if(this.tablist.resize){ - //make the tabs zero width so that they don't interfere with width calc, then reset - var s = this.tablist.domNode.style; - s.width="0"; - var width = domGeometry.getContentBox(this.domNode).w; - s.width=""; - this.tablist.resize({w: width}); - } - - // and call resize() on the selected pane just to tell it that it's been made visible - if(sc && sc.resize){ - sc.resize(); - } - } - }, - - destroy: function(){ - if(this.tablist){ - this.tablist.destroy(); - } - this.inherited(arguments); - } -}); - -}); - -}, -'dijit/form/Form':function(){ -define("dijit/form/Form", [ - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/_base/event", // event.stop - "dojo/_base/kernel", // kernel.deprecated - "dojo/sniff", // has("ie") - "../_Widget", - "../_TemplatedMixin", - "./_FormMixin", - "../layout/_ContentPaneResizeMixin" -], function(declare, domAttr, event, kernel, has, _Widget, _TemplatedMixin, _FormMixin, _ContentPaneResizeMixin){ - - // module: - // dijit/form/Form - - - return declare("dijit.form.Form", [_Widget, _TemplatedMixin, _FormMixin, _ContentPaneResizeMixin], { - // summary: - // Widget corresponding to HTML form tag, for validation and serialization - // - // example: - // | <form data-dojo-type="dijit/form/Form" id="myForm"> - // | Name: <input type="text" name="name" /> - // | </form> - // | myObj = {name: "John Doe"}; - // | dijit.byId('myForm').set('value', myObj); - // | - // | myObj=dijit.byId('myForm').get('value'); - - // HTML <FORM> attributes - - // name: String? - // Name of form for scripting. - name: "", - - // action: String? - // Server-side form handler. - action: "", - - // method: String? - // HTTP method used to submit the form, either "GET" or "POST". - method: "", - - // encType: String? - // Encoding type for the form, ex: application/x-www-form-urlencoded. - encType: "", - - // accept-charset: String? - // List of supported charsets. - "accept-charset": "", - - // accept: String? - // List of MIME types for file upload. - accept: "", - - // target: String? - // Target frame for the document to be opened in. - target: "", - - templateString: "<form data-dojo-attach-point='containerNode' data-dojo-attach-event='onreset:_onReset,onsubmit:_onSubmit' ${!nameAttrSetting}></form>", - - postMixInProperties: function(){ - // Setup name=foo string to be referenced from the template (but only if a name has been specified) - // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8660 - this.nameAttrSetting = this.name ? ("name='" + this.name + "'") : ""; - this.inherited(arguments); - }, - - execute: function(/*Object*/ /*===== formContents =====*/){ - // summary: - // Deprecated: use submit() - // tags: - // deprecated - }, - - onExecute: function(){ - // summary: - // Deprecated: use onSubmit() - // tags: - // deprecated - }, - - _setEncTypeAttr: function(/*String*/ value){ - this.encType = value; - domAttr.set(this.domNode, "encType", value); - if(has("ie")){ this.domNode.encoding = value; } - }, - - reset: function(/*Event?*/ e){ - // summary: - // restores all widget values back to their init values, - // calls onReset() which can cancel the reset by returning false - - // create fake event so we can know if preventDefault() is called - var faux = { - returnValue: true, // the IE way - preventDefault: function(){ // not IE - this.returnValue = false; - }, - stopPropagation: function(){}, - currentTarget: e ? e.target : this.domNode, - target: e ? e.target : this.domNode - }; - // if return value is not exactly false, and haven't called preventDefault(), then reset - if(!(this.onReset(faux) === false) && faux.returnValue){ - this.inherited(arguments, []); - } - }, - - onReset: function(/*Event?*/ /*===== e =====*/){ - // summary: - // Callback when user resets the form. This method is intended - // to be over-ridden. When the `reset` method is called - // programmatically, the return value from `onReset` is used - // to compute whether or not resetting should proceed - // tags: - // callback - return true; // Boolean - }, - - _onReset: function(e){ - this.reset(e); - event.stop(e); - return false; - }, - - _onSubmit: function(e){ - var fp = this.constructor.prototype; - // TODO: remove this if statement beginning with 2.0 - if(this.execute != fp.execute || this.onExecute != fp.onExecute){ - kernel.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0"); - this.onExecute(); - this.execute(this.getValues()); - } - if(this.onSubmit(e) === false){ // only exactly false stops submit - event.stop(e); - } - }, - - onSubmit: function(/*Event?*/ /*===== e =====*/){ - // summary: - // Callback when user submits the form. - // description: - // This method is intended to be over-ridden, but by default it checks and - // returns the validity of form elements. When the `submit` - // method is called programmatically, the return value from - // `onSubmit` is used to compute whether or not submission - // should proceed - // tags: - // extension - - return this.isValid(); // Boolean - }, - - submit: function(){ - // summary: - // programmatically submit form if and only if the `onSubmit` returns true - if(!(this.onSubmit() === false)){ - this.containerNode.submit(); - } - } - }); -}); - -}, -'dojo/store/Memory':function(){ -define("dojo/store/Memory", ["../_base/declare", "./util/QueryResults", "./util/SimpleQueryEngine" /*=====, "./api/Store" =====*/], -function(declare, QueryResults, SimpleQueryEngine /*=====, Store =====*/){ - -// module: -// dojo/store/Memory - -// No base class, but for purposes of documentation, the base class is dojo/store/api/Store -var base = null; -/*===== base = Store; =====*/ - -return declare("dojo.store.Memory", base, { - // summary: - // This is a basic in-memory object store. It implements dojo/store/api/Store. - constructor: function(options){ - // summary: - // Creates a memory object store. - // options: dojo/store/Memory - // This provides any configuration information that will be mixed into the store. - // This should generally include the data property to provide the starting set of data. - for(var i in options){ - this[i] = options[i]; - } - this.setData(this.data || []); - }, - // data: Array - // The array of all the objects in the memory store - data:null, - - // idProperty: String - // Indicates the property to use as the identity property. The values of this - // property should be unique. - idProperty: "id", - - // index: Object - // An index of data indices into the data array by id - index:null, - - // queryEngine: Function - // Defines the query engine to use for querying the data store - queryEngine: SimpleQueryEngine, - get: function(id){ - // summary: - // Retrieves an object by its identity - // id: Number - // The identity to use to lookup the object - // returns: Object - // The object in the store that matches the given id. - return this.data[this.index[id]]; - }, - getIdentity: function(object){ - // summary: - // Returns an object's identity - // object: Object - // The object to get the identity from - // returns: Number - return object[this.idProperty]; - }, - put: function(object, options){ - // summary: - // Stores an object - // object: Object - // The object to store. - // options: dojo/store/api/Store.PutDirectives? - // Additional metadata for storing the data. Includes an "id" - // property if a specific id is to be used. - // returns: Number - var data = this.data, - index = this.index, - idProperty = this.idProperty; - var id = object[idProperty] = (options && "id" in options) ? options.id : idProperty in object ? object[idProperty] : Math.random(); - if(id in index){ - // object exists - if(options && options.overwrite === false){ - throw new Error("Object already exists"); - } - // replace the entry in data - data[index[id]] = object; - }else{ - // add the new object - index[id] = data.push(object) - 1; - } - return id; - }, - add: function(object, options){ - // summary: - // Creates an object, throws an error if the object already exists - // object: Object - // The object to store. - // options: dojo/store/api/Store.PutDirectives? - // Additional metadata for storing the data. Includes an "id" - // property if a specific id is to be used. - // returns: Number - (options = options || {}).overwrite = false; - // call put with overwrite being false - return this.put(object, options); - }, - remove: function(id){ - // summary: - // Deletes an object by its identity - // id: Number - // The identity to use to delete the object - // returns: Boolean - // Returns true if an object was removed, falsy (undefined) if no object matched the id - var index = this.index; - var data = this.data; - if(id in index){ - data.splice(index[id], 1); - // now we have to reindex - this.setData(data); - return true; - } - }, - query: function(query, options){ - // summary: - // Queries the store for objects. - // query: Object - // The query to use for retrieving objects from the store. - // options: dojo/store/api/Store.QueryOptions? - // The optional arguments to apply to the resultset. - // returns: dojo/store/api/Store.QueryResults - // The results of the query, extended with iterative methods. - // - // example: - // Given the following store: - // - // | var store = new Memory({ - // | data: [ - // | {id: 1, name: "one", prime: false }, - // | {id: 2, name: "two", even: true, prime: true}, - // | {id: 3, name: "three", prime: true}, - // | {id: 4, name: "four", even: true, prime: false}, - // | {id: 5, name: "five", prime: true} - // | ] - // | }); - // - // ...find all items where "prime" is true: - // - // | var results = store.query({ prime: true }); - // - // ...or find all items where "even" is true: - // - // | var results = store.query({ even: true }); - return QueryResults(this.queryEngine(query, options)(this.data)); - }, - setData: function(data){ - // summary: - // Sets the given data as the source for this store, and indexes it - // data: Object[] - // An array of objects to use as the source of data. - if(data.items){ - // just for convenience with the data format IFRS expects - this.idProperty = data.identifier; - data = this.data = data.items; - }else{ - this.data = data; - } - this.index = {}; - for(var i = 0, l = data.length; i < l; i++){ - this.index[data[i][this.idProperty]] = i; - } - } -}); - -}); - -}, -'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n", -'dijit/_base/sniff':function(){ -define("dijit/_base/sniff", [ "dojo/uacss" ], function(){ - - // module: - // dijit/_base/sniff - - /*===== - return { - // summary: - // Deprecated, back compatibility module, new code should require dojo/uacss directly instead of this module. - }; - =====*/ -}); - -}, -'dijit/Toolbar':function(){ -define("dijit/Toolbar", [ - "require", - "dojo/_base/declare", // declare - "dojo/has", - "dojo/keys", // keys.LEFT_ARROW keys.RIGHT_ARROW - "dojo/ready", - "./_Widget", - "./_KeyNavContainer", - "./_TemplatedMixin" -], function(require, declare, has, keys, ready, _Widget, _KeyNavContainer, _TemplatedMixin){ - - // module: - // dijit/Toolbar - - - // Back compat w/1.6, remove for 2.0 - if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/ToolbarSeparator"]; - require(requires); // use indirection so modules not rolled into a build - }); - } - - return declare("dijit.Toolbar", [_Widget, _TemplatedMixin, _KeyNavContainer], { - // summary: - // A Toolbar widget, used to hold things like `dijit.Editor` buttons - - templateString: - '<div class="dijit" role="toolbar" tabIndex="${tabIndex}" data-dojo-attach-point="containerNode">' + - '</div>', - - baseClass: "dijitToolbar", - - postCreate: function(){ - this.inherited(arguments); - - this.connectKeyNavHandlers( - this.isLeftToRight() ? [keys.LEFT_ARROW] : [keys.RIGHT_ARROW], - this.isLeftToRight() ? [keys.RIGHT_ARROW] : [keys.LEFT_ARROW] - ); - } - }); -}); - -}, -'dijit/layout/StackContainer':function(){ -define("dijit/layout/StackContainer", [ - "dojo/_base/array", // array.forEach array.indexOf array.some - "dojo/cookie", // cookie - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.replace - "dojo/has", // has("dijit-legacy-requires") - "dojo/_base/lang", // lang.extend - "dojo/ready", - "dojo/topic", // publish - "../registry", // registry.byId - "../_WidgetBase", - "./_LayoutWidget", - "dojo/i18n!../nls/common" -], function(array, cookie, declare, domClass, has, lang, ready, topic, - registry, _WidgetBase, _LayoutWidget){ - -// module: -// dijit/layout/StackContainer - -// Back compat w/1.6, remove for 2.0 -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/layout/StackController"]; - require(requires); // use indirection so modules not rolled into a build - }); -} - -var StackContainer = declare("dijit.layout.StackContainer", _LayoutWidget, { - // summary: - // A container that has multiple children, but shows only - // one child at a time - // - // description: - // A container for widgets (ContentPanes, for example) That displays - // only one Widget at a time. - // - // Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild - // - // Can be base class for container, Wizard, Show, etc. - // - // See `StackContainer.ChildWidgetProperties` for details on the properties that can be set on - // children of a `StackContainer`. - - // doLayout: Boolean - // If true, change the size of my currently displayed child to match my size - doLayout: true, - - // persist: Boolean - // Remembers the selected child across sessions - persist: false, - - baseClass: "dijitStackContainer", - -/*===== - // selectedChildWidget: [readonly] dijit._Widget - // References the currently selected child widget, if any. - // Adjust selected child with selectChild() method. - selectedChildWidget: null, -=====*/ - - buildRendering: function(){ - this.inherited(arguments); - domClass.add(this.domNode, "dijitLayoutContainer"); - this.containerNode.setAttribute("role", "tabpanel"); - }, - - postCreate: function(){ - this.inherited(arguments); - this.connect(this.domNode, "onkeypress", this._onKeyPress); - }, - - startup: function(){ - if(this._started){ return; } - - var children = this.getChildren(); - - // Setup each page panel to be initially hidden - array.forEach(children, this._setupChild, this); - - // Figure out which child to initially display, defaulting to first one - if(this.persist){ - this.selectedChildWidget = registry.byId(cookie(this.id + "_selectedChild")); - }else{ - array.some(children, function(child){ - if(child.selected){ - this.selectedChildWidget = child; - } - return child.selected; - }, this); - } - var selected = this.selectedChildWidget; - if(!selected && children[0]){ - selected = this.selectedChildWidget = children[0]; - selected.selected = true; - } - - // Publish information about myself so any StackControllers can initialize. - // This needs to happen before this.inherited(arguments) so that for - // TabContainer, this._contentBox doesn't include the space for the tab labels. - topic.publish(this.id+"-startup", {children: children, selected: selected}); - - // Startup each child widget, and do initial layout like setting this._contentBox, - // then calls this.resize() which does the initial sizing on the selected child. - this.inherited(arguments); - }, - - resize: function(){ - // Overrides _LayoutWidget.resize() - // Resize is called when we are first made visible (it's called from startup() - // if we are initially visible). If this is the first time we've been made - // visible then show our first child. - if(!this._hasBeenShown){ - this._hasBeenShown = true; - var selected = this.selectedChildWidget; - if(selected){ - this._showChild(selected); - } - } - this.inherited(arguments); - }, - - _setupChild: function(/*dijit/_WidgetBase*/ child){ - // Overrides _LayoutWidget._setupChild() - - this.inherited(arguments); - - domClass.replace(child.domNode, "dijitHidden", "dijitVisible"); - - // remove the title attribute so it doesn't show up when i hover - // over a node - child.domNode.title = ""; - }, - - addChild: function(/*dijit/_WidgetBase*/ child, /*Integer?*/ insertIndex){ - // Overrides _Container.addChild() to do layout and publish events - - this.inherited(arguments); - - if(this._started){ - topic.publish(this.id+"-addChild", child, insertIndex); // publish - - // in case the tab titles have overflowed from one line to two lines - // (or, if this if first child, from zero lines to one line) - // TODO: w/ScrollingTabController this is no longer necessary, although - // ScrollTabController.resize() does need to get called to show/hide - // the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild(). - // If this is updated to not layout [except for initial child added / last child removed], update - // "childless startup" test in StackContainer.html to check for no resize event after second addChild() - this.layout(); - - // if this is the first child, then select it - if(!this.selectedChildWidget){ - this.selectChild(child); - } - } - }, - - removeChild: function(/*dijit/_WidgetBase*/ page){ - // Overrides _Container.removeChild() to do layout and publish events - - this.inherited(arguments); - - if(this._started){ - // this will notify any tablists to remove a button; do this first because it may affect sizing - topic.publish(this.id + "-removeChild", page); // publish - } - - // If all our children are being destroyed than don't run the code below (to select another page), - // because we are deleting every page one by one - if(this._descendantsBeingDestroyed){ return; } - - // Select new page to display, also updating TabController to show the respective tab. - // Do this before layout call because it can affect the height of the TabController. - if(this.selectedChildWidget === page){ - this.selectedChildWidget = undefined; - if(this._started){ - var children = this.getChildren(); - if(children.length){ - this.selectChild(children[0]); - } - } - } - - if(this._started){ - // In case the tab titles now take up one line instead of two lines - // (note though that ScrollingTabController never overflows to multiple lines), - // or the height has changed slightly because of addition/removal of tab which close icon - this.layout(); - } - }, - - selectChild: function(/*dijit/_WidgetBase|String*/ page, /*Boolean*/ animate){ - // summary: - // Show the given widget (which must be one of my children) - // page: - // Reference to child widget or id of child widget - - page = registry.byId(page); - - if(this.selectedChildWidget != page){ - // Deselect old page and select new one - var d = this._transition(page, this.selectedChildWidget, animate); - this._set("selectedChildWidget", page); - topic.publish(this.id+"-selectChild", page); // publish - - if(this.persist){ - cookie(this.id + "_selectedChild", this.selectedChildWidget.id); - } - } - - return d; // If child has an href, promise that fires when the child's href finishes loading - }, - - _transition: function(newWidget, oldWidget /*===== , animate =====*/){ - // summary: - // Hide the old widget and display the new widget. - // Subclasses should override this. - // newWidget: dijit/_WidgetBase - // The newly selected widget. - // oldWidget: dijit/_WidgetBase - // The previously selected widget. - // animate: Boolean - // Used by AccordionContainer to turn on/off slide effect. - // tags: - // protected extension - if(oldWidget){ - this._hideChild(oldWidget); - } - var d = this._showChild(newWidget); - - // Size the new widget, in case this is the first time it's being shown, - // or I have been resized since the last time it was shown. - // Note that page must be visible for resizing to work. - if(newWidget.resize){ - if(this.doLayout){ - newWidget.resize(this._containerContentBox || this._contentBox); - }else{ - // the child should pick it's own size but we still need to call resize() - // (with no arguments) to let the widget lay itself out - newWidget.resize(); - } - } - - return d; // If child has an href, promise that fires when the child's href finishes loading - }, - - _adjacent: function(/*Boolean*/ forward){ - // summary: - // Gets the next/previous child widget in this container from the current selection. - - // TODO: remove for 2.0 if this isn't being used. Otherwise, fix to skip disabled tabs. - - var children = this.getChildren(); - var index = array.indexOf(children, this.selectedChildWidget); - index += forward ? 1 : children.length - 1; - return children[ index % children.length ]; // dijit/_WidgetBase - }, - - forward: function(){ - // summary: - // Advance to next page. - return this.selectChild(this._adjacent(true), true); - }, - - back: function(){ - // summary: - // Go back to previous page. - return this.selectChild(this._adjacent(false), true); - }, - - _onKeyPress: function(e){ - topic.publish(this.id+"-containerKeyPress", { e: e, page: this}); // publish - }, - - layout: function(){ - // Implement _LayoutWidget.layout() virtual method. - var child = this.selectedChildWidget; - if(child && child.resize){ - if(this.doLayout){ - child.resize(this._containerContentBox || this._contentBox); - }else{ - child.resize(); - } - } - }, - - _showChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Show the specified child by changing it's CSS, and call _onShow()/onShow() so - // it can do any updates it needs regarding loading href's etc. - // returns: - // Promise that fires when page has finished showing, or true if there's no href - var children = this.getChildren(); - page.isFirstChild = (page == children[0]); - page.isLastChild = (page == children[children.length-1]); - page._set("selected", true); - - domClass.replace(page.domNode, "dijitVisible", "dijitHidden"); - - return (page._onShow && page._onShow()) || true; - }, - - _hideChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Hide the specified child by changing it's CSS, and call _onHide() so - // it's notified. - page._set("selected", false); - domClass.replace(page.domNode, "dijitHidden", "dijitVisible"); - - page.onHide && page.onHide(); - }, - - closeChild: function(/*dijit/_WidgetBase*/ page){ - // summary: - // Callback when user clicks the [X] to remove a page. - // If onClose() returns true then remove and destroy the child. - // tags: - // private - var remove = page.onClose(this, page); - if(remove){ - this.removeChild(page); - // makes sure we can clean up executeScripts in ContentPane onUnLoad - page.destroyRecursive(); - } - }, - - destroyDescendants: function(/*Boolean*/ preserveDom){ - this._descendantsBeingDestroyed = true; - this.selectedChildWidget = undefined; - array.forEach(this.getChildren(), function(child){ - if(!preserveDom){ - this.removeChild(child); - } - child.destroyRecursive(preserveDom); - }, this); - this._descendantsBeingDestroyed = false; - } -}); - -StackContainer.ChildWidgetProperties = { - // summary: - // These properties can be specified for the children of a StackContainer. - - // selected: Boolean - // Specifies that this widget should be the initially displayed pane. - // Note: to change the selected child use `dijit/layout/StackContainer.selectChild` - selected: false, - - // disabled: Boolean - // Specifies that the button to select this pane should be disabled. - // Doesn't affect programmatic selection of the pane, nor does it deselect the pane if it is currently selected. - disabled: false, - - // closable: Boolean - // True if user can close (destroy) this child, such as (for example) clicking the X on the tab. - closable: false, - - // iconClass: String - // CSS Class specifying icon to use in label associated with this pane. - iconClass: "dijitNoIcon", - - // showTitle: Boolean - // When true, display title of this widget as tab label etc., rather than just using - // icon specified in iconClass - showTitle: true -}; - -// Since any widget can be specified as a StackContainer child, mix them -// into the base widget class. (This is a hack, but it's effective.) -// This is for the benefit of the parser. Remove for 2.0. Also, hide from doc viewer. -lang.extend(_WidgetBase, /*===== {} || =====*/ StackContainer.ChildWidgetProperties); - -return StackContainer; -}); - -}, -'dojo/regexp':function(){ -define("dojo/regexp", ["./_base/kernel", "./_base/lang"], function(dojo, lang){ - -// module: -// dojo/regexp - -var regexp = { - // summary: - // Regular expressions and Builder resources -}; -lang.setObject("dojo.regexp", regexp); - -regexp.escapeString = function(/*String*/str, /*String?*/except){ - // summary: - // Adds escape sequences for special characters in regular expressions - // except: - // a String with special characters to be left unescaped - - return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){ - if(except && except.indexOf(ch) != -1){ - return ch; - } - return "\\" + ch; - }); // String -}; - -regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){ - // summary: - // Builds a regular expression that groups subexpressions - // description: - // A utility function used by some of the RE generators. The - // subexpressions are constructed by the function, re, in the second - // parameter. re builds one subexpression for each elem in the array - // a, in the first parameter. Returns a string for a regular - // expression that groups all the subexpressions. - // arr: - // A single value or an array of values. - // re: - // A function. Takes one parameter and converts it to a regular - // expression. - // nonCapture: - // If true, uses non-capturing match, otherwise matches are retained - // by regular expression. Defaults to false - - // case 1: a is a single value. - if(!(arr instanceof Array)){ - return re(arr); // String - } - - // case 2: a is an array - var b = []; - for(var i = 0; i < arr.length; i++){ - // convert each elem to a RE - b.push(re(arr[i])); - } - - // join the REs as alternatives in a RE group. - return regexp.group(b.join("|"), nonCapture); // String -}; - -regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){ - // summary: - // adds group match to expression - // nonCapture: - // If true, uses non-capturing match, otherwise matches are retained - // by regular expression. - return "(" + (nonCapture ? "?:":"") + expression + ")"; // String -}; - -return regexp; -}); - -}, -'dijit/DropDownMenu':function(){ -require({cache:{ -'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\"\n\t data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n"}}); -define("dijit/DropDownMenu", [ - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "dojo/text!./templates/Menu.html", - "./_OnDijitClickMixin", - "./_MenuBase" -], function(declare, event, keys, template, _OnDijitClickMixin, _MenuBase){ - - // module: - // dijit/DropDownMenu - - return declare("dijit.DropDownMenu", [_MenuBase, _OnDijitClickMixin], { - // summary: - // A menu, without features for context menu (Meaning, drop down menu) - - templateString: template, - - baseClass: "dijitMenu", - - postCreate: function(){ - this.inherited(arguments); - var l = this.isLeftToRight(); - this._openSubMenuKey = l ? keys.RIGHT_ARROW : keys.LEFT_ARROW; - this._closeSubMenuKey = l ? keys.LEFT_ARROW : keys.RIGHT_ARROW; - this.connectKeyNavHandlers([keys.UP_ARROW], [keys.DOWN_ARROW]); - }, - - _onKeyPress: function(/*Event*/ evt){ - // summary: - // Handle keyboard based menu navigation. - // tags: - // protected - - if(evt.ctrlKey || evt.altKey){ return; } - - switch(evt.charOrCode){ - case this._openSubMenuKey: - this._moveToPopup(evt); - event.stop(evt); - break; - case this._closeSubMenuKey: - if(this.parentMenu){ - if(this.parentMenu._isMenuBar){ - this.parentMenu.focusPrev(); - }else{ - this.onCancel(false); - } - }else{ - event.stop(evt); - } - break; - } - } - }); -}); - -}, -'dijit/form/_FormMixin':function(){ -define("dijit/form/_FormMixin", [ - "dojo/_base/array", // array.every array.filter array.forEach array.indexOf array.map - "dojo/_base/declare", // declare - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.hitch lang.isArray - "dojo/on", - "dojo/window" // winUtils.scrollIntoView -], function(array, declare, kernel, lang, on, winUtils){ - - // module: - // dijit/form/_FormMixin - - return declare("dijit.form._FormMixin", null, { - // summary: - // Mixin for containers of form widgets (i.e. widgets that represent a single value - // and can be children of a `<form>` node or `dijit/form/Form` widget) - // description: - // Can extract all the form widgets - // values and combine them into a single javascript object, or alternately - // take such an object and set the values for all the contained - // form widgets - - /*===== - // value: Object - // Name/value hash for each child widget with a name and value. - // Child widgets without names are not part of the hash. - // - // If there are multiple child widgets w/the same name, value is an array, - // unless they are radio buttons in which case value is a scalar (since only - // one radio button can be checked at a time). - // - // If a child widget's name is a dot separated list (like a.b.c.d), it's a nested structure. - // - // Example: - // | { name: "John Smith", interests: ["sports", "movies"] } - =====*/ - - // state: [readonly] String - // Will be "Error" if one or more of the child widgets has an invalid value, - // "Incomplete" if not all of the required child widgets are filled in. Otherwise, "", - // which indicates that the form is ready to be submitted. - state: "", - - // TODO: - // * Repeater - // * better handling for arrays. Often form elements have names with [] like - // * people[3].sex (for a list of people [{name: Bill, sex: M}, ...]) - - - _getDescendantFormWidgets: function(/*dijit/_WidgetBase[]?*/ children){ - // summary: - // Returns all form widget descendants, searching through non-form child widgets like BorderContainer - var res = []; - array.forEach(children || this.getChildren(), function(child){ - if("value" in child){ - res.push(child); - }else{ - res = res.concat(this._getDescendantFormWidgets(child.getChildren())); - } - }, this); - return res; - }, - - reset: function(){ - array.forEach(this._getDescendantFormWidgets(), function(widget){ - if(widget.reset){ - widget.reset(); - } - }); - }, - - validate: function(){ - // summary: - // returns if the form is valid - same as isValid - but - // provides a few additional (ui-specific) features: - // - // 1. it will highlight any sub-widgets that are not valid - // 2. it will call focus() on the first invalid sub-widget - var didFocus = false; - return array.every(array.map(this._getDescendantFormWidgets(), function(widget){ - // Need to set this so that "required" widgets get their - // state set. - widget._hasBeenBlurred = true; - var valid = widget.disabled || !widget.validate || widget.validate(); - if(!valid && !didFocus){ - // Set focus of the first non-valid widget - winUtils.scrollIntoView(widget.containerNode || widget.domNode); - widget.focus(); - didFocus = true; - } - return valid; - }), function(item){ return item; }); - }, - - setValues: function(val){ - kernel.deprecated(this.declaredClass+"::setValues() is deprecated. Use set('value', val) instead.", "", "2.0"); - return this.set('value', val); - }, - _setValueAttr: function(/*Object*/ obj){ - // summary: - // Fill in form values from according to an Object (in the format returned by get('value')) - - // generate map from name --> [list of widgets with that name] - var map = { }; - array.forEach(this._getDescendantFormWidgets(), function(widget){ - if(!widget.name){ return; } - var entry = map[widget.name] || (map[widget.name] = [] ); - entry.push(widget); - }); - - for(var name in map){ - if(!map.hasOwnProperty(name)){ - continue; - } - var widgets = map[name], // array of widgets w/this name - values = lang.getObject(name, false, obj); // list of values for those widgets - - if(values === undefined){ - continue; - } - if(!lang.isArray(values)){ - values = [ values ]; - } - if(typeof widgets[0].checked == 'boolean'){ - // for checkbox/radio, values is a list of which widgets should be checked - array.forEach(widgets, function(w){ - w.set('value', array.indexOf(values, w.value) != -1); - }); - }else if(widgets[0].multiple){ - // it takes an array (e.g. multi-select) - widgets[0].set('value', values); - }else{ - // otherwise, values is a list of values to be assigned sequentially to each widget - array.forEach(widgets, function(w, i){ - w.set('value', values[i]); - }); - } - } - - /*** - * TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets) - - array.forEach(this.containerNode.elements, function(element){ - if(element.name == ''){return}; // like "continue" - var namePath = element.name.split("."); - var myObj=obj; - var name=namePath[namePath.length-1]; - for(var j=1,len2=namePath.length;j<len2;++j){ - var p=namePath[j - 1]; - // repeater support block - var nameA=p.split("["); - if(nameA.length > 1){ - if(typeof(myObj[nameA[0]]) == "undefined"){ - myObj[nameA[0]]=[ ]; - } // if - - nameIndex=parseInt(nameA[1]); - if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){ - myObj[nameA[0]][nameIndex] = { }; - } - myObj=myObj[nameA[0]][nameIndex]; - continue; - } // repeater support ends - - if(typeof(myObj[p]) == "undefined"){ - myObj=undefined; - break; - }; - myObj=myObj[p]; - } - - if(typeof(myObj) == "undefined"){ - return; // like "continue" - } - if(typeof(myObj[name]) == "undefined" && this.ignoreNullValues){ - return; // like "continue" - } - - // TODO: widget values (just call set('value', ...) on the widget) - - // TODO: maybe should call dojo.getNodeProp() instead - switch(element.type){ - case "checkbox": - element.checked = (name in myObj) && - array.some(myObj[name], function(val){ return val == element.value; }); - break; - case "radio": - element.checked = (name in myObj) && myObj[name] == element.value; - break; - case "select-multiple": - element.selectedIndex=-1; - array.forEach(element.options, function(option){ - option.selected = array.some(myObj[name], function(val){ return option.value == val; }); - }); - break; - case "select-one": - element.selectedIndex="0"; - array.forEach(element.options, function(option){ - option.selected = option.value == myObj[name]; - }); - break; - case "hidden": - case "text": - case "textarea": - case "password": - element.value = myObj[name] || ""; - break; - } - }); - */ - - // Note: no need to call this._set("value", ...) as the child updates will trigger onChange events - // which I am monitoring. - }, - - getValues: function(){ - kernel.deprecated(this.declaredClass+"::getValues() is deprecated. Use get('value') instead.", "", "2.0"); - return this.get('value'); - }, - _getValueAttr: function(){ - // summary: - // Returns Object representing form values. See description of `value` for details. - // description: - - // The value is updated into this.value every time a child has an onChange event, - // so in the common case this function could just return this.value. However, - // that wouldn't work when: - // - // 1. User presses return key to submit a form. That doesn't fire an onchange event, - // and even if it did it would come too late due to the defer(...) in _handleOnChange() - // - // 2. app for some reason calls this.get("value") while the user is typing into a - // form field. Not sure if that case needs to be supported or not. - - // get widget values - var obj = { }; - array.forEach(this._getDescendantFormWidgets(), function(widget){ - var name = widget.name; - if(!name || widget.disabled){ return; } - - // Single value widget (checkbox, radio, or plain <input> type widget) - var value = widget.get('value'); - - // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays - if(typeof widget.checked == 'boolean'){ - if(/Radio/.test(widget.declaredClass)){ - // radio button - if(value !== false){ - lang.setObject(name, value, obj); - }else{ - // give radio widgets a default of null - value = lang.getObject(name, false, obj); - if(value === undefined){ - lang.setObject(name, null, obj); - } - } - }else{ - // checkbox/toggle button - var ary=lang.getObject(name, false, obj); - if(!ary){ - ary=[]; - lang.setObject(name, ary, obj); - } - if(value !== false){ - ary.push(value); - } - } - }else{ - var prev=lang.getObject(name, false, obj); - if(typeof prev != "undefined"){ - if(lang.isArray(prev)){ - prev.push(value); - }else{ - lang.setObject(name, [prev, value], obj); - } - }else{ - // unique name - lang.setObject(name, value, obj); - } - } - }); - - /*** - * code for plain input boxes (see also domForm.formToObject, can we use that instead of this code? - * but it doesn't understand [] notation, presumably) - var obj = { }; - array.forEach(this.containerNode.elements, function(elm){ - if(!elm.name) { - return; // like "continue" - } - var namePath = elm.name.split("."); - var myObj=obj; - var name=namePath[namePath.length-1]; - for(var j=1,len2=namePath.length;j<len2;++j){ - var nameIndex = null; - var p=namePath[j - 1]; - var nameA=p.split("["); - if(nameA.length > 1){ - if(typeof(myObj[nameA[0]]) == "undefined"){ - myObj[nameA[0]]=[ ]; - } // if - nameIndex=parseInt(nameA[1]); - if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){ - myObj[nameA[0]][nameIndex] = { }; - } - }else if(typeof(myObj[nameA[0]]) == "undefined"){ - myObj[nameA[0]] = { } - } // if - - if(nameA.length == 1){ - myObj=myObj[nameA[0]]; - }else{ - myObj=myObj[nameA[0]][nameIndex]; - } // if - } // for - - if((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type == "radio" && elm.checked)){ - if(name == name.split("[")[0]){ - myObj[name]=elm.value; - }else{ - // can not set value when there is no name - } - }else if(elm.type == "checkbox" && elm.checked){ - if(typeof(myObj[name]) == 'undefined'){ - myObj[name]=[ ]; - } - myObj[name].push(elm.value); - }else if(elm.type == "select-multiple"){ - if(typeof(myObj[name]) == 'undefined'){ - myObj[name]=[ ]; - } - for(var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){ - if(elm.options[jdx].selected){ - myObj[name].push(elm.options[jdx].value); - } - } - } // if - name=undefined; - }); // forEach - ***/ - return obj; - }, - - isValid: function(){ - // summary: - // Returns true if all of the widgets are valid. - // Deprecated, will be removed in 2.0. Use get("state") instead. - - return this.state == ""; - }, - - onValidStateChange: function(/*Boolean*/ /*===== isValid =====*/){ - // summary: - // Stub function to connect to if you want to do something - // (like disable/enable a submit button) when the valid - // state changes on the form as a whole. - // - // Deprecated. Will be removed in 2.0. Use watch("state", ...) instead. - }, - - _getState: function(){ - // summary: - // Compute what this.state should be based on state of children - var states = array.map(this._descendants, function(w){ - return w.get("state") || ""; - }); - - return array.indexOf(states, "Error") >= 0 ? "Error" : - array.indexOf(states, "Incomplete") >= 0 ? "Incomplete" : ""; - }, - - disconnectChildren: function(){ - // summary: - // Deprecated method. Applications no longer need to call this. Remove for 2.0. - }, - - connectChildren: function(/*Boolean*/ inStartup){ - // summary: - // You can call this function directly, ex. in the event that you - // programmatically add a widget to the form *after* the form has been - // initialized. - - // TODO: rename for 2.0 - - this._descendants = this._getDescendantFormWidgets(); - - // To get notifications from children they need to be started. Children didn't used to need to be started, - // so for back-compat, start them here - array.forEach(this._descendants, function(child){ - if(!child._started){ child.startup(); } - }); - - if(!inStartup){ - this._onChildChange(); - } - }, - - _onChildChange: function(/*String*/ attr){ - // summary: - // Called when child's value or disabled state changes - - // The unit tests expect state update to be synchronous, so update it immediately. - if(!attr || attr == "state" || attr == "disabled"){ - this._set("state", this._getState()); - } - - // Use defer() to collapse value changes in multiple children into a single - // update to my value. Multiple updates will occur on: - // 1. Form.set() - // 2. Form.reset() - // 3. user selecting a radio button (which will de-select another radio button, - // causing two onChange events) - if(!attr || attr == "value" || attr == "disabled" || attr == "checked"){ - if(this._onChangeDelayTimer){ - this._onChangeDelayTimer.remove(); - } - this._onChangeDelayTimer = this.defer(function(){ - delete this._onChangeDelayTimer; - this._set("value", this.get("value")); - }, 10); - } - }, - - startup: function(){ - this.inherited(arguments); - - // Set initial this.value and this.state. Don't emit watch() notifications. - this._descendants = this._getDescendantFormWidgets(); - this.value = this.get("value"); - this.state = this._getState(); - - // Initialize value and valid/invalid state tracking. - var self = this; - this.own( - on( - this.containerNode, - "attrmodified-state, attrmodified-disabled, attrmodified-value, attrmodified-checked", - function(evt){ - if(evt.target == self.domNode){ - return; // ignore events that I fire on myself because my children changed - } - self._onChildChange(evt.type.replace("attrmodified-", "")); - } - ) - ); - - // Make state change call onValidStateChange(), will be removed in 2.0 - this.watch("state", function(attr, oldVal, newVal){ this.onValidStateChange(newVal == ""); }); - }, - - destroy: function(){ - this.inherited(arguments); - } - - }); -}); - -}, -'dojo/data/util/simpleFetch':function(){ -define("dojo/data/util/simpleFetch", ["../../_base/lang", "../../_base/kernel", "./sorter"], - function(lang, kernel, sorter){ - // module: - // dojo/data/util/simpleFetch - // summary: - // The simpleFetch mixin is designed to serve as a set of function(s) that can - // be mixed into other datastore implementations to accelerate their development. - -var simpleFetch = {}; -lang.setObject("dojo.data.util.simpleFetch", simpleFetch); - -simpleFetch.errorHandler = function(/*Object*/ errorData, /*Object*/ requestObject){ - // summary: - // The error handler when there is an error fetching items. This function should not be called - // directly and is used by simpleFetch.fetch(). - if(requestObject.onError){ - var scope = requestObject.scope || kernel.global; - requestObject.onError.call(scope, errorData, requestObject); - } -}; - -simpleFetch.fetchHandler = function(/*Array*/ items, /*Object*/ requestObject){ - // summary: - // The handler when items are sucessfully fetched. This function should not be called directly - // and is used by simpleFetch.fetch(). - var oldAbortFunction = requestObject.abort || null, - aborted = false, - - startIndex = requestObject.start?requestObject.start: 0, - endIndex = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length; - - requestObject.abort = function(){ - aborted = true; - if(oldAbortFunction){ - oldAbortFunction.call(requestObject); - } - }; - - var scope = requestObject.scope || kernel.global; - if(!requestObject.store){ - requestObject.store = this; - } - if(requestObject.onBegin){ - requestObject.onBegin.call(scope, items.length, requestObject); - } - if(requestObject.sort){ - items.sort(sorter.createSortFunction(requestObject.sort, this)); - } - if(requestObject.onItem){ - for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){ - var item = items[i]; - if(!aborted){ - requestObject.onItem.call(scope, item, requestObject); - } - } - } - if(requestObject.onComplete && !aborted){ - var subset = null; - if(!requestObject.onItem){ - subset = items.slice(startIndex, endIndex); - } - requestObject.onComplete.call(scope, subset, requestObject); - } -}; - -simpleFetch.fetch = function(/* Object? */ request){ - // summary: - // The simpleFetch mixin is designed to serve as a set of function(s) that can - // be mixed into other datastore implementations to accelerate their development. - // description: - // The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems() - // call by returning an array of all the found items that matched the query. The simpleFetch mixin - // is not designed to work for datastores that respond to a fetch() call by incrementally - // loading items, or sequentially loading partial batches of the result - // set. For datastores that mixin simpleFetch, simpleFetch - // implements a fetch method that automatically handles eight of the fetch() - // arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope - // The class mixing in simpleFetch should not implement fetch(), - // but should instead implement a _fetchItems() method. The _fetchItems() - // method takes three arguments, the keywordArgs object that was passed - // to fetch(), a callback function to be called when the result array is - // available, and an error callback to be called if something goes wrong. - // The _fetchItems() method should ignore any keywordArgs parameters for - // start, count, onBegin, onItem, onComplete, onError, sort, and scope. - // The _fetchItems() method needs to correctly handle any other keywordArgs - // parameters, including the query parameter and any optional parameters - // (such as includeChildren). The _fetchItems() method should create an array of - // result items and pass it to the fetchHandler along with the original request object -- - // or, the _fetchItems() method may, if it wants to, create an new request object - // with other specifics about the request that are specific to the datastore and pass - // that as the request object to the handler. - // - // For more information on this specific function, see dojo/data/api/Read.fetch() - // - // request: - // The keywordArgs parameter may either be an instance of - // conforming to dojo/data/api/Request or may be a simple anonymous object - // that may contain any of the following: - // | { - // | query: query-object or query-string, - // | queryOptions: object, - // | onBegin: Function, - // | onItem: Function, - // | onComplete: Function, - // | onError: Function, - // | scope: object, - // | start: int - // | count: int - // | sort: array - // | } - // All implementations should accept keywordArgs objects with any of - // the 9 standard properties: query, onBegin, onItem, onComplete, onError - // scope, sort, start, and count. Some implementations may accept additional - // properties in the keywordArgs object as valid parameters, such as - // {includeOutliers:true}. - // - // ####The *query* parameter - // - // The query may be optional in some data store implementations. - // The dojo/data/api/Read API does not specify the syntax or semantics - // of the query itself -- each different data store implementation - // may have its own notion of what a query should look like. - // However, as of dojo 0.9, 1.0, and 1.1, all the provided datastores in dojo.data - // and dojox.data support an object structure query, where the object is a set of - // name/value parameters such as { attrFoo: valueBar, attrFoo1: valueBar1}. Most of the - // dijit widgets, such as ComboBox assume this to be the case when working with a datastore - // when they dynamically update the query. Therefore, for maximum compatibility with dijit - // widgets the recommended query parameter is a key/value object. That does not mean that the - // the datastore may not take alternative query forms, such as a simple string, a Date, a number, - // or a mix of such. Ultimately, The dojo/data/api/Read API is agnostic about what the query - // format. - // - // Further note: In general for query objects that accept strings as attribute - // value matches, the store should also support basic filtering capability, such as * - // (match any character) and ? (match single character). An example query that is a query object - // would be like: { attrFoo: "value*"}. Which generally means match all items where they have - // an attribute named attrFoo, with a value that starts with 'value'. - // - // ####The *queryOptions* parameter - // - // The queryOptions parameter is an optional parameter used to specify options that may modify - // the query in some fashion, such as doing a case insensitive search, or doing a deep search - // where all items in a hierarchical representation of data are scanned instead of just the root - // items. It currently defines two options that all datastores should attempt to honor if possible: - // | { - // | ignoreCase: boolean, // Whether or not the query should match case sensitively or not. Default behaviour is false. - // | deep: boolean // Whether or not a fetch should do a deep search of items and all child - // | // items instead of just root-level items in a datastore. Default is false. - // | } - // - // ####The *onBegin* parameter. - // - // function(size, request); - // If an onBegin callback function is provided, the callback function - // will be called just once, before the first onItem callback is called. - // The onBegin callback function will be passed two arguments, the - // the total number of items identified and the Request object. If the total number is - // unknown, then size will be -1. Note that size is not necessarily the size of the - // collection of items returned from the query, as the request may have specified to return only a - // subset of the total set of items through the use of the start and count parameters. - // - // ####The *onItem* parameter. - // - // function(item, request); - // - // If an onItem callback function is provided, the callback function - // will be called as each item in the result is received. The callback - // function will be passed two arguments: the item itself, and the - // Request object. - // - // ####The *onComplete* parameter. - // - // function(items, request); - // - // If an onComplete callback function is provided, the callback function - // will be called just once, after the last onItem callback is called. - // Note that if the onItem callback is not present, then onComplete will be passed - // an array containing all items which matched the query and the request object. - // If the onItem callback is present, then onComplete is called as: - // onComplete(null, request). - // - // ####The *onError* parameter. - // - // function(errorData, request); - // - // If an onError callback function is provided, the callback function - // will be called if there is any sort of error while attempting to - // execute the query. - // The onError callback function will be passed two arguments: - // an Error object and the Request object. - // - // ####The *scope* parameter. - // - // If a scope object is provided, all of the callback functions (onItem, - // onComplete, onError, etc) will be invoked in the context of the scope - // object. In the body of the callback function, the value of the "this" - // keyword will be the scope object. If no scope object is provided, - // the callback functions will be called in the context of dojo.global(). - // For example, onItem.call(scope, item, request) vs. - // onItem.call(dojo.global(), item, request) - // - // ####The *start* parameter. - // - // If a start parameter is specified, this is a indication to the datastore to - // only start returning items once the start number of items have been located and - // skipped. When this parameter is paired with 'count', the store should be able - // to page across queries with millions of hits by only returning subsets of the - // hits for each query - // - // ####The *count* parameter. - // - // If a count parameter is specified, this is a indication to the datastore to - // only return up to that many items. This allows a fetch call that may have - // millions of item matches to be paired down to something reasonable. - // - // ####The *sort* parameter. - // - // If a sort parameter is specified, this is a indication to the datastore to - // sort the items in some manner before returning the items. The array is an array of - // javascript objects that must conform to the following format to be applied to the - // fetching of items: - // | { - // | attribute: attribute || attribute-name-string, - // | descending: true|false; // Optional. Default is false. - // | } - // Note that when comparing attributes, if an item contains no value for the attribute - // (undefined), then it the default ascending sort logic should push it to the bottom - // of the list. In the descending order case, it such items should appear at the top of the list. - - request = request || {}; - if(!request.store){ - request.store = this; - } - - this._fetchItems(request, lang.hitch(this, "fetchHandler"), lang.hitch(this, "errorHandler")); - return request; // Object -}; - -return simpleFetch; -}); - -}, -'dijit/Menu':function(){ -define("dijit/Menu", [ - "require", - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/dom", // dom.byId dom.isDescendant - "dojo/dom-attr", // domAttr.get domAttr.set domAttr.has domAttr.remove - "dojo/dom-geometry", // domStyle.getComputedStyle domGeometry.position - "dojo/dom-style", // domStyle.getComputedStyle - "dojo/keys", // keys.F10 - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/sniff", // has("ie"), has("quirks") - "dojo/_base/window", // win.body win.doc.documentElement win.doc.frames - "dojo/window", // winUtils.get - "./popup", - "./DropDownMenu", - "dojo/ready" -], function(require, array, declare, event, dom, domAttr, domGeometry, domStyle, keys, lang, on, - has, win, winUtils, pm, DropDownMenu, ready){ - -// module: -// dijit/Menu - -// Back compat w/1.6, remove for 2.0 -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/MenuItem", "dijit/PopupMenuItem", "dijit/CheckedMenuItem", "dijit/MenuSeparator"]; - require(requires); // use indirection so modules not rolled into a build - }); -} - -return declare("dijit.Menu", DropDownMenu, { - // summary: - // A context menu you can assign to multiple elements - - constructor: function(/*===== params, srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified: - // - // - use srcNodeRef.innerHTML as my contents - // - replace srcNodeRef with my generated DOM tree - - this._bindings = []; - }, - - // targetNodeIds: [const] String[] - // Array of dom node ids of nodes to attach to. - // Fill this with nodeIds upon widget creation and it becomes context menu for those nodes. - targetNodeIds: [], - - // selector: String? - // CSS expression to apply this Menu to descendants of targetNodeIds, rather than to - // the nodes specified by targetNodeIds themselves. Useful for applying a Menu to - // a range of rows in a table, tree, etc. - // - // The application must require() an appropriate level of dojo/query to handle the selector. - selector: "", - - // TODO: in 2.0 remove support for multiple targetNodeIds. selector gives the same effect. - // So, change targetNodeIds to a targetNodeId: "", remove bindDomNode()/unBindDomNode(), etc. - -/*===== - // currentTarget: [readonly] DOMNode - // For context menus, set to the current node that the Menu is being displayed for. - // Useful so that the menu actions can be tailored according to the node - currentTarget: null, -=====*/ - - // contextMenuForWindow: [const] Boolean - // If true, right clicking anywhere on the window will cause this context menu to open. - // If false, must specify targetNodeIds. - contextMenuForWindow: false, - - // leftClickToOpen: [const] Boolean - // If true, menu will open on left click instead of right click, similar to a file menu. - leftClickToOpen: false, - - // refocus: Boolean - // When this menu closes, re-focus the element which had focus before it was opened. - refocus: true, - - postCreate: function(){ - if(this.contextMenuForWindow){ - this.bindDomNode(this.ownerDocumentBody); - }else{ - // TODO: should have _setTargetNodeIds() method to handle initialization and a possible - // later set('targetNodeIds', ...) call. There's also a problem that targetNodeIds[] - // gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610) - array.forEach(this.targetNodeIds, this.bindDomNode, this); - } - this.inherited(arguments); - }, - - // thanks burstlib! - _iframeContentWindow: function(/* HTMLIFrameElement */iframe_el){ - // summary: - // Returns the window reference of the passed iframe - // tags: - // private - return winUtils.get(this._iframeContentDocument(iframe_el)) || - // Moz. TODO: is this available when defaultView isn't? - this._iframeContentDocument(iframe_el)['__parent__'] || - (iframe_el.name && win.doc.frames[iframe_el.name]) || null; // Window - }, - - _iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){ - // summary: - // Returns a reference to the document object inside iframe_el - // tags: - // protected - return iframe_el.contentDocument // W3 - || (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE - || (iframe_el.name && win.doc.frames[iframe_el.name] && win.doc.frames[iframe_el.name].document) - || null; // HTMLDocument - }, - - bindDomNode: function(/*String|DomNode*/ node){ - // summary: - // Attach menu to given node - node = dom.byId(node, this.ownerDocument); - - var cn; // Connect node - - // Support context menus on iframes. Rather than binding to the iframe itself we need - // to bind to the <body> node inside the iframe. - if(node.tagName.toLowerCase() == "iframe"){ - var iframe = node, - window = this._iframeContentWindow(iframe); - cn = win.body(window.document); - }else{ - // To capture these events at the top level, attach to <html>, not <body>. - // Otherwise right-click context menu just doesn't work. - cn = (node == win.body(this.ownerDocument) ? this.ownerDocument.documentElement : node); - } - - - // "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode()) - var binding = { - node: node, - iframe: iframe - }; - - // Save info about binding in _bindings[], and make node itself record index(+1) into - // _bindings[] array. Prefix w/_dijitMenu to avoid setting an attribute that may - // start with a number, which fails on FF/safari. - domAttr.set(node, "_dijitMenu" + this.id, this._bindings.push(binding)); - - // Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished - // loading yet, in which case we need to wait for the onload event first, and then connect - // On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so - // we need to monitor keyboard events in addition to the oncontextmenu event. - var doConnects = lang.hitch(this, function(cn){ - var selector = this.selector, - delegatedEvent = selector ? - function(eventType){ return on.selector(selector, eventType); } : - function(eventType){ return eventType; }, - self = this; - return [ - // TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu, - // rather than shift-F10? - on(cn, delegatedEvent(this.leftClickToOpen ? "click" : "contextmenu"), function(evt){ - // Schedule context menu to be opened unless it's already been scheduled from onkeydown handler - event.stop(evt); - self._scheduleOpen(this, iframe, {x: evt.pageX, y: evt.pageY}); - }), - on(cn, delegatedEvent("keydown"), function(evt){ - if(evt.shiftKey && evt.keyCode == keys.F10){ - event.stop(evt); - self._scheduleOpen(this, iframe); // no coords - open near target node - } - }) - ]; - }); - binding.connects = cn ? doConnects(cn) : []; - - if(iframe){ - // Setup handler to [re]bind to the iframe when the contents are initially loaded, - // and every time the contents change. - // Need to do this b/c we are actually binding to the iframe's <body> node. - // Note: can't use connect.connect(), see #9609. - - binding.onloadHandler = lang.hitch(this, function(){ - // want to remove old connections, but IE throws exceptions when trying to - // access the <body> node because it's already gone, or at least in a state of limbo - - var window = this._iframeContentWindow(iframe); - cn = win.body(window.document) - binding.connects = doConnects(cn); - }); - if(iframe.addEventListener){ - iframe.addEventListener("load", binding.onloadHandler, false); - }else{ - iframe.attachEvent("onload", binding.onloadHandler); - } - } - }, - - unBindDomNode: function(/*String|DomNode*/ nodeName){ - // summary: - // Detach menu from given node - - var node; - try{ - node = dom.byId(nodeName, this.ownerDocument); - }catch(e){ - // On IE the dom.byId() call will get an exception if the attach point was - // the <body> node of an <iframe> that has since been reloaded (and thus the - // <body> node is in a limbo state of destruction. - return; - } - - // node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array - var attrName = "_dijitMenu" + this.id; - if(node && domAttr.has(node, attrName)){ - var bid = domAttr.get(node, attrName)-1, b = this._bindings[bid], h; - while((h = b.connects.pop())){ - h.remove(); - } - - // Remove listener for iframe onload events - var iframe = b.iframe; - if(iframe){ - if(iframe.removeEventListener){ - iframe.removeEventListener("load", b.onloadHandler, false); - }else{ - iframe.detachEvent("onload", b.onloadHandler); - } - } - - domAttr.remove(node, attrName); - delete this._bindings[bid]; - } - }, - - _scheduleOpen: function(/*DomNode?*/ target, /*DomNode?*/ iframe, /*Object?*/ coords){ - // summary: - // Set timer to display myself. Using a timer rather than displaying immediately solves - // two problems: - // - // 1. IE: without the delay, focus work in "open" causes the system - // context menu to appear in spite of stopEvent. - // - // 2. Avoid double-shows on linux, where shift-F10 generates an oncontextmenu event - // even after a event.stop(e). (Shift-F10 on windows doesn't generate the - // oncontextmenu event.) - - if(!this._openTimer){ - this._openTimer = this.defer(function(){ - delete this._openTimer; - this._openMyself({ - target: target, - iframe: iframe, - coords: coords - }); - }, 1); - } - }, - - _openMyself: function(args){ - // summary: - // Internal function for opening myself when the user does a right-click or something similar. - // args: - // This is an Object containing: - // - // - target: The node that is being clicked - // - iframe: If an `<iframe>` is being clicked, iframe points to that iframe - // - coords: Put menu at specified x/y position in viewport, or if iframe is - // specified, then relative to iframe. - // - // _openMyself() formerly took the event object, and since various code references - // evt.target (after connecting to _openMyself()), using an Object for parameters - // (so that old code still works). - - var target = args.target, - iframe = args.iframe, - coords = args.coords; - - // To be used by MenuItem event handlers to tell which node the menu was opened on - this.currentTarget = target; - - // Get coordinates to open menu, either at specified (mouse) position or (if triggered via keyboard) - // then near the node the menu is assigned to. - if(coords){ - if(iframe){ - // Specified coordinates are on <body> node of an <iframe>, convert to match main document - var ifc = domGeometry.position(iframe, true), - window = this._iframeContentWindow(iframe), - scroll = domGeometry.docScroll(window.document); - - var cs = domStyle.getComputedStyle(iframe), - tp = domStyle.toPixelValue, - left = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingLeft)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderLeftWidth) : 0), - top = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingTop)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderTopWidth) : 0); - - coords.x += ifc.x + left - scroll.x; - coords.y += ifc.y + top - scroll.y; - } - }else{ - coords = domGeometry.position(target, true); - coords.x += 10; - coords.y += 10; - } - - var self=this; - var prevFocusNode = this._focusManager.get("prevNode"); - var curFocusNode = this._focusManager.get("curNode"); - var savedFocusNode = !curFocusNode || (dom.isDescendant(curFocusNode, this.domNode)) ? prevFocusNode : curFocusNode; - - function closeAndRestoreFocus(){ - // user has clicked on a menu or popup - if(self.refocus && savedFocusNode){ - savedFocusNode.focus(); - } - pm.close(self); - } - pm.open({ - popup: this, - x: coords.x, - y: coords.y, - onExecute: closeAndRestoreFocus, - onCancel: closeAndRestoreFocus, - orient: this.isLeftToRight() ? 'L' : 'R' - }); - this.focus(); - - this._onBlur = function(){ - this.inherited('_onBlur', arguments); - // Usually the parent closes the child widget but if this is a context - // menu then there is no parent - pm.close(this); - // don't try to restore focus; user has clicked another part of the screen - // and set focus there - }; - }, - - destroy: function(){ - array.forEach(this._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this); - this.inherited(arguments); - } -}); - -}); - -}, -'dijit/form/_CheckBoxMixin':function(){ -define("dijit/form/_CheckBoxMixin", [ - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/_base/event" // event.stop -], function(declare, domAttr, event){ - - // module: - // dijit/form/_CheckBoxMixin - - return declare("dijit.form._CheckBoxMixin", null, { - // summary: - // Mixin to provide widget functionality corresponding to an HTML checkbox - // - // description: - // User interacts with real html inputs. - // On onclick (which occurs by mouse click, space-bar, or - // using the arrow keys to switch the selected radio button), - // we update the state of the checkbox/radio. - // - - // type: [private] String - // type attribute on `<input>` node. - // Overrides `dijit/form/Button.type`. Users should not change this value. - type: "checkbox", - - // value: String - // As an initialization parameter, equivalent to value field on normal checkbox - // (if checked, the value is passed as the value when form is submitted). - value: "on", - - // readOnly: Boolean - // Should this widget respond to user input? - // In markup, this is specified as "readOnly". - // Similar to disabled except readOnly form values are submitted. - readOnly: false, - - // aria-pressed for toggle buttons, and aria-checked for checkboxes - _aria_attr: "aria-checked", - - _setReadOnlyAttr: function(/*Boolean*/ value){ - this._set("readOnly", value); - domAttr.set(this.focusNode, 'readOnly', value); - }, - - // Override dijit/form/Button._setLabelAttr() since we don't even have a containerNode. - // Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox/layout/TabContainer - _setLabelAttr: undefined, - - _getSubmitValue: function(/*String*/ value){ - return !value && value !== 0 ? "on" : value; - }, - - _setValueAttr: function(newValue){ - newValue = this._getSubmitValue(newValue); // "on" to match browser native behavior when value unspecified - this._set("value", newValue); - domAttr.set(this.focusNode, "value", newValue); - }, - - reset: function(){ - this.inherited(arguments); - // Handle unlikely event that the <input type=checkbox> value attribute has changed - this._set("value", this.params.value || "on"); - domAttr.set(this.focusNode, 'value', this.value); - }, - - _onClick: function(/*Event*/ e){ - // summary: - // Internal function to handle click actions - need to check - // readOnly, since button no longer does that check. - if(this.readOnly){ - event.stop(e); - return false; - } - return this.inherited(arguments); - } - }); -}); - -}, -'dijit/layout/ContentPane':function(){ -define("dijit/layout/ContentPane", [ - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.mixin lang.delegate lang.hitch lang.isFunction lang.isObject - "../_Widget", - "../_Container", - "./_ContentPaneResizeMixin", - "dojo/string", // string.substitute - "dojo/html", // html._ContentSetter - "dojo/i18n!../nls/loading", - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/_base/Deferred", // Deferred - "dojo/dom", // dom.byId - "dojo/dom-attr", // domAttr.attr - "dojo/dom-construct", // empty() - "dojo/_base/xhr", // xhr.get - "dojo/i18n", // i18n.getLocalization - "dojo/when" -], function(kernel, lang, _Widget, _Container, _ContentPaneResizeMixin, string, html, nlsLoading, - array, declare, Deferred, dom, domAttr, domConstruct, xhr, i18n, when){ - -// module: -// dijit/layout/ContentPane - - -return declare("dijit.layout.ContentPane", [_Widget, _Container, _ContentPaneResizeMixin], { - // summary: - // A widget containing an HTML fragment, specified inline - // or by uri. Fragment may include widgets. - // - // description: - // This widget embeds a document fragment in the page, specified - // either by uri, javascript generated markup or DOM reference. - // Any widgets within this content are instantiated and managed, - // but laid out according to the HTML structure. Unlike IFRAME, - // ContentPane embeds a document fragment as would be found - // inside the BODY tag of a full HTML document. It should not - // contain the HTML, HEAD, or BODY tags. - // For more advanced functionality with scripts and - // stylesheets, see dojox/layout/ContentPane. This widget may be - // used stand alone or as a base class for other widgets. - // ContentPane is useful as a child of other layout containers - // such as BorderContainer or TabContainer, but note that those - // widgets can contain any widget as a child. - // - // example: - // Some quick samples: - // To change the innerHTML: - // | cp.set('content', '<b>new content</b>')` - // Or you can send it a NodeList: - // | cp.set('content', dojo.query('div [class=selected]', userSelection)) - // To do an ajax update: - // | cp.set('href', url) - - // href: String - // The href of the content that displays now. - // Set this at construction if you want to load data externally when the - // pane is shown. (Set preload=true to load it immediately.) - // Changing href after creation doesn't have any effect; Use set('href', ...); - href: "", - - // content: String|DomNode|NodeList|dijit/_Widget - // The innerHTML of the ContentPane. - // Note that the initialization parameter / argument to set("content", ...) - // can be a String, DomNode, Nodelist, or _Widget. - content: "", - - // extractContent: Boolean - // Extract visible content from inside of `<body> .... </body>`. - // I.e., strip `<html>` and `<head>` (and it's contents) from the href - extractContent: false, - - // parseOnLoad: Boolean - // Parse content and create the widgets, if any. - parseOnLoad: true, - - // parserScope: String - // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo, - // will search for data-dojo-type (or dojoType). For backwards compatibility - // reasons defaults to dojo._scopeName (which is "dojo" except when - // multi-version support is used, when it will be something like dojo16, dojo20, etc.) - parserScope: kernel._scopeName, - - // preventCache: Boolean - // Prevent caching of data from href's by appending a timestamp to the href. - preventCache: false, - - // preload: Boolean - // Force load of data on initialization even if pane is hidden. - preload: false, - - // refreshOnShow: Boolean - // Refresh (re-download) content when pane goes from hidden to shown - refreshOnShow: false, - - // loadingMessage: String - // Message that shows while downloading - loadingMessage: "<span class='dijitContentPaneLoading'><span class='dijitInline dijitIconLoading'></span>${loadingState}</span>", - - // errorMessage: String - // Message that shows if an error occurs - errorMessage: "<span class='dijitContentPaneError'><span class='dijitInline dijitIconError'></span>${errorState}</span>", - - // isLoaded: [readonly] Boolean - // True if the ContentPane has data in it, either specified - // during initialization (via href or inline content), or set - // via set('content', ...) / set('href', ...) - // - // False if it doesn't have any content, or if ContentPane is - // still in the process of downloading href. - isLoaded: false, - - baseClass: "dijitContentPane", - - /*====== - // ioMethod: dojo/_base/xhr.get|dojo._base/xhr.post - // Function that should grab the content specified via href. - ioMethod: dojo.xhrGet, - ======*/ - - // ioArgs: Object - // Parameters to pass to xhrGet() request, for example: - // | <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="href: './bar', ioArgs: {timeout: 500}"> - ioArgs: {}, - - // onLoadDeferred: [readonly] dojo.Deferred - // This is the `dojo.Deferred` returned by set('href', ...) and refresh(). - // Calling onLoadDeferred.then() registers your - // callback to be called only once, when the prior set('href', ...) call or - // the initial href parameter to the constructor finishes loading. - // - // This is different than an onLoad() handler which gets called any time any href - // or content is loaded. - onLoadDeferred: null, - - // Cancel _WidgetBase's _setTitleAttr because we don't want the title attribute (used to specify - // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the - // entire pane. - _setTitleAttr: null, - - // Flag to parser that I'll parse my contents, so it shouldn't. - stopParser: true, - - // template: [private] Boolean - // Flag from the parser that this ContentPane is inside a template - // so the contents are pre-parsed. - // TODO: this declaration can be commented out in 2.0 - template: false, - - create: function(params, srcNodeRef){ - // Convert a srcNodeRef argument into a content parameter, so that the original contents are - // processed in the same way as contents set via set("content", ...), calling the parser etc. - // Avoid modifying original params object since that breaks NodeList instantiation, see #11906. - if((!params || !params.template) && srcNodeRef && !("href" in params) && !("content" in params)){ - srcNodeRef = dom.byId(srcNodeRef); - var df = srcNodeRef.ownerDocument.createDocumentFragment(); - while(srcNodeRef.firstChild){ - df.appendChild(srcNodeRef.firstChild); - } - params = lang.delegate(params, {content: df}); - } - this.inherited(arguments, [params, srcNodeRef]); - }, - - postMixInProperties: function(){ - this.inherited(arguments); - var messages = i18n.getLocalization("dijit", "loading", this.lang); - this.loadingMessage = string.substitute(this.loadingMessage, messages); - this.errorMessage = string.substitute(this.errorMessage, messages); - }, - - buildRendering: function(){ - this.inherited(arguments); - - // Since we have no template we need to set this.containerNode ourselves, to make getChildren() work. - // For subclasses of ContentPane that do have a template, does nothing. - if(!this.containerNode){ - this.containerNode = this.domNode; - } - - // remove the title attribute so it doesn't show up when hovering - // over a node (TODO: remove in 2.0, no longer needed after #11490) - this.domNode.title = ""; - - if(!domAttr.get(this.domNode,"role")){ - this.domNode.setAttribute("role", "group"); - } - }, - - startup: function(){ - // summary: - // Call startup() on all children including non _Widget ones like dojo/dnd/Source objects - - // This starts all the widgets - this.inherited(arguments); - - // And this catches stuff like dojo/dnd/Source - if(this._contentSetter){ - array.forEach(this._contentSetter.parseResults, function(obj){ - if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ - obj.startup(); - obj._started = true; - } - }, this); - } - }, - - _startChildren: function(){ - // summary: - // Called when content is loaded. Calls startup on each child widget. Similar to ContentPane.startup() - // itself, but avoids marking the ContentPane itself as "restarted" (see #15581). - - // This starts all the widgets - array.forEach(this.getChildren(), function(obj){ - if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ - obj.startup(); - obj._started = true; - } - }); - - // And this catches stuff like dojo/dnd/Source - if(this._contentSetter){ - array.forEach(this._contentSetter.parseResults, function(obj){ - if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){ - obj.startup(); - obj._started = true; - } - }, this); - } - }, - - setHref: function(/*String|Uri*/ href){ - // summary: - // Deprecated. Use set('href', ...) instead. - kernel.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0"); - return this.set("href", href); - }, - _setHrefAttr: function(/*String|Uri*/ href){ - // summary: - // Hook so set("href", ...) works. - // description: - // Reset the (external defined) content of this pane and replace with new url - // Note: It delays the download until widget is shown if preload is false. - // href: - // url to the page you want to get, must be within the same domain as your mainpage - - // Cancel any in-flight requests (a set('href', ...) will cancel any in-flight set('href', ...)) - this.cancel(); - - this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); - this.onLoadDeferred.then(lang.hitch(this, "onLoad")); - - this._set("href", href); - - // _setHrefAttr() is called during creation and by the user, after creation. - // Assuming preload == false, only in the second case do we actually load the URL; - // otherwise it's done in startup(), and only if this widget is shown. - if(this.preload || (this._created && this._isShown())){ - this._load(); - }else{ - // Set flag to indicate that href needs to be loaded the next time the - // ContentPane is made visible - this._hrefChanged = true; - } - - return this.onLoadDeferred; // Deferred - }, - - setContent: function(/*String|DomNode|Nodelist*/data){ - // summary: - // Deprecated. Use set('content', ...) instead. - kernel.deprecated("dijit.layout.ContentPane.setContent() is deprecated. Use set('content', ...) instead.", "", "2.0"); - this.set("content", data); - }, - _setContentAttr: function(/*String|DomNode|Nodelist*/data){ - // summary: - // Hook to make set("content", ...) work. - // Replaces old content with data content, include style classes from old content - // data: - // the new Content may be String, DomNode or NodeList - // - // if data is a NodeList (or an array of nodes) nodes are copied - // so you can import nodes from another document implicitly - - // clear href so we can't run refresh and clear content - // refresh should only work if we downloaded the content - this._set("href", ""); - - // Cancel any in-flight requests (a set('content', ...) will cancel any in-flight set('href', ...)) - this.cancel(); - - // Even though user is just setting content directly, still need to define an onLoadDeferred - // because the _onLoadHandler() handler is still getting called from setContent() - this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); - if(this._created){ - // For back-compat reasons, call onLoad() for set('content', ...) - // calls but not for content specified in srcNodeRef (ie: <div data-dojo-type=ContentPane>...</div>) - // or as initialization parameter (ie: new ContentPane({content: ...}) - this.onLoadDeferred.then(lang.hitch(this, "onLoad")); - } - - this._setContent(data || ""); - - this._isDownloaded = false; // mark that content is from a set('content') not a set('href') - - return this.onLoadDeferred; // Deferred - }, - _getContentAttr: function(){ - // summary: - // Hook to make get("content") work - return this.containerNode.innerHTML; - }, - - cancel: function(){ - // summary: - // Cancels an in-flight download of content - if(this._xhrDfd && (this._xhrDfd.fired == -1)){ - this._xhrDfd.cancel(); - } - delete this._xhrDfd; // garbage collect - - this.onLoadDeferred = null; - }, - - destroy: function(){ - this.cancel(); - this.inherited(arguments); - }, - - destroyRecursive: function(/*Boolean*/ preserveDom){ - // summary: - // Destroy the ContentPane and its contents - - // if we have multiple controllers destroying us, bail after the first - if(this._beingDestroyed){ - return; - } - this.inherited(arguments); - }, - - _onShow: function(){ - // summary: - // Called when the ContentPane is made visible - // description: - // For a plain ContentPane, this is called on initialization, from startup(). - // If the ContentPane is a hidden pane of a TabContainer etc., then it's - // called whenever the pane is made visible. - // - // Does necessary processing, including href download and layout/resize of - // child widget(s) - - this.inherited(arguments); - - if(this.href){ - if(!this._xhrDfd && // if there's an href that isn't already being loaded - (!this.isLoaded || this._hrefChanged || this.refreshOnShow) - ){ - return this.refresh(); // If child has an href, promise that fires when the load is complete - } - } - }, - - refresh: function(){ - // summary: - // [Re]download contents of href and display - // description: - // 1. cancels any currently in-flight requests - // 2. posts "loading..." message - // 3. sends XHR to download new data - - // Cancel possible prior in-flight request - this.cancel(); - - this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel")); - this.onLoadDeferred.then(lang.hitch(this, "onLoad")); - this._load(); - return this.onLoadDeferred; // If child has an href, promise that fires when refresh is complete - }, - - _load: function(){ - // summary: - // Load/reload the href specified in this.href - - // display loading message - this._setContent(this.onDownloadStart(), true); - - var self = this; - var getArgs = { - preventCache: (this.preventCache || this.refreshOnShow), - url: this.href, - handleAs: "text" - }; - if(lang.isObject(this.ioArgs)){ - lang.mixin(getArgs, this.ioArgs); - } - - var hand = (this._xhrDfd = (this.ioMethod || xhr.get)(getArgs)), - returnedHtml; - - hand.then( - function(html){ - returnedHtml = html; - try{ - self._isDownloaded = true; - return self._setContent(html, false); - }catch(err){ - self._onError('Content', err); // onContentError - } - }, - function(err){ - if(!hand.canceled){ - // show error message in the pane - self._onError('Download', err); // onDownloadError - } - delete self._xhrDfd; - return err; - } - ).then(function(){ - self.onDownloadEnd(); - delete self._xhrDfd; - return returnedHtml; - }); - - // Remove flag saying that a load is needed - delete this._hrefChanged; - }, - - _onLoadHandler: function(data){ - // summary: - // This is called whenever new content is being loaded - this._set("isLoaded", true); - try{ - this.onLoadDeferred.resolve(data); - }catch(e){ - console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message); - } - }, - - _onUnloadHandler: function(){ - // summary: - // This is called whenever the content is being unloaded - this._set("isLoaded", false); - try{ - this.onUnload(); - }catch(e){ - console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message); - } - }, - - destroyDescendants: function(/*Boolean*/ preserveDom){ - // summary: - // Destroy all the widgets inside the ContentPane and empty containerNode - - // Make sure we call onUnload (but only when the ContentPane has real content) - if(this.isLoaded){ - this._onUnloadHandler(); - } - - // Even if this.isLoaded == false there might still be a "Loading..." message - // to erase, so continue... - - // For historical reasons we need to delete all widgets under this.containerNode, - // even ones that the user has created manually. - var setter = this._contentSetter; - array.forEach(this.getChildren(), function(widget){ - if(widget.destroyRecursive){ - // All widgets will hit this branch - widget.destroyRecursive(preserveDom); - }else if(widget.destroy){ - // Things like dojo/dnd/Source have destroy(), not destroyRecursive() - widget.destroy(preserveDom); - } - widget._destroyed = true; - }); - if(setter){ - // Most of the widgets in setter.parseResults have already been destroyed, but - // things like Menu that have been moved to <body> haven't yet - array.forEach(setter.parseResults, function(widget){ - if(!widget._destroyed){ - if(widget.destroyRecursive){ - // All widgets will hit this branch - widget.destroyRecursive(preserveDom); - }else if(widget.destroy){ - // Things like dojo/dnd/Source have destroy(), not destroyRecursive() - widget.destroy(preserveDom); - } - widget._destroyed = true; - } - }); - delete setter.parseResults; - } - - // And then clear away all the DOM nodes - if(!preserveDom){ - domConstruct.empty(this.containerNode); - } - - // Delete any state information we have about current contents - delete this._singleChild; - }, - - _setContent: function(/*String|DocumentFragment*/ cont, /*Boolean*/ isFakeContent){ - // summary: - // Insert the content into the container node - // returns: - // Returns a Deferred promise that is resolved when the content is parsed. - - // first get rid of child widgets - this.destroyDescendants(); - - // html.set will take care of the rest of the details - // we provide an override for the error handling to ensure the widget gets the errors - // configure the setter instance with only the relevant widget instance properties - // NOTE: unless we hook into attr, or provide property setters for each property, - // we need to re-configure the ContentSetter with each use - var setter = this._contentSetter; - if(! (setter && setter instanceof html._ContentSetter)){ - setter = this._contentSetter = new html._ContentSetter({ - node: this.containerNode, - _onError: lang.hitch(this, this._onError), - onContentError: lang.hitch(this, function(e){ - // fires if a domfault occurs when we are appending this.errorMessage - // like for instance if domNode is a UL and we try append a DIV - var errMess = this.onContentError(e); - try{ - this.containerNode.innerHTML = errMess; - }catch(e){ - console.error('Fatal '+this.id+' could not change content due to '+e.message, e); - } - })/*, - _onError */ - }); - } - - var setterParams = lang.mixin({ - cleanContent: this.cleanContent, - extractContent: this.extractContent, - parseContent: !cont.domNode && this.parseOnLoad, - parserScope: this.parserScope, - startup: false, - dir: this.dir, - lang: this.lang, - textDir: this.textDir - }, this._contentSetterParams || {}); - - var p = setter.set( (lang.isObject(cont) && cont.domNode) ? cont.domNode : cont, setterParams ); - - // dojox/layout/html/_base::_ContentSetter.set() returns a Promise that indicates when everything is completed. - // dojo/html::_ContentSetter.set() currently returns the DOMNode, but that will be changed for 2.0. - // So, if set() returns a promise then use it, otherwise fallback to waiting on setter.parseDeferred - var self = this; - return when(p && p.then ? p : setter.parseDeferred, function(){ - // setter params must be pulled afresh from the ContentPane each time - delete self._contentSetterParams; - - if(!isFakeContent){ - if(self._started){ - // Startup each top level child widget (and they will start their children, recursively) - self._startChildren(); - - // Call resize() on each of my child layout widgets, - // or resize() on my single child layout widget... - // either now (if I'm currently visible) or when I become visible - self._scheduleLayout(); - } - self._onLoadHandler(cont); - } - }); - }, - - _onError: function(type, err, consoleText){ - this.onLoadDeferred.reject(err); - - // shows user the string that is returned by on[type]Error - // override on[type]Error and return your own string to customize - var errText = this['on' + type + 'Error'].call(this, err); - if(consoleText){ - console.error(consoleText, err); - }else if(errText){// a empty string won't change current content - this._setContent(errText, true); - } - }, - - // EVENT's, should be overide-able - onLoad: function(/*===== data =====*/){ - // summary: - // Event hook, is called after everything is loaded and widgetified - // tags: - // callback - }, - - onUnload: function(){ - // summary: - // Event hook, is called before old content is cleared - // tags: - // callback - }, - - onDownloadStart: function(){ - // summary: - // Called before download starts. - // description: - // The string returned by this function will be the html - // that tells the user we are loading something. - // Override with your own function if you want to change text. - // tags: - // extension - return this.loadingMessage; - }, - - onContentError: function(/*Error*/ /*===== error =====*/){ - // summary: - // Called on DOM faults, require faults etc. in content. - // - // In order to display an error message in the pane, return - // the error message from this method, as an HTML string. - // - // By default (if this method is not overriden), it returns - // nothing, so the error message is just printed to the console. - // tags: - // extension - }, - - onDownloadError: function(/*Error*/ /*===== error =====*/){ - // summary: - // Called when download error occurs. - // - // In order to display an error message in the pane, return - // the error message from this method, as an HTML string. - // - // Default behavior (if this method is not overriden) is to display - // the error message inside the pane. - // tags: - // extension - return this.errorMessage; - }, - - onDownloadEnd: function(){ - // summary: - // Called when download is finished. - // tags: - // callback - } -}); - -}); - -}, -'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n", -'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n", -'dijit/_KeyNavContainer':function(){ -define("dijit/_KeyNavContainer", [ - "dojo/_base/kernel", // kernel.deprecated - "./_Container", - "./_FocusMixin", - "dojo/_base/array", // array.forEach - "dojo/keys", // keys.END keys.HOME - "dojo/_base/declare", // declare - "dojo/_base/event", // event.stop - "dojo/dom-attr", // domAttr.set - "dojo/_base/lang" // lang.hitch -], function(kernel, _Container, _FocusMixin, array, keys, declare, event, domAttr, lang){ - - - // module: - // dijit/_KeyNavContainer - - return declare("dijit._KeyNavContainer", [_FocusMixin, _Container], { - // summary: - // A _Container with keyboard navigation of its children. - // description: - // To use this mixin, call connectKeyNavHandlers() in - // postCreate(). - // It provides normalized keyboard and focusing code for Container - // widgets. - -/*===== - // focusedChild: [protected] Widget - // The currently focused child widget, or null if there isn't one - focusedChild: null, -=====*/ - - // tabIndex: String - // Tab index of the container; same as HTML tabIndex attribute. - // Note then when user tabs into the container, focus is immediately - // moved to the first item in the container. - tabIndex: "0", - - connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){ - // summary: - // Call in postCreate() to attach the keyboard handlers - // to the container. - // preKeyCodes: keys[] - // Key codes for navigating to the previous child. - // nextKeyCodes: keys[] - // Key codes for navigating to the next child. - // tags: - // protected - - // TODO: call this automatically from my own postCreate() - - var keyCodes = (this._keyNavCodes = {}); - var prev = lang.hitch(this, "focusPrev"); - var next = lang.hitch(this, "focusNext"); - array.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; }); - array.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; }); - keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild"); - keyCodes[keys.END] = lang.hitch(this, "focusLastChild"); - this.connect(this.domNode, "onkeypress", "_onContainerKeypress"); - this.connect(this.domNode, "onfocus", "_onContainerFocus"); - }, - - startupKeyNavChildren: function(){ - kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0"); - }, - - startup: function(){ - this.inherited(arguments); - array.forEach(this.getChildren(), lang.hitch(this, "_startupChild")); - }, - - addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){ - this.inherited(arguments); - this._startupChild(widget); - }, - - focus: function(){ - // summary: - // Default focus() implementation: focus the first child. - this.focusFirstChild(); - }, - - focusFirstChild: function(){ - // summary: - // Focus the first focusable child in the container. - // tags: - // protected - this.focusChild(this._getFirstFocusableChild()); - }, - - focusLastChild: function(){ - // summary: - // Focus the last focusable child in the container. - // tags: - // protected - this.focusChild(this._getLastFocusableChild()); - }, - - focusNext: function(){ - // summary: - // Focus the next widget - // tags: - // protected - this.focusChild(this._getNextFocusableChild(this.focusedChild, 1)); - }, - - focusPrev: function(){ - // summary: - // Focus the last focusable node in the previous widget - // (ex: go to the ComboButton icon section rather than button section) - // tags: - // protected - this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true); - }, - - focusChild: function(/*dijit/_WidgetBase*/ widget, /*Boolean*/ last){ - // summary: - // Focus specified child widget. - // widget: - // Reference to container's child widget - // last: - // If true and if widget has multiple focusable nodes, focus the - // last one instead of the first one - // tags: - // protected - - if(!widget){ return; } - - if(this.focusedChild && widget !== this.focusedChild){ - this._onChildBlur(this.focusedChild); // used by _MenuBase - } - widget.set("tabIndex", this.tabIndex); // for IE focus outline to appear, must set tabIndex before focs - widget.focus(last ? "end" : "start"); - this._set("focusedChild", widget); - }, - - _startupChild: function(/*dijit/_WidgetBase*/ widget){ - // summary: - // Setup for each child widget - // description: - // Sets tabIndex=-1 on each child, so that the tab key will - // leave the container rather than visiting each child. - // tags: - // private - - widget.set("tabIndex", "-1"); - - this.connect(widget, "_onFocus", function(){ - // Set valid tabIndex so tabbing away from widget goes to right place, see #10272 - widget.set("tabIndex", this.tabIndex); - }); - this.connect(widget, "_onBlur", function(){ - widget.set("tabIndex", "-1"); - }); - }, - - _onContainerFocus: function(evt){ - // summary: - // Handler for when the container gets focus - // description: - // Initially the container itself has a tabIndex, but when it gets - // focus, switch focus to first child... - // tags: - // private - - // Note that we can't use _onFocus() because switching focus from the - // _onFocus() handler confuses the focus.js code - // (because it causes _onFocusNode() to be called recursively) - // Also, _onFocus() would fire when focus went directly to a child widget due to mouse click. - - // Ignore spurious focus events: - // 1. focus on a child widget bubbles on FF - // 2. on IE, clicking the scrollbar of a select dropdown moves focus from the focused child item to me - if(evt.target !== this.domNode || this.focusedChild){ return; } - - this.focusFirstChild(); - - // and then set the container's tabIndex to -1, - // (don't remove as that breaks Safari 4) - // so that tab or shift-tab will go to the fields after/before - // the container, rather than the container itself - domAttr.set(this.domNode, "tabIndex", "-1"); - }, - - _onBlur: function(evt){ - // When focus is moved away the container, and its descendant (popup) widgets, - // then restore the container's tabIndex so that user can tab to it again. - // Note that using _onBlur() so that this doesn't happen when focus is shifted - // to one of my child widgets (typically a popup) - if(this.tabIndex){ - domAttr.set(this.domNode, "tabIndex", this.tabIndex); - } - this.focusedChild = null; - this.inherited(arguments); - }, - - _onContainerKeypress: function(evt){ - // summary: - // When a key is pressed, if it's an arrow key etc. then - // it's handled here. - // tags: - // private - if(evt.ctrlKey || evt.altKey){ return; } - var func = this._keyNavCodes[evt.charOrCode]; - if(func){ - func(); - event.stop(evt); - } - }, - - _onChildBlur: function(/*dijit/_WidgetBase*/ /*===== widget =====*/){ - // summary: - // Called when focus leaves a child widget to go - // to a sibling widget. - // Used by MenuBase.js (TODO: move code there) - // tags: - // protected - }, - - _getFirstFocusableChild: function(){ - // summary: - // Returns first child that can be focused - return this._getNextFocusableChild(null, 1); // dijit/_WidgetBase - }, - - _getLastFocusableChild: function(){ - // summary: - // Returns last child that can be focused - return this._getNextFocusableChild(null, -1); // dijit/_WidgetBase - }, - - _getNextFocusableChild: function(child, dir){ - // summary: - // Returns the next or previous focusable child, compared - // to "child" - // child: Widget - // The current widget - // dir: Integer - // - 1 = after - // - -1 = before - if(child){ - child = this._getSiblingOfChild(child, dir); - } - var children = this.getChildren(); - for(var i=0; i < children.length; i++){ - if(!child){ - child = children[(dir>0) ? 0 : (children.length-1)]; - } - if(child.isFocusable()){ - return child; // dijit/_WidgetBase - } - child = this._getSiblingOfChild(child, dir); - } - // no focusable child found - return null; // dijit/_WidgetBase - } - }); -}); - -}, -'dijit/layout/utils':function(){ -define("dijit/layout/utils", [ - "dojo/_base/array", // array.filter array.forEach - "dojo/dom-class", // domClass.add domClass.remove - "dojo/dom-geometry", // domGeometry.marginBox - "dojo/dom-style", // domStyle.getComputedStyle - "dojo/_base/lang", // lang.mixin - "../main" // for exporting symbols to dijit, remove in 2.0 -], function(array, domClass, domGeometry, domStyle, lang, dijit){ - - // module: - // dijit/layout/utils - - var layout = lang.getObject("layout", true, dijit); - /*===== - layout = { - // summary: - // marginBox2contentBox() and layoutChildren() - }; - =====*/ - - layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){ - // summary: - // Given the margin-box size of a node, return its content box size. - // Functions like domGeometry.contentBox() but is more reliable since it doesn't have - // to wait for the browser to compute sizes. - var cs = domStyle.getComputedStyle(node); - var me = domGeometry.getMarginExtents(node, cs); - var pb = domGeometry.getPadBorderExtents(node, cs); - return { - l: domStyle.toPixelValue(node, cs.paddingLeft), - t: domStyle.toPixelValue(node, cs.paddingTop), - w: mb.w - (me.w + pb.w), - h: mb.h - (me.h + pb.h) - }; - }; - - function capitalize(word){ - return word.substring(0,1).toUpperCase() + word.substring(1); - } - - function size(widget, dim){ - // size the child - var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim); - - // record child's size - if(newSize){ - // if the child returned it's new size then use that - lang.mixin(widget, newSize); - }else{ - // otherwise, call getMarginBox(), but favor our own numbers when we have them. - // the browser lies sometimes - lang.mixin(widget, domGeometry.getMarginBox(widget.domNode)); - lang.mixin(widget, dim); - } - } - - layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children, - /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){ - // summary: - // Layout a bunch of child dom nodes within a parent dom node - // container: - // parent node - // dim: - // {l, t, w, h} object specifying dimensions of container into which to place children - // children: - // An array of Widgets or at least objects containing: - // - // - domNode: pointer to DOM node to position - // - region or layoutAlign: position to place DOM node - // - resize(): (optional) method to set size of node - // - id: (optional) Id of widgets, referenced from resize object, below. - // changedRegionId: - // If specified, the slider for the region with the specified id has been dragged, and thus - // the region's height or width should be adjusted according to changedRegionSize - // changedRegionSize: - // See changedRegionId. - - // copy dim because we are going to modify it - dim = lang.mixin({}, dim); - - domClass.add(container, "dijitLayoutContainer"); - - // Move "client" elements to the end of the array for layout. a11y dictates that the author - // needs to be able to put them in the document in tab-order, but this algorithm requires that - // client be last. TODO: move these lines to LayoutContainer? Unneeded other places I think. - children = array.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; }) - .concat(array.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; })); - - // set positions/sizes - array.forEach(children, function(child){ - var elm = child.domNode, - pos = (child.region || child.layoutAlign); - if(!pos){ - throw new Error("No region setting for " + child.id) - } - - // set elem to upper left corner of unused space; may move it later - var elmStyle = elm.style; - elmStyle.left = dim.l+"px"; - elmStyle.top = dim.t+"px"; - elmStyle.position = "absolute"; - - domClass.add(elm, "dijitAlign" + capitalize(pos)); - - // Size adjustments to make to this child widget - var sizeSetting = {}; - - // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align - // panes and width adjustment for left/right align panes. - if(changedRegionId && changedRegionId == child.id){ - sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize; - } - - // set size && adjust record of remaining space. - // note that setting the width of a <div> may affect its height. - if(pos == "top" || pos == "bottom"){ - sizeSetting.w = dim.w; - size(child, sizeSetting); - dim.h -= child.h; - if(pos == "top"){ - dim.t += child.h; - }else{ - elmStyle.top = dim.t + dim.h + "px"; - } - }else if(pos == "left" || pos == "right"){ - sizeSetting.h = dim.h; - size(child, sizeSetting); - dim.w -= child.w; - if(pos == "left"){ - dim.l += child.w; - }else{ - elmStyle.left = dim.l + dim.w + "px"; - } - }else if(pos == "client" || pos == "center"){ - size(child, dim); - } - }); - }; - - - return { - marginBox2contentBox: layout.marginBox2contentBox, - layoutChildren: layout.layoutChildren - }; -}); - -}, -'dijit/_Contained':function(){ -define("dijit/_Contained", [ - "dojo/_base/declare", // declare - "./registry" // registry.getEnclosingWidget(), registry.byNode() -], function(declare, registry){ - - // module: - // dijit/_Contained - - return declare("dijit._Contained", null, { - // summary: - // Mixin for widgets that are children of a container widget - // - // example: - // | // make a basic custom widget that knows about it's parents - // | declare("my.customClass",[dijit._Widget,dijit._Contained],{}); - - _getSibling: function(/*String*/ which){ - // summary: - // Returns next or previous sibling - // which: - // Either "next" or "previous" - // tags: - // private - var node = this.domNode; - do{ - node = node[which+"Sibling"]; - }while(node && node.nodeType != 1); - return node && registry.byNode(node); // dijit/_WidgetBase - }, - - getPreviousSibling: function(){ - // summary: - // Returns null if this is the first child of the parent, - // otherwise returns the next element sibling to the "left". - - return this._getSibling("previous"); // dijit/_WidgetBase - }, - - getNextSibling: function(){ - // summary: - // Returns null if this is the last child of the parent, - // otherwise returns the next element sibling to the "right". - - return this._getSibling("next"); // dijit/_WidgetBase - }, - - getIndexInParent: function(){ - // summary: - // Returns the index of this widget within its container parent. - // It returns -1 if the parent does not exist, or if the parent - // is not a dijit._Container - - var p = this.getParent(); - if(!p || !p.getIndexOfChild){ - return -1; // int - } - return p.getIndexOfChild(this); // int - } - }); -}); - -}, -'dijit/form/DataList':function(){ -define("dijit/form/DataList", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.byId - "dojo/_base/lang", // lang.trim - "dojo/query", // query - "dojo/store/Memory", - "../registry" // registry.add registry.remove -], function(declare, dom, lang, query, MemoryStore, registry){ - - // module: - // dijit/form/DataList - - function toItem(/*DOMNode*/ option){ - // summary: - // Convert `<option>` node to hash - return { - id: option.value, - value: option.value, - name: lang.trim(option.innerText || option.textContent || '') - }; - } - - return declare("dijit.form.DataList", MemoryStore, { - // summary: - // Inefficient but small data store specialized for inlined data via OPTION tags - // - // description: - // Provides a store for inlined data like: - // - // | <datalist> - // | <option value="AL">Alabama</option> - // | ... - - constructor: function(params, srcNodeRef){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String - // Attach widget to this DOM node. - - // store pointer to original DOM tree - this.domNode = dom.byId(srcNodeRef); - - lang.mixin(this, params); - if(this.id){ - registry.add(this); // add to registry so it can be easily found by id - } - this.domNode.style.display = "none"; - - this.inherited(arguments, [{ - data: query("option", this.domNode).map(toItem) - }]); - }, - - destroy: function(){ - registry.remove(this.id); - }, - - fetchSelectedItem: function(){ - // summary: - // Get the option marked as selected, like `<option selected>`. - // Not part of dojo.data API. - var option = query("> option[selected]", this.domNode)[0] || query("> option", this.domNode)[0]; - return option && toItem(option); - } - }); -}); - -}, -'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"\n\t\t\t\trole=\"heading\" level=\"1\"></span>\n\t\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"-1\">\n\t\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t\t</span>\n\t</div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n", -'dijit/form/CheckBox':function(){ -require({cache:{ -'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" role=\"${type}\" aria-checked=\"false\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n"}}); -define("dijit/form/CheckBox", [ - "require", - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/has", // has("dijit-legacy-requires") - "dojo/query", // query - "dojo/ready", - "./ToggleButton", - "./_CheckBoxMixin", - "dojo/text!./templates/CheckBox.html", - "dojo/NodeList-dom" // NodeList.addClass/removeClass -], function(require, declare, domAttr, has, query, ready, ToggleButton, _CheckBoxMixin, template){ - - // module: - // dijit/form/CheckBox - - // Back compat w/1.6, remove for 2.0 - if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/form/RadioButton"]; - require(requires); // use indirection so modules not rolled into a build - }); - } - - return declare("dijit.form.CheckBox", [ToggleButton, _CheckBoxMixin], { - // summary: - // Same as an HTML checkbox, but with fancy styling. - // - // description: - // User interacts with real html inputs. - // On onclick (which occurs by mouse click, space-bar, or - // using the arrow keys to switch the selected radio button), - // we update the state of the checkbox/radio. - // - // There are two modes: - // - // 1. High contrast mode - // 2. Normal mode - // - // In case 1, the regular html inputs are shown and used by the user. - // In case 2, the regular html inputs are invisible but still used by - // the user. They are turned quasi-invisible and overlay the background-image. - - templateString: template, - - baseClass: "dijitCheckBox", - - _setValueAttr: function(/*String|Boolean*/ newValue, /*Boolean*/ priorityChange){ - // summary: - // Handler for value= attribute to constructor, and also calls to - // set('value', val). - // description: - // During initialization, just saves as attribute to the `<input type=checkbox>`. - // - // After initialization, - // when passed a boolean, controls whether or not the CheckBox is checked. - // If passed a string, changes the value attribute of the CheckBox (the one - // specified as "value" when the CheckBox was constructed - // (ex: `<input data-dojo-type="dijit/CheckBox" value="chicken">`). - // - // `widget.set('value', string)` will check the checkbox and change the value to the - // specified string. - // - // `widget.set('value', boolean)` will change the checked state. - - if(typeof newValue == "string"){ - this.inherited(arguments); - newValue = true; - } - if(this._created){ - this.set('checked', newValue, priorityChange); - } - }, - _getValueAttr: function(){ - // summary: - // Hook so get('value') works. - // description: - // If the CheckBox is checked, returns the value attribute. - // Otherwise returns false. - return (this.checked ? this.value : false); - }, - - // Override behavior from Button, since we don't have an iconNode - _setIconClassAttr: null, - - postMixInProperties: function(){ - this.inherited(arguments); - - // Need to set initial checked state as part of template, so that form submit works. - // domAttr.set(node, "checked", bool) doesn't work on IE until node has been attached - // to <body>, see #8666 - this.checkedAttrSetting = this.checked ? "checked" : ""; - }, - - _fillContent: function(){ - // Override Button::_fillContent() since it doesn't make sense for CheckBox, - // since CheckBox doesn't even have a container - }, - - _onFocus: function(){ - if(this.id){ - query("label[for='"+this.id+"']").addClass("dijitFocusedLabel"); - } - this.inherited(arguments); - }, - - _onBlur: function(){ - if(this.id){ - query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel"); - } - this.inherited(arguments); - } - }); -}); - -}, -'dijit/tree/_dndSelector':function(){ -define("dijit/tree/_dndSelector", [ - "dojo/_base/array", // array.filter array.forEach array.map - "dojo/_base/connect", // connect.isCopyKey - "dojo/_base/declare", // declare - "dojo/_base/Deferred", // Deferred - "dojo/_base/kernel", // global - "dojo/_base/lang", // lang.hitch - "dojo/cookie", // cookie - "dojo/mouse", // mouse.isLeft - "dojo/on", - "dojo/touch", - "./_dndContainer" -], function(array, connect, declare, Deferred, kernel, lang, cookie, mouse, on, touch, _dndContainer){ - - // module: - // dijit/tree/_dndSelector - - - return declare("dijit.tree._dndSelector", _dndContainer, { - // summary: - // This is a base class for `dijit/tree/dndSource` , and isn't meant to be used directly. - // It's based on `dojo/dnd/Selector`. - // tags: - // protected - - /*===== - // selection: Object - // (id to DomNode) map for every TreeNode that's currently selected. - // The DOMNode is the TreeNode.rowNode. - selection: {}, - =====*/ - - constructor: function(){ - // summary: - // Initialization - // tags: - // private - - this.selection={}; - this.anchor = null; - - if(!this.cookieName && this.tree.id){ - this.cookieName = this.tree.id + "SaveSelectedCookie"; - } - - this.events.push( - on(this.tree.domNode, touch.press, lang.hitch(this,"onMouseDown")), - on(this.tree.domNode, touch.release, lang.hitch(this,"onMouseUp")), - on(this.tree.domNode, touch.move, lang.hitch(this,"onMouseMove")) - ); - }, - - // singular: Boolean - // Allows selection of only one element, if true. - // Tree hasn't been tested in singular=true mode, unclear if it works. - singular: false, - - // methods - getSelectedTreeNodes: function(){ - // summary: - // Returns a list of selected node(s). - // Used by dndSource on the start of a drag. - // tags: - // protected - var nodes=[], sel = this.selection; - for(var i in sel){ - nodes.push(sel[i]); - } - return nodes; - }, - - selectNone: function(){ - // summary: - // Unselects all items - // tags: - // private - - this.setSelection([]); - return this; // self - }, - - destroy: function(){ - // summary: - // Prepares the object to be garbage-collected - this.inherited(arguments); - this.selection = this.anchor = null; - }, - addTreeNode: function(/*dijit/Tree._TreeNode*/ node, /*Boolean?*/isAnchor){ - // summary: - // add node to current selection - // node: Node - // node to add - // isAnchor: Boolean - // Whether the node should become anchor. - - this.setSelection(this.getSelectedTreeNodes().concat( [node] )); - if(isAnchor){ this.anchor = node; } - return node; - }, - removeTreeNode: function(/*dijit/Tree._TreeNode*/ node){ - // summary: - // remove node from current selection - // node: Node - // node to remove - this.setSelection(this._setDifference(this.getSelectedTreeNodes(), [node])); - return node; - }, - isTreeNodeSelected: function(/*dijit/Tree._TreeNode*/ node){ - // summary: - // return true if node is currently selected - // node: Node - // the node to check whether it's in the current selection - - return node.id && !!this.selection[node.id]; - }, - setSelection: function(/*dijit/Tree._TreeNode[]*/ newSelection){ - // summary: - // set the list of selected nodes to be exactly newSelection. All changes to the - // selection should be passed through this function, which ensures that derived - // attributes are kept up to date. Anchor will be deleted if it has been removed - // from the selection, but no new anchor will be added by this function. - // newSelection: Node[] - // list of tree nodes to make selected - var oldSelection = this.getSelectedTreeNodes(); - array.forEach(this._setDifference(oldSelection, newSelection), lang.hitch(this, function(node){ - node.setSelected(false); - if(this.anchor == node){ - delete this.anchor; - } - delete this.selection[node.id]; - })); - array.forEach(this._setDifference(newSelection, oldSelection), lang.hitch(this, function(node){ - node.setSelected(true); - this.selection[node.id] = node; - })); - this._updateSelectionProperties(); - }, - _setDifference: function(xs,ys){ - // summary: - // Returns a copy of xs which lacks any objects - // occurring in ys. Checks for membership by - // modifying and then reading the object, so it will - // not properly handle sets of numbers or strings. - - array.forEach(ys, function(y){ y.__exclude__ = true; }); - var ret = array.filter(xs, function(x){ return !x.__exclude__; }); - - // clean up after ourselves. - array.forEach(ys, function(y){ delete y['__exclude__'] }); - return ret; - }, - _updateSelectionProperties: function(){ - // summary: - // Update the following tree properties from the current selection: - // path[s], selectedItem[s], selectedNode[s] - - var selected = this.getSelectedTreeNodes(); - var paths = [], nodes = [], selects = []; - array.forEach(selected, function(node){ - var ary = node.getTreePath(), model = this.tree.model; - nodes.push(node); - paths.push(ary); - ary = array.map(ary, function(item){ - return model.getIdentity(item); - }, this); - selects.push(ary.join("/")) - }, this); - var items = array.map(nodes,function(node){ return node.item; }); - this.tree._set("paths", paths); - this.tree._set("path", paths[0] || []); - this.tree._set("selectedNodes", nodes); - this.tree._set("selectedNode", nodes[0] || null); - this.tree._set("selectedItems", items); - this.tree._set("selectedItem", items[0] || null); - if (this.tree.persist && selects.length > 0) { - cookie(this.cookieName, selects.join(","), {expires:365}); - } - }, - _getSavedPaths: function(){ - // summary: - // Returns paths of nodes that were selected previously and saved in the cookie. - - var tree = this.tree; - if(tree.persist && tree.dndController.cookieName){ - var oreo, paths = []; - oreo = cookie(tree.dndController.cookieName); - if(oreo){ - paths = array.map(oreo.split(","), function(path){ - return path.split("/"); - }) - } - return paths; - } - }, - // mouse events - onMouseDown: function(e){ - // summary: - // Event processor for onmousedown/ontouchstart - // e: Event - // onmousedown/ontouchstart event - // tags: - // protected - - // ignore click on expando node - if(!this.current || this.tree.isExpandoNode(e.target, this.current)){ return; } - - if(mouse.isLeft(e)){ - // Prevent text selection while dragging on desktop, see #16328. But don't call preventDefault() - // for mobile because it will break things completely, see #15838. - e.preventDefault(); - }else if(e.type != "touchstart"){ - // Ignore right click - return; - } - - var treeNode = this.current, - copy = connect.isCopyKey(e), id = treeNode.id; - - // if shift key is not pressed, and the node is already in the selection, - // delay deselection until onmouseup so in the case of DND, deselection - // will be canceled by onmousemove. - if(!this.singular && !e.shiftKey && this.selection[id]){ - this._doDeselect = true; - return; - }else{ - this._doDeselect = false; - } - this.userSelect(treeNode, copy, e.shiftKey); - }, - - onMouseUp: function(e){ - // summary: - // Event processor for onmouseup/ontouchend - // e: Event - // onmouseup/ontouchend event - // tags: - // protected - - // _doDeselect is the flag to indicate that the user wants to either ctrl+click on - // a already selected item (to deselect the item), or click on a not-yet selected item - // (which should remove all current selection, and add the clicked item). This can not - // be done in onMouseDown, because the user may start a drag after mousedown. By moving - // the deselection logic here, the user can drags an already selected item. - if(!this._doDeselect){ return; } - this._doDeselect = false; - this.userSelect(this.current, connect.isCopyKey(e), e.shiftKey); - }, - onMouseMove: function(/*===== e =====*/){ - // summary: - // event processor for onmousemove/ontouchmove - // e: Event - // onmousemove/ontouchmove event - this._doDeselect = false; - }, - - _compareNodes: function(n1, n2){ - if(n1 === n2){ - return 0; - } - - if('sourceIndex' in document.documentElement){ //IE - //TODO: does not yet work if n1 and/or n2 is a text node - return n1.sourceIndex - n2.sourceIndex; - }else if('compareDocumentPosition' in document.documentElement){ //FF, Opera - return n1.compareDocumentPosition(n2) & 2 ? 1: -1; - }else if(document.createRange){ //Webkit - var r1 = doc.createRange(); - r1.setStartBefore(n1); - - var r2 = doc.createRange(); - r2.setStartBefore(n2); - - return r1.compareBoundaryPoints(r1.END_TO_END, r2); - }else{ - throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser"); - } - }, - - userSelect: function(node, multi, range){ - // summary: - // Add or remove the given node from selection, responding - // to a user action such as a click or keypress. - // multi: Boolean - // Indicates whether this is meant to be a multi-select action (e.g. ctrl-click) - // range: Boolean - // Indicates whether this is meant to be a ranged action (e.g. shift-click) - // tags: - // protected - - if(this.singular){ - if(this.anchor == node && multi){ - this.selectNone(); - }else{ - this.setSelection([node]); - this.anchor = node; - } - }else{ - if(range && this.anchor){ - var cr = this._compareNodes(this.anchor.rowNode, node.rowNode), - begin, end, anchor = this.anchor; - - if(cr < 0){ //current is after anchor - begin = anchor; - end = node; - }else{ //current is before anchor - begin = node; - end = anchor; - } - var nodes = []; - //add everything betweeen begin and end inclusively - while(begin != end){ - nodes.push(begin); - begin = this.tree._getNextNode(begin); - } - nodes.push(end); - - this.setSelection(nodes); - }else{ - if( this.selection[ node.id ] && multi ){ - this.removeTreeNode( node ); - }else if(multi){ - this.addTreeNode(node, true); - }else{ - this.setSelection([node]); - this.anchor = node; - } - } - } - }, - - getItem: function(/*String*/ key){ - // summary: - // Returns the dojo/dnd/Container._Item (representing a dragged node) by it's key (id). - // Called by dojo/dnd/Source.checkAcceptance(). - // tags: - // protected - - var widget = this.selection[key]; - return { - data: widget, - type: ["treeNode"] - }; // dojo/dnd/Container._Item - }, - - forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){ - // summary: - // Iterates over selected items; - // see `dojo/dnd/Container.forInItems()` for details - o = o || kernel.global; - for(var id in this.selection){ - // console.log("selected item id: " + id); - f.call(o, this.getItem(id), id, this); - } - } - }); -}); - -}, -'dijit/_Container':function(){ -define("dijit/_Container", [ - "dojo/_base/array", // array.forEach array.indexOf - "dojo/_base/declare", // declare - "dojo/dom-construct" // domConstruct.place -], function(array, declare, domConstruct){ - - // module: - // dijit/_Container - - return declare("dijit._Container", null, { - // summary: - // Mixin for widgets that contain HTML and/or a set of widget children. - - buildRendering: function(){ - this.inherited(arguments); - if(!this.containerNode){ - // all widgets with descendants must set containerNode - this.containerNode = this.domNode; - } - }, - - addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){ - // summary: - // Makes the given widget a child of this widget. - // description: - // Inserts specified child widget's dom node as a child of this widget's - // container node, and possibly does other processing (such as layout). - // - // Functionality is undefined if this widget contains anything besides - // a list of child widgets (ie, if it contains arbitrary non-widget HTML). - - var refNode = this.containerNode; - if(insertIndex && typeof insertIndex == "number"){ - var children = this.getChildren(); - if(children && children.length >= insertIndex){ - refNode = children[insertIndex-1].domNode; - insertIndex = "after"; - } - } - domConstruct.place(widget.domNode, refNode, insertIndex); - - // If I've been started but the child widget hasn't been started, - // start it now. Make sure to do this after widget has been - // inserted into the DOM tree, so it can see that it's being controlled by me, - // so it doesn't try to size itself. - if(this._started && !widget._started){ - widget.startup(); - } - }, - - removeChild: function(/*Widget|int*/ widget){ - // summary: - // Removes the passed widget instance from this widget but does - // not destroy it. You can also pass in an integer indicating - // the index within the container to remove (ie, removeChild(5) removes the sixth widget). - - if(typeof widget == "number"){ - widget = this.getChildren()[widget]; - } - - if(widget){ - var node = widget.domNode; - if(node && node.parentNode){ - node.parentNode.removeChild(node); // detach but don't destroy - } - } - }, - - hasChildren: function(){ - // summary: - // Returns true if widget has child widgets, i.e. if this.containerNode contains widgets. - return this.getChildren().length > 0; // Boolean - }, - - _getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){ - // summary: - // Get the next or previous widget sibling of child - // dir: - // if 1, get the next sibling - // if -1, get the previous sibling - // tags: - // private - var children = this.getChildren(), - idx = array.indexOf(this.getChildren(), child); // int - return children[idx + dir]; - }, - - getIndexOfChild: function(/*dijit/_WidgetBase*/ child){ - // summary: - // Gets the index of the child in this container or -1 if not found - return array.indexOf(this.getChildren(), child); // int - } - }); -}); - -}, -'dojo/data/ItemFileReadStore':function(){ -define("dojo/data/ItemFileReadStore", ["../_base/kernel", "../_base/lang", "../_base/declare", "../_base/array", "../_base/xhr", - "../Evented", "./util/filter", "./util/simpleFetch", "../date/stamp" -], function(kernel, lang, declare, array, xhr, Evented, filterUtil, simpleFetch, dateStamp){ - -// module: -// dojo/data/ItemFileReadStore - -var ItemFileReadStore = declare("dojo.data.ItemFileReadStore", [Evented],{ - // summary: - // The ItemFileReadStore implements the dojo/data/api/Read API and reads - // data from JSON files that have contents in this format -- - // | { items: [ - // | { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]}, - // | { name:'Fozzie Bear', wears:['hat', 'tie']}, - // | { name:'Miss Piggy', pets:'Foo-Foo'} - // | ]} - // Note that it can also contain an 'identifier' property that specified which attribute on the items - // in the array of items that acts as the unique identifier for that item. - - constructor: function(/* Object */ keywordParameters){ - // summary: - // constructor - // keywordParameters: - // {url: String} {data: jsonObject} {typeMap: object} - // The structure of the typeMap object is as follows: - // | { - // | type0: function || object, - // | type1: function || object, - // | ... - // | typeN: function || object - // | } - // Where if it is a function, it is assumed to be an object constructor that takes the - // value of _value as the initialization parameters. If it is an object, then it is assumed - // to be an object of general form: - // | { - // | type: function, //constructor. - // | deserialize: function(value) //The function that parses the value and constructs the object defined by type appropriately. - // | } - - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = []; - this._loadFinished = false; - this._jsonFileUrl = keywordParameters.url; - this._ccUrl = keywordParameters.url; - this.url = keywordParameters.url; - this._jsonData = keywordParameters.data; - this.data = null; - this._datatypeMap = keywordParameters.typeMap || {}; - if(!this._datatypeMap['Date']){ - //If no default mapping for dates, then set this as default. - //We use the dojo/date/stamp here because the ISO format is the 'dojo way' - //of generically representing dates. - this._datatypeMap['Date'] = { - type: Date, - deserialize: function(value){ - return dateStamp.fromISOString(value); - } - }; - } - this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true}; - this._itemsByIdentity = null; - this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item. - this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item. - this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item. - this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity - this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset. - this._queuedFetches = []; - if(keywordParameters.urlPreventCache !== undefined){ - this.urlPreventCache = keywordParameters.urlPreventCache?true:false; - } - if(keywordParameters.hierarchical !== undefined){ - this.hierarchical = keywordParameters.hierarchical?true:false; - } - if(keywordParameters.clearOnClose){ - this.clearOnClose = true; - } - if("failOk" in keywordParameters){ - this.failOk = keywordParameters.failOk?true:false; - } - }, - - url: "", // use "" rather than undefined for the benefit of the parser (#3539) - - //Internal var, crossCheckUrl. Used so that setting either url or _jsonFileUrl, can still trigger a reload - //when clearOnClose and close is used. - _ccUrl: "", - - data: null, // define this so that the parser can populate it - - typeMap: null, //Define so parser can populate. - - // clearOnClose: Boolean - // Parameter to allow users to specify if a close call should force a reload or not. - // By default, it retains the old behavior of not clearing if close is called. But - // if set true, the store will be reset to default state. Note that by doing this, - // all item handles will become invalid and a new fetch must be issued. - clearOnClose: false, - - // urlPreventCache: Boolean - // Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url. - // Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option. - // Added for tracker: #6072 - urlPreventCache: false, - - // failOk: Boolean - // Parameter for specifying that it is OK for the xhrGet call to fail silently. - failOk: false, - - // hierarchical: Boolean - // Parameter to indicate to process data from the url as hierarchical - // (data items can contain other data items in js form). Default is true - // for backwards compatibility. False means only root items are processed - // as items, all child objects outside of type-mapped objects and those in - // specific reference format, are left straight JS data objects. - hierarchical: true, - - _assertIsItem: function(/* dojo/data/api/Item */ item){ - // summary: - // This function tests whether the item passed in is indeed an item in the store. - // item: - // The item to test for being contained by the store. - if(!this.isItem(item)){ - throw new Error(this.declaredClass + ": Invalid item argument."); - } - }, - - _assertIsAttribute: function(/* attribute-name-string */ attribute){ - // summary: - // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store. - // attribute: - // The attribute to test for being contained by the store. - if(typeof attribute !== "string"){ - throw new Error(this.declaredClass + ": Invalid attribute argument."); - } - }, - - getValue: function( /* dojo/data/api/Item */ item, - /* attribute-name-string */ attribute, - /* value? */ defaultValue){ - // summary: - // See dojo/data/api/Read.getValue() - var values = this.getValues(item, attribute); - return (values.length > 0)?values[0]:defaultValue; // mixed - }, - - getValues: function(/* dojo/data/api/Item */ item, - /* attribute-name-string */ attribute){ - // summary: - // See dojo/data/api/Read.getValues() - - this._assertIsItem(item); - this._assertIsAttribute(attribute); - // Clone it before returning. refs: #10474 - return (item[attribute] || []).slice(0); // Array - }, - - getAttributes: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Read.getAttributes() - this._assertIsItem(item); - var attributes = []; - for(var key in item){ - // Save off only the real item attributes, not the special id marks for O(1) isItem. - if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){ - attributes.push(key); - } - } - return attributes; // Array - }, - - hasAttribute: function( /* dojo/data/api/Item */ item, - /* attribute-name-string */ attribute){ - // summary: - // See dojo/data/api/Read.hasAttribute() - this._assertIsItem(item); - this._assertIsAttribute(attribute); - return (attribute in item); - }, - - containsValue: function(/* dojo/data/api/Item */ item, - /* attribute-name-string */ attribute, - /* anything */ value){ - // summary: - // See dojo/data/api/Read.containsValue() - var regexp = undefined; - if(typeof value === "string"){ - regexp = filterUtil.patternToRegExp(value, false); - } - return this._containsValue(item, attribute, value, regexp); //boolean. - }, - - _containsValue: function( /* dojo/data/api/Item */ item, - /* attribute-name-string */ attribute, - /* anything */ value, - /* RegExp?*/ regexp){ - // summary: - // Internal function for looking at the values contained by the item. - // description: - // Internal function for looking at the values contained by the item. This - // function allows for denoting if the comparison should be case sensitive for - // strings or not (for handling filtering cases where string case should not matter) - // item: - // The data item to examine for attribute values. - // attribute: - // The attribute to inspect. - // value: - // The value to match. - // regexp: - // Optional regular expression generated off value if value was of string type to handle wildcarding. - // If present and attribute values are string, then it can be used for comparison instead of 'value' - return array.some(this.getValues(item, attribute), function(possibleValue){ - if(possibleValue !== null && !lang.isObject(possibleValue) && regexp){ - if(possibleValue.toString().match(regexp)){ - return true; // Boolean - } - }else if(value === possibleValue){ - return true; // Boolean - } - }); - }, - - isItem: function(/* anything */ something){ - // summary: - // See dojo/data/api/Read.isItem() - if(something && something[this._storeRefPropName] === this){ - if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){ - return true; - } - } - return false; // Boolean - }, - - isItemLoaded: function(/* anything */ something){ - // summary: - // See dojo/data/api/Read.isItemLoaded() - return this.isItem(something); //boolean - }, - - loadItem: function(/* object */ keywordArgs){ - // summary: - // See dojo/data/api/Read.loadItem() - this._assertIsItem(keywordArgs.item); - }, - - getFeatures: function(){ - // summary: - // See dojo/data/api/Read.getFeatures() - return this._features; //Object - }, - - getLabel: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Read.getLabel() - if(this._labelAttr && this.isItem(item)){ - return this.getValue(item,this._labelAttr); //String - } - return undefined; //undefined - }, - - getLabelAttributes: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Read.getLabelAttributes() - if(this._labelAttr){ - return [this._labelAttr]; //array - } - return null; //null - }, - - filter: function(/* Object */ requestArgs, /* item[] */ arrayOfItems, /* Function */ findCallback){ - // summary: - // This method handles the basic filtering needs for ItemFile* based stores. - var items = [], - i, key; - - if(requestArgs.query){ - var value, - ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false; - - //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the - //same value for each item examined. Much more efficient. - var regexpList = {}; - for(key in requestArgs.query){ - value = requestArgs.query[key]; - if(typeof value === "string"){ - regexpList[key] = filterUtil.patternToRegExp(value, ignoreCase); - }else if(value instanceof RegExp){ - regexpList[key] = value; - } - } - for(i = 0; i < arrayOfItems.length; ++i){ - var match = true; - var candidateItem = arrayOfItems[i]; - if(candidateItem === null){ - match = false; - }else{ - for(key in requestArgs.query){ - value = requestArgs.query[key]; - if(!this._containsValue(candidateItem, key, value, regexpList[key])){ - match = false; - } - } - } - if(match){ - items.push(candidateItem); - } - } - findCallback(items, requestArgs); - }else{ - // We want a copy to pass back in case the parent wishes to sort the array. - // We shouldn't allow resort of the internal list, so that multiple callers - // can get lists and sort without affecting each other. We also need to - // filter out any null values that have been left as a result of deleteItem() - // calls in ItemFileWriteStore. - for(i = 0; i < arrayOfItems.length; ++i){ - var item = arrayOfItems[i]; - if(item !== null){ - items.push(item); - } - } - findCallback(items, requestArgs); - } - }, - - _fetchItems: function( /* Object */ keywordArgs, - /* Function */ findCallback, - /* Function */ errorCallback){ - // summary: - // See dojo/data/util.simpleFetch.fetch() - var self = this; - - if(this._loadFinished){ - this.filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions), findCallback); - }else{ - //Do a check on the JsonFileUrl and crosscheck it. - //If it doesn't match the cross-check, it needs to be updated - //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - kernel.deprecated(this.declaredClass + ": ", - "To change the url, set the url property of the store," + - " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); - this._ccUrl = this._jsonFileUrl; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - if(this.data != null){ - this._jsonData = this.data; - this.data = null; - } - - if(this._jsonFileUrl){ - //If fetches come in before the loading has finished, but while - //a load is in progress, we have to defer the fetching to be - //invoked in the callback. - if(this._loadInProgress){ - this._queuedFetches.push({args: keywordArgs, filter: lang.hitch(self, "filter"), findCallback: lang.hitch(self, findCallback)}); - }else{ - this._loadInProgress = true; - var getArgs = { - url: self._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk - }; - var getHandler = xhr.get(getArgs); - getHandler.addCallback(function(data){ - try{ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - self._loadInProgress = false; - - self.filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions), findCallback); - self._handleQueuedFetches(); - }catch(e){ - self._loadFinished = true; - self._loadInProgress = false; - errorCallback(e, keywordArgs); - } - }); - getHandler.addErrback(function(error){ - self._loadInProgress = false; - errorCallback(error, keywordArgs); - }); - - //Wire up the cancel to abort of the request - //This call cancel on the deferred if it hasn't been called - //yet and then will chain to the simple abort of the - //simpleFetch keywordArgs - var oldAbort = null; - if(keywordArgs.abort){ - oldAbort = keywordArgs.abort; - } - keywordArgs.abort = function(){ - var df = getHandler; - if(df && df.fired === -1){ - df.cancel(); - df = null; - } - if(oldAbort){ - oldAbort.call(keywordArgs); - } - }; - } - }else if(this._jsonData){ - try{ - this._loadFinished = true; - this._getItemsFromLoadedData(this._jsonData); - this._jsonData = null; - self.filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions), findCallback); - }catch(e){ - errorCallback(e, keywordArgs); - } - }else{ - errorCallback(new Error(this.declaredClass + ": No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs); - } - } - }, - - _handleQueuedFetches: function(){ - // summary: - // Internal function to execute delayed request in the store. - - //Execute any deferred fetches now. - if(this._queuedFetches.length > 0){ - for(var i = 0; i < this._queuedFetches.length; i++){ - var fData = this._queuedFetches[i], - delayedQuery = fData.args, - delayedFilter = fData.filter, - delayedFindCallback = fData.findCallback; - if(delayedFilter){ - delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions), delayedFindCallback); - }else{ - this.fetchItemByIdentity(delayedQuery); - } - } - this._queuedFetches = []; - } - }, - - _getItemsArray: function(/*object?*/queryOptions){ - // summary: - // Internal function to determine which list of items to search over. - // queryOptions: The query options parameter, if any. - if(queryOptions && queryOptions.deep){ - return this._arrayOfAllItems; - } - return this._arrayOfTopLevelItems; - }, - - close: function(/*dojo/data/api/Request|Object?*/ request){ - // summary: - // See dojo/data/api/Read.close() - if(this.clearOnClose && - this._loadFinished && - !this._loadInProgress){ - //Reset all internalsback to default state. This will force a reload - //on next fetch. This also checks that the data or url param was set - //so that the store knows it can get data. Without one of those being set, - //the next fetch will trigger an error. - - if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && - (this.url == "" || this.url == null) - ) && this.data == null){ - console.debug(this.declaredClass + ": WARNING! Data reload " + - " information has not been provided." + - " Please set 'url' or 'data' to the appropriate value before" + - " the next fetch"); - } - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = []; - this._loadFinished = false; - this._itemsByIdentity = null; - this._loadInProgress = false; - this._queuedFetches = []; - } - }, - - _getItemsFromLoadedData: function(/* Object */ dataObject){ - // summary: - // Function to parse the loaded data into item format and build the internal items array. - // description: - // Function to parse the loaded data into item format and build the internal items array. - // dataObject: - // The JS data object containing the raw data to convery into item format. - // returns: Array - // Array of items in store item format. - - // First, we define a couple little utility functions... - var addingArrays = false, - self = this; - - function valueIsAnItem(/* anything */ aValue){ - // summary: - // Given any sort of value that could be in the raw json data, - // return true if we should interpret the value as being an - // item itself, rather than a literal value or a reference. - // example: - // | false == valueIsAnItem("Kermit"); - // | false == valueIsAnItem(42); - // | false == valueIsAnItem(new Date()); - // | false == valueIsAnItem({_type:'Date', _value:'1802-05-14'}); - // | false == valueIsAnItem({_reference:'Kermit'}); - // | true == valueIsAnItem({name:'Kermit', color:'green'}); - // | true == valueIsAnItem({iggy:'pop'}); - // | true == valueIsAnItem({foo:42}); - return (aValue !== null) && - (typeof aValue === "object") && - (!lang.isArray(aValue) || addingArrays) && - (!lang.isFunction(aValue)) && - (aValue.constructor == Object || lang.isArray(aValue)) && - (typeof aValue._reference === "undefined") && - (typeof aValue._type === "undefined") && - (typeof aValue._value === "undefined") && - self.hierarchical; - } - - function addItemAndSubItemsToArrayOfAllItems(/* dojo/data/api/Item */ anItem){ - self._arrayOfAllItems.push(anItem); - for(var attribute in anItem){ - var valueForAttribute = anItem[attribute]; - if(valueForAttribute){ - if(lang.isArray(valueForAttribute)){ - var valueArray = valueForAttribute; - for(var k = 0; k < valueArray.length; ++k){ - var singleValue = valueArray[k]; - if(valueIsAnItem(singleValue)){ - addItemAndSubItemsToArrayOfAllItems(singleValue); - } - } - }else{ - if(valueIsAnItem(valueForAttribute)){ - addItemAndSubItemsToArrayOfAllItems(valueForAttribute); - } - } - } - } - } - - this._labelAttr = dataObject.label; - - // We need to do some transformations to convert the data structure - // that we read from the file into a format that will be convenient - // to work with in memory. - - // Step 1: Walk through the object hierarchy and build a list of all items - var i, - item; - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = dataObject.items; - - for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){ - item = this._arrayOfTopLevelItems[i]; - if(lang.isArray(item)){ - addingArrays = true; - } - addItemAndSubItemsToArrayOfAllItems(item); - item[this._rootItemPropName]=true; - } - - // Step 2: Walk through all the attribute values of all the items, - // and replace single values with arrays. For example, we change this: - // { name:'Miss Piggy', pets:'Foo-Foo'} - // into this: - // { name:['Miss Piggy'], pets:['Foo-Foo']} - // - // We also store the attribute names so we can validate our store - // reference and item id special properties for the O(1) isItem - var allAttributeNames = {}, - key; - - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; - for(key in item){ - if(key !== this._rootItemPropName){ - var value = item[key]; - if(value !== null){ - if(!lang.isArray(value)){ - item[key] = [value]; - } - }else{ - item[key] = [null]; - } - } - allAttributeNames[key]=key; - } - } - - // Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName - // This should go really fast, it will generally never even run the loop. - while(allAttributeNames[this._storeRefPropName]){ - this._storeRefPropName += "_"; - } - while(allAttributeNames[this._itemNumPropName]){ - this._itemNumPropName += "_"; - } - while(allAttributeNames[this._reverseRefMap]){ - this._reverseRefMap += "_"; - } - - // Step 4: Some data files specify an optional 'identifier', which is - // the name of an attribute that holds the identity of each item. - // If this data file specified an identifier attribute, then build a - // hash table of items keyed by the identity of the items. - var arrayOfValues; - - var identifier = dataObject.identifier; - if(identifier){ - this._itemsByIdentity = {}; - this._features['dojo.data.api.Identity'] = identifier; - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; - arrayOfValues = item[identifier]; - var identity = arrayOfValues[0]; - if(!Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ - this._itemsByIdentity[identity] = item; - }else{ - if(this._jsonFileUrl){ - throw new Error(this.declaredClass + ": The json data as specified by: [" + this._jsonFileUrl + "] is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]"); - }else if(this._jsonData){ - throw new Error(this.declaredClass + ": The json data provided by the creation arguments is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]"); - } - } - } - }else{ - this._features['dojo.data.api.Identity'] = Number; - } - - // Step 5: Walk through all the items, and set each item's properties - // for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true. - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; - item[this._storeRefPropName] = this; - item[this._itemNumPropName] = i; - } - - // Step 6: We walk through all the attribute values of all the items, - // looking for type/value literals and item-references. - // - // We replace item-references with pointers to items. For example, we change: - // { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } - // into this: - // { name:['Kermit'], friends:[miss_piggy] } - // (where miss_piggy is the object representing the 'Miss Piggy' item). - // - // We replace type/value pairs with typed-literals. For example, we change: - // { name:['Nelson Mandela'], born:[{_type:'Date', _value:'1918-07-18'}] } - // into this: - // { name:['Kermit'], born:(new Date(1918, 6, 18)) } - // - // We also generate the associate map for all items for the O(1) isItem function. - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } - for(key in item){ - arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}] - for(var j = 0; j < arrayOfValues.length; ++j){ - value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}} - if(value !== null && typeof value == "object"){ - if(("_type" in value) && ("_value" in value)){ - var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber' - var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}} - if(!mappingObj){ - throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'"); - }else if(lang.isFunction(mappingObj)){ - arrayOfValues[j] = new mappingObj(value._value); - }else if(lang.isFunction(mappingObj.deserialize)){ - arrayOfValues[j] = mappingObj.deserialize(value._value); - }else{ - throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function"); - } - } - if(value._reference){ - var referenceDescription = value._reference; // example: {name:'Miss Piggy'} - if(!lang.isObject(referenceDescription)){ - // example: 'Miss Piggy' - // from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]} - arrayOfValues[j] = this._getItemByIdentity(referenceDescription); - }else{ - // example: {name:'Miss Piggy'} - // from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } - for(var k = 0; k < this._arrayOfAllItems.length; ++k){ - var candidateItem = this._arrayOfAllItems[k], - found = true; - for(var refKey in referenceDescription){ - if(candidateItem[refKey] != referenceDescription[refKey]){ - found = false; - } - } - if(found){ - arrayOfValues[j] = candidateItem; - } - } - } - if(this.referenceIntegrity){ - var refItem = arrayOfValues[j]; - if(this.isItem(refItem)){ - this._addReferenceToMap(refItem, item, key); - } - } - }else if(this.isItem(value)){ - //It's a child item (not one referenced through _reference). - //We need to treat this as a referenced item, so it can be cleaned up - //in a write store easily. - if(this.referenceIntegrity){ - this._addReferenceToMap(value, item, key); - } - } - } - } - } - } - }, - - _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){ - // summary: - // Method to add an reference map entry for an item and attribute. - // description: - // Method to add an reference map entry for an item and attribute. - // refItem: - // The item that is referenced. - // parentItem: - // The item that holds the new reference to refItem. - // attribute: - // The attribute on parentItem that contains the new reference. - - //Stub function, does nothing. Real processing is in ItemFileWriteStore. - }, - - getIdentity: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Identity.getIdentity() - var identifier = this._features['dojo.data.api.Identity']; - if(identifier === Number){ - return item[this._itemNumPropName]; // Number - }else{ - var arrayOfValues = item[identifier]; - if(arrayOfValues){ - return arrayOfValues[0]; // Object|String - } - } - return null; // null - }, - - fetchItemByIdentity: function(/* Object */ keywordArgs){ - // summary: - // See dojo/data/api/Identity.fetchItemByIdentity() - - // Hasn't loaded yet, we have to trigger the load. - var item, - scope; - if(!this._loadFinished){ - var self = this; - //Do a check on the JsonFileUrl and crosscheck it. - //If it doesn't match the cross-check, it needs to be updated - //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - kernel.deprecated(this.declaredClass + ": ", - "To change the url, set the url property of the store," + - " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); - this._ccUrl = this._jsonFileUrl; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - if(this.data != null && this._jsonData == null){ - this._jsonData = this.data; - this.data = null; - } - - if(this._jsonFileUrl){ - - if(this._loadInProgress){ - this._queuedFetches.push({args: keywordArgs}); - }else{ - this._loadInProgress = true; - var getArgs = { - url: self._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk - }; - var getHandler = xhr.get(getArgs); - getHandler.addCallback(function(data){ - var scope = keywordArgs.scope?keywordArgs.scope:kernel.global; - try{ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - self._loadInProgress = false; - item = self._getItemByIdentity(keywordArgs.identity); - if(keywordArgs.onItem){ - keywordArgs.onItem.call(scope, item); - } - self._handleQueuedFetches(); - }catch(error){ - self._loadInProgress = false; - if(keywordArgs.onError){ - keywordArgs.onError.call(scope, error); - } - } - }); - getHandler.addErrback(function(error){ - self._loadInProgress = false; - if(keywordArgs.onError){ - var scope = keywordArgs.scope?keywordArgs.scope:kernel.global; - keywordArgs.onError.call(scope, error); - } - }); - } - - }else if(this._jsonData){ - // Passed in data, no need to xhr. - self._getItemsFromLoadedData(self._jsonData); - self._jsonData = null; - self._loadFinished = true; - item = self._getItemByIdentity(keywordArgs.identity); - if(keywordArgs.onItem){ - scope = keywordArgs.scope?keywordArgs.scope:kernel.global; - keywordArgs.onItem.call(scope, item); - } - } - }else{ - // Already loaded. We can just look it up and call back. - item = this._getItemByIdentity(keywordArgs.identity); - if(keywordArgs.onItem){ - scope = keywordArgs.scope?keywordArgs.scope:kernel.global; - keywordArgs.onItem.call(scope, item); - } - } - }, - - _getItemByIdentity: function(/* Object */ identity){ - // summary: - // Internal function to look an item up by its identity map. - var item = null; - if(this._itemsByIdentity){ - // If this map is defined, we need to just try to get it. If it fails - // the item does not exist. - if(Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ - item = this._itemsByIdentity[identity]; - } - }else if (Object.hasOwnProperty.call(this._arrayOfAllItems, identity)){ - item = this._arrayOfAllItems[identity]; - } - if(item === undefined){ - item = null; - } - return item; // Object - }, - - getIdentityAttributes: function(/* dojo/data/api/Item */ item){ - // summary: - // See dojo/data/api/Identity.getIdentityAttributes() - - var identifier = this._features['dojo.data.api.Identity']; - if(identifier === Number){ - // If (identifier === Number) it means getIdentity() just returns - // an integer item-number for each item. The dojo/data/api/Identity - // spec says we need to return null if the identity is not composed - // of attributes - return null; // null - }else{ - return [identifier]; // Array - } - }, - - _forceLoad: function(){ - // summary: - // Internal function to force a load of the store if it hasn't occurred yet. This is required - // for specific functions to work properly. - var self = this; - //Do a check on the JsonFileUrl and crosscheck it. - //If it doesn't match the cross-check, it needs to be updated - //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - kernel.deprecated(this.declaredClass + ": ", - "To change the url, set the url property of the store," + - " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); - this._ccUrl = this._jsonFileUrl; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - if(this.data != null){ - this._jsonData = this.data; - this.data = null; - } - - if(this._jsonFileUrl){ - var getArgs = { - url: this._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk, - sync: true - }; - var getHandler = xhr.get(getArgs); - getHandler.addCallback(function(data){ - try{ - //Check to be sure there wasn't another load going on concurrently - //So we don't clobber data that comes in on it. If there is a load going on - //then do not save this data. It will potentially clobber current data. - //We mainly wanted to sync/wait here. - //TODO: Revisit the loading scheme of this store to improve multi-initial - //request handling. - if(self._loadInProgress !== true && !self._loadFinished){ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - }else if(self._loadInProgress){ - //Okay, we hit an error state we can't recover from. A forced load occurred - //while an async load was occurring. Since we cannot block at this point, the best - //that can be managed is to throw an error. - throw new Error(this.declaredClass + ": Unable to perform a synchronous load, an async load is in progress."); - } - }catch(e){ - console.log(e); - throw e; - } - }); - getHandler.addErrback(function(error){ - throw error; - }); - }else if(this._jsonData){ - self._getItemsFromLoadedData(self._jsonData); - self._jsonData = null; - self._loadFinished = true; - } - } -}); -//Mix in the simple fetch implementation to this class. -lang.extend(ItemFileReadStore,simpleFetch); - -return ItemFileReadStore; - -}); - -}, -'dojo/html':function(){ -define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"], - function(kernel, lang, darray, declare, dom, domConstruct, parser){ - // module: - // dojo/html - - var html = { - // summary: - // TODOC - }; - lang.setObject("dojo.html", html); - - // the parser might be needed.. - - // idCounter is incremented with each instantiation to allow assignment of a unique id for tracking, logging purposes - var idCounter = 0; - - html._secureForInnerHtml = function(/*String*/ cont){ - // summary: - // removes !DOCTYPE and title elements from the html string. - // - // khtml is picky about dom faults, you can't attach a style or `<title>` node as child of body - // must go into head, so we need to cut out those tags - // cont: - // An html string for insertion into the dom - // - return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String - }; - - html._emptyNode = domConstruct.empty; - /*===== - dojo.html._emptyNode = function(node){ - // summary: - // Removes all child nodes from the given node. Deprecated, should use dojo/dom-constuct.empty() directly - // instead. - // node: DOMNode - // the parent element - }; - =====*/ - - html._setNodeContent = function(/*DomNode*/ node, /*String|DomNode|NodeList*/ cont){ - // summary: - // inserts the given content into the given node - // node: - // the parent element - // content: - // the content to be set on the parent element. - // This can be an html string, a node reference or a NodeList, dojo/NodeList, Array or other enumerable list of nodes - - // always empty - domConstruct.empty(node); - - if(cont){ - if(typeof cont == "string"){ - cont = domConstruct.toDom(cont, node.ownerDocument); - } - if(!cont.nodeType && lang.isArrayLike(cont)){ - // handle as enumerable, but it may shrink as we enumerate it - for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0){ - domConstruct.place( cont[i], node, "last"); - } - }else{ - // pass nodes, documentFragments and unknowns through to dojo.place - domConstruct.place(cont, node, "last"); - } - } - - // return DomNode - return node; - }; - - // we wrap up the content-setting operation in a object - html._ContentSetter = declare("dojo.html._ContentSetter", null, - { - // node: DomNode|String - // An node which will be the parent element that we set content into - node: "", - - // content: String|DomNode|DomNode[] - // The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes - content: "", - - // id: String? - // Usually only used internally, and auto-generated with each instance - id: "", - - // cleanContent: Boolean - // Should the content be treated as a full html document, - // and the real content stripped of <html>, <body> wrapper before injection - cleanContent: false, - - // extractContent: Boolean - // Should the content be treated as a full html document, - // and the real content stripped of `<html> <body>` wrapper before injection - extractContent: false, - - // parseContent: Boolean - // Should the node by passed to the parser after the new content is set - parseContent: false, - - // parserScope: String - // Flag passed to parser. Root for attribute names to search for. If scopeName is dojo, - // will search for data-dojo-type (or dojoType). For backwards compatibility - // reasons defaults to dojo._scopeName (which is "dojo" except when - // multi-version support is used, when it will be something like dojo16, dojo20, etc.) - parserScope: kernel._scopeName, - - // startup: Boolean - // Start the child widgets after parsing them. Only obeyed if parseContent is true. - startup: true, - - // lifecycle methods - constructor: function(/*Object*/ params, /*String|DomNode*/ node){ - // summary: - // Provides a configurable, extensible object to wrap the setting on content on a node - // call the set() method to actually set the content.. - - // the original params are mixed directly into the instance "this" - lang.mixin(this, params || {}); - - // give precedence to params.node vs. the node argument - // and ensure its a node, not an id string - node = this.node = dom.byId( this.node || node ); - - if(!this.id){ - this.id = [ - "Setter", - (node) ? node.id || node.tagName : "", - idCounter++ - ].join("_"); - } - }, - set: function(/* String|DomNode|NodeList? */ cont, /*Object?*/ params){ - // summary: - // front-end to the set-content sequence - // cont: - // An html string, node or enumerable list of nodes for insertion into the dom - // If not provided, the object's content property will be used - if(undefined !== cont){ - this.content = cont; - } - // in the re-use scenario, set needs to be able to mixin new configuration - if(params){ - this._mixin(params); - } - - this.onBegin(); - this.setContent(); - - var ret = this.onEnd(); - - if(ret && ret.then){ - // Make dojox/html/_ContentSetter.set() return a Promise that resolves when load and parse complete. - return ret; - }else{ - // Vanilla dojo/html._ContentSetter.set() returns a DOMNode for back compat. For 2.0, switch it to - // return a Deferred like above. - return this.node; - } - }, - - setContent: function(){ - // summary: - // sets the content on the node - - var node = this.node; - if(!node){ - // can't proceed - throw new Error(this.declaredClass + ": setContent given no node"); - } - try{ - node = html._setNodeContent(node, this.content); - }catch(e){ - // check if a domfault occurs when we are appending this.errorMessage - // like for instance if domNode is a UL and we try append a DIV - - // FIXME: need to allow the user to provide a content error message string - var errMess = this.onContentError(e); - try{ - node.innerHTML = errMess; - }catch(e){ - console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e); - } - } - // always put back the node for the next method - this.node = node; // DomNode - }, - - empty: function(){ - // summary: - // cleanly empty out existing content - - // If there is a parse in progress, cancel it. - if(this.parseDeferred){ - if(!this.parseDeferred.isResolved()){ - this.parseDeferred.cancel(); - } - delete this.parseDeferred; - } - - // destroy any widgets from a previous run - // NOTE: if you don't want this you'll need to empty - // the parseResults array property yourself to avoid bad things happening - if(this.parseResults && this.parseResults.length){ - darray.forEach(this.parseResults, function(w){ - if(w.destroy){ - w.destroy(); - } - }); - delete this.parseResults; - } - // this is fast, but if you know its already empty or safe, you could - // override empty to skip this step - domConstruct.empty(this.node); - }, - - onBegin: function(){ - // summary: - // Called after instantiation, but before set(); - // It allows modification of any of the object properties - - // including the node and content provided - before the set operation actually takes place - // This default implementation checks for cleanContent and extractContent flags to - // optionally pre-process html string content - var cont = this.content; - - if(lang.isString(cont)){ - if(this.cleanContent){ - cont = html._secureForInnerHtml(cont); - } - - if(this.extractContent){ - var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); - if(match){ cont = match[1]; } - } - } - - // clean out the node and any cruft associated with it - like widgets - this.empty(); - - this.content = cont; - return this.node; // DomNode - }, - - onEnd: function(){ - // summary: - // Called after set(), when the new content has been pushed into the node - // It provides an opportunity for post-processing before handing back the node to the caller - // This default implementation checks a parseContent flag to optionally run the dojo parser over the new content - if(this.parseContent){ - // populates this.parseResults and this.parseDeferred if you need those.. - this._parse(); - } - return this.node; // DomNode - // TODO: for 2.0 return a Promise indicating that the parse completed. - }, - - tearDown: function(){ - // summary: - // manually reset the Setter instance if its being re-used for example for another set() - // description: - // tearDown() is not called automatically. - // In normal use, the Setter instance properties are simply allowed to fall out of scope - // but the tearDown method can be called to explicitly reset this instance. - delete this.parseResults; - delete this.parseDeferred; - delete this.node; - delete this.content; - }, - - onContentError: function(err){ - return "Error occurred setting content: " + err; - }, - - onExecError: function(err){ - return "Error occurred executing scripts: " + err; - }, - - _mixin: function(params){ - // mix properties/methods into the instance - // TODO: the intention with tearDown is to put the Setter's state - // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params) - // so we could do something here to move the original properties aside for later restoration - var empty = {}, key; - for(key in params){ - if(key in empty){ continue; } - // TODO: here's our opportunity to mask the properties we don't consider configurable/overridable - // .. but history shows we'll almost always guess wrong - this[key] = params[key]; - } - }, - _parse: function(){ - // summary: - // runs the dojo parser over the node contents, storing any results in this.parseResults - // and the parse promise in this.parseDeferred - // Any errors resulting from parsing are passed to _onError for handling - - var rootNode = this.node; - try{ - // store the results (widgets, whatever) for potential retrieval - var inherited = {}; - darray.forEach(["dir", "lang", "textDir"], function(name){ - if(this[name]){ - inherited[name] = this[name]; - } - }, this); - var self = this; - this.parseDeferred = parser.parse({ - rootNode: rootNode, - noStart: !this.startup, - inherited: inherited, - scope: this.parserScope - }).then(function(results){ - return self.parseResults = results; - }); - }catch(e){ - this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id); - } - }, - - _onError: function(type, err, consoleText){ - // summary: - // shows user the string that is returned by on[type]Error - // override/implement on[type]Error and return your own string to customize - var errText = this['on' + type + 'Error'].call(this, err); - if(consoleText){ - console.error(consoleText, err); - }else if(errText){ // a empty string won't change current content - html._setNodeContent(this.node, errText, true); - } - } - }); // end declare() - - html.set = function(/*DomNode*/ node, /*String|DomNode|NodeList*/ cont, /*Object?*/ params){ - // summary: - // inserts (replaces) the given content into the given node. dojo.place(cont, node, "only") - // may be a better choice for simple HTML insertion. - // description: - // Unless you need to use the params capabilities of this method, you should use - // dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting - // an HTML string into the DOM, but it only handles inserting an HTML string as DOM - // elements, or inserting a DOM node. dojo.place does not handle NodeList insertions - // or the other capabilities as defined by the params object for this method. - // node: - // the parent element that will receive the content - // cont: - // the content to be set on the parent element. - // This can be an html string, a node reference or a NodeList, dojo/NodeList, Array or other enumerable list of nodes - // params: - // Optional flags/properties to configure the content-setting. See dojo/html/_ContentSetter - // example: - // A safe string/node/nodelist content replacement/injection with hooks for extension - // Example Usage: - // | html.set(node, "some string"); - // | html.set(node, contentNode, {options}); - // | html.set(node, myNode.childNodes, {options}); - if(undefined == cont){ - console.warn("dojo.html.set: no cont argument provided, using empty string"); - cont = ""; - } - if(!params){ - // simple and fast - return html._setNodeContent(node, cont, true); - }else{ - // more options but slower - // note the arguments are reversed in order, to match the convention for instantiation via the parser - var op = new html._ContentSetter(lang.mixin( - params, - { content: cont, node: node } - )); - return op.set(); - } - }; - - return html; -}); - -}, -'dijit/_PaletteMixin':function(){ -define("dijit/_PaletteMixin", [ - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/dom-class", // domClass.add domClass.remove - "dojo/dom-construct", // domConstruct.create domConstruct.place - "dojo/_base/event", // event.stop - "dojo/keys", // keys - "dojo/_base/lang", // lang.getObject - "./_CssStateMixin", - "./focus", - "./typematic" -], function(declare, domAttr, domClass, domConstruct, event, keys, lang, _CssStateMixin, focus, typematic){ - -// module: -// dijit/_PaletteMixin - -return declare("dijit._PaletteMixin", [_CssStateMixin], { - // summary: - // A keyboard accessible palette, for picking a color/emoticon/etc. - // description: - // A mixin for a grid showing various entities, so the user can pick a certain entity. - - // defaultTimeout: Number - // Number of milliseconds before a held key or button becomes typematic - defaultTimeout: 500, - - // timeoutChangeRate: Number - // Fraction of time used to change the typematic timer between events - // 1.0 means that each typematic event fires at defaultTimeout intervals - // Less than 1.0 means that each typematic event fires at an increasing faster rate - timeoutChangeRate: 0.90, - - // value: String - // Currently selected color/emoticon/etc. - value: "", - - // _selectedCell: [private] Integer - // Index of the currently selected cell. Initially, none selected - _selectedCell: -1, - -/*===== - // _currentFocus: [private] DomNode - // The currently focused cell (if the palette itself has focus), or otherwise - // the cell to be focused when the palette itself gets focus. - // Different from value, which represents the selected (i.e. clicked) cell. - _currentFocus: null, -=====*/ - -/*===== - // _xDim: [protected] Integer - // This is the number of cells horizontally across. - _xDim: null, -=====*/ - -/*===== - // _yDim: [protected] Integer - // This is the number of cells vertically down. - _yDim: null, -=====*/ - - // tabIndex: String - // Widget tab index. - tabIndex: "0", - - // cellClass: [protected] String - // CSS class applied to each cell in the palette - cellClass: "dijitPaletteCell", - - // dyeClass: [protected] Constructor - // Constructor for Object created for each cell of the palette. - // dyeClass should implements dijit.Dye interface - dyeClass: null, - - // summary: String - // Localized summary for the palette table - summary: '', - _setSummaryAttr: "paletteTableNode", - - _dyeFactory: function(value /*===== , row, col, title =====*/){ - // summary: - // Return instance of dijit.Dye for specified cell of palette - // tags: - // extension - - // Remove string support for 2.0 - var dyeClassObj = typeof this.dyeClass == "string" ? lang.getObject(this.dyeClass) : this.dyeClass; - return new dyeClassObj(value); - }, - - _preparePalette: function(choices, titles) { - // summary: - // Subclass must call _preparePalette() from postCreate(), passing in the tooltip - // for each cell - // choices: String[][] - // id's for each cell of the palette, used to create Dye JS object for each cell - // titles: String[] - // Localized tooltip for each cell - - this._cells = []; - var url = this._blankGif; - - this.connect(this.gridNode, "ondijitclick", "_onCellClick"); - - for(var row=0; row < choices.length; row++){ - var rowNode = domConstruct.create("tr", {tabIndex: "-1"}, this.gridNode); - for(var col=0; col < choices[row].length; col++){ - var value = choices[row][col]; - if(value){ - var cellObject = this._dyeFactory(value, row, col, titles[value]); - - var cellNode = domConstruct.create("td", { - "class": this.cellClass, - tabIndex: "-1", - title: titles[value], - role: "gridcell" - }, rowNode); - - // prepare cell inner structure - cellObject.fillCell(cellNode, url); - - cellNode.idx = this._cells.length; - - // save cell info into _cells - this._cells.push({node:cellNode, dye:cellObject}); - } - } - } - this._xDim = choices[0].length; - this._yDim = choices.length; - - // Now set all events - // The palette itself is navigated to with the tab key on the keyboard - // Keyboard navigation within the Palette is with the arrow keys - // Spacebar selects the cell. - // For the up key the index is changed by negative the x dimension. - - var keyIncrementMap = { - UP_ARROW: -this._xDim, - // The down key the index is increase by the x dimension. - DOWN_ARROW: this._xDim, - // Right and left move the index by 1. - RIGHT_ARROW: this.isLeftToRight() ? 1 : -1, - LEFT_ARROW: this.isLeftToRight() ? -1 : 1 - }; - for(var key in keyIncrementMap){ - this.own( - typematic.addKeyListener( - this.domNode, - {charOrCode:keys[key], ctrlKey:false, altKey:false, shiftKey:false}, - this, - function(){ - var increment = keyIncrementMap[key]; - return function(count){ this._navigateByKey(increment, count); }; - }(), - this.timeoutChangeRate, - this.defaultTimeout - ) - ); - } - }, - - postCreate: function(){ - this.inherited(arguments); - - // Set initial navigable node. - this._setCurrent(this._cells[0].node); - }, - - focus: function(){ - // summary: - // Focus this widget. Puts focus on the most recently focused cell. - - // The cell already has tabIndex set, just need to set CSS and focus it - focus.focus(this._currentFocus); - }, - - _onCellClick: function(/*Event*/ evt){ - // summary: - // Handler for click, enter key & space key. Selects the cell. - // evt: - // The event. - // tags: - // private - - var target = evt.target; - - // Find TD associated with click event. For ColorPalette user likely clicked IMG inside of TD - while(target.tagName != "TD"){ - if(!target.parentNode || target == this.gridNode){ // probably can never happen, but just in case - return; - } - target = target.parentNode; - } - - var value = this._getDye(target).getValue(); - - // First focus the clicked cell, and then send onChange() notification. - // onChange() (via _setValueAttr) must be after the focus call, because - // it may trigger a refocus to somewhere else (like the Editor content area), and that - // second focus should win. - this._setCurrent(target); - focus.focus(target); - this._setValueAttr(value, true); - - event.stop(evt); - }, - - _setCurrent: function(/*DomNode*/ node){ - // summary: - // Sets which node is the focused cell. - // description: - // At any point in time there's exactly one - // cell with tabIndex != -1. If focus is inside the palette then - // focus is on that cell. - // - // After calling this method, arrow key handlers and mouse click handlers - // should focus the cell in a setTimeout(). - // tags: - // protected - if("_currentFocus" in this){ - // Remove tabIndex on old cell - domAttr.set(this._currentFocus, "tabIndex", "-1"); - } - - // Set tabIndex of new cell - this._currentFocus = node; - if(node){ - domAttr.set(node, "tabIndex", this.tabIndex); - } - }, - - _setValueAttr: function(value, priorityChange){ - // summary: - // This selects a cell. It triggers the onChange event. - // value: String - // Value of the cell to select - // tags: - // protected - // priorityChange: Boolean? - // Optional parameter used to tell the select whether or not to fire - // onChange event. - - // clear old selected cell - if(this._selectedCell >= 0){ - domClass.remove(this._cells[this._selectedCell].node, this.cellClass + "Selected"); - } - this._selectedCell = -1; - - // search for cell matching specified value - if(value){ - for(var i = 0; i < this._cells.length; i++){ - if(value == this._cells[i].dye.getValue()){ - this._selectedCell = i; - domClass.add(this._cells[i].node, this.cellClass + "Selected"); - break; - } - } - } - - // record new value, or null if no matching cell - this._set("value", this._selectedCell >= 0 ? value : null); - - if(priorityChange || priorityChange === undefined){ - this.onChange(value); - } - }, - - onChange: function(/*===== value =====*/){ - // summary: - // Callback when a cell is selected. - // value: String - // Value corresponding to cell. - }, - - _navigateByKey: function(increment, typeCount){ - // summary: - // This is the callback for typematic. - // It changes the focus and the highlighed cell. - // increment: - // How much the key is navigated. - // typeCount: - // How many times typematic has fired. - // tags: - // private - - // typecount == -1 means the key is released. - if(typeCount == -1){ return; } - - var newFocusIndex = this._currentFocus.idx + increment; - if(newFocusIndex < this._cells.length && newFocusIndex > -1){ - var focusNode = this._cells[newFocusIndex].node; - this._setCurrent(focusNode); - - // Actually focus the node, for the benefit of screen readers. - // Use defer because IE doesn't like changing focus inside of an event handler - this.defer(lang.hitch(focus, "focus", focusNode)); - } - }, - - _getDye: function(/*DomNode*/ cell){ - // summary: - // Get JS object for given cell DOMNode - - return this._cells[cell.idx].dye; - } -}); - -/*===== -declare("dijit.Dye", - null, - { - // summary: - // Interface for the JS Object associated with a palette cell (i.e. DOMNode) - - constructor: function(alias, row, col){ - // summary: - // Initialize according to value or alias like "white" - // alias: String - }, - - getValue: function(){ - // summary: - // Return "value" of cell; meaning of "value" varies by subclass. - // description: - // For example color hex value, emoticon ascii value etc, entity hex value. - }, - - fillCell: function(cell, blankGif){ - // summary: - // Add cell DOMNode inner structure - // cell: DomNode - // The surrounding cell - // blankGif: String - // URL for blank cell image - } - } -); -=====*/ - -}); - -}, -'dijit/form/ValidationTextBox':function(){ -require({cache:{ -'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}}); -define("dijit/form/ValidationTextBox", [ - "dojo/_base/declare", // declare - "dojo/_base/kernel", // kernel.deprecated - "dojo/i18n", // i18n.getLocalization - "./TextBox", - "../Tooltip", - "dojo/text!./templates/ValidationTextBox.html", - "dojo/i18n!./nls/validate" -], function(declare, kernel, i18n, TextBox, Tooltip, template){ - - // module: - // dijit/form/ValidationTextBox - - - /*===== - var __Constraints = { - // locale: String - // locale used for validation, picks up value from this widget's lang attribute - // _flags_: anything - // various flags passed to pattern function - }; - =====*/ - - var ValidationTextBox; - return ValidationTextBox = declare("dijit.form.ValidationTextBox", TextBox, { - // summary: - // Base class for textbox widgets with the ability to validate content of various types and provide user feedback. - - templateString: template, - - // required: Boolean - // User is required to enter data into this field. - required: false, - - // promptMessage: String - // If defined, display this hint string immediately on focus to the textbox, if empty. - // Also displays if the textbox value is Incomplete (not yet valid but will be with additional input). - // Think of this like a tooltip that tells the user what to do, not an error message - // that tells the user what they've done wrong. - // - // Message disappears when user starts typing. - promptMessage: "", - - // invalidMessage: String - // The message to display if value is invalid. - // The translated string value is read from the message file by default. - // Set to "" to use the promptMessage instead. - invalidMessage: "$_unset_$", - - // missingMessage: String - // The message to display if value is empty and the field is required. - // The translated string value is read from the message file by default. - // Set to "" to use the invalidMessage instead. - missingMessage: "$_unset_$", - - // message: String - // Currently error/prompt message. - // When using the default tooltip implementation, this will only be - // displayed when the field is focused. - message: "", - - // constraints: __Constraints - // user-defined object needed to pass parameters to the validator functions - constraints: {}, - - // pattern: [extension protected] String|Function(constraints) returning a string. - // This defines the regular expression used to validate the input. - // Do not add leading ^ or $ characters since the widget adds these. - // A function may be used to generate a valid pattern when dependent on constraints or other runtime factors. - // set('pattern', String|Function). - pattern: ".*", - - // regExp: Deprecated [extension protected] String. Use "pattern" instead. - regExp: "", - - regExpGen: function(/*__Constraints*/ /*===== constraints =====*/){ - // summary: - // Deprecated. Use set('pattern', Function) instead. - }, - - // state: [readonly] String - // Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error) - state: "", - - // tooltipPosition: String[] - // See description of `dijit/Tooltip.defaultPosition` for details on this parameter. - tooltipPosition: [], - - _deprecateRegExp: function(attr, value){ - if(value != ValidationTextBox.prototype[attr]){ - kernel.deprecated("ValidationTextBox id="+this.id+", set('" + attr + "', ...) is deprecated. Use set('pattern', ...) instead.", "", "2.0"); - this.set('pattern', value); - } - }, - _setRegExpGenAttr: function(/*Function*/ newFcn){ - this._deprecateRegExp("regExpGen", newFcn); - this.regExpGen = this._getPatternAttr; // backward compat with this.regExpGen(this.constraints) - }, - _setRegExpAttr: function(/*String*/ value){ - this._deprecateRegExp("regExp", value); - }, - - _setValueAttr: function(){ - // summary: - // Hook so set('value', ...) works. - this.inherited(arguments); - this.validate(this.focused); - }, - - validator: function(/*anything*/ value, /*__Constraints*/ constraints){ - // summary: - // Overridable function used to validate the text input against the regular expression. - // tags: - // protected - return (new RegExp("^(?:" + this._getPatternAttr(constraints) + ")"+(this.required?"":"?")+"$")).test(value) && - (!this.required || !this._isEmpty(value)) && - (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean - }, - - _isValidSubset: function(){ - // summary: - // Returns true if the value is either already valid or could be made valid by appending characters. - // This is used for validation while the user [may be] still typing. - return this.textbox.value.search(this._partialre) == 0; - }, - - isValid: function(/*Boolean*/ /*===== isFocused =====*/){ - // summary: - // Tests if value is valid. - // Can override with your own routine in a subclass. - // tags: - // protected - return this.validator(this.textbox.value, this.constraints); - }, - - _isEmpty: function(value){ - // summary: - // Checks for whitespace - return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean - }, - - getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){ - // summary: - // Return an error message to show if appropriate - // tags: - // protected - var invalid = this.invalidMessage == "$_unset_$" ? this.messages.invalidMessage : - !this.invalidMessage ? this.promptMessage : this.invalidMessage; - var missing = this.missingMessage == "$_unset_$" ? this.messages.missingMessage : - !this.missingMessage ? invalid : this.missingMessage; - return (this.required && this._isEmpty(this.textbox.value)) ? missing : invalid; // String - }, - - getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){ - // summary: - // Return a hint message to show when widget is first focused - // tags: - // protected - return this.promptMessage; // String - }, - - _maskValidSubsetError: true, - validate: function(/*Boolean*/ isFocused){ - // summary: - // Called by oninit, onblur, and onkeypress. - // description: - // Show missing or invalid messages if appropriate, and highlight textbox field. - // tags: - // protected - var message = ""; - var isValid = this.disabled || this.isValid(isFocused); - if(isValid){ this._maskValidSubsetError = true; } - var isEmpty = this._isEmpty(this.textbox.value); - var isValidSubset = !isValid && isFocused && this._isValidSubset(); - this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && (this._maskValidSubsetError || (isValidSubset && !this._hasBeenBlurred && isFocused))) ? "Incomplete" : "Error")); - this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true"); - - if(this.state == "Error"){ - this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus - message = this.getErrorMessage(isFocused); - }else if(this.state == "Incomplete"){ - message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete - this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused - }else if(isEmpty){ - message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text - } - this.set("message", message); - - return isValid; - }, - - displayMessage: function(/*String*/ message){ - // summary: - // Overridable method to display validation errors/hints. - // By default uses a tooltip. - // tags: - // extension - if(message && this.focused){ - Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight()); - }else{ - Tooltip.hide(this.domNode); - } - }, - - _refreshState: function(){ - // Overrides TextBox._refreshState() - if(this._created){ - this.validate(this.focused); - } - this.inherited(arguments); - }, - - //////////// INITIALIZATION METHODS /////////////////////////////////////// - - constructor: function(params /*===== , srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree. - - this.constraints = {}; - this.baseClass += ' dijitValidationTextBox'; - }, - - startup: function(){ - this.inherited(arguments); - this._refreshState(); // after all _set* methods have run - }, - - _setConstraintsAttr: function(/*__Constraints*/ constraints){ - if(!constraints.locale && this.lang){ - constraints.locale = this.lang; - } - this._set("constraints", constraints); - this._refreshState(); - }, - - _setPatternAttr: function(/*String|Function*/ pattern){ - this._set("pattern", pattern); // don't set on INPUT to avoid native HTML5 validation - }, - - _getPatternAttr: function(/*__Constraints*/ constraints){ - // summary: - // Hook to get the current regExp and to compute the partial validation RE. - var p = this.pattern; - var type = (typeof p).toLowerCase(); - if(type == "function"){ - p = this.pattern(constraints || this.constraints); - } - if(p != this._lastRegExp){ - var partialre = ""; - this._lastRegExp = p; - // parse the regexp and produce a new regexp that matches valid subsets - // if the regexp is .* then there's no use in matching subsets since everything is valid - if(p != ".*"){ - p.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g, - function(re){ - switch(re.charAt(0)){ - case '{': - case '+': - case '?': - case '*': - case '^': - case '$': - case '|': - case '(': - partialre += re; - break; - case ")": - partialre += "|$)"; - break; - default: - partialre += "(?:"+re+"|$)"; - break; - } - }); - } - try{ // this is needed for now since the above regexp parsing needs more test verification - "".search(partialre); - }catch(e){ // should never be here unless the original RE is bad or the parsing is bad - partialre = this.pattern; - console.warn('RegExp error in ' + this.declaredClass + ': ' + this.pattern); - } // should never be here unless the original RE is bad or the parsing is bad - this._partialre = "^(?:" + partialre + ")$"; - } - return p; - }, - - postMixInProperties: function(){ - this.inherited(arguments); - this.messages = i18n.getLocalization("dijit.form", "validate", this.lang); - this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints - }, - - _setDisabledAttr: function(/*Boolean*/ value){ - this.inherited(arguments); // call FormValueWidget._setDisabledAttr() - this._refreshState(); - }, - - _setRequiredAttr: function(/*Boolean*/ value){ - this._set("required", value); - this.focusNode.setAttribute("aria-required", value); - this._refreshState(); - }, - - _setMessageAttr: function(/*String*/ message){ - this._set("message", message); - this.displayMessage(message); - }, - - reset:function(){ - // Overrides dijit/form/TextBox.reset() by also - // hiding errors about partial matches - this._maskValidSubsetError = true; - this.inherited(arguments); - }, - - _onBlur: function(){ - // the message still exists but for back-compat, and to erase the tooltip - // (if the message is being displayed as a tooltip), call displayMessage('') - this.displayMessage(''); - - this.inherited(arguments); - } - }); -}); - -}, -'dijit/_base/typematic':function(){ -define("dijit/_base/typematic", ["../typematic"], function(){ - - /*===== - return { - // summary: - // Deprecated, for back-compat, just loads top level module - }; - =====*/ - -}); - -}, -'dijit/layout/BorderContainer':function(){ -define("dijit/layout/BorderContainer", [ - "dojo/_base/array", // array.filter array.forEach array.map - "dojo/cookie", // cookie - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.remove domClass.toggle - "dojo/dom-construct", // domConstruct.destroy domConstruct.place - "dojo/dom-geometry", // domGeometry.marginBox - "dojo/dom-style", // domStyle.style - "dojo/_base/event", // event.stop - "dojo/keys", - "dojo/_base/lang", // lang.getObject lang.hitch - "dojo/on", - "dojo/touch", - "../_WidgetBase", - "../_Widget", - "../_TemplatedMixin", - "./_LayoutWidget", - "./utils" // layoutUtils.layoutChildren -], function(array, cookie, declare, domClass, domConstruct, domGeometry, domStyle, event, keys, lang, on, touch, - _WidgetBase, _Widget, _TemplatedMixin, _LayoutWidget, layoutUtils){ - -// module: -// dijit/layout/BorderContainer - -var _Splitter = declare("dijit.layout._Splitter", [_Widget, _TemplatedMixin ], -{ - // summary: - // A draggable spacer between two items in a `dijit/layout/BorderContainer`. - // description: - // This is instantiated by `dijit/layout/BorderContainer`. Users should not - // create it directly. - // tags: - // private - -/*===== - // container: [const] dijit/layout/BorderContainer - // Pointer to the parent BorderContainer - container: null, - - // child: [const] dijit/layout/_LayoutWidget - // Pointer to the pane associated with this splitter - child: null, - - // region: [const] String - // Region of pane associated with this splitter. - // "top", "bottom", "left", "right". - region: null, -=====*/ - - // live: [const] Boolean - // If true, the child's size changes and the child widget is redrawn as you drag the splitter; - // otherwise, the size doesn't change until you drop the splitter (by mouse-up) - live: true, - - templateString: '<div class="dijitSplitter" data-dojo-attach-event="onkeypress:_onKeyPress,press:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" role="separator"><div class="dijitSplitterThumb"></div></div>', - - constructor: function(){ - this._handlers = []; - }, - - postMixInProperties: function(){ - this.inherited(arguments); - - this.horizontal = /top|bottom/.test(this.region); - this._factor = /top|left/.test(this.region) ? 1 : -1; - this._cookieName = this.container.id + "_" + this.region; - }, - - buildRendering: function(){ - this.inherited(arguments); - - domClass.add(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V")); - - if(this.container.persist){ - // restore old size - var persistSize = cookie(this._cookieName); - if(persistSize){ - this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize; - } - } - }, - - _computeMaxSize: function(){ - // summary: - // Return the maximum size that my corresponding pane can be set to - - var dim = this.horizontal ? 'h' : 'w', - childSize = domGeometry.getMarginBox(this.child.domNode)[dim], - center = array.filter(this.container.getChildren(), function(child){ return child.region == "center";})[0], - spaceAvailable = domGeometry.getMarginBox(center.domNode)[dim]; // can expand until center is crushed to 0 - - return Math.min(this.child.maxSize, childSize + spaceAvailable); - }, - - _startDrag: function(e){ - if(!this.cover){ - this.cover = domConstruct.place("<div class=dijitSplitterCover></div>", this.child.domNode, "after"); - } - domClass.add(this.cover, "dijitSplitterCoverActive"); - - // Safeguard in case the stop event was missed. Shouldn't be necessary if we always get the mouse up. - if(this.fake){ domConstruct.destroy(this.fake); } - if(!(this._resize = this.live)){ //TODO: disable live for IE6? - // create fake splitter to display at old position while we drag - (this.fake = this.domNode.cloneNode(true)).removeAttribute("id"); - domClass.add(this.domNode, "dijitSplitterShadow"); - domConstruct.place(this.fake, this.domNode, "after"); - } - domClass.add(this.domNode, "dijitSplitterActive dijitSplitter" + (this.horizontal ? "H" : "V") + "Active"); - if(this.fake){ - domClass.remove(this.fake, "dijitSplitterHover dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover"); - } - - //Performance: load data info local vars for onmousevent function closure - var factor = this._factor, - isHorizontal = this.horizontal, - axis = isHorizontal ? "pageY" : "pageX", - pageStart = e[axis], - splitterStyle = this.domNode.style, - dim = isHorizontal ? 'h' : 'w', - childStart = domGeometry.getMarginBox(this.child.domNode)[dim], - max = this._computeMaxSize(), - min = this.child.minSize || 20, - region = this.region, - splitterAttr = region == "top" || region == "bottom" ? "top" : "left", // style attribute of splitter to adjust - splitterStart = parseInt(splitterStyle[splitterAttr], 10), - resize = this._resize, - layoutFunc = lang.hitch(this.container, "_layoutChildren", this.child.id), - de = this.ownerDocument; - - this._handlers = this._handlers.concat([ - on(de, touch.move, this._drag = function(e, forceResize){ - var delta = e[axis] - pageStart, - childSize = factor * delta + childStart, - boundChildSize = Math.max(Math.min(childSize, max), min); - - if(resize || forceResize){ - layoutFunc(boundChildSize); - } - // TODO: setting style directly (usually) sets content box size, need to set margin box size - splitterStyle[splitterAttr] = delta + splitterStart + factor*(boundChildSize - childSize) + "px"; - }), - on(de, "dragstart", event.stop), - on(this.ownerDocumentBody, "selectstart", event.stop), - on(de, touch.release, lang.hitch(this, "_stopDrag")) - ]); - event.stop(e); - }, - - _onMouse: function(e){ - // summary: - // Handler for onmouseenter / onmouseleave events - var o = (e.type == "mouseover" || e.type == "mouseenter"); - domClass.toggle(this.domNode, "dijitSplitterHover", o); - domClass.toggle(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o); - }, - - _stopDrag: function(e){ - try{ - if(this.cover){ - domClass.remove(this.cover, "dijitSplitterCoverActive"); - } - if(this.fake){ domConstruct.destroy(this.fake); } - domClass.remove(this.domNode, "dijitSplitterActive dijitSplitter" - + (this.horizontal ? "H" : "V") + "Active dijitSplitterShadow"); - this._drag(e); //TODO: redundant with onmousemove? - this._drag(e, true); - }finally{ - this._cleanupHandlers(); - delete this._drag; - } - - if(this.container.persist){ - cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365}); - } - }, - - _cleanupHandlers: function(){ - var h; - while(h = this._handlers.pop()){ h.remove(); } - }, - - _onKeyPress: function(/*Event*/ e){ - // should we apply typematic to this? - this._resize = true; - var horizontal = this.horizontal; - var tick = 1; - switch(e.charOrCode){ - case horizontal ? keys.UP_ARROW : keys.LEFT_ARROW: - tick *= -1; -// break; - case horizontal ? keys.DOWN_ARROW : keys.RIGHT_ARROW: - break; - default: -// this.inherited(arguments); - return; - } - var childSize = domGeometry.getMarginSize(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick; - this.container._layoutChildren(this.child.id, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize)); - event.stop(e); - }, - - destroy: function(){ - this._cleanupHandlers(); - delete this.child; - delete this.container; - delete this.cover; - delete this.fake; - this.inherited(arguments); - } -}); - -var _Gutter = declare("dijit.layout._Gutter", [_Widget, _TemplatedMixin], -{ - // summary: - // Just a spacer div to separate side pane from center pane. - // Basically a trick to lookup the gutter/splitter width from the theme. - // description: - // Instantiated by `dijit/layout/BorderContainer`. Users should not - // create directly. - // tags: - // private - - templateString: '<div class="dijitGutter" role="presentation"></div>', - - postMixInProperties: function(){ - this.inherited(arguments); - this.horizontal = /top|bottom/.test(this.region); - }, - - buildRendering: function(){ - this.inherited(arguments); - domClass.add(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V")); - } -}); - -var BorderContainer = declare("dijit.layout.BorderContainer", _LayoutWidget, { - // summary: - // Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides. - // description: - // A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;", - // that contains a child widget marked region="center" and optionally children widgets marked - // region equal to "top", "bottom", "leading", "trailing", "left" or "right". - // Children along the edges will be laid out according to width or height dimensions and may - // include optional splitters (splitter="true") to make them resizable by the user. The remaining - // space is designated for the center region. - // - // The outer size must be specified on the BorderContainer node. Width must be specified for the sides - // and height for the top and bottom, respectively. No dimensions should be specified on the center; - // it will fill the remaining space. Regions named "leading" and "trailing" may be used just like - // "left" and "right" except that they will be reversed in right-to-left environments. - // - // For complex layouts, multiple children can be specified for a single region. In this case, the - // layoutPriority flag on the children determines which child is closer to the edge (low layoutPriority) - // and which child is closer to the center (high layoutPriority). layoutPriority can also be used - // instead of the design attribute to control layout precedence of horizontal vs. vertical panes. - // - // See `BorderContainer.ChildWidgetProperties` for details on the properties that can be set on - // children of a `BorderContainer`. - // example: - // | <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design: 'sidebar', gutters: false" - // | style="width: 400px; height: 300px;"> - // | <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'top'">header text</div> - // | <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'right', splitter: true" style="width: 200px;">table of contents</div> - // | <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">client area</div> - // | </div> - - // design: String - // Which design is used for the layout: - // - // - "headline" (default) where the top and bottom extend the full width of the container - // - "sidebar" where the left and right sides extend from top to bottom. - design: "headline", - - // gutters: [const] Boolean - // Give each pane a border and margin. - // Margin determined by domNode.paddingLeft. - // When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing. - gutters: true, - - // liveSplitters: [const] Boolean - // Specifies whether splitters resize as you drag (true) or only upon mouseup (false) - liveSplitters: true, - - // persist: Boolean - // Save splitter positions in a cookie. - persist: false, - - baseClass: "dijitBorderContainer", - - // _splitterClass: Function||String - // Optional hook to override the default Splitter widget used by BorderContainer - _splitterClass: _Splitter, - - postMixInProperties: function(){ - // change class name to indicate that BorderContainer is being used purely for - // layout (like LayoutContainer) rather than for pretty formatting. - if(!this.gutters){ - this.baseClass += "NoGutter"; - } - this.inherited(arguments); - }, - - startup: function(){ - if(this._started){ return; } - array.forEach(this.getChildren(), this._setupChild, this); - this.inherited(arguments); - }, - - _setupChild: function(/*dijit/_WidgetBase*/ child){ - // Override _LayoutWidget._setupChild(). - - var region = child.region; - if(region){ - this.inherited(arguments); - - domClass.add(child.domNode, this.baseClass+"Pane"); - - var ltr = this.isLeftToRight(); - if(region == "leading"){ region = ltr ? "left" : "right"; } - if(region == "trailing"){ region = ltr ? "right" : "left"; } - - // Create draggable splitter for resizing pane, - // or alternately if splitter=false but BorderContainer.gutters=true then - // insert dummy div just for spacing - if(region != "center" && (child.splitter || this.gutters) && !child._splitterWidget){ - var _Splitter = child.splitter ? this._splitterClass : _Gutter; - if(lang.isString(_Splitter)){ - _Splitter = lang.getObject(_Splitter); // for back-compat, remove in 2.0 - } - var splitter = new _Splitter({ - id: child.id + "_splitter", - container: this, - child: child, - region: region, - live: this.liveSplitters - }); - splitter.isSplitter = true; - child._splitterWidget = splitter; - - domConstruct.place(splitter.domNode, child.domNode, "after"); - - // Splitters aren't added as Contained children, so we need to call startup explicitly - splitter.startup(); - } - child.region = region; // TODO: technically wrong since it overwrites "trailing" with "left" etc. - } - }, - - layout: function(){ - // Implement _LayoutWidget.layout() virtual method. - this._layoutChildren(); - }, - - addChild: function(/*dijit/_WidgetBase*/ child, /*Integer?*/ insertIndex){ - // Override _LayoutWidget.addChild(). - this.inherited(arguments); - if(this._started){ - this.layout(); //OPT - } - }, - - removeChild: function(/*dijit/_WidgetBase*/ child){ - // Override _LayoutWidget.removeChild(). - - var region = child.region; - var splitter = child._splitterWidget; - if(splitter){ - splitter.destroy(); - delete child._splitterWidget; - } - this.inherited(arguments); - - if(this._started){ - this._layoutChildren(); - } - // Clean up whatever style changes we made to the child pane. - // Unclear how height and width should be handled. - domClass.remove(child.domNode, this.baseClass+"Pane"); - domStyle.set(child.domNode, { - top: "auto", - bottom: "auto", - left: "auto", - right: "auto", - position: "static" - }); - domStyle.set(child.domNode, region == "top" || region == "bottom" ? "width" : "height", "auto"); - }, - - getChildren: function(){ - // Override _LayoutWidget.getChildren() to only return real children, not the splitters. - return array.filter(this.inherited(arguments), function(widget){ - return !widget.isSplitter; - }); - }, - - // TODO: remove in 2.0 - getSplitter: function(/*String*/region){ - // summary: - // Returns the widget responsible for rendering the splitter associated with region - // tags: - // deprecated - return array.filter(this.getChildren(), function(child){ - return child.region == region; - })[0]._splitterWidget; - }, - - resize: function(newSize, currentSize){ - // Overrides _LayoutWidget.resize(). - - // resetting potential padding to 0px to provide support for 100% width/height + padding - // TODO: this hack doesn't respect the box model and is a temporary fix - if(!this.cs || !this.pe){ - var node = this.domNode; - this.cs = domStyle.getComputedStyle(node); - this.pe = domGeometry.getPadExtents(node, this.cs); - this.pe.r = domStyle.toPixelValue(node, this.cs.paddingRight); - this.pe.b = domStyle.toPixelValue(node, this.cs.paddingBottom); - - domStyle.set(node, "padding", "0px"); - } - - this.inherited(arguments); - }, - - _layoutChildren: function(/*String?*/ changedChildId, /*Number?*/ changedChildSize){ - // summary: - // This is the main routine for setting size/position of each child. - // description: - // With no arguments, measures the height of top/bottom panes, the width - // of left/right panes, and then sizes all panes accordingly. - // - // With changedRegion specified (as "left", "top", "bottom", or "right"), - // it changes that region's width/height to changedRegionSize and - // then resizes other regions that were affected. - // changedChildId: - // Id of the child which should be resized because splitter was dragged. - // changedChildSize: - // The new width/height (in pixels) to make specified child - - if(!this._borderBox || !this._borderBox.h){ - // We are currently hidden, or we haven't been sized by our parent yet. - // Abort. Someone will resize us later. - return; - } - - // Generate list of wrappers of my children in the order that I want layoutChildren() - // to process them (i.e. from the outside to the inside) - var wrappers = array.map(this.getChildren(), function(child, idx){ - return { - pane: child, - weight: [ - child.region == "center" ? Infinity : 0, - child.layoutPriority, - (this.design == "sidebar" ? 1 : -1) * (/top|bottom/.test(child.region) ? 1 : -1), - idx - ] - }; - }, this); - wrappers.sort(function(a, b){ - var aw = a.weight, bw = b.weight; - for(var i=0; i<aw.length; i++){ - if(aw[i] != bw[i]){ - return aw[i] - bw[i]; - } - } - return 0; - }); - - // Make new list, combining the externally specified children with splitters and gutters - var childrenAndSplitters = []; - array.forEach(wrappers, function(wrapper){ - var pane = wrapper.pane; - childrenAndSplitters.push(pane); - if(pane._splitterWidget){ - childrenAndSplitters.push(pane._splitterWidget); - } - }); - - // Compute the box in which to lay out my children - var dim = { - l: this.pe.l, - t: this.pe.t, - w: this._borderBox.w - this.pe.w, - h: this._borderBox.h - this.pe.h - }; - - // Layout the children, possibly changing size due to a splitter drag - layoutUtils.layoutChildren(this.domNode, dim, childrenAndSplitters, - changedChildId, changedChildSize); - }, - - destroyRecursive: function(){ - // Destroy splitters first, while getChildren() still works - array.forEach(this.getChildren(), function(child){ - var splitter = child._splitterWidget; - if(splitter){ - splitter.destroy(); - } - delete child._splitterWidget; - }); - - // Then destroy the real children, and myself - this.inherited(arguments); - } -}); - -BorderContainer.ChildWidgetProperties = { - // summary: - // These properties can be specified for the children of a BorderContainer. - - // region: [const] String - // Values: "top", "bottom", "leading", "trailing", "left", "right", "center". - // See the `dijit/layout/BorderContainer` description for details. - region: '', - - // layoutPriority: [const] Number - // Children with a higher layoutPriority will be placed closer to the BorderContainer center, - // between children with a lower layoutPriority. - layoutPriority: 0, - - // splitter: [const] Boolean - // Parameter for children where region != "center". - // If true, enables user to resize the widget by putting a draggable splitter between - // this widget and the region=center widget. - splitter: false, - - // minSize: [const] Number - // Specifies a minimum size (in pixels) for this widget when resized by a splitter. - minSize: 0, - - // maxSize: [const] Number - // Specifies a maximum size (in pixels) for this widget when resized by a splitter. - maxSize: Infinity -}; - -// Since any widget can be specified as a LayoutContainer child, mix it -// into the base widget class. (This is a hack, but it's effective.) -// This is for the benefit of the parser. Remove for 2.0. Also, hide from doc viewer. -lang.extend(_WidgetBase, /*===== {} || =====*/ BorderContainer.ChildWidgetProperties); - -// For monkey patching -BorderContainer._Splitter = _Splitter; -BorderContainer._Gutter = _Gutter; - -return BorderContainer; -}); - -}, -'dijit/_base':function(){ -define("dijit/_base", [ - "./main", - "./a11y", // used to be in dijit/_base/manager - "./WidgetSet", // used to be in dijit/_base/manager - "./_base/focus", - "./_base/manager", - "./_base/place", - "./_base/popup", - "./_base/scroll", - "./_base/sniff", - "./_base/typematic", - "./_base/wai", - "./_base/window" -], function(dijit){ - - // module: - // dijit/_base - - /*===== - return { - // summary: - // Includes all the modules in dijit/_base - }; - =====*/ - - return dijit._base; -}); - -}, -'dojo/window':function(){ -define("dojo/window", ["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style"], - function(lang, has, baseWindow, dom, geom, style){ - - // module: - // dojo/window - - var window = { - // summary: - // TODOC - - getBox: function(/*Document?*/ doc){ - // summary: - // Returns the dimensions and scroll position of the viewable area of a browser window - - doc = doc || baseWindow.doc; - - var - scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement, - // get scroll position - scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work - w, h; - - if(has("touch")){ // if(scrollbars not supported) - var uiWindow = window.get(doc); // use UI window, not dojo.global window - // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight - w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated - h = uiWindow.innerHeight || scrollRoot.clientHeight; - }else{ - // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight - // uiWindow.innerWidth/Height includes the scrollbar and cannot be used - w = scrollRoot.clientWidth; - h = scrollRoot.clientHeight; - } - return { - l: scroll.x, - t: scroll.y, - w: w, - h: h - }; - }, - - get: function(/*Document*/ doc){ - // summary: - // Get window object associated with document doc. - // doc: - // The document to get the associated window for. - - // In some IE versions (at least 6.0), document.parentWindow does not return a - // reference to the real window object (maybe a copy), so we must fix it as well - // We use IE specific execScript to attach the real window reference to - // document._parentWindow for later use - if(has("ie") && window !== document.parentWindow){ - /* - In IE 6, only the variable "window" can be used to connect events (others - may be only copies). - */ - doc.parentWindow.execScript("document._parentWindow = window;", "Javascript"); - //to prevent memory leak, unset it after use - //another possibility is to add an onUnload handler which seems overkill to me (liucougar) - var win = doc._parentWindow; - doc._parentWindow = null; - return win; // Window - } - - return doc.parentWindow || doc.defaultView; // Window - }, - - scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){ - // summary: - // Scroll the passed node into view, if it is not already. - - // don't rely on node.scrollIntoView working just because the function is there - - try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method - node = dom.byId(node); - var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined? - body = baseWindow.body(doc), - html = doc.documentElement || body.parentNode, - isIE = has("ie"), isWK = has("webkit"); - // if an untested browser, then use the native method - if((!(has("mozilla") || isIE || isWK || has("opera")) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){ - node.scrollIntoView(false); // short-circuit to native if possible - return; - } - var backCompat = doc.compatMode == 'BackCompat', - clientAreaRoot = (isIE >= 9 && "frameElement" in node.ownerDocument.parentWindow) - ? ((html.clientHeight > 0 && html.clientWidth > 0 && (body.clientHeight == 0 || body.clientWidth == 0 || body.clientHeight > html.clientHeight || body.clientWidth > html.clientWidth)) ? html : body) - : (backCompat ? body : html), - scrollRoot = isWK ? body : clientAreaRoot, - rootWidth = clientAreaRoot.clientWidth, - rootHeight = clientAreaRoot.clientHeight, - rtl = !geom.isBodyLtr(doc), - nodePos = pos || geom.position(node), - el = node.parentNode, - isFixed = function(el){ - return ((isIE <= 6 || (isIE && backCompat))? false : (style.get(el, 'position').toLowerCase() == "fixed")); - }; - if(isFixed(node)){ return; } // nothing to do - - while(el){ - if(el == body){ el = scrollRoot; } - var elPos = geom.position(el), - fixedPos = isFixed(el); - - if(el == scrollRoot){ - elPos.w = rootWidth; elPos.h = rootHeight; - if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x - if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0 - if(elPos.y < 0 || !isIE){ elPos.y = 0; } - }else{ - var pb = geom.getPadBorderExtents(el); - elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; - var clientSize = el.clientWidth, - scrollBarSize = elPos.w - clientSize; - if(clientSize > 0 && scrollBarSize > 0){ - elPos.w = clientSize; - elPos.x += (rtl && (isIE || el.clientLeft > pb.l/*Chrome*/)) ? scrollBarSize : 0; - } - clientSize = el.clientHeight; - scrollBarSize = elPos.h - clientSize; - if(clientSize > 0 && scrollBarSize > 0){ - elPos.h = clientSize; - } - } - if(fixedPos){ // bounded by viewport, not parents - if(elPos.y < 0){ - elPos.h += elPos.y; elPos.y = 0; - } - if(elPos.x < 0){ - elPos.w += elPos.x; elPos.x = 0; - } - if(elPos.y + elPos.h > rootHeight){ - elPos.h = rootHeight - elPos.y; - } - if(elPos.x + elPos.w > rootWidth){ - elPos.w = rootWidth - elPos.x; - } - } - // calculate overflow in all 4 directions - var l = nodePos.x - elPos.x, // beyond left: < 0 - t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0 - r = l + nodePos.w - elPos.w, // beyond right: > 0 - bot = t + nodePos.h - elPos.h; // beyond bottom: > 0 - if(r * l > 0){ - var s = Math[l < 0? "max" : "min"](l, r); - if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; } - nodePos.x += el.scrollLeft; - el.scrollLeft += s; - nodePos.x -= el.scrollLeft; - } - if(bot * t > 0){ - nodePos.y += el.scrollTop; - el.scrollTop += Math[t < 0? "max" : "min"](t, bot); - nodePos.y -= el.scrollTop; - } - el = (el != scrollRoot) && !fixedPos && el.parentNode; - } - }catch(error){ - console.error('scrollIntoView: ' + error); - node.scrollIntoView(false); - } - } - }; - - 1 && lang.setObject("dojo.window", window); - - return window; -}); - -}, -'dojo/number':function(){ -define("dojo/number", [/*===== "./_base/declare", =====*/ "./_base/lang", "./i18n", "./i18n!./cldr/nls/number", "./string", "./regexp"], - function(/*===== declare, =====*/ lang, i18n, nlsNumber, dstring, dregexp){ - -// module: -// dojo/number - -var number = { - // summary: - // localized formatting and parsing routines for Number -}; -lang.setObject("dojo.number", number); - -/*===== -number.__FormatOptions = declare(null, { - // pattern: String? - // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) - // with this string. Default value is based on locale. Overriding this property will defeat - // localization. Literal characters in patterns are not supported. - // type: String? - // choose a format type based on the locale from the following: - // decimal, scientific (not yet supported), percent, currency. decimal by default. - // places: Number? - // fixed number of decimal places to show. This overrides any - // information in the provided pattern. - // round: Number? - // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 - // means do not round. - // locale: String? - // override the locale used to determine formatting rules - // fractional: Boolean? - // If false, show no decimal places, overriding places and pattern settings. -}); -=====*/ - -number.format = function(/*Number*/ value, /*number.__FormatOptions?*/ options){ - // summary: - // Format a Number as a String, using locale-specific settings - // description: - // Create a string from a Number using a known localized pattern. - // Formatting patterns appropriate to the locale are chosen from the - // [Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and - // delimiters. - // If value is Infinity, -Infinity, or is not a valid JavaScript number, return null. - // value: - // the number to be formatted - - options = lang.mixin({}, options || {}); - var locale = i18n.normalizeLocale(options.locale), - bundle = i18n.getLocalization("dojo.cldr", "number", locale); - options.customs = bundle; - var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"]; - if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null - return number._applyPattern(value, pattern, options); // String -}; - -//number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough -number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough - -number._applyPattern = function(/*Number*/ value, /*String*/ pattern, /*number.__FormatOptions?*/ options){ - // summary: - // Apply pattern to format value as a string using options. Gives no - // consideration to local customs. - // value: - // the number to be formatted. - // pattern: - // a pattern string as described by - // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) - // options: number.__FormatOptions? - // _applyPattern is usually called via `dojo/number.format()` which - // populates an extra property in the options parameter, "customs". - // The customs object specifies group and decimal parameters if set. - - //TODO: support escapes - options = options || {}; - var group = options.customs.group, - decimal = options.customs.decimal, - patternList = pattern.split(';'), - positivePattern = patternList[0]; - pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern); - - //TODO: only test against unescaped - if(pattern.indexOf('%') != -1){ - value *= 100; - }else if(pattern.indexOf('\u2030') != -1){ - value *= 1000; // per mille - }else if(pattern.indexOf('\u00a4') != -1){ - group = options.customs.currencyGroup || group;//mixins instead? - decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead? - pattern = pattern.replace(/\u00a4{1,3}/, function(match){ - var prop = ["symbol", "currency", "displayName"][match.length-1]; - return options[prop] || options.currency || ""; - }); - }else if(pattern.indexOf('E') != -1){ - throw new Error("exponential notation not supported"); - } - - //TODO: support @ sig figs? - var numberPatternRE = number._numberPatternRE; - var numberPattern = positivePattern.match(numberPatternRE); - if(!numberPattern){ - throw new Error("unable to find a number expression in pattern: "+pattern); - } - if(options.fractional === false){ options.places = 0; } - return pattern.replace(numberPatternRE, - number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round})); -}; - -number.round = function(/*Number*/ value, /*Number?*/ places, /*Number?*/ increment){ - // summary: - // Rounds to the nearest value with the given number of decimal places, away from zero - // description: - // Rounds to the nearest value with the given number of decimal places, away from zero if equal. - // Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by - // fractional increments also, such as the nearest quarter. - // NOTE: Subject to floating point errors. See dojox/math/round for experimental workaround. - // value: - // The number to round - // places: - // The number of decimal places where rounding takes place. Defaults to 0 for whole rounding. - // Must be non-negative. - // increment: - // Rounds next place to nearest value of increment/10. 10 by default. - // example: - // | >>> number.round(-0.5) - // | -1 - // | >>> number.round(162.295, 2) - // | 162.29 // note floating point error. Should be 162.3 - // | >>> number.round(10.71, 0, 2.5) - // | 10.75 - var factor = 10 / (increment || 10); - return (factor * +value).toFixed(places) / factor; // Number -}; - -if((0.9).toFixed() == 0){ - // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit - // is just after the rounding place and is >=5 - var round = number.round; - number.round = function(v, p, m){ - var d = Math.pow(10, -p || 0), a = Math.abs(v); - if(!v || a >= d){ - d = 0; - }else{ - a /= d; - if(a < 0.5 || a >= 0.95){ - d = 0; - } - } - return round(v, p, m) + (v > 0 ? d : -d); - }; - - // Use "doc hint" so the doc parser ignores this new definition of round(), and uses the one above. - /*===== number.round = round; =====*/ -} - -/*===== -number.__FormatAbsoluteOptions = declare(null, { - // decimal: String? - // the decimal separator - // group: String? - // the group separator - // places: Number|String? - // number of decimal places. the range "n,m" will format to m places. - // round: Number? - // 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 - // means don't round. -}); -=====*/ - -number._formatAbsolute = function(/*Number*/ value, /*String*/ pattern, /*number.__FormatAbsoluteOptions?*/ options){ - // summary: - // Apply numeric pattern to absolute value using options. Gives no - // consideration to local customs. - // value: - // the number to be formatted, ignores sign - // pattern: - // the number portion of a pattern (e.g. `#,##0.00`) - options = options || {}; - if(options.places === true){options.places=0;} - if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit - - var patternParts = pattern.split("."), - comma = typeof options.places == "string" && options.places.indexOf(","), - maxPlaces = options.places; - if(comma){ - maxPlaces = options.places.substring(comma + 1); - }else if(!(maxPlaces >= 0)){ - maxPlaces = (patternParts[1] || []).length; - } - if(!(options.round < 0)){ - value = number.round(value, maxPlaces, options.round); - } - - var valueParts = String(Math.abs(value)).split("."), - fractional = valueParts[1] || ""; - if(patternParts[1] || options.places){ - if(comma){ - options.places = options.places.substring(0, comma); - } - // Pad fractional with trailing zeros - var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1); - if(pad > fractional.length){ - valueParts[1] = dstring.pad(fractional, pad, '0', true); - } - - // Truncate fractional - if(maxPlaces < fractional.length){ - valueParts[1] = fractional.substr(0, maxPlaces); - } - }else{ - if(valueParts[1]){ valueParts.pop(); } - } - - // Pad whole with leading zeros - var patternDigits = patternParts[0].replace(',', ''); - pad = patternDigits.indexOf("0"); - if(pad != -1){ - pad = patternDigits.length - pad; - if(pad > valueParts[0].length){ - valueParts[0] = dstring.pad(valueParts[0], pad); - } - - // Truncate whole - if(patternDigits.indexOf("#") == -1){ - valueParts[0] = valueParts[0].substr(valueParts[0].length - pad); - } - } - - // Add group separators - var index = patternParts[0].lastIndexOf(','), - groupSize, groupSize2; - if(index != -1){ - groupSize = patternParts[0].length - index - 1; - var remainder = patternParts[0].substr(0, index); - index = remainder.lastIndexOf(','); - if(index != -1){ - groupSize2 = remainder.length - index - 1; - } - } - var pieces = []; - for(var whole = valueParts[0]; whole;){ - var off = whole.length - groupSize; - pieces.push((off > 0) ? whole.substr(off) : whole); - whole = (off > 0) ? whole.slice(0, off) : ""; - if(groupSize2){ - groupSize = groupSize2; - delete groupSize2; - } - } - valueParts[0] = pieces.reverse().join(options.group || ","); - - return valueParts.join(options.decimal || "."); -}; - -/*===== -number.__RegexpOptions = declare(null, { - // pattern: String? - // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) - // with this string. Default value is based on locale. Overriding this property will defeat - // localization. - // type: String? - // choose a format type based on the locale from the following: - // decimal, scientific (not yet supported), percent, currency. decimal by default. - // locale: String? - // override the locale used to determine formatting rules - // strict: Boolean? - // strict parsing, false by default. Strict parsing requires input as produced by the format() method. - // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators - // places: Number|String? - // number of decimal places to accept: Infinity, a positive number, or - // a range "n,m". Defined by pattern or Infinity if pattern not provided. -}); -=====*/ -number.regexp = function(/*number.__RegexpOptions?*/ options){ - // summary: - // Builds the regular needed to parse a number - // description: - // Returns regular expression with positive and negative match, group - // and decimal separators - return number._parseInfo(options).regexp; // String -}; - -number._parseInfo = function(/*Object?*/ options){ - options = options || {}; - var locale = i18n.normalizeLocale(options.locale), - bundle = i18n.getLocalization("dojo.cldr", "number", locale), - pattern = options.pattern || bundle[(options.type || "decimal") + "Format"], -//TODO: memoize? - group = bundle.group, - decimal = bundle.decimal, - factor = 1; - - if(pattern.indexOf('%') != -1){ - factor /= 100; - }else if(pattern.indexOf('\u2030') != -1){ - factor /= 1000; // per mille - }else{ - var isCurrency = pattern.indexOf('\u00a4') != -1; - if(isCurrency){ - group = bundle.currencyGroup || group; - decimal = bundle.currencyDecimal || decimal; - } - } - - //TODO: handle quoted escapes - var patternList = pattern.split(';'); - if(patternList.length == 1){ - patternList.push("-" + patternList[0]); - } - - var re = dregexp.buildGroupRE(patternList, function(pattern){ - pattern = "(?:"+dregexp.escapeString(pattern, '.')+")"; - return pattern.replace(number._numberPatternRE, function(format){ - var flags = { - signed: false, - separator: options.strict ? group : [group,""], - fractional: options.fractional, - decimal: decimal, - exponent: false - }, - - parts = format.split('.'), - places = options.places; - - // special condition for percent (factor != 1) - // allow decimal places even if not specified in pattern - if(parts.length == 1 && factor != 1){ - parts[1] = "###"; - } - if(parts.length == 1 || places === 0){ - flags.fractional = false; - }else{ - if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0') + 1 : Infinity; } - if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified - if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; } - flags.places = places; - } - var groups = parts[0].split(','); - if(groups.length > 1){ - flags.groupSize = groups.pop().length; - if(groups.length > 1){ - flags.groupSize2 = groups.pop().length; - } - } - return "("+number._realNumberRegexp(flags)+")"; - }); - }, true); - - if(isCurrency){ - // substitute the currency symbol for the placeholder in the pattern - re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){ - var prop = ["symbol", "currency", "displayName"][target.length-1], - symbol = dregexp.escapeString(options[prop] || options.currency || ""); - before = before ? "[\\s\\xa0]" : ""; - after = after ? "[\\s\\xa0]" : ""; - if(!options.strict){ - if(before){before += "*";} - if(after){after += "*";} - return "(?:"+before+symbol+after+")?"; - } - return before+symbol+after; - }); - } - -//TODO: substitute localized sign/percent/permille/etc.? - - // normalize whitespace and return - return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object -}; - -/*===== -number.__ParseOptions = declare(null, { - // pattern: String? - // override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) - // with this string. Default value is based on locale. Overriding this property will defeat - // localization. Literal characters in patterns are not supported. - // type: String? - // choose a format type based on the locale from the following: - // decimal, scientific (not yet supported), percent, currency. decimal by default. - // locale: String? - // override the locale used to determine formatting rules - // strict: Boolean? - // strict parsing, false by default. Strict parsing requires input as produced by the format() method. - // Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators - // fractional: Boolean|Array? - // Whether to include the fractional portion, where the number of decimal places are implied by pattern - // or explicit 'places' parameter. The value [true,false] makes the fractional portion optional. -}); -=====*/ -number.parse = function(/*String*/ expression, /*number.__ParseOptions?*/ options){ - // summary: - // Convert a properly formatted string to a primitive Number, using - // locale-specific settings. - // description: - // Create a Number from a string using a known localized pattern. - // Formatting patterns are chosen appropriate to the locale - // and follow the syntax described by - // [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns) - // Note that literal characters in patterns are not supported. - // expression: - // A string representation of a Number - var info = number._parseInfo(options), - results = (new RegExp("^"+info.regexp+"$")).exec(expression); - if(!results){ - return NaN; //NaN - } - var absoluteMatch = results[1]; // match for the positive expression - if(!results[1]){ - if(!results[2]){ - return NaN; //NaN - } - // matched the negative pattern - absoluteMatch =results[2]; - info.factor *= -1; - } - - // Transform it to something Javascript can parse as a number. Normalize - // decimal point and strip out group separators or alternate forms of whitespace - absoluteMatch = absoluteMatch. - replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), ""). - replace(info.decimal, "."); - // Adjust for negative sign, percent, etc. as necessary - return absoluteMatch * info.factor; //Number -}; - -/*===== -number.__RealNumberRegexpFlags = declare(null, { - // places: Number? - // The integer number of decimal places or a range given as "n,m". If - // not given, the decimal part is optional and the number of places is - // unlimited. - // decimal: String? - // A string for the character used as the decimal point. Default - // is ".". - // fractional: Boolean|Array? - // Whether decimal places are used. Can be true, false, or [true, - // false]. Default is [true, false] which means optional. - // exponent: Boolean|Array? - // Express in exponential notation. Can be true, false, or [true, - // false]. Default is [true, false], (i.e. will match if the - // exponential part is present are not). - // eSigned: Boolean|Array? - // The leading plus-or-minus sign on the exponent. Can be true, - // false, or [true, false]. Default is [true, false], (i.e. will - // match if it is signed or unsigned). flags in regexp.integer can be - // applied. -}); -=====*/ - -number._realNumberRegexp = function(/*__RealNumberRegexpFlags?*/ flags){ - // summary: - // Builds a regular expression to match a real number in exponential - // notation - - // assign default values to missing parameters - flags = flags || {}; - //TODO: use mixin instead? - if(!("places" in flags)){ flags.places = Infinity; } - if(typeof flags.decimal != "string"){ flags.decimal = "."; } - if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; } - if(!("exponent" in flags)){ flags.exponent = [true, false]; } - if(!("eSigned" in flags)){ flags.eSigned = [true, false]; } - - var integerRE = number._integerRegexp(flags), - decimalRE = dregexp.buildGroupRE(flags.fractional, - function(q){ - var re = ""; - if(q && (flags.places!==0)){ - re = "\\" + flags.decimal; - if(flags.places == Infinity){ - re = "(?:" + re + "\\d+)?"; - }else{ - re += "\\d{" + flags.places + "}"; - } - } - return re; - }, - true - ); - - var exponentRE = dregexp.buildGroupRE(flags.exponent, - function(q){ - if(q){ return "([eE]" + number._integerRegexp({ signed: flags.eSigned}) + ")"; } - return ""; - } - ); - - var realRE = integerRE + decimalRE; - // allow for decimals without integers, e.g. .25 - if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";} - return realRE + exponentRE; // String -}; - -/*===== -number.__IntegerRegexpFlags = declare(null, { - // signed: Boolean? - // The leading plus-or-minus sign. Can be true, false, or `[true,false]`. - // Default is `[true, false]`, (i.e. will match if it is signed - // or unsigned). - // separator: String? - // The character used as the thousands separator. Default is no - // separator. For more than one symbol use an array, e.g. `[",", ""]`, - // makes ',' optional. - // groupSize: Number? - // group size between separators - // groupSize2: Number? - // second grouping, where separators 2..n have a different interval than the first separator (for India) -}); -=====*/ - -number._integerRegexp = function(/*number.__IntegerRegexpFlags?*/ flags){ - // summary: - // Builds a regular expression that matches an integer - - // assign default values to missing parameters - flags = flags || {}; - if(!("signed" in flags)){ flags.signed = [true, false]; } - if(!("separator" in flags)){ - flags.separator = ""; - }else if(!("groupSize" in flags)){ - flags.groupSize = 3; - } - - var signRE = dregexp.buildGroupRE(flags.signed, - function(q){ return q ? "[-+]" : ""; }, - true - ); - - var numberRE = dregexp.buildGroupRE(flags.separator, - function(sep){ - if(!sep){ - return "(?:\\d+)"; - } - - sep = dregexp.escapeString(sep); - if(sep == " "){ sep = "\\s"; } - else if(sep == "\xa0"){ sep = "\\s\\xa0"; } - - var grp = flags.groupSize, grp2 = flags.groupSize2; - //TODO: should we continue to enforce that numbers with separators begin with 1-9? See #6933 - if(grp2){ - var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})"; - return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE; - } - return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)"; - }, - true - ); - - return signRE + numberRE; // String -}; - -return number; -}); - -}, -'dijit/_FocusMixin':function(){ -define("dijit/_FocusMixin", [ - "./focus", - "./_WidgetBase", - "dojo/_base/declare", // declare - "dojo/_base/lang" // lang.extend -], function(focus, _WidgetBase, declare, lang){ - - // module: - // dijit/_FocusMixin - - // We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below - // to be last in the inheritance chain, so mixin to _WidgetBase. - lang.extend(_WidgetBase, { - // focused: [readonly] Boolean - // This widget or a widget it contains has focus, or is "active" because - // it was recently clicked. - focused: false, - - onFocus: function(){ - // summary: - // Called when the widget becomes "active" because - // it or a widget inside of it either has focus, or has recently - // been clicked. - // tags: - // callback - }, - - onBlur: function(){ - // summary: - // Called when the widget stops being "active" because - // focus moved to something outside of it, or the user - // clicked somewhere outside of it, or the widget was - // hidden. - // tags: - // callback - }, - - _onFocus: function(){ - // summary: - // This is where widgets do processing for when they are active, - // such as changing CSS classes. See onFocus() for more details. - // tags: - // protected - this.onFocus(); - }, - - _onBlur: function(){ - // summary: - // This is where widgets do processing for when they stop being active, - // such as changing CSS classes. See onBlur() for more details. - // tags: - // protected - this.onBlur(); - } - }); - - return declare("dijit._FocusMixin", null, { - // summary: - // Mixin to widget to provide _onFocus() and _onBlur() methods that - // fire when a widget or its descendants get/lose focus - - // flag that I want _onFocus()/_onBlur() notifications from focus manager - _focusManager: focus - }); - -}); - -}, -'dojo/data/util/filter':function(){ -define("dojo/data/util/filter", ["../../_base/lang"], function(lang){ - // module: - // dojo/data/util/filter - // summary: - // TODOC - -var filter = {}; -lang.setObject("dojo.data.util.filter", filter); - -filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){ - // summary: - // Helper function to convert a simple pattern to a regular expression for matching. - // description: - // Returns a regular expression object that conforms to the defined conversion rules. - // For example: - // - // - ca* -> /^ca.*$/ - // - *ca* -> /^.*ca.*$/ - // - *c\*a* -> /^.*c\*a.*$/ - // - *c\*a?* -> /^.*c\*a..*$/ - // - // and so on. - // pattern: string - // A simple matching pattern to convert that follows basic rules: - // - // - * Means match anything, so ca* means match anything starting with ca - // - ? Means match single character. So, b?b will match to bob and bab, and so on. - // - \ is an escape character. So for example, \* means do not treat * as a match, but literal character *. - // - // To use a \ as a character in the string, it must be escaped. So in the pattern it should be - // represented by \\ to be treated as an ordinary \ character instead of an escape. - // ignoreCase: - // An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing - // By default, it is assumed case sensitive. - - var rxp = "^"; - var c = null; - for(var i = 0; i < pattern.length; i++){ - c = pattern.charAt(i); - switch(c){ - case '\\': - rxp += c; - i++; - rxp += pattern.charAt(i); - break; - case '*': - rxp += ".*"; break; - case '?': - rxp += "."; break; - case '$': - case '^': - case '/': - case '+': - case '.': - case '|': - case '(': - case ')': - case '{': - case '}': - case '[': - case ']': - rxp += "\\"; //fallthrough - default: - rxp += c; - } - } - rxp += "$"; - if(ignoreCase){ - return new RegExp(rxp,"mi"); //RegExp - }else{ - return new RegExp(rxp,"m"); //RegExp - } - -}; - -return filter; -}); - -}, -'dijit/_WidgetsInTemplateMixin':function(){ -define("dijit/_WidgetsInTemplateMixin", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/parser" // parser.parse -], function(array, declare, parser){ - - // module: - // dijit/_WidgetsInTemplateMixin - - return declare("dijit._WidgetsInTemplateMixin", null, { - // summary: - // Mixin to supplement _TemplatedMixin when template contains widgets - - // _earlyTemplatedStartup: Boolean - // A fallback to preserve the 1.0 - 1.3 behavior of children in - // templates having their startup called before the parent widget - // fires postCreate. Defaults to 'false', causing child widgets to - // have their .startup() called immediately before a parent widget - // .startup(), but always after the parent .postCreate(). Set to - // 'true' to re-enable to previous, arguably broken, behavior. - _earlyTemplatedStartup: false, - - // widgetsInTemplate: [protected] Boolean - // Should we parse the template to find widgets that might be - // declared in markup inside it? (Remove for 2.0 and assume true) - widgetsInTemplate: true, - - _beforeFillContent: function(){ - if(this.widgetsInTemplate){ - // Before copying over content, instantiate widgets in template - var node = this.domNode; - - var cw = (this._startupWidgets = parser.parse(node, { - noStart: !this._earlyTemplatedStartup, - template: true, - inherited: {dir: this.dir, lang: this.lang, textDir: this.textDir}, - propsThis: this, // so data-dojo-props of widgets in the template can reference "this" to refer to me - scope: "dojo" // even in multi-version mode templates use dojoType/data-dojo-type - })); - - if(!cw.isFulfilled()){ - throw new Error(this.declaredClass + ": parser returned unfilled promise (probably waiting for module auto-load), " + - "unsupported by _WidgetsInTemplateMixin. Must pre-load all supporting widgets before instantiation."); - } - - // _WidgetBase::destroy() will destroy any supporting widgets under this.domNode. - // If we wanted to, we could call this.own() on anything in this._startupWidgets that was moved outside - // of this.domNode (like Dialog, which is moved to <body>). - - this._attachTemplateNodes(cw, function(n,p){ - return n[p]; - }); - } - }, - - startup: function(){ - array.forEach(this._startupWidgets, function(w){ - if(w && !w._started && w.startup){ - w.startup(); - } - }); - this.inherited(arguments); - } - }); -}); - -}, -'dojo/fx/Toggler':function(){ -define("dojo/fx/Toggler", ["../_base/lang","../_base/declare","../_base/fx", "../_base/connect"], - function(lang, declare, baseFx, connectUtil){ - // module: - // dojo/fx/Toggler - -return declare("dojo.fx.Toggler", null, { - // summary: - // A simple `dojo.Animation` toggler API. - // description: - // class constructor for an animation toggler. It accepts a packed - // set of arguments about what type of animation to use in each - // direction, duration, etc. All available members are mixed into - // these animations from the constructor (for example, `node`, - // `showDuration`, `hideDuration`). - // example: - // | var t = new dojo/fx/Toggler({ - // | node: "nodeId", - // | showDuration: 500, - // | // hideDuration will default to "200" - // | showFunc: dojo/fx/wipeIn, - // | // hideFunc will default to "fadeOut" - // | }); - // | t.show(100); // delay showing for 100ms - // | // ...time passes... - // | t.hide(); - - // node: DomNode - // the node to target for the showing and hiding animations - node: null, - - // showFunc: Function - // The function that returns the `dojo.Animation` to show the node - showFunc: baseFx.fadeIn, - - // hideFunc: Function - // The function that returns the `dojo.Animation` to hide the node - hideFunc: baseFx.fadeOut, - - // showDuration: - // Time in milliseconds to run the show Animation - showDuration: 200, - - // hideDuration: - // Time in milliseconds to run the hide Animation - hideDuration: 200, - - // FIXME: need a policy for where the toggler should "be" the next - // time show/hide are called if we're stopped somewhere in the - // middle. - // FIXME: also would be nice to specify individual showArgs/hideArgs mixed into - // each animation individually. - // FIXME: also would be nice to have events from the animations exposed/bridged - - /*===== - _showArgs: null, - _showAnim: null, - - _hideArgs: null, - _hideAnim: null, - - _isShowing: false, - _isHiding: false, - =====*/ - - constructor: function(args){ - var _t = this; - - lang.mixin(_t, args); - _t.node = args.node; - _t._showArgs = lang.mixin({}, args); - _t._showArgs.node = _t.node; - _t._showArgs.duration = _t.showDuration; - _t.showAnim = _t.showFunc(_t._showArgs); - - _t._hideArgs = lang.mixin({}, args); - _t._hideArgs.node = _t.node; - _t._hideArgs.duration = _t.hideDuration; - _t.hideAnim = _t.hideFunc(_t._hideArgs); - - connectUtil.connect(_t.showAnim, "beforeBegin", lang.hitch(_t.hideAnim, "stop", true)); - connectUtil.connect(_t.hideAnim, "beforeBegin", lang.hitch(_t.showAnim, "stop", true)); - }, - - show: function(delay){ - // summary: - // Toggle the node to showing - // delay: Integer? - // Amount of time to stall playing the show animation - return this.showAnim.play(delay || 0); - }, - - hide: function(delay){ - // summary: - // Toggle the node to hidden - // delay: Integer? - // Amount of time to stall playing the hide animation - return this.hideAnim.play(delay || 0); - } -}); - -}); - -}, -'dijit/form/FilteringSelect':function(){ -define("dijit/form/FilteringSelect", [ - "dojo/data/util/filter", // filter.patternToRegExp - "dojo/_base/declare", // declare - "dojo/_base/lang", // lang.mixin - "dojo/when", - "./MappedTextBox", - "./ComboBoxMixin" -], function(filter, declare, lang, when, MappedTextBox, ComboBoxMixin){ - - // module: - // dijit/form/FilteringSelect - - return declare("dijit.form.FilteringSelect", [MappedTextBox, ComboBoxMixin], { - // summary: - // An enhanced version of the HTML SELECT tag, populated dynamically - // - // description: - // An enhanced version of the HTML SELECT tag, populated dynamically. It works - // very nicely with very large data sets because it can load and page data as needed. - // It also resembles ComboBox, but does not allow values outside of the provided ones. - // If OPTION tags are used as the data provider via markup, then the - // OPTION tag's child text node is used as the displayed value when selected - // while the OPTION tag's value attribute is used as the widget value on form submit. - // To set the default value when using OPTION tags, specify the selected - // attribute on 1 of the child OPTION tags. - // - // Similar features: - // - // - There is a drop down list of possible values. - // - You can only enter a value from the drop down list. (You can't - // enter an arbitrary value.) - // - The value submitted with the form is the hidden value (ex: CA), - // not the displayed value a.k.a. label (ex: California) - // - // Enhancements over plain HTML version: - // - // - If you type in some text then it will filter down the list of - // possible values in the drop down list. - // - List can be specified either as a static list or via a javascript - // function (that can get the list from a server) - - // required: Boolean - // True (default) if user is required to enter a value into this field. - required: true, - - _lastDisplayedValue: "", - - _isValidSubset: function(){ - return this._opened; - }, - - isValid: function(){ - // Overrides ValidationTextBox.isValid() - return !!this.item || (!this.required && this.get('displayedValue') == ""); // #5974 - }, - - _refreshState: function(){ - if(!this.searchTimer){ // state will be refreshed after results are returned - this.inherited(arguments); - } - }, - - _callbackSetLabel: function( - /*Array*/ result, - /*Object*/ query, - /*Object*/ options, - /*Boolean?*/ priorityChange){ - // summary: - // Callback from dojo.store after lookup of user entered value finishes - - // setValue does a synchronous lookup, - // so it calls _callbackSetLabel directly, - // and so does not pass dataObject - // still need to test against _lastQuery in case it came too late - if((query && query[this.searchAttr] !== this._lastQuery) || (!query && result.length && this.store.getIdentity(result[0]) != this._lastQuery)){ - return; - } - if(!result.length){ - //#3268: don't modify display value on bad input - //#3285: change CSS to indicate error - this.set("value", '', priorityChange || (priorityChange === undefined && !this.focused), this.textbox.value, null); - }else{ - this.set('item', result[0], priorityChange); - } - }, - - _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){ - // Callback when a data store query completes. - // Overrides ComboBox._openResultList() - - // #3285: tap into search callback to see if user's query resembles a match - if(query[this.searchAttr] !== this._lastQuery){ - return; - } - this.inherited(arguments); - - if(this.item === undefined){ // item == undefined for keyboard search - // If the search returned no items that means that the user typed - // in something invalid (and they can't make it valid by typing more characters), - // so flag the FilteringSelect as being in an invalid state - this.validate(true); - } - }, - - _getValueAttr: function(){ - // summary: - // Hook for get('value') to work. - - // don't get the textbox value but rather the previously set hidden value. - // Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur - return this.valueNode.value; - }, - - _getValueField: function(){ - // Overrides ComboBox._getValueField() - return "value"; - }, - - _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){ - // summary: - // Hook so set('value', value) works. - // description: - // Sets the value of the select. - // Also sets the label to the corresponding value by reverse lookup. - if(!this._onChangeActive){ priorityChange = null; } - - if(item === undefined){ - if(value === null || value === ''){ - value = ''; - if(!lang.isString(displayedValue)){ - this._setDisplayedValueAttr(displayedValue||'', priorityChange); - return; - } - } - - var self = this; - this._lastQuery = value; - when(this.store.get(value), function(item){ - self._callbackSetLabel(item? [item] : [], undefined, undefined, priorityChange); - }); - }else{ - this.valueNode.value = value; - this.inherited(arguments); - } - }, - - _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){ - // summary: - // Set the displayed valued in the input box, and the hidden value - // that gets submitted, based on a dojo.data store item. - // description: - // Users shouldn't call this function; they should be calling - // set('item', value) - // tags: - // private - this.inherited(arguments); - this._lastDisplayedValue = this.textbox.value; - }, - - _getDisplayQueryString: function(/*String*/ text){ - return text.replace(/([\\\*\?])/g, "\\$1"); - }, - - _setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){ - // summary: - // Hook so set('displayedValue', label) works. - // description: - // Sets textbox to display label. Also performs reverse lookup - // to set the hidden value. label should corresponding to item.searchAttr. - - if(label == null){ label = ''; } - - // This is called at initialization along with every custom setter. - // Usually (or always?) the call can be ignored. If it needs to be - // processed then at least make sure that the XHR request doesn't trigger an onChange() - // event, even if it returns after creation has finished - if(!this._created){ - if(!("displayedValue" in this.params)){ - return; - } - priorityChange = false; - } - - // Do a reverse lookup to map the specified displayedValue to the hidden value. - // Note that if there's a custom labelFunc() this code - if(this.store){ - this.closeDropDown(); - var query = lang.clone(this.query); // #6196: populate query with user-specifics - - // Generate query - var qs = this._getDisplayQueryString(label), q; - if(this.store._oldAPI){ - // remove this branch for 2.0 - q = qs; - }else{ - // Query on searchAttr is a regex for benefit of dojo/store/Memory, - // but with a toString() method to help dojo/store/JsonRest. - // Search string like "Co*" converted to regex like /^Co.*$/i. - q = filter.patternToRegExp(qs, this.ignoreCase); - q.toString = function(){ return qs; }; - } - this._lastQuery = query[this.searchAttr] = q; - - // If the label is not valid, the callback will never set it, - // so the last valid value will get the warning textbox. Set the - // textbox value now so that the impending warning will make - // sense to the user - this.textbox.value = label; - this._lastDisplayedValue = label; - this._set("displayedValue", label); // for watch("displayedValue") notification - var _this = this; - var options = { - ignoreCase: this.ignoreCase, - deep: true - }; - lang.mixin(options, this.fetchProperties); - this._fetchHandle = this.store.query(query, options); - when(this._fetchHandle, function(result){ - _this._fetchHandle = null; - _this._callbackSetLabel(result || [], query, options, priorityChange); - }, function(err){ - _this._fetchHandle = null; - if(!_this._cancelingQuery){ // don't treat canceled query as an error - console.error('dijit.form.FilteringSelect: ' + err.toString()); - } - }); - } - }, - - undo: function(){ - this.set('displayedValue', this._lastDisplayedValue); - } - }); -}); - -}, -'dojo/data/util/sorter':function(){ -define("dojo/data/util/sorter", ["../../_base/lang"], function(lang){ - // module: - // dojo/data/util/sorter - // summary: - // TODOC - -var sorter = {}; -lang.setObject("dojo.data.util.sorter", sorter); - -sorter.basicComparator = function( /*anything*/ a, - /*anything*/ b){ - // summary: - // Basic comparison function that compares if an item is greater or less than another item - // description: - // returns 1 if a > b, -1 if a < b, 0 if equal. - // 'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list. - // And compared to each other, null is equivalent to undefined. - - //null is a problematic compare, so if null, we set to undefined. - //Makes the check logic simple, compact, and consistent - //And (null == undefined) === true, so the check later against null - //works for undefined and is less bytes. - var r = -1; - if(a === null){ - a = undefined; - } - if(b === null){ - b = undefined; - } - if(a == b){ - r = 0; - }else if(a > b || a == null){ - r = 1; - } - return r; //int {-1,0,1} -}; - -sorter.createSortFunction = function( /* attributes[] */sortSpec, /*dojo/data/api/Read*/ store){ - // summary: - // Helper function to generate the sorting function based off the list of sort attributes. - // description: - // The sort function creation will look for a property on the store called 'comparatorMap'. If it exists - // it will look in the mapping for comparisons function for the attributes. If one is found, it will - // use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates. - // Returns the sorting function for this particular list of attributes and sorting directions. - // sortSpec: - // A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending. - // The objects should be formatted as follows: - // | { - // | attribute: "attributeName-string" || attribute, - // | descending: true|false; // Default is false. - // | } - // store: - // The datastore object to look up item values from. - - var sortFunctions=[]; - - function createSortFunction(attr, dir, comp, s){ - //Passing in comp and s (comparator and store), makes this - //function much faster. - return function(itemA, itemB){ - var a = s.getValue(itemA, attr); - var b = s.getValue(itemB, attr); - return dir * comp(a,b); //int - }; - } - var sortAttribute; - var map = store.comparatorMap; - var bc = sorter.basicComparator; - for(var i = 0; i < sortSpec.length; i++){ - sortAttribute = sortSpec[i]; - var attr = sortAttribute.attribute; - if(attr){ - var dir = (sortAttribute.descending) ? -1 : 1; - var comp = bc; - if(map){ - if(typeof attr !== "string" && ("toString" in attr)){ - attr = attr.toString(); - } - comp = map[attr] || bc; - } - sortFunctions.push(createSortFunction(attr, - dir, comp, store)); - } - } - return function(rowA, rowB){ - var i=0; - while(i < sortFunctions.length){ - var ret = sortFunctions[i++](rowA, rowB); - if(ret !== 0){ - return ret;//int - } - } - return 0; //int - }; // Function -}; - -return sorter; -}); - -}, -'dijit/form/_ButtonMixin':function(){ -define("dijit/form/_ButtonMixin", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "dojo/_base/event", // event.stop - "../registry" // registry.byNode -], function(declare, dom, event, registry){ - -// module: -// dijit/form/_ButtonMixin - -return declare("dijit.form._ButtonMixin", null, { - // summary: - // A mixin to add a thin standard API wrapper to a normal HTML button - // description: - // A label should always be specified (through innerHTML) or the label attribute. - // - // Attach points: - // - // - focusNode (required): this node receives focus - // - valueNode (optional): this node's value gets submitted with FORM elements - // - containerNode (optional): this node gets the innerHTML assignment for label - // example: - // | <button data-dojo-type="dijit/form/Button" onClick="...">Hello world</button> - // example: - // | var button1 = new Button({label: "hello world", onClick: foo}); - // | dojo.body().appendChild(button1.domNode); - - // label: HTML String - // Content to display in button. - label: "", - - // type: [const] String - // Type of button (submit, reset, button, checkbox, radio) - type: "button", - - _onClick: function(/*Event*/ e){ - // summary: - // Internal function to handle click actions - if(this.disabled){ - event.stop(e); - return false; - } - var preventDefault = this.onClick(e) === false; // user click actions - if(!preventDefault && this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a non-form widget needs to be signalled - for(var node=this.domNode; node.parentNode; node=node.parentNode){ - var widget=registry.byNode(node); - if(widget && typeof widget._onSubmit == "function"){ - widget._onSubmit(e); - preventDefault = true; - break; - } - } - } - if(preventDefault){ - e.preventDefault(); - } - return !preventDefault; - }, - - postCreate: function(){ - this.inherited(arguments); - dom.setSelectable(this.focusNode, false); - }, - - onClick: function(/*Event*/ /*===== e =====*/){ - // summary: - // Callback for when button is clicked. - // If type="submit", return true to perform submit, or false to cancel it. - // type: - // callback - return true; // Boolean - }, - - _setLabelAttr: function(/*String*/ content){ - // summary: - // Hook for set('label', ...) to work. - // description: - // Set the label (text) of the button; takes an HTML string. - this._set("label", content); - (this.containerNode||this.focusNode).innerHTML = content; - } -}); - -}); - -}, -'dojo/colors':function(){ -define("dojo/colors", ["./_base/kernel", "./_base/lang", "./_base/Color", "./_base/array"], function(dojo, lang, Color, ArrayUtil){ - // module: - // dojo/colors - - /*===== - return { - // summary: - // Color utilities, extending Base dojo.Color - }; - =====*/ - - var ColorExt = {}; - lang.setObject("dojo.colors", ColorExt); - -//TODO: this module appears to break naming conventions - - // this is a standard conversion prescribed by the CSS3 Color Module - var hue2rgb = function(m1, m2, h){ - if(h < 0){ ++h; } - if(h > 1){ --h; } - var h6 = 6 * h; - if(h6 < 1){ return m1 + (m2 - m1) * h6; } - if(2 * h < 1){ return m2; } - if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; } - return m1; - }; - // Override base Color.fromRgb with the impl in this module - dojo.colorFromRgb = Color.fromRgb = function(/*String*/ color, /*dojo/_base/Color?*/ obj){ - // summary: - // get rgb(a) array from css-style color declarations - // description: - // this function can handle all 4 CSS3 Color Module formats: rgb, - // rgba, hsl, hsla, including rgb(a) with percentage values. - var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/); - if(m){ - var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a; - if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){ - var r = c[0]; - if(r.charAt(r.length - 1) == "%"){ - // 3 rgb percentage values - a = ArrayUtil.map(c, function(x){ - return parseFloat(x) * 2.56; - }); - if(l == 4){ a[3] = c[3]; } - return Color.fromArray(a, obj); // dojo/_base/Color - } - return Color.fromArray(c, obj); // dojo/_base/Color - } - if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){ - // normalize hsl values - var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360, - S = parseFloat(c[1]) / 100, - L = parseFloat(c[2]) / 100, - // calculate rgb according to the algorithm - // recommended by the CSS3 Color Module - m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S, - m1 = 2 * L - m2; - a = [ - hue2rgb(m1, m2, H + 1 / 3) * 256, - hue2rgb(m1, m2, H) * 256, - hue2rgb(m1, m2, H - 1 / 3) * 256, - 1 - ]; - if(l == 4){ a[3] = c[3]; } - return Color.fromArray(a, obj); // dojo/_base/Color - } - } - return null; // dojo/_base/Color - }; - - var confine = function(c, low, high){ - // summary: - // sanitize a color component by making sure it is a number, - // and clamping it to valid values - c = Number(c); - return isNaN(c) ? high : c < low ? low : c > high ? high : c; // Number - }; - - Color.prototype.sanitize = function(){ - // summary: - // makes sure that the object has correct attributes - var t = this; - t.r = Math.round(confine(t.r, 0, 255)); - t.g = Math.round(confine(t.g, 0, 255)); - t.b = Math.round(confine(t.b, 0, 255)); - t.a = confine(t.a, 0, 1); - return this; // dojo/_base/Color - }; - - ColorExt.makeGrey = Color.makeGrey = function(/*Number*/ g, /*Number?*/ a){ - // summary: - // creates a greyscale color with an optional alpha - return Color.fromArray([g, g, g, a]); // dojo/_base/Color - }; - - // mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings - lang.mixin(Color.named, { - "aliceblue": [240,248,255], - "antiquewhite": [250,235,215], - "aquamarine": [127,255,212], - "azure": [240,255,255], - "beige": [245,245,220], - "bisque": [255,228,196], - "blanchedalmond": [255,235,205], - "blueviolet": [138,43,226], - "brown": [165,42,42], - "burlywood": [222,184,135], - "cadetblue": [95,158,160], - "chartreuse": [127,255,0], - "chocolate": [210,105,30], - "coral": [255,127,80], - "cornflowerblue": [100,149,237], - "cornsilk": [255,248,220], - "crimson": [220,20,60], - "cyan": [0,255,255], - "darkblue": [0,0,139], - "darkcyan": [0,139,139], - "darkgoldenrod": [184,134,11], - "darkgray": [169,169,169], - "darkgreen": [0,100,0], - "darkgrey": [169,169,169], - "darkkhaki": [189,183,107], - "darkmagenta": [139,0,139], - "darkolivegreen": [85,107,47], - "darkorange": [255,140,0], - "darkorchid": [153,50,204], - "darkred": [139,0,0], - "darksalmon": [233,150,122], - "darkseagreen": [143,188,143], - "darkslateblue": [72,61,139], - "darkslategray": [47,79,79], - "darkslategrey": [47,79,79], - "darkturquoise": [0,206,209], - "darkviolet": [148,0,211], - "deeppink": [255,20,147], - "deepskyblue": [0,191,255], - "dimgray": [105,105,105], - "dimgrey": [105,105,105], - "dodgerblue": [30,144,255], - "firebrick": [178,34,34], - "floralwhite": [255,250,240], - "forestgreen": [34,139,34], - "gainsboro": [220,220,220], - "ghostwhite": [248,248,255], - "gold": [255,215,0], - "goldenrod": [218,165,32], - "greenyellow": [173,255,47], - "grey": [128,128,128], - "honeydew": [240,255,240], - "hotpink": [255,105,180], - "indianred": [205,92,92], - "indigo": [75,0,130], - "ivory": [255,255,240], - "khaki": [240,230,140], - "lavender": [230,230,250], - "lavenderblush": [255,240,245], - "lawngreen": [124,252,0], - "lemonchiffon": [255,250,205], - "lightblue": [173,216,230], - "lightcoral": [240,128,128], - "lightcyan": [224,255,255], - "lightgoldenrodyellow": [250,250,210], - "lightgray": [211,211,211], - "lightgreen": [144,238,144], - "lightgrey": [211,211,211], - "lightpink": [255,182,193], - "lightsalmon": [255,160,122], - "lightseagreen": [32,178,170], - "lightskyblue": [135,206,250], - "lightslategray": [119,136,153], - "lightslategrey": [119,136,153], - "lightsteelblue": [176,196,222], - "lightyellow": [255,255,224], - "limegreen": [50,205,50], - "linen": [250,240,230], - "magenta": [255,0,255], - "mediumaquamarine": [102,205,170], - "mediumblue": [0,0,205], - "mediumorchid": [186,85,211], - "mediumpurple": [147,112,219], - "mediumseagreen": [60,179,113], - "mediumslateblue": [123,104,238], - "mediumspringgreen": [0,250,154], - "mediumturquoise": [72,209,204], - "mediumvioletred": [199,21,133], - "midnightblue": [25,25,112], - "mintcream": [245,255,250], - "mistyrose": [255,228,225], - "moccasin": [255,228,181], - "navajowhite": [255,222,173], - "oldlace": [253,245,230], - "olivedrab": [107,142,35], - "orange": [255,165,0], - "orangered": [255,69,0], - "orchid": [218,112,214], - "palegoldenrod": [238,232,170], - "palegreen": [152,251,152], - "paleturquoise": [175,238,238], - "palevioletred": [219,112,147], - "papayawhip": [255,239,213], - "peachpuff": [255,218,185], - "peru": [205,133,63], - "pink": [255,192,203], - "plum": [221,160,221], - "powderblue": [176,224,230], - "rosybrown": [188,143,143], - "royalblue": [65,105,225], - "saddlebrown": [139,69,19], - "salmon": [250,128,114], - "sandybrown": [244,164,96], - "seagreen": [46,139,87], - "seashell": [255,245,238], - "sienna": [160,82,45], - "skyblue": [135,206,235], - "slateblue": [106,90,205], - "slategray": [112,128,144], - "slategrey": [112,128,144], - "snow": [255,250,250], - "springgreen": [0,255,127], - "steelblue": [70,130,180], - "tan": [210,180,140], - "thistle": [216,191,216], - "tomato": [255,99,71], - "turquoise": [64,224,208], - "violet": [238,130,238], - "wheat": [245,222,179], - "whitesmoke": [245,245,245], - "yellowgreen": [154,205,50] - }); - - return Color; // TODO: return ColorExt, not Color -}); - -}, -'dijit/registry':function(){ -define("dijit/registry", [ - "dojo/_base/array", // array.forEach array.map - "dojo/sniff", // has("ie") - "dojo/_base/unload", // unload.addOnWindowUnload - "dojo/_base/window", // win.body - "./main" // dijit._scopeName -], function(array, has, unload, win, dijit){ - - // module: - // dijit/registry - - var _widgetTypeCtr = {}, hash = {}; - - var registry = { - // summary: - // Registry of existing widget on page, plus some utility methods. - - // length: Number - // Number of registered widgets - length: 0, - - add: function(widget){ - // summary: - // Add a widget to the registry. If a duplicate ID is detected, a error is thrown. - // widget: dijit/_WidgetBase - // Any dijit/_WidgetBase subclass. - if(hash[widget.id]){ - throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); - } - hash[widget.id] = widget; - this.length++; - }, - - remove: function(/*String*/ id){ - // summary: - // Remove a widget from the registry. Does not destroy the widget; simply - // removes the reference. - if(hash[id]){ - delete hash[id]; - this.length--; - } - }, - - byId: function(/*String|Widget*/ id){ - // summary: - // Find a widget by it's id. - // If passed a widget then just returns the widget. - return typeof id == "string" ? hash[id] : id; // dijit/_WidgetBase - }, - - byNode: function(/*DOMNode*/ node){ - // summary: - // Returns the widget corresponding to the given DOMNode - return hash[node.getAttribute("widgetId")]; // dijit/_WidgetBase - }, - - toArray: function(){ - // summary: - // Convert registry into a true Array - // - // example: - // Work with the widget .domNodes in a real Array - // | array.map(registry.toArray(), function(w){ return w.domNode; }); - - var ar = []; - for(var id in hash){ - ar.push(hash[id]); - } - return ar; // dijit/_WidgetBase[] - }, - - getUniqueId: function(/*String*/widgetType){ - // summary: - // Generates a unique id for a given widgetType - - var id; - do{ - id = widgetType + "_" + - (widgetType in _widgetTypeCtr ? - ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0); - }while(hash[id]); - return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String - }, - - findWidgets: function(root, skipNode){ - // summary: - // Search subtree under root returning widgets found. - // Doesn't search for nested widgets (ie, widgets inside other widgets). - // root: DOMNode - // Node to search under. - // skipNode: DOMNode - // If specified, don't search beneath this node (usually containerNode). - - var outAry = []; - - function getChildrenHelper(root){ - for(var node = root.firstChild; node; node = node.nextSibling){ - if(node.nodeType == 1){ - var widgetId = node.getAttribute("widgetId"); - if(widgetId){ - var widget = hash[widgetId]; - if(widget){ // may be null on page w/multiple dojo's loaded - outAry.push(widget); - } - }else if(node !== skipNode){ - getChildrenHelper(node); - } - } - } - } - - getChildrenHelper(root); - return outAry; - }, - - _destroyAll: function(){ - // summary: - // Code to destroy all widgets and do other cleanup on page unload - - // Clean up focus manager lingering references to widgets and nodes - dijit._curFocus = null; - dijit._prevFocus = null; - dijit._activeStack = []; - - // Destroy all the widgets, top down - array.forEach(registry.findWidgets(win.body()), function(widget){ - // Avoid double destroy of widgets like Menu that are attached to <body> - // even though they are logically children of other widgets. - if(!widget._destroyed){ - if(widget.destroyRecursive){ - widget.destroyRecursive(); - }else if(widget.destroy){ - widget.destroy(); - } - } - }); - }, - - getEnclosingWidget: function(/*DOMNode*/ node){ - // summary: - // Returns the widget whose DOM tree contains the specified DOMNode, or null if - // the node is not contained within the DOM tree of any widget - while(node){ - var id = node.nodeType == 1 && node.getAttribute("widgetId"); - if(id){ - return hash[id]; - } - node = node.parentNode; - } - return null; - }, - - // In case someone needs to access hash. - // Actually, this is accessed from WidgetSet back-compatibility code - _hash: hash - }; - - dijit.registry = registry; - - return registry; -}); - -}, -'dijit/tree/_dndContainer':function(){ -define("dijit/tree/_dndContainer", [ - "dojo/aspect", // aspect.after - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.remove domClass.replace - "dojo/_base/event", // event.stop - "dojo/_base/lang", // lang.mixin lang.hitch - "dojo/on", - "dojo/touch" -], function(aspect, declare,domClass, event, lang, on, touch){ - - // module: - // dijit/tree/_dndContainer - - /*===== - var __Args = { - // summary: - // A dict of parameters for Tree source configuration. - // isSource: Boolean? - // Can be used as a DnD source. Defaults to true. - // accept: String[] - // List of accepted types (text strings) for a target; defaults to - // ["text", "treeNode"] - // copyOnly: Boolean? - // Copy items, if true, use a state of Ctrl key otherwise, - // dragThreshold: Number - // The move delay in pixels before detecting a drag; 0 by default - // betweenThreshold: Integer - // Distance from upper/lower edge of node to allow drop to reorder nodes - }; - =====*/ - - return declare("dijit.tree._dndContainer", null, { - - // summary: - // This is a base class for `dijit/tree/_dndSelector`, and isn't meant to be used directly. - // It's modeled after `dojo/dnd/Container`. - // tags: - // protected - - /*===== - // current: DomNode - // The currently hovered TreeNode.rowNode (which is the DOM node - // associated w/a given node in the tree, excluding it's descendants) - current: null, - =====*/ - - constructor: function(tree, params){ - // summary: - // A constructor of the Container - // tree: Node - // Node or node's id to build the container on - // params: __Args - // A dict of parameters, which gets mixed into the object - // tags: - // private - this.tree = tree; - this.node = tree.domNode; // TODO: rename; it's not a TreeNode but the whole Tree - lang.mixin(this, params); - - // class-specific variables - this.current = null; // current TreeNode's DOM node - - // states - this.containerState = ""; - domClass.add(this.node, "dojoDndContainer"); - - // set up events - this.events = [ - // Mouse (or touch) enter/leave on Tree itself - on(this.node, touch.enter, lang.hitch(this, "onOverEvent")), - on(this.node, touch.leave, lang.hitch(this, "onOutEvent")), - - // switching between TreeNodes - aspect.after(this.tree, "_onNodeMouseEnter", lang.hitch(this, "onMouseOver"), true), - aspect.after(this.tree, "_onNodeMouseLeave", lang.hitch(this, "onMouseOut"), true), - - // cancel text selection and text dragging - on(this.node, "dragstart", lang.hitch(event, "stop")), - on(this.node, "selectstart", lang.hitch(event, "stop")) - ]; - }, - - destroy: function(){ - // summary: - // Prepares this object to be garbage-collected - - var h; - while(h = this.events.pop()){ h.remove(); } - - // this.clearItems(); - this.node = this.parent = null; - }, - - // mouse events - onMouseOver: function(widget /*===== , evt =====*/){ - // summary: - // Called when mouse is moved over a TreeNode - // widget: TreeNode - // evt: Event - // tags: - // protected - this.current = widget; - }, - - onMouseOut: function(/*===== widget, evt =====*/){ - // summary: - // Called when mouse is moved away from a TreeNode - // widget: TreeNode - // evt: Event - // tags: - // protected - this.current = null; - }, - - _changeState: function(type, newState){ - // summary: - // Changes a named state to new state value - // type: String - // A name of the state to change - // newState: String - // new state - var prefix = "dojoDnd" + type; - var state = type.toLowerCase() + "State"; - //domClass.replace(this.node, prefix + newState, prefix + this[state]); - domClass.replace(this.node, prefix + newState, prefix + this[state]); - this[state] = newState; - }, - - _addItemClass: function(node, type){ - // summary: - // Adds a class with prefix "dojoDndItem" - // node: Node - // A node - // type: String - // A variable suffix for a class name - domClass.add(node, "dojoDndItem" + type); - }, - - _removeItemClass: function(node, type){ - // summary: - // Removes a class with prefix "dojoDndItem" - // node: Node - // A node - // type: String - // A variable suffix for a class name - domClass.remove(node, "dojoDndItem" + type); - }, - - onOverEvent: function(){ - // summary: - // This function is called once, when mouse is over our container - // tags: - // protected - this._changeState("Container", "Over"); - }, - - onOutEvent: function(){ - // summary: - // This function is called once, when mouse is out of our container - // tags: - // protected - this._changeState("Container", ""); - } - }); -}); - -}, -'url:dijit/templates/InlineEditBox.html':"<span data-dojo-attach-point=\"editNode\" role=\"presentation\" class=\"dijitReset dijitInline dijitOffScreen\"\n\tdata-dojo-attach-event=\"onkeypress: _onKeyPress\"\n\t><span data-dojo-attach-point=\"editorPlaceholder\"></span\n\t><span data-dojo-attach-point=\"buttonContainer\"\n\t\t><button data-dojo-type=\"dijit/form/Button\" data-dojo-props=\"label: '${buttonSave}', 'class': 'saveButton'\"\n\t\t\tdata-dojo-attach-point=\"saveButton\" data-dojo-attach-event=\"onClick:save\"></button\n\t\t><button data-dojo-type=\"dijit/form/Button\" data-dojo-props=\"label: '${buttonCancel}', 'class': 'cancelButton'\"\n\t\t\tdata-dojo-attach-point=\"cancelButton\" data-dojo-attach-event=\"onClick:cancel\"></button\n\t></span\n></span>\n", -'dijit/_base/wai':function(){ -define("dijit/_base/wai", [ - "dojo/dom-attr", // domAttr.attr - "dojo/_base/lang", // lang.mixin - "../main", // export symbols to dijit - "../hccss" // not using this module directly, but loading it sets CSS flag on <html> -], function(domAttr, lang, dijit){ - - // module: - // dijit/_base/wai - - var exports = { - // summary: - // Deprecated methods for setting/getting wai roles and states. - // New code should call setAttribute()/getAttribute() directly. - // - // Also loads hccss to apply dj_a11y class to root node if machine is in high-contrast mode. - - hasWaiRole: function(/*Element*/ elem, /*String?*/ role){ - // summary: - // Determines if an element has a particular role. - // returns: - // True if elem has the specific role attribute and false if not. - // For backwards compatibility if role parameter not provided, - // returns true if has a role - var waiRole = this.getWaiRole(elem); - return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0); - }, - - getWaiRole: function(/*Element*/ elem){ - // summary: - // Gets the role for an element (which should be a wai role). - // returns: - // The role of elem or an empty string if elem - // does not have a role. - return lang.trim((domAttr.get(elem, "role") || "").replace("wairole:","")); - }, - - setWaiRole: function(/*Element*/ elem, /*String*/ role){ - // summary: - // Sets the role on an element. - // description: - // Replace existing role attribute with new role. - - domAttr.set(elem, "role", role); - }, - - removeWaiRole: function(/*Element*/ elem, /*String*/ role){ - // summary: - // Removes the specified role from an element. - // Removes role attribute if no specific role provided (for backwards compat.) - - var roleValue = domAttr.get(elem, "role"); - if(!roleValue){ return; } - if(role){ - var t = lang.trim((" " + roleValue + " ").replace(" " + role + " ", " ")); - domAttr.set(elem, "role", t); - }else{ - elem.removeAttribute("role"); - } - }, - - hasWaiState: function(/*Element*/ elem, /*String*/ state){ - // summary: - // Determines if an element has a given state. - // description: - // Checks for an attribute called "aria-"+state. - // returns: - // true if elem has a value for the given state and - // false if it does not. - - return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state); - }, - - getWaiState: function(/*Element*/ elem, /*String*/ state){ - // summary: - // Gets the value of a state on an element. - // description: - // Checks for an attribute called "aria-"+state. - // returns: - // The value of the requested state on elem - // or an empty string if elem has no value for state. - - return elem.getAttribute("aria-"+state) || ""; - }, - - setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){ - // summary: - // Sets a state on an element. - // description: - // Sets an attribute called "aria-"+state. - - elem.setAttribute("aria-"+state, value); - }, - - removeWaiState: function(/*Element*/ elem, /*String*/ state){ - // summary: - // Removes a state from an element. - // description: - // Sets an attribute called "aria-"+state. - - elem.removeAttribute("aria-"+state); - } - }; - - lang.mixin(dijit, exports); - - /*===== return exports; =====*/ - return dijit; // for back compat :-( -}); - -}, -'dijit/form/_FormSelectWidget':function(){ -define("dijit/form/_FormSelectWidget", [ - "dojo/_base/array", // array.filter array.forEach array.map array.some - "dojo/_base/Deferred", - "dojo/aspect", // aspect.after - "dojo/data/util/sorter", // util.sorter.createSortFunction - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "dojo/dom-class", // domClass.toggle - "dojo/_base/kernel", // _scopeName - "dojo/_base/lang", // lang.delegate lang.isArray lang.isObject lang.hitch - "dojo/query", // query - "dojo/when", - "dojo/store/util/QueryResults", - "./_FormValueWidget" -], function(array, Deferred, aspect, sorter, declare, dom, domClass, kernel, lang, query, when, - QueryResults, _FormValueWidget){ - -// module: -// dijit/form/_FormSelectWidget - -/*===== -var __SelectOption = { - // 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. - // selected: Boolean - // Whether or not we are a selected option - // disabled: Boolean - // Whether or not this specific option is disabled -}; -=====*/ - -var _FormSelectWidget = declare("dijit.form._FormSelectWidget", _FormValueWidget, { - // summary: - // Extends _FormValueWidget in order to provide "select-specific" - // values - i.e., those values that are unique to `<select>` elements. - // This also provides the mechanism for reading the elements from - // a store, if desired. - - // multiple: [const] Boolean - // Whether or not we are multi-valued - multiple: false, - - // options: __SelectOption[] - // The set of options for our select item. Roughly corresponds to - // the html `<option>` tag. - options: null, - - // store: dojo/store/api/Store - // A store to use for getting our list of options - rather than reading them - // from the `<option>` html tags. Should support getIdentity(). - // For back-compat store can also be a dojo/data/api/Identity. - store: null, - - // query: object - // A query to use when fetching items from our store - query: null, - - // queryOptions: object - // Query options to use when fetching from the store - queryOptions: null, - - // labelAttr: String? - // The entries in the drop down list come from this attribute in the dojo.store items. - // If ``store`` is set, labelAttr must be set too, unless store is an old-style - // dojo.data store rather than a new dojo/store. - labelAttr: "", - - // onFetch: Function - // A callback to do with an onFetch - but before any items are actually - // iterated over (i.e. to filter even further what you want to add) - onFetch: null, - - // sortByLabel: Boolean - // Flag to sort the options returned from a store by the label of - // the store. - sortByLabel: true, - - - // loadChildrenOnOpen: Boolean - // By default loadChildren is called when the items are fetched from the - // store. This property allows delaying loadChildren (and the creation - // of the options/menuitems) until the user clicks the button to open the - // dropdown. - loadChildrenOnOpen: false, - - // onLoadDeferred: [readonly] dojo.Deferred - // This is the `dojo.Deferred` returned by setStore(). - // Calling onLoadDeferred.then() registers your - // callback to be called only once, when the prior setStore completes. - onLoadDeferred: null, - - getOptions: function(/*anything*/ valueOrIdx){ - // summary: - // Returns a given option (or options). - // valueOrIdx: - // If passed in as a string, that string is used to look up the option - // in the array of options - based on the value property. - // (See dijit/form/_FormSelectWidget.__SelectOption). - // - // If passed in a number, then the option with the given index (0-based) - // within this select will be returned. - // - // If passed in a dijit/form/_FormSelectWidget.__SelectOption, the same option will be - // returned if and only if it exists within this select. - // - // If passed an array, then an array will be returned with each element - // in the array being looked up. - // - // If not passed a value, then all options will be returned - // - // returns: - // The option corresponding with the given value or index. null - // is returned if any of the following are true: - // - // - A string value is passed in which doesn't exist - // - An index is passed in which is outside the bounds of the array of options - // - A dijit/form/_FormSelectWidget.__SelectOption is passed in which is not a part of the select - - // NOTE: the compare for passing in a dijit/form/_FormSelectWidget.__SelectOption checks - // if the value property matches - NOT if the exact option exists - // NOTE: if passing in an array, null elements will be placed in the returned - // array when a value is not found. - var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length; - - if(lookupValue === undefined){ - return opts; // __SelectOption[] - } - if(lang.isArray(lookupValue)){ - return array.map(lookupValue, "return this.getOptions(item);", this); // __SelectOption[] - } - if(lang.isObject(valueOrIdx)){ - // We were passed an option - so see if it's in our array (directly), - // and if it's not, try and find it by value. - if(!array.some(this.options, function(o, idx){ - if(o === lookupValue || - (o.value && o.value === lookupValue.value)){ - lookupValue = idx; - return true; - } - return false; - })){ - lookupValue = -1; - } - } - if(typeof lookupValue == "string"){ - for(var i=0; i<l; i++){ - if(opts[i].value === lookupValue){ - lookupValue = i; - break; - } - } - } - if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){ - return this.options[lookupValue]; // __SelectOption - } - return null; // null - }, - - addOption: function(/*__SelectOption|__SelectOption[]*/ option){ - // summary: - // Adds an option or options to the end of the select. If value - // of the option is empty or missing, a separator is created instead. - // Passing in an array of options will yield slightly better performance - // since the children are only loaded once. - if(!lang.isArray(option)){ option = [option]; } - array.forEach(option, function(i){ - if(i && lang.isObject(i)){ - this.options.push(i); - } - }, this); - this._loadChildren(); - }, - - removeOption: function(/*String|__SelectOption|Number|Array*/ valueOrIdx){ - // summary: - // Removes the given option or options. You can remove by string - // (in which case the value is removed), number (in which case the - // index in the options array is removed), or select option (in - // which case, the select option with a matching value is removed). - // You can also pass in an array of those values for a slightly - // better performance since the children are only loaded once. - if(!lang.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; } - var oldOpts = this.getOptions(valueOrIdx); - array.forEach(oldOpts, function(i){ - // We can get null back in our array - if our option was not found. In - // that case, we don't want to blow up... - if(i){ - this.options = array.filter(this.options, function(node){ - return (node.value !== i.value || node.label !== i.label); - }); - this._removeOptionItem(i); - } - }, this); - this._loadChildren(); - }, - - updateOption: function(/*__SelectOption|__SelectOption[]*/ newOption){ - // summary: - // Updates the values of the given option. The option to update - // is matched based on the value of the entered option. Passing - // in an array of new options will yield better performance since - // the children will only be loaded once. - if(!lang.isArray(newOption)){ newOption = [newOption]; } - array.forEach(newOption, function(i){ - var oldOpt = this.getOptions(i), k; - if(oldOpt){ - for(k in i){ oldOpt[k] = i[k]; } - } - }, this); - this._loadChildren(); - }, - - setStore: function(store, - selectedValue, - fetchArgs){ - // summary: - // Sets the store you would like to use with this select widget. - // The selected value is the value of the new store to set. This - // function returns the original store, in case you want to reuse - // it or something. - // store: dojo/store/api/Store - // The dojo.store you would like to use - it MUST implement getIdentity() - // and MAY implement observe(). - // For backwards-compatibility this can also be a data.data store, in which case - // it MUST implement dojo/data/api/Identity, - // and MAY implement dojo/data/api/Notification. - // selectedValue: anything? - // The value that this widget should set itself to *after* the store - // has been loaded - // fetchArgs: Object? - // Hash of parameters to set filter on store, etc. - // - // - query: new value for Select.query, - // - queryOptions: new value for Select.queryOptions, - // - onFetch: callback function for each item in data (Deprecated) - var oStore = this.store; - fetchArgs = fetchArgs || {}; - - if(oStore !== store){ - // Our store has changed, so cancel any listeners on old store (remove for 2.0) - var h; - while((h = this._notifyConnections.pop())){ h.remove(); } - - // For backwards-compatibility, accept dojo.data store in addition to dojo.store.store. Remove in 2.0. - if(!store.get){ - lang.mixin(store, { - _oldAPI: true, - get: function(id){ - // summary: - // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity. - // Like dojo.store.DataStore.get() except returns native item. - var deferred = new Deferred(); - this.fetchItemByIdentity({ - identity: id, - onItem: function(object){ - deferred.resolve(object); - }, - onError: function(error){ - deferred.reject(error); - } - }); - return deferred.promise; - }, - query: function(query, options){ - // summary: - // Queries the store for objects. Like dojo/store/DataStore.query() - // except returned Deferred contains array of native items. - var deferred = new Deferred(function(){ if(fetchHandle.abort){ fetchHandle.abort(); } } ); - deferred.total = new Deferred(); - var fetchHandle = this.fetch(lang.mixin({ - query: query, - onBegin: function(count){ - deferred.total.resolve(count); - }, - onComplete: function(results){ - deferred.resolve(results); - }, - onError: function(error){ - deferred.reject(error); - } - }, options)); - return new QueryResults(deferred); - } - }); - - if(store.getFeatures()["dojo.data.api.Notification"]){ - this._notifyConnections = [ - aspect.after(store, "onNew", lang.hitch(this, "_onNewItem"), true), - aspect.after(store, "onDelete", lang.hitch(this, "_onDeleteItem"), true), - aspect.after(store, "onSet", lang.hitch(this, "_onSetItem"), true) - ]; - } - } - this._set("store", store); // Our store has changed, so update our notifications - } - - // Remove existing options (if there are any) - if(this.options && this.options.length){ - this.removeOption(this.options); - } - - // Cancel listener for updates to old store - if(this._queryRes && this._queryRes.close){ - this._queryRes.close(); - } - - // If user has specified new query and query options along with this new store, then use them. - if(fetchArgs.query){ - this._set("query", fetchArgs.query); - this._set("queryOptions", fetchArgs.queryOptions); - } - - // Add our new options - if(store){ - this._loadingStore = true; - this.onLoadDeferred = new Deferred(); - - // Run query - // Save result in this._queryRes so we can cancel the listeners we register below - this._queryRes = store.query(this.query, this.queryOptions); - when(this._queryRes, lang.hitch(this, function(items){ - - if(this.sortByLabel && !fetchArgs.sort && items.length){ - if(items[0].getValue){ - // Old dojo.data API to access items, remove for 2.0 - items.sort(sorter.createSortFunction([{ - attribute: store.getLabelAttributes(items[0])[0] - }], store)); - }else{ - var labelAttr = this.labelAttr; - items.sort(function(a, b){ - return a[labelAttr] > b[labelAttr] ? 1 : b[labelAttr] > a[labelAttr] ? -1 : 0; - }); - } - } - - if(fetchArgs.onFetch){ - items = fetchArgs.onFetch.call(this, items, fetchArgs); - } - - // TODO: Add these guys as a batch, instead of separately - array.forEach(items, function(i){ - this._addOptionForItem(i); - }, this); - - // Register listener for store updates - if(this._queryRes.observe){ - this._queryRes.observe(lang.hitch(this, function(object, deletedFrom, insertedInto){ - if(deletedFrom == insertedInto){ - this._onSetItem(object); - }else{ - if(deletedFrom != -1){ - this._onDeleteItem(object); - } - if(insertedInto != -1){ - this._onNewItem(object); - } - } - }), true); - } - - // Set our value (which might be undefined), and then tweak - // it to send a change event with the real value - this._loadingStore = false; - this.set("value", "_pendingValue" in this ? this._pendingValue : selectedValue); - delete this._pendingValue; - - if(!this.loadChildrenOnOpen){ - this._loadChildren(); - }else{ - this._pseudoLoadChildren(items); - } - this.onLoadDeferred.resolve(true); - this.onSetStore(); - }), function(err){ - console.error('dijit.form.Select: ' + err.toString()); - this.onLoadDeferred.reject(err); - }); - } - return oStore; // dojo/data/api/Identity - }, - - // TODO: implement set() and watch() for store and query, although not sure how to handle - // setting them individually rather than together (as in setStore() above) - - _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ - // summary: - // set the value of the widget. - // If a string is passed, then we set our value from looking it up. - if(!this._onChangeActive){ priorityChange = null; } - if(this._loadingStore){ - // Our store is loading - so save our value, and we'll set it when - // we're done - this._pendingValue = newValue; - return; - } - var opts = this.getOptions() || []; - if(!lang.isArray(newValue)){ - newValue = [newValue]; - } - array.forEach(newValue, function(i, idx){ - if(!lang.isObject(i)){ - i = i + ""; - } - if(typeof i === "string"){ - newValue[idx] = array.filter(opts, function(node){ - return node.value === i; - })[0] || {value: "", label: ""}; - } - }, this); - - // Make sure some sane default is set - newValue = array.filter(newValue, function(i){ return i && i.value; }); - if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){ - newValue[0] = opts[0]; - } - array.forEach(opts, function(i){ - i.selected = array.some(newValue, function(v){ return v.value === i.value; }); - }); - var val = array.map(newValue, function(i){ return i.value; }), - disp = array.map(newValue, function(i){ return i.label; }); - - if(typeof val == "undefined" || typeof val[0] == "undefined"){ return; } // not fully initialized yet or a failed value lookup - this._setDisplay(this.multiple ? disp : disp[0]); - this.inherited(arguments, [ this.multiple ? val : val[0], priorityChange ]); - this._updateSelection(); - }, - - _getDisplayedValueAttr: function(){ - // summary: - // returns the displayed value of the widget - var val = this.get("value"); - if(!lang.isArray(val)){ - val = [val]; - } - var ret = array.map(this.getOptions(val), function(v){ - if(v && "label" in v){ - return v.label; - }else if(v){ - return v.value; - } - return null; - }, this); - return this.multiple ? ret : ret[0]; - }, - - _loadChildren: function(){ - // summary: - // Loads the children represented by this widget's options. - // reset the menu to make it populatable on the next click - if(this._loadingStore){ return; } - array.forEach(this._getChildren(), function(child){ - child.destroyRecursive(); - }); - // Add each menu item - array.forEach(this.options, this._addOptionItem, this); - - // Update states - this._updateSelection(); - }, - - _updateSelection: function(){ - // summary: - // Sets the "selected" class on the item for styling purposes - this._set("value", this._getValueFromOpts()); - var val = this.value; - if(!lang.isArray(val)){ - val = [val]; - } - if(val && val[0]){ - array.forEach(this._getChildren(), function(child){ - var isSelected = array.some(val, function(v){ - return child.option && (v === child.option.value); - }); - domClass.toggle(child.domNode, this.baseClass.replace(/\s+|$/g, "SelectedOption "), isSelected); - child.domNode.setAttribute("aria-selected", isSelected ? "true" : "false"); - }, this); - } - }, - - _getValueFromOpts: function(){ - // summary: - // Returns the value of the widget by reading the options for - // the selected flag - var opts = this.getOptions() || []; - if(!this.multiple && opts.length){ - // Mirror what a select does - choose the first one - var opt = array.filter(opts, function(i){ - return i.selected; - })[0]; - if(opt && opt.value){ - return opt.value; - }else{ - opts[0].selected = true; - return opts[0].value; - } - }else if(this.multiple){ - // Set value to be the sum of all selected - return array.map(array.filter(opts, function(i){ - return i.selected; - }), function(i){ - return i.value; - }) || []; - } - return ""; - }, - - // Internal functions to call when we have store notifications come in - _onNewItem: function(/*item*/ item, /*Object?*/ parentInfo){ - if(!parentInfo || !parentInfo.parent){ - // Only add it if we are top-level - this._addOptionForItem(item); - } - }, - _onDeleteItem: function(/*item*/ item){ - var store = this.store; - this.removeOption(store.getIdentity(item)); - }, - _onSetItem: function(/*item*/ item){ - this.updateOption(this._getOptionObjForItem(item)); - }, - - _getOptionObjForItem: function(item){ - // summary: - // Returns an option object based off the given item. The "value" - // of the option item will be the identity of the item, the "label" - // of the option will be the label of the item. - - // remove getLabel() call for 2.0 (it's to support the old dojo.data API) - var store = this.store, - label = (this.labelAttr && this.labelAttr in item) ? item[this.labelAttr] : store.getLabel(item), - value = (label ? store.getIdentity(item) : null); - return {value: value, label: label, item: item}; // __SelectOption - }, - - _addOptionForItem: function(/*item*/ item){ - // summary: - // Creates (and adds) the option for the given item - var store = this.store; - if(store.isItemLoaded && !store.isItemLoaded(item)){ - // We are not loaded - so let's load it and add later. - // Remove for 2.0 (it's the old dojo.data API) - store.loadItem({item: item, onItem: function(i){ - this._addOptionForItem(i); - }, - scope: this}); - return; - } - var newOpt = this._getOptionObjForItem(item); - this.addOption(newOpt); - }, - - constructor: function(params /*===== , srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree - - // Saves off our value, if we have an initial one set so we - // can use it if we have a store as well (see startup()) - this._oValue = (params || {}).value || null; - this._notifyConnections = []; // remove for 2.0 - }, - - buildRendering: function(){ - this.inherited(arguments); - dom.setSelectable(this.focusNode, false); - }, - - _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. - if(!this.options){ - this.options = - this.srcNodeRef - ? query("> *", this.srcNodeRef).map( - function(node){ - if(node.getAttribute("type") === "separator"){ - return { value: "", label: "", selected: false, disabled: false }; - } - return { - value: (node.getAttribute("data-" + kernel._scopeName + "-value") || node.getAttribute("value")), - label: String(node.innerHTML), - // FIXME: disabled and selected are not valid on complex markup children (which is why we're - // looking for data-dojo-value above. perhaps we should data-dojo-props="" this whole thing?) - // decide before 1.6 - selected: node.getAttribute("selected") || false, - disabled: node.getAttribute("disabled") || false - }; - }, - this) - : []; - } - if(!this.value){ - this._set("value", this._getValueFromOpts()); - }else if(this.multiple && typeof this.value == "string"){ - this._set("value", this.value.split(",")); - } - }, - - 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 - this.connect(this, "onChange", "_updateSelection"); - - // moved from startup - // Connects in our store, if we have one defined - var store = this.store; - if(store && (store.getIdentity || store.getFeatures()["dojo.data.api.Identity"])){ - // Temporarily set our store to null so that it will get set - // and connected appropriately - this.store = null; - this.setStore(store, this._oValue); - } - }, - - startup: function(){ - // summary: - this._loadChildren(); - this.inherited(arguments); - }, - - destroy: function(){ - // summary: - // Clean up our connections - - var h; - while((h = this._notifyConnections.pop())){ h.remove(); } - - // Cancel listener for store updates - if(this._queryRes && this._queryRes.close){ - this._queryRes.close(); - } - - this.inherited(arguments); - }, - - _addOptionItem: function(/*__SelectOption*/ /*===== option =====*/){ - // summary: - // User-overridable function which, for the given option, adds an - // item to the select. If the option doesn't have a value, then a - // separator is added in that place. Make sure to store the option - // in the created option widget. - }, - - _removeOptionItem: function(/*__SelectOption*/ /*===== option =====*/){ - // summary: - // User-overridable function which, for the given option, removes - // its item from the select. - }, - - _setDisplay: function(/*String or String[]*/ /*===== newDisplay =====*/){ - // summary: - // Overridable function which will set the display for the - // widget. newDisplay is either a string (in the case of - // single selects) or array of strings (in the case of multi-selects) - }, - - _getChildren: function(){ - // summary: - // Overridable function to return the children that this widget contains. - return []; - }, - - _getSelectedOptionsAttr: function(){ - // summary: - // hooks into this.attr to provide a mechanism for getting the - // option items for the current value of the widget. - return this.getOptions(this.get("value")); - }, - - _pseudoLoadChildren: function(/*item[]*/ /*===== items =====*/){ - // summary: - // a function that will "fake" loading children, if needed, and - // if we have set to not load children until the widget opens. - // items: - // An array of items that will be loaded, when needed - }, - - onSetStore: function(){ - // summary: - // a function that can be connected to in order to receive a - // notification that the store has finished loading and all options - // from that store are available - } -}); - -/*===== -_FormSelectWidget.__SelectOption = __SelectOption; -=====*/ - -return _FormSelectWidget; - -}); - -}, -'dijit/form/Select':function(){ -require({cache:{ -'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"listbox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitInputField dijitButtonText\" data-dojo-attach-point=\"containerNode,_popupStateNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitValidationContainer\"\n\t\t\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t/></div\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td\n\t\t><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer\"\n\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t\t${_buttonInputDisabled}\n\t\t/></td\n\t></tr></tbody\n></table>\n"}}); -define("dijit/form/Select", [ - "dojo/_base/array", // array.forEach - "dojo/_base/declare", // declare - "dojo/dom-attr", // domAttr.set - "dojo/dom-class", // domClass.add domClass.remove domClass.toggle - "dojo/dom-geometry", // domGeometry.setMarginBox - "dojo/_base/event", // event.stop - "dojo/i18n", // i18n.getLocalization - "dojo/_base/lang", // lang.hitch - "dojo/sniff", // has("ie") - "./_FormSelectWidget", - "../_HasDropDown", - "../Menu", - "../MenuItem", - "../MenuSeparator", - "../Tooltip", - "dojo/text!./templates/Select.html", - "dojo/i18n!./nls/validate" -], function(array, declare, domAttr, domClass, domGeometry, event, i18n, lang, has, - _FormSelectWidget, _HasDropDown, Menu, MenuItem, MenuSeparator, Tooltip, template){ - -// module: -// dijit/form/Select - - -var _SelectMenu = declare("dijit.form._SelectMenu", Menu, { - // summary: - // An internally-used menu for dropdown that allows us a vertical scrollbar - - // Override Menu.autoFocus setting so that opening a Select highlights the current value. - autoFocus: true, - - buildRendering: function(){ - // summary: - // Stub in our own changes, so that our domNode is not a table - // otherwise, we won't respond correctly to heights/overflows - this.inherited(arguments); - var o = (this.menuTableNode = this.domNode); - var n = (this.domNode = this.ownerDocument.createElement("div")); - n.style.cssText = "overflow-x: hidden; overflow-y: scroll"; - if(o.parentNode){ - o.parentNode.replaceChild(n, o); - } - domClass.remove(o, "dijitMenuTable"); - n.className = o.className + " dijitSelectMenu"; - o.className = "dijitReset dijitMenuTable"; - o.setAttribute("role", "listbox"); - n.setAttribute("role", "presentation"); - n.appendChild(o); - }, - - postCreate: function(){ - // summary: - // stop mousemove from selecting text on IE to be consistent with other browsers - - this.inherited(arguments); - - this.connect(this.domNode, "onselectstart", event.stop); - }, - - - focus: function(){ - // summary: - // Overridden so that the previously selected value will be focused instead of only the first item - var found = false, - val = this.parentWidget.value; - if(lang.isArray(val)){ - val = val[val.length-1]; - } - if(val){ // if focus selected - array.forEach(this.parentWidget._getChildren(), function(child){ - if(child.option && (val === child.option.value)){ // find menu item widget with this value - found = true; - this.focusChild(child, false); // focus previous selection - } - }, this); - } - if(!found){ - this.inherited(arguments); // focus first item by default - } - }, - - resize: function(/*Object*/ mb){ - // summary: - // Overridden so that we are able to handle resizing our - // internal widget. Note that this is not a "full" resize - // implementation - it only works correctly if you pass it a - // marginBox. - // - // mb: Object - // The margin box to set this dropdown to. - if(mb){ - domGeometry.setMarginBox(this.domNode, mb); - if("w" in mb){ - // We've explicitly set the wrapper <div>'s width, so set <table> width to match. - // 100% is safer than a pixel value because there may be a scroll bar with - // browser/OS specific width. - this.menuTableNode.style.width = "100%"; - } - } - } -}); - -var Select = declare("dijit.form.Select", [_FormSelectWidget, _HasDropDown], { - // summary: - // This is a "styleable" select box - it is basically a DropDownButton which - // can take a `<select>` as its input. - - baseClass: "dijitSelect dijitValidationTextBox", - - templateString: template, - - _buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events - - // required: Boolean - // Can be true or false, default is false. - required: false, - - // state: [readonly] String - // "Incomplete" if this select is required but unset (i.e. blank value), "" otherwise - state: "", - - // message: String - // Currently displayed error/prompt message - message: "", - - // tooltipPosition: String[] - // See description of `dijit/Tooltip.defaultPosition` for details on this parameter. - tooltipPosition: [], - - // emptyLabel: string - // What to display in an "empty" dropdown - emptyLabel: " ", // - - // _isLoaded: Boolean - // Whether or not we have been loaded - _isLoaded: false, - - // _childrenLoaded: Boolean - // Whether or not our children have been loaded - _childrenLoaded: false, - - _fillContent: function(){ - // summary: - // Set the value to be the first, or the selected index - this.inherited(arguments); - // set value from selected option - if(this.options.length && !this.value && this.srcNodeRef){ - var si = this.srcNodeRef.selectedIndex || 0; // || 0 needed for when srcNodeRef is not a SELECT - this.value = this.options[si >= 0 ? si : 0].value; - } - // Create the dropDown widget - this.dropDown = new _SelectMenu({ id: this.id + "_menu", parentWidget: this }); - domClass.add(this.dropDown.domNode, this.baseClass.replace(/\s+|$/g, "Menu ")); - }, - - _getMenuItemForOption: function(/*_FormSelectWidget.__SelectOption*/ option){ - // summary: - // For the given option, return the menu item that should be - // used to display it. This can be overridden as needed - if(!option.value && !option.label){ - // We are a separator (no label set for it) - return new MenuSeparator({ownerDocument: this.ownerDocument}); - }else{ - // Just a regular menu option - var click = lang.hitch(this, "_setValueAttr", option); - var item = new MenuItem({ - option: option, - label: option.label || this.emptyLabel, - onClick: click, - ownerDocument: this.ownerDocument, - dir: this.dir, - disabled: option.disabled || false - }); - item.focusNode.setAttribute("role", "option"); - return item; - } - }, - - _addOptionItem: function(/*_FormSelectWidget.__SelectOption*/ option){ - // summary: - // For the given option, add an option to our dropdown. - // If the option doesn't have a value, then a separator is added - // in that place. - if(this.dropDown){ - this.dropDown.addChild(this._getMenuItemForOption(option)); - } - }, - - _getChildren: function(){ - if(!this.dropDown){ - return []; - } - return this.dropDown.getChildren(); - }, - - _loadChildren: function(/*Boolean*/ loadMenuItems){ - // summary: - // Resets the menu and the length attribute of the button - and - // ensures that the label is appropriately set. - // loadMenuItems: Boolean - // actually loads the child menu items - we only do this when we are - // populating for showing the dropdown. - - if(loadMenuItems === true){ - // this.inherited destroys this.dropDown's child widgets (MenuItems). - // Avoid this.dropDown (Menu widget) having a pointer to a destroyed widget (which will cause - // issues later in _setSelected). (see #10296) - if(this.dropDown){ - delete this.dropDown.focusedChild; - } - if(this.options.length){ - this.inherited(arguments); - }else{ - // Drop down menu is blank but add one blank entry just so something appears on the screen - // to let users know that they are no choices (mimicing native select behavior) - array.forEach(this._getChildren(), function(child){ child.destroyRecursive(); }); - var item = new MenuItem({ - ownerDocument: this.ownerDocument, - label: this.emptyLabel - }); - this.dropDown.addChild(item); - } - }else{ - this._updateSelection(); - } - - this._isLoaded = false; - this._childrenLoaded = true; - - if(!this._loadingStore){ - // Don't call this if we are loading - since we will handle it later - this._setValueAttr(this.value, false); - } - }, - - _refreshState: function(){ - if(this._started){ - this.validate(this.focused); - } - }, - - startup: function(){ - this.inherited(arguments); - this._refreshState(); // after all _set* methods have run - }, - - _setValueAttr: function(value){ - this.inherited(arguments); - domAttr.set(this.valueNode, "value", this.get("value")); - this._refreshState(); // to update this.state - }, - - _setDisabledAttr: function(/*Boolean*/ value){ - this.inherited(arguments); - this._refreshState(); // to update this.state - }, - - _setRequiredAttr: function(/*Boolean*/ value){ - this._set("required", value); - this.focusNode.setAttribute("aria-required", value); - this._refreshState(); // to update this.state - }, - - _setOptionsAttr: function(/*Array*/ options){ - this._isLoaded = false; - this._set('options', options); - }, - - _setDisplay: function(/*String*/ newDisplay){ - // summary: - // sets the display for the given value (or values) - var lbl = newDisplay || this.emptyLabel; - this.containerNode.innerHTML = '<span role="option" class="dijitReset dijitInline ' + this.baseClass.replace(/\s+|$/g, "Label ")+'">' + lbl + '</span>'; - }, - - validate: function(/*Boolean*/ isFocused){ - // summary: - // Called by oninit, onblur, and onkeypress, and whenever required/disabled state changes - // description: - // Show missing or invalid messages if appropriate, and highlight textbox field. - // Used when a select is initially set to no value and the user is required to - // set the value. - - var isValid = this.disabled || this.isValid(isFocused); - this._set("state", isValid ? "" : (this._hasBeenBlurred ? "Error" : "Incomplete")); - this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true"); - var message = isValid ? "" : this._missingMsg; - if(message && this.focused && this._hasBeenBlurred){ - Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight()); - }else{ - Tooltip.hide(this.domNode); - } - this._set("message", message); - return isValid; - }, - - isValid: function(/*Boolean*/ /*===== isFocused =====*/){ - // summary: - // Whether or not this is a valid value. The only way a Select - // can be invalid is when it's required but nothing is selected. - return (!this.required || this.value === 0 || !(/^\s*$/.test(this.value || ""))); // handle value is null or undefined - }, - - reset: function(){ - // summary: - // Overridden so that the state will be cleared. - this.inherited(arguments); - Tooltip.hide(this.domNode); - this._refreshState(); // to update this.state - }, - - postMixInProperties: function(){ - // summary: - // set the missing message - this.inherited(arguments); - this._missingMsg = i18n.getLocalization("dijit.form", "validate", this.lang).missingMessage; - }, - - postCreate: function(){ - // summary: - // stop mousemove from selecting text on IE to be consistent with other browsers - - this.inherited(arguments); - - this.connect(this.domNode, "onselectstart", event.stop); - this.domNode.setAttribute("aria-expanded", "false"); - - if(has("ie") < 9){ - // IE INPUT tag fontFamily has to be set directly using STYLE - // the defer gives IE a chance to render the TextBox and to deal with font inheritance - this.defer(function(){ - try{ - var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed - if(s){ - var ff = s.fontFamily; - if(ff){ - var inputs = this.domNode.getElementsByTagName("INPUT"); - if(inputs){ - for(var i=0; i < inputs.length; i++){ - inputs[i].style.fontFamily = ff; - } - } - } - } - }catch(e){/*when used in a Dialog, and this is called before the dialog is - shown, s.fontFamily would trigger "Invalid Argument" error.*/} - }); - } - }, - - _setStyleAttr: function(/*String||Object*/ value){ - this.inherited(arguments); - domClass.toggle(this.domNode, this.baseClass.replace(/\s+|$/g, "FixedWidth "), !!this.domNode.style.width); - }, - - isLoaded: function(){ - return this._isLoaded; - }, - - loadDropDown: function(/*Function*/ loadCallback){ - // summary: - // populates the menu - this._loadChildren(true); - this._isLoaded = true; - loadCallback(); - }, - - closeDropDown: function(){ - // overriding _HasDropDown.closeDropDown() - this.inherited(arguments); - - if(this.dropDown && this.dropDown.menuTableNode){ - // Erase possible width: 100% setting from _SelectMenu.resize(). - // Leaving it would interfere with the next openDropDown() call, which - // queries the natural size of the drop down. - this.dropDown.menuTableNode.style.width = ""; - } - }, - - destroy: function(preserveDom){ - if(this.dropDown && !this.dropDown._destroyed){ - this.dropDown.destroyRecursive(preserveDom); - delete this.dropDown; - } - this.inherited(arguments); - }, - - _onFocus: function(){ - this.validate(true); // show tooltip if second focus of required tooltip, but no selection - this.inherited(arguments); - }, - - _onBlur: function(){ - Tooltip.hide(this.domNode); - this.inherited(arguments); - this.validate(false); - } -}); - -Select._Menu = _SelectMenu; // for monkey patching - -return Select; -}); - -}, -'dojo/store/util/QueryResults':function(){ -define("dojo/store/util/QueryResults", ["../../_base/array", "../../_base/lang", "../../_base/Deferred" -], function(array, lang, Deferred){ - -// module: -// dojo/store/util/QueryResults - -var QueryResults = function(results){ - // summary: - // A function that wraps the results of a store query with additional - // methods. - // description: - // QueryResults is a basic wrapper that allows for array-like iteration - // over any kind of returned data from a query. While the simplest store - // will return a plain array of data, other stores may return deferreds or - // promises; this wrapper makes sure that *all* results can be treated - // the same. - // - // Additional methods include `forEach`, `filter` and `map`. - // results: Array|dojo/promise/Promise - // The result set as an array, or a promise for an array. - // returns: - // An array-like object that can be used for iterating over. - // example: - // Query a store and iterate over the results. - // - // | store.query({ prime: true }).forEach(function(item){ - // | // do something - // | }); - - if(!results){ - return results; - } - // if it is a promise it may be frozen - if(results.then){ - results = lang.delegate(results); - } - function addIterativeMethod(method){ - if(!results[method]){ - results[method] = function(){ - var args = arguments; - return Deferred.when(results, function(results){ - Array.prototype.unshift.call(args, results); - return QueryResults(array[method].apply(array, args)); - }); - }; - } - } - addIterativeMethod("forEach"); - addIterativeMethod("filter"); - addIterativeMethod("map"); - if(!results.total){ - results.total = Deferred.when(results, function(results){ - return results.length; - }); - } - return results; // Object -}; - -lang.setObject("dojo.store.util.QueryResults", QueryResults); - -return QueryResults; - -}); - -}, -'dijit/form/_ListBase':function(){ -define("dijit/form/_ListBase", [ - "dojo/_base/declare", // declare - "dojo/on", - "dojo/window" // winUtils.scrollIntoView -], function(declare, on, winUtils){ - -// module: -// dijit/form/_ListBase - -return declare( "dijit.form._ListBase", null, { - // summary: - // Focus-less menu to handle UI events consistently - // Abstract methods that must be defined externally: - // - // - onSelect: item is active (mousedown but not yet mouseup, or keyboard arrow selected but no Enter) - // - onDeselect: cancels onSelect - // tags: - // private - - // selected: DOMNode - // currently selected node - selected: null, - - _listConnect: function(/*String|Function*/ eventType, /*String*/ callbackFuncName){ - // summary: - // Connects 'containerNode' to specified method of this object - // and automatically registers for 'disconnect' on widget destroy. - // description: - // Provide widget-specific analog to 'connect'. - // The callback function is called with the normal event object, - // but also a second parameter is passed that indicates which list item - // actually received the event. - // returns: - // A handle that can be passed to `disconnect` in order to disconnect - // before the widget is destroyed. - // tags: - // private - - var self = this; - return self.own(on(self.containerNode, - on.selector( - function(eventTarget, selector, target){ - return eventTarget.parentNode == target; - }, - eventType - ), - function(evt){ - evt.preventDefault(); - self[callbackFuncName](evt, this); - } - )); - }, - - selectFirstNode: function(){ - // summary: - // Select the first displayed item in the list. - var first = this.containerNode.firstChild; - while(first && first.style.display == "none"){ - first = first.nextSibling; - } - this._setSelectedAttr(first); - }, - - selectLastNode: function(){ - // summary: - // Select the last displayed item in the list - var last = this.containerNode.lastChild; - while(last && last.style.display == "none"){ - last = last.previousSibling; - } - this._setSelectedAttr(last); - }, - - selectNextNode: function(){ - // summary: - // Select the item just below the current selection. - // If nothing selected, select first node. - var selectedNode = this.selected; - if(!selectedNode){ - this.selectFirstNode(); - }else{ - var next = selectedNode.nextSibling; - while(next && next.style.display == "none"){ - next = next.nextSibling; - } - if(!next){ - this.selectFirstNode(); - }else{ - this._setSelectedAttr(next); - } - } - }, - - selectPreviousNode: function(){ - // summary: - // Select the item just above the current selection. - // If nothing selected, select last node (if - // you select Previous and try to keep scrolling up the list). - var selectedNode = this.selected; - if(!selectedNode){ - this.selectLastNode(); - }else{ - var prev = selectedNode.previousSibling; - while(prev && prev.style.display == "none"){ - prev = prev.previousSibling; - } - if(!prev){ - this.selectLastNode(); - }else{ - this._setSelectedAttr(prev); - } - } - }, - - _setSelectedAttr: function(/*DomNode*/ node){ - // summary: - // Does the actual select. - if(this.selected != node){ - var selectedNode = this.selected; - if(selectedNode){ - this.onDeselect(selectedNode); - this.selected = null; - } - if(node){ - this.selected = node; - winUtils.scrollIntoView(node); - this.onSelect(node); - } - }else if(node){ - this.onSelect(node); - } - } -}); - -}); - -}, -'dijit/form/_FormWidget':function(){ -define("dijit/form/_FormWidget", [ - "dojo/_base/declare", // declare - "dojo/has", // has("dijit-legacy-requires") - "dojo/_base/kernel", // kernel.deprecated - "dojo/ready", - "../_Widget", - "../_CssStateMixin", - "../_TemplatedMixin", - "./_FormWidgetMixin" -], function(declare, has, kernel, ready, _Widget, _CssStateMixin, _TemplatedMixin, _FormWidgetMixin){ - - -// module: -// dijit/form/_FormWidget - -// Back compat w/1.6, remove for 2.0 -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/form/_FormValueWidget"]; - require(requires); // use indirection so modules not rolled into a build - }); -} - -return declare("dijit.form._FormWidget", [_Widget, _TemplatedMixin, _CssStateMixin, _FormWidgetMixin], { - // summary: - // Base class for widgets corresponding to native HTML elements such as `<checkbox>` or `<button>`, - // which can be children of a `<form>` node or a `dijit/form/Form` widget. - // - // description: - // Represents a single HTML element. - // All these widgets should have these attributes just like native HTML input elements. - // You can set them during widget construction or afterwards, via `dijit/_WidgetBase.set()`. - // - // They also share some common methods. - - setDisabled: function(/*Boolean*/ disabled){ - // summary: - // Deprecated. Use set('disabled', ...) instead. - kernel.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0"); - this.set('disabled', disabled); - }, - - setValue: function(/*String*/ value){ - // summary: - // Deprecated. Use set('value', ...) instead. - kernel.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use set('value',"+value+") instead.", "", "2.0"); - this.set('value', value); - }, - - getValue: function(){ - // summary: - // Deprecated. Use get('value') instead. - kernel.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0"); - return this.get('value'); - }, - - postMixInProperties: function(){ - // Setup name=foo string to be referenced from the template (but only if a name has been specified) - // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660. - // Regarding escaping, see heading "Attribute values" in - // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2 - this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/"/g, """) + '"') : ''; - this.inherited(arguments); - }, - - // Override automatic assigning type --> focusNode, it causes exception on IE. - // Instead, type must be specified as ${type} in the template, as part of the original DOM - _setTypeAttr: null -}); - -}); - -}, -'dojo/DeferredList':function(){ -define("dojo/DeferredList", ["./_base/kernel", "./_base/Deferred", "./_base/array"], function(dojo, Deferred, darray){ - // module: - // dojo/DeferredList - - -dojo.DeferredList = function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){ - // summary: - // Deprecated, use dojo/promise/all instead. - // Provides event handling for a group of Deferred objects. - // description: - // DeferredList takes an array of existing deferreds and returns a new deferred of its own - // this new deferred will typically have its callback fired when all of the deferreds in - // the given list have fired their own deferreds. The parameters `fireOnOneCallback` and - // fireOnOneErrback, will fire before all the deferreds as appropriate - // list: - // The list of deferreds to be synchronizied with this DeferredList - // fireOnOneCallback: - // Will cause the DeferredLists callback to be fired as soon as any - // of the deferreds in its list have been fired instead of waiting until - // the entire list has finished - // fireonOneErrback: - // Will cause the errback to fire upon any of the deferreds errback - // canceller: - // A deferred canceller function, see dojo.Deferred - var resultList = []; - Deferred.call(this); - var self = this; - if(list.length === 0 && !fireOnOneCallback){ - this.resolve([0, []]); - } - var finished = 0; - darray.forEach(list, function(item, i){ - item.then(function(result){ - if(fireOnOneCallback){ - self.resolve([i, result]); - }else{ - addResult(true, result); - } - },function(error){ - if(fireOnOneErrback){ - self.reject(error); - }else{ - addResult(false, error); - } - if(consumeErrors){ - return null; - } - throw error; - }); - function addResult(succeeded, result){ - resultList[i] = [succeeded, result]; - finished++; - if(finished === list.length){ - self.resolve(resultList); - } - - } - }); -}; -dojo.DeferredList.prototype = new Deferred(); - -dojo.DeferredList.prototype.gatherResults = function(deferredList){ - // summary: - // Gathers the results of the deferreds for packaging - // as the parameters to the Deferred Lists' callback - // deferredList: dojo/DeferredList - // The deferred list from which this function gathers results. - // returns: dojo/DeferredList - // The newly created deferred list which packs results as - // parameters to its callback. - - var d = new dojo.DeferredList(deferredList, false, true, false); - d.addCallback(function(results){ - var ret = []; - darray.forEach(results, function(result){ - ret.push(result[1]); - }); - return ret; - }); - return d; -}; - -return dojo.DeferredList; -}); - -}, -'dojo/dnd/common':function(){ -define("dojo/dnd/common", ["../_base/connect", "../_base/kernel", "../_base/lang", "../dom"], - function(connect, kernel, lang, dom){ - -// module: -// dojo/dnd/common - -var exports = lang.getObject("dojo.dnd", true); -/*===== -// TODO: for 2.0, replace line above with this code. -var exports = { - // summary: - // TODOC -}; -=====*/ - -exports.getCopyKeyState = connect.isCopyKey; - -exports._uniqueId = 0; -exports.getUniqueId = function(){ - // summary: - // returns a unique string for use with any DOM element - var id; - do{ - id = kernel._scopeName + "Unique" + (++exports._uniqueId); - }while(dom.byId(id)); - return id; -}; - -exports._empty = {}; - -exports.isFormElement = function(/*Event*/ e){ - // summary: - // returns true if user clicked on a form element - var t = e.target; - if(t.nodeType == 3 /*TEXT_NODE*/){ - t = t.parentNode; - } - return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean -}; - -return exports; -}); - -}, -'dijit/CheckedMenuItem':function(){ -require({cache:{ -'url:dijit/templates/CheckedMenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitemcheckbox\" tabIndex=\"-1\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">✓</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\"> </td>\n</tr>\n"}}); -define("dijit/CheckedMenuItem", [ - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.toggle - "./MenuItem", - "dojo/text!./templates/CheckedMenuItem.html", - "./hccss" -], function(declare, domClass, MenuItem, template){ - - // module: - // dijit/CheckedMenuItem - - return declare("dijit.CheckedMenuItem", MenuItem, { - // summary: - // A checkbox-like menu item for toggling on and off - - templateString: template, - - // checked: Boolean - // Our checked state - checked: false, - _setCheckedAttr: function(/*Boolean*/ checked){ - // summary: - // Hook so attr('checked', bool) works. - // Sets the class and state for the check box. - domClass.toggle(this.domNode, "dijitCheckedMenuItemChecked", checked); - this.domNode.setAttribute("aria-checked", checked ? "true" : "false"); - this._set("checked", checked); - }, - - iconClass: "", // override dijitNoIcon - - onChange: function(/*Boolean*/ /*===== checked =====*/){ - // summary: - // User defined function to handle check/uncheck events - // tags: - // callback - }, - - _onClick: function(evt){ - // summary: - // Clicking this item just toggles its state - // tags: - // private - if(!this.disabled){ - this.set("checked", !this.checked); - this.onChange(this.checked); - } - this.onClick(evt); - } - }); -}); - -}, -'dijit/Viewport':function(){ -define("dijit/Viewport", [ - "dojo/Evented", - "dojo/on", - "dojo/ready", - "dojo/sniff", - "dojo/_base/window", // global - "dojo/window" // getBox() -], function(Evented, on, ready, has, win, winUtils){ - - // module: - // dijit/Viewport - - /*===== - return { - // summary: - // Utility singleton to watch for viewport resizes, avoiding duplicate notifications - // which can lead to infinite loops. - // description: - // Usage: Viewport.on("resize", myCallback). - // - // myCallback() is called without arguments in case it's _WidgetBase.resize(), - // which would interpret the argument as the size to make the widget. - }; - =====*/ - - var Viewport = new Evented(); - - ready(200, function(){ - var oldBox = winUtils.getBox(); - Viewport._rlh = on(win.global, "resize", function(){ - var newBox = winUtils.getBox(); - if(oldBox.h == newBox.h && oldBox.w == newBox.w){ return; } - oldBox = newBox; - Viewport.emit("resize"); - }); - - // Also catch zoom changes on IE8, since they don't naturally generate resize events - if(has("ie") == 8){ - var deviceXDPI = screen.deviceXDPI; - setInterval(function(){ - if(screen.deviceXDPI != deviceXDPI){ - deviceXDPI = screen.deviceXDPI; - Viewport.emit("resize"); - } - }, 500); - } - }); - - return Viewport; -}); - -}, -'dijit/_base/place':function(){ -define("dijit/_base/place", [ - "dojo/_base/array", // array.forEach - "dojo/_base/lang", // lang.isArray, lang.mixin - "dojo/window", // windowUtils.getBox - "../place", - "../main" // export to dijit namespace -], function(array, lang, windowUtils, place, dijit){ - - // module: - // dijit/_base/place - - - var exports = { - // summary: - // Deprecated back compatibility module, new code should use dijit/place directly instead of using this module. - }; - - exports.getViewport = function(){ - // summary: - // Deprecated method to return the dimensions and scroll position of the viewable area of a browser window. - // New code should use windowUtils.getBox() - - return windowUtils.getBox(); - }; - - exports.placeOnScreen = place.at; - - exports.placeOnScreenAroundElement = function(node, aroundNode, aroundCorners, layoutNode){ - // summary: - // Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object - // for the "around" argument and finds a proper processor to place a node. - // Deprecated, new code should use dijit/place.around() instead. - - // Convert old style {"BL": "TL", "BR": "TR"} type argument - // to style needed by dijit.place code: - // [ - // {aroundCorner: "BL", corner: "TL" }, - // {aroundCorner: "BR", corner: "TR" } - // ] - var positions; - if(lang.isArray(aroundCorners)){ - positions = aroundCorners; - }else{ - positions = []; - for(var key in aroundCorners){ - positions.push({aroundCorner: key, corner: aroundCorners[key]}); - } - } - - return place.around(node, aroundNode, positions, true, layoutNode); - }; - - exports.placeOnScreenAroundNode = exports.placeOnScreenAroundElement; - /*===== - exports.placeOnScreenAroundNode = function(node, aroundNode, aroundCorners, layoutNode){ - // summary: - // Position node adjacent or kitty-corner to aroundNode - // such that it's fully visible in viewport. - // Deprecated, new code should use dijit/place.around() instead. - }; - =====*/ - - exports.placeOnScreenAroundRectangle = exports.placeOnScreenAroundElement; - /*===== - exports.placeOnScreenAroundRectangle = function(node, aroundRect, aroundCorners, layoutNode){ - // summary: - // Like dijit.placeOnScreenAroundNode(), except that the "around" - // parameter is an arbitrary rectangle on the screen (x, y, width, height) - // instead of a dom node. - // Deprecated, new code should use dijit/place.around() instead. - }; - =====*/ - - exports.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){ - // summary: - // Deprecated method, unneeded when using dijit/place directly. - // Transforms the passed array of preferred positions into a format suitable for - // passing as the aroundCorners argument to dijit/place.placeOnScreenAroundElement. - // position: String[] - // This variable controls the position of the drop down. - // It's an array of strings with the following values: - // - // - before: places drop down to the left of the target node/widget, or to the right in - // the case of RTL scripts like Hebrew and Arabic - // - after: places drop down to the right of the target node/widget, or to the left in - // the case of RTL scripts like Hebrew and Arabic - // - above: drop down goes above target node - // - below: drop down goes below target node - // - // The list is positions is tried, in order, until a position is found where the drop down fits - // within the viewport. - // leftToRight: Boolean - // Whether the popup will be displaying in leftToRight mode. - - var align = {}; - array.forEach(position, function(pos){ - var ltr = leftToRight; - switch(pos){ - case "after": - align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR"; - break; - case "before": - align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL"; - break; - case "below-alt": - ltr = !ltr; - // fall through - case "below": - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - align[ltr ? "BL" : "BR"] = ltr ? "TL" : "TR"; - align[ltr ? "BR" : "BL"] = ltr ? "TR" : "TL"; - break; - case "above-alt": - ltr = !ltr; - // fall through - case "above": - default: - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - align[ltr ? "TL" : "TR"] = ltr ? "BL" : "BR"; - align[ltr ? "TR" : "TL"] = ltr ? "BR" : "BL"; - break; - } - }); - return align; - }; - - lang.mixin(dijit, exports); - - /*===== return exports; =====*/ - return dijit; // for back compat :-( -}); - -}, -'dijit/MenuSeparator':function(){ -require({cache:{ -'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>"}}); -define("dijit/MenuSeparator", [ - "dojo/_base/declare", // declare - "dojo/dom", // dom.setSelectable - "./_WidgetBase", - "./_TemplatedMixin", - "./_Contained", - "dojo/text!./templates/MenuSeparator.html" -], function(declare, dom, _WidgetBase, _TemplatedMixin, _Contained, template){ - - // module: - // dijit/MenuSeparator - - return declare("dijit.MenuSeparator", [_WidgetBase, _TemplatedMixin, _Contained], { - // summary: - // A line between two menu items - - templateString: template, - - buildRendering: function(){ - this.inherited(arguments); - dom.setSelectable(this.domNode, false); - }, - - isFocusable: function(){ - // summary: - // Override to always return false - // tags: - // protected - - return false; // Boolean - } - }); -}); - -}, -'dijit/form/_ComboBoxMenu':function(){ -define("dijit/form/_ComboBoxMenu", [ - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add domClass.remove - "dojo/dom-style", // domStyle.get - "dojo/keys", // keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW - "../_WidgetBase", - "../_TemplatedMixin", - "./_ComboBoxMenuMixin", - "./_ListMouseMixin" -], function(declare, domClass, domStyle, keys, - _WidgetBase, _TemplatedMixin, _ComboBoxMenuMixin, _ListMouseMixin){ - - - // module: - // dijit/form/_ComboBoxMenu - - return declare("dijit.form._ComboBoxMenu",[_WidgetBase, _TemplatedMixin, _ListMouseMixin, _ComboBoxMenuMixin], { - // summary: - // Focus-less menu for internal use in `dijit/form/ComboBox` - // Abstract methods that must be defined externally: - // - // - onChange: item was explicitly chosen (mousedown somewhere on the menu and mouseup somewhere on the menu) - // - onPage: next(1) or previous(-1) button pressed - // tags: - // private - - templateString: "<div class='dijitReset dijitMenu' data-dojo-attach-point='containerNode' style='overflow: auto; overflow-x: hidden;' role='listbox'>" - +"<div class='dijitMenuItem dijitMenuPreviousButton' data-dojo-attach-point='previousButton' role='option'></div>" - +"<div class='dijitMenuItem dijitMenuNextButton' data-dojo-attach-point='nextButton' role='option'></div>" - +"</div>", - - baseClass: "dijitComboBoxMenu", - - postCreate: function(){ - this.inherited(arguments); - if(!this.isLeftToRight()){ - domClass.add(this.previousButton, "dijitMenuItemRtl"); - domClass.add(this.nextButton, "dijitMenuItemRtl"); - } - }, - - _createMenuItem: function(){ - // note: not using domConstruct.create() because need to specify document - var item = this.ownerDocument.createElement("div"); - item.className = "dijitReset dijitMenuItem" +(this.isLeftToRight() ? "" : " dijitMenuItemRtl"); - item.setAttribute("role", "option"); - return item; - }, - - onHover: function(/*DomNode*/ node){ - // summary: - // Add hover CSS - domClass.add(node, "dijitMenuItemHover"); - }, - - onUnhover: function(/*DomNode*/ node){ - // summary: - // Remove hover CSS - domClass.remove(node, "dijitMenuItemHover"); - }, - - onSelect: function(/*DomNode*/ node){ - // summary: - // Add selected CSS - domClass.add(node, "dijitMenuItemSelected"); - }, - - onDeselect: function(/*DomNode*/ node){ - // summary: - // Remove selected CSS - domClass.remove(node, "dijitMenuItemSelected"); - }, - - _page: function(/*Boolean*/ up){ - // summary: - // Handles page-up and page-down keypresses - - var scrollamount = 0; - var oldscroll = this.domNode.scrollTop; - var height = domStyle.get(this.domNode, "height"); - // if no item is highlighted, highlight the first option - if(!this.getHighlightedOption()){ - this.selectNextNode(); - } - while(scrollamount<height){ - var highlighted_option = this.getHighlightedOption(); - if(up){ - // stop at option 1 - if(!highlighted_option.previousSibling || - highlighted_option.previousSibling.style.display == "none"){ - break; - } - this.selectPreviousNode(); - }else{ - // stop at last option - if(!highlighted_option.nextSibling || - highlighted_option.nextSibling.style.display == "none"){ - break; - } - this.selectNextNode(); - } - // going backwards - var newscroll = this.domNode.scrollTop; - scrollamount += (newscroll-oldscroll)*(up ? -1:1); - oldscroll = newscroll; - } - }, - - handleKey: function(evt){ - // summary: - // Handle keystroke event forwarded from ComboBox, returning false if it's - // a keystroke I recognize and process, true otherwise. - switch(evt.keyCode){ - case keys.DOWN_ARROW: - this.selectNextNode(); - return false; - case keys.PAGE_DOWN: - this._page(false); - return false; - case keys.UP_ARROW: - this.selectPreviousNode(); - return false; - case keys.PAGE_UP: - this._page(true); - return false; - default: - return true; - } - } - }); -}); - -}, -'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">▼</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">◀</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">▶</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>", -'dijit/Dialog':function(){ -require({cache:{ -'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"\n\t\t\t\trole=\"heading\" level=\"1\"></span>\n\t\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"-1\">\n\t\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t\t</span>\n\t</div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n"}}); -define("dijit/Dialog", [ - "require", - "dojo/_base/array", // array.forEach array.indexOf array.map - "dojo/_base/connect", // connect._keypress - "dojo/_base/declare", // declare - "dojo/_base/Deferred", // Deferred - "dojo/dom", // dom.isDescendant - "dojo/dom-class", // domClass.add domClass.contains - "dojo/dom-geometry", // domGeometry.position - "dojo/dom-style", // domStyle.set - "dojo/_base/event", // event.stop - "dojo/_base/fx", // fx.fadeIn fx.fadeOut - "dojo/i18n", // i18n.getLocalization - "dojo/keys", - "dojo/_base/lang", // lang.mixin lang.hitch - "dojo/on", - "dojo/ready", - "dojo/sniff", // has("ie") has("opera") has("dijit-legacy-requires") - "dojo/window", // winUtils.getBox, winUtils.get - "dojo/dnd/Moveable", // Moveable - "dojo/dnd/TimedMoveable", // TimedMoveable - "./focus", - "./_base/manager", // manager.defaultDuration - "./_Widget", - "./_TemplatedMixin", - "./_CssStateMixin", - "./form/_FormMixin", - "./_DialogMixin", - "./DialogUnderlay", - "./layout/ContentPane", - "dojo/text!./templates/Dialog.html", - "./main", // for back-compat, exporting dijit._underlay (remove in 2.0) - "dojo/i18n!./nls/common" -], function(require, array, connect, declare, Deferred, - dom, domClass, domGeometry, domStyle, event, fx, i18n, keys, lang, on, ready, has, winUtils, - Moveable, TimedMoveable, focus, manager, _Widget, _TemplatedMixin, _CssStateMixin, _FormMixin, _DialogMixin, - DialogUnderlay, ContentPane, template, dijit){ - - // module: - // dijit/Dialog - - /*===== - dijit._underlay = function(kwArgs){ - // summary: - // A shared instance of a `dijit.DialogUnderlay` - // - // description: - // A shared instance of a `dijit.DialogUnderlay` created and - // used by `dijit.Dialog`, though never created until some Dialog - // or subclass thereof is shown. - }; - =====*/ - - var _DialogBase = declare("dijit._DialogBase", [_TemplatedMixin, _FormMixin, _DialogMixin, _CssStateMixin], { - templateString: template, - - baseClass: "dijitDialog", - - cssStateNodes: { - closeButtonNode: "dijitDialogCloseIcon" - }, - - // Map widget attributes to DOMNode attributes. - _setTitleAttr: [ - { node: "titleNode", type: "innerHTML" }, - { node: "titleBar", type: "attribute" } - ], - - // open: [readonly] Boolean - // True if Dialog is currently displayed on screen. - open: false, - - // duration: Integer - // The time in milliseconds it takes the dialog to fade in and out - duration: manager.defaultDuration, - - // refocus: Boolean - // A Toggle to modify the default focus behavior of a Dialog, which - // is to re-focus the element which had focus before being opened. - // False will disable refocusing. Default: true - refocus: true, - - // autofocus: Boolean - // A Toggle to modify the default focus behavior of a Dialog, which - // is to focus on the first dialog element after opening the dialog. - // False will disable autofocusing. Default: true - autofocus: true, - - // _firstFocusItem: [private readonly] DomNode - // The pointer to the first focusable node in the dialog. - // Set by `dijit/_DialogMixin._getFocusItems()`. - _firstFocusItem: null, - - // _lastFocusItem: [private readonly] DomNode - // The pointer to which node has focus prior to our dialog. - // Set by `dijit/_DialogMixin._getFocusItems()`. - _lastFocusItem: null, - - // doLayout: [protected] Boolean - // Don't change this parameter from the default value. - // This ContentPane parameter doesn't make sense for Dialog, since Dialog - // is never a child of a layout container, nor can you specify the size of - // Dialog in order to control the size of an inner widget. - doLayout: false, - - // draggable: Boolean - // Toggles the moveable aspect of the Dialog. If true, Dialog - // can be dragged by it's title. If false it will remain centered - // in the viewport. - draggable: true, - - _setDraggableAttr: function(/*Boolean*/ val){ - // Avoid _WidgetBase behavior of copying draggable attribute to this.domNode, - // as that prevents text select on modern browsers (#14452) - this._set("draggable", val); - }, - - // aria-describedby: String - // Allows the user to add an aria-describedby attribute onto the dialog. The value should - // be the id of the container element of text that describes the dialog purpose (usually - // the first text in the dialog). - // | <div data-dojo-type="dijit/Dialog" aria-describedby="intro" .....> - // | <div id="intro">Introductory text</div> - // | <div>rest of dialog contents</div> - // | </div> - "aria-describedby": "", - - // maxRatio: Number - // Maximum size to allow the dialog to expand to, relative to viewport size - maxRatio: 0.9, - - postMixInProperties: function(){ - var _nlsResources = i18n.getLocalization("dijit", "common"); - lang.mixin(this, _nlsResources); - this.inherited(arguments); - }, - - postCreate: function(){ - domStyle.set(this.domNode, { - display: "none", - position:"absolute" - }); - this.ownerDocumentBody.appendChild(this.domNode); - - this.inherited(arguments); - - this.connect(this, "onExecute", "hide"); - this.connect(this, "onCancel", "hide"); - this._modalconnects = []; - }, - - onLoad: function(){ - // summary: - // Called when data has been loaded from an href. - // Unlike most other callbacks, this function can be connected to (via `dojo.connect`) - // but should *not* be overridden. - // tags: - // callback - - // when href is specified we need to reposition the dialog after the data is loaded - // and find the focusable elements - this._position(); - if(this.autofocus && DialogLevelManager.isTop(this)){ - this._getFocusItems(this.domNode); - focus.focus(this._firstFocusItem); - } - this.inherited(arguments); - }, - - _onBlur: function(by){ - this.inherited(arguments); - - // If focus was accidentally removed from the dialog, such as if the user clicked a blank - // area of the screen, or clicked the browser's address bar and then tabbed into the page, - // then refocus. Won't do anything if focus was removed because the Dialog was closed, or - // because a new Dialog popped up on top of the old one. - var refocus = lang.hitch(this, function(){ - if(this.open && !this._destroyed && DialogLevelManager.isTop(this)){ - this._getFocusItems(this.domNode); - focus.focus(this._firstFocusItem); - } - }); - if(by == "mouse"){ - // wait for mouse up, and then refocus dialog; otherwise doesn't work - on.once(this.ownerDocument, "mouseup", refocus); - }else{ - refocus(); - } - }, - - _endDrag: function(){ - // summary: - // Called after dragging the Dialog. Saves the position of the dialog in the viewport, - // and also adjust position to be fully within the viewport, so user doesn't lose access to handle - var nodePosition = domGeometry.position(this.domNode), - viewport = winUtils.getBox(this.ownerDocument); - nodePosition.y = Math.min(Math.max(nodePosition.y, 0), (viewport.h - nodePosition.h)); - nodePosition.x = Math.min(Math.max(nodePosition.x, 0), (viewport.w - nodePosition.w)); - this._relativePosition = nodePosition; - this._position(); - }, - - _setup: function(){ - // summary: - // Stuff we need to do before showing the Dialog for the first - // time (but we defer it until right beforehand, for - // performance reasons). - // tags: - // private - - var node = this.domNode; - - if(this.titleBar && this.draggable){ - this._moveable = new ((has("ie") == 6) ? TimedMoveable // prevent overload, see #5285 - : Moveable)(node, { handle: this.titleBar }); - this.connect(this._moveable, "onMoveStop", "_endDrag"); - }else{ - domClass.add(node,"dijitDialogFixed"); - } - - this.underlayAttrs = { - dialogId: this.id, - "class": array.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" "), - ownerDocument: this.ownerDocument - }; - }, - - _size: function(){ - // summary: - // If necessary, shrink dialog contents so dialog fits in viewport - // tags: - // private - - this._checkIfSingleChild(); - - // If we resized the dialog contents earlier, reset them back to original size, so - // that if the user later increases the viewport size, the dialog can display w/out a scrollbar. - // Need to do this before the domGeometry.position(this.domNode) call below. - if(this._singleChild){ - if(typeof this._singleChildOriginalStyle != "undefined"){ - this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle; - delete this._singleChildOriginalStyle; - } - }else{ - domStyle.set(this.containerNode, { - width:"auto", - height:"auto" - }); - } - - var bb = domGeometry.position(this.domNode); - - // Get viewport size but then reduce it by a bit; Dialog should always have some space around it - // to indicate that it's a popup. This will also compensate for possible scrollbars on viewport. - var viewport = winUtils.getBox(this.ownerDocument); - viewport.w *= this.maxRatio; - viewport.h *= this.maxRatio; - - if(bb.w >= viewport.w || bb.h >= viewport.h){ - // Reduce size of dialog contents so that dialog fits in viewport - - var containerSize = domGeometry.position(this.containerNode), - w = Math.min(bb.w, viewport.w) - (bb.w - containerSize.w), - h = Math.min(bb.h, viewport.h) - (bb.h - containerSize.h); - - if(this._singleChild && this._singleChild.resize){ - if(typeof this._singleChildOriginalStyle == "undefined"){ - this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText; - } - this._singleChild.resize({w: w, h: h}); - }else{ - domStyle.set(this.containerNode, { - width: w + "px", - height: h + "px", - overflow: "auto", - position: "relative" // workaround IE bug moving scrollbar or dragging dialog - }); - } - }else{ - if(this._singleChild && this._singleChild.resize){ - this._singleChild.resize(); - } - } - }, - - _position: function(){ - // summary: - // Position modal dialog in the viewport. If no relative offset - // in the viewport has been determined (by dragging, for instance), - // center the node. Otherwise, use the Dialog's stored relative offset, - // and position the node to top: left: values based on the viewport. - if(!domClass.contains(this.ownerDocumentBody, "dojoMove")){ // don't do anything if called during auto-scroll - var node = this.domNode, - viewport = winUtils.getBox(this.ownerDocument), - p = this._relativePosition, - bb = p ? null : domGeometry.position(node), - l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)), - t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2)) - ; - domStyle.set(node,{ - left: l + "px", - top: t + "px" - }); - } - }, - - _onKey: function(/*Event*/ evt){ - // summary: - // Handles the keyboard events for accessibility reasons - // tags: - // private - - if(evt.charOrCode){ - var node = evt.target; - if(evt.charOrCode === keys.TAB){ - this._getFocusItems(this.domNode); - } - var singleFocusItem = (this._firstFocusItem == this._lastFocusItem); - // see if we are shift-tabbing from first focusable item on dialog - if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){ - if(!singleFocusItem){ - focus.focus(this._lastFocusItem); // send focus to last item in dialog - } - event.stop(evt); - }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){ - if(!singleFocusItem){ - focus.focus(this._firstFocusItem); // send focus to first item in dialog - } - event.stop(evt); - }else{ - // see if the key is for the dialog - while(node){ - if(node == this.domNode || domClass.contains(node, "dijitPopup")){ - if(evt.charOrCode == keys.ESCAPE){ - this.onCancel(); - }else{ - return; // just let it go - } - } - node = node.parentNode; - } - // this key is for the disabled document window - if(evt.charOrCode !== keys.TAB){ // allow tabbing into the dialog for a11y - event.stop(evt); - // opera won't tab to a div - }else if(!has("opera")){ - try{ - this._firstFocusItem.focus(); - }catch(e){ /*squelch*/ } - } - } - } - }, - - show: function(){ - // summary: - // Display the dialog - // returns: dojo/_base/Deferred - // Deferred object that resolves when the display animation is complete - - if(this.open){ return; } - - if(!this._started){ - this.startup(); - } - - // first time we show the dialog, there's some initialization stuff to do - if(!this._alreadyInitialized){ - this._setup(); - this._alreadyInitialized=true; - } - - if(this._fadeOutDeferred){ - this._fadeOutDeferred.cancel(); - } - - // Recenter Dialog if user scrolls browser. Connecting to document doesn't work on IE, need to use window. - var win = winUtils.get(this.ownerDocument); - this._modalconnects.push(on(win, "scroll", lang.hitch(this, "resize"))); - - this._modalconnects.push(on(this.domNode, connect._keypress, lang.hitch(this, "_onKey"))); - - domStyle.set(this.domNode, { - opacity:0, - display:"" - }); - - this._set("open", true); - this._onShow(); // lazy load trigger - - this._size(); - this._position(); - - // fade-in Animation object, setup below - var fadeIn; - - this._fadeInDeferred = new Deferred(lang.hitch(this, function(){ - fadeIn.stop(); - delete this._fadeInDeferred; - })); - - fadeIn = fx.fadeIn({ - node: this.domNode, - duration: this.duration, - beforeBegin: lang.hitch(this, function(){ - DialogLevelManager.show(this, this.underlayAttrs); - }), - onEnd: lang.hitch(this, function(){ - if(this.autofocus && DialogLevelManager.isTop(this)){ - // find focusable items each time dialog is shown since if dialog contains a widget the - // first focusable items can change - this._getFocusItems(this.domNode); - focus.focus(this._firstFocusItem); - } - this._fadeInDeferred.resolve(true); - delete this._fadeInDeferred; - }) - }).play(); - - return this._fadeInDeferred; - }, - - hide: function(){ - // summary: - // Hide the dialog - // returns: dojo/_base/Deferred - // Deferred object that resolves when the hide animation is complete - - // If we haven't been initialized yet then we aren't showing and we can just return. - // Likewise if we are already hidden, or are currently fading out. - if(!this._alreadyInitialized || !this.open){ - return; - } - if(this._fadeInDeferred){ - this._fadeInDeferred.cancel(); - } - - // fade-in Animation object, setup below - var fadeOut; - - this._fadeOutDeferred = new Deferred(lang.hitch(this, function(){ - fadeOut.stop(); - delete this._fadeOutDeferred; - })); - // fire onHide when the promise resolves. - this._fadeOutDeferred.then(lang.hitch(this, 'onHide')); - - fadeOut = fx.fadeOut({ - node: this.domNode, - duration: this.duration, - onEnd: lang.hitch(this, function(){ - this.domNode.style.display = "none"; - DialogLevelManager.hide(this); - this._fadeOutDeferred.resolve(true); - delete this._fadeOutDeferred; - }) - }).play(); - - if(this._scrollConnected){ - this._scrollConnected = false; - } - var h; - while(h = this._modalconnects.pop()){ - h.remove(); - } - - if(this._relativePosition){ - delete this._relativePosition; - } - this._set("open", false); - - return this._fadeOutDeferred; - }, - - resize: function(){ - // summary: - // Called when viewport scrolled or size changed. Position the Dialog and the underlay. - // tags: - // private - if(this.domNode.style.display != "none"){ - if(DialogUnderlay._singleton){ // avoid race condition during show() - DialogUnderlay._singleton.layout(); - } - this._position(); - this._size(); - } - }, - - destroy: function(){ - if(this._fadeInDeferred){ - this._fadeInDeferred.cancel(); - } - if(this._fadeOutDeferred){ - this._fadeOutDeferred.cancel(); - } - if(this._moveable){ - this._moveable.destroy(); - } - var h; - while(h = this._modalconnects.pop()){ - h.remove(); - } - - DialogLevelManager.hide(this); - - this.inherited(arguments); - } - }); - - var Dialog = declare("dijit.Dialog", [ContentPane, _DialogBase], { - // summary: - // A modal dialog Widget. - // description: - // Pops up a modal dialog window, blocking access to the screen - // and also graying out the screen Dialog is extended from - // ContentPane so it supports all the same parameters (href, etc.). - // example: - // | <div data-dojo-type="dijit/Dialog" data-dojo-props="href: 'test.html'"></div> - // example: - // | var foo = new Dialog({ title: "test dialog", content: "test content" }; - // | foo.placeAt(win.body()); - // | foo.startup(); - }); - Dialog._DialogBase = _DialogBase; // for monkey patching and dojox/widget/DialogSimple - - var DialogLevelManager = Dialog._DialogLevelManager = { - // summary: - // Controls the various active "levels" on the page, starting with the - // stuff initially visible on the page (at z-index 0), and then having an entry for - // each Dialog shown. - - _beginZIndex: 950, - - show: function(/*dijit/_WidgetBase*/ dialog, /*Object*/ underlayAttrs){ - // summary: - // Call right before fade-in animation for new dialog. - // Saves current focus, displays/adjusts underlay for new dialog, - // and sets the z-index of the dialog itself. - // - // New dialog will be displayed on top of all currently displayed dialogs. - // - // Caller is responsible for setting focus in new dialog after the fade-in - // animation completes. - - // Save current focus - ds[ds.length-1].focus = focus.curNode; - - // Display the underlay, or if already displayed then adjust for this new dialog - // TODO: one underlay per document (based on dialog.ownerDocument) - var underlay = DialogUnderlay._singleton; - if(!underlay || underlay._destroyed){ - underlay = dijit._underlay = DialogUnderlay._singleton = new DialogUnderlay(underlayAttrs); - }else{ - underlay.set(dialog.underlayAttrs); - } - - // Set z-index a bit above previous dialog - var zIndex = ds[ds.length-1].dialog ? ds[ds.length-1].zIndex + 2 : Dialog._DialogLevelManager._beginZIndex; - if(ds.length == 1){ // first dialog - underlay.show(); - } - domStyle.set(DialogUnderlay._singleton.domNode, 'zIndex', zIndex - 1); - - // Dialog - domStyle.set(dialog.domNode, 'zIndex', zIndex); - - ds.push({dialog: dialog, underlayAttrs: underlayAttrs, zIndex: zIndex}); - }, - - hide: function(/*dijit/_WidgetBase*/ dialog){ - // summary: - // Called when the specified dialog is hidden/destroyed, after the fade-out - // animation ends, in order to reset page focus, fix the underlay, etc. - // If the specified dialog isn't open then does nothing. - // - // Caller is responsible for either setting display:none on the dialog domNode, - // or calling dijit/popup.hide(), or removing it from the page DOM. - - if(ds[ds.length-1].dialog == dialog){ - // Removing the top (or only) dialog in the stack, return focus - // to previous dialog - - ds.pop(); - - var pd = ds[ds.length-1]; // the new active dialog (or the base page itself) - - // Adjust underlay, unless the underlay widget has already been destroyed - // because we are being called during page unload (when all widgets are destroyed) - if(!DialogUnderlay._singleton._destroyed){ - if(ds.length == 1){ - // Returning to original page. Hide the underlay. - DialogUnderlay._singleton.hide(); - }else{ - // Popping back to previous dialog, adjust underlay. - domStyle.set(DialogUnderlay._singleton.domNode, 'zIndex', pd.zIndex - 1); - DialogUnderlay._singleton.set(pd.underlayAttrs); - } - } - - // Adjust focus - if(dialog.refocus){ - // If we are returning control to a previous dialog but for some reason - // that dialog didn't have a focused field, set focus to first focusable item. - // This situation could happen if two dialogs appeared at nearly the same time, - // since a dialog doesn't set it's focus until the fade-in is finished. - var focus = pd.focus; - if(pd.dialog && (!focus || !dom.isDescendant(focus, pd.dialog.domNode))){ - pd.dialog._getFocusItems(pd.dialog.domNode); - focus = pd.dialog._firstFocusItem; - } - - if(focus){ - // Refocus the button that spawned the Dialog. This will fail in corner cases including - // page unload on IE, because the dijit/form/Button that launched the Dialog may get destroyed - // before this code runs. (#15058) - try{ - focus.focus(); - }catch(e){} - } - } - }else{ - // Removing a dialog out of order (#9944, #10705). - // Don't need to mess with underlay or z-index or anything. - var idx = array.indexOf(array.map(ds, function(elem){return elem.dialog}), dialog); - if(idx != -1){ - ds.splice(idx, 1); - } - } - }, - - isTop: function(/*dijit/_WidgetBase*/ dialog){ - // summary: - // Returns true if specified Dialog is the top in the task - return ds[ds.length-1].dialog == dialog; - } - }; - - // Stack representing the various active "levels" on the page, starting with the - // stuff initially visible on the page (at z-index 0), and then having an entry for - // each Dialog shown. - // Each element in stack has form { - // dialog: dialogWidget, - // focus: returnFromGetFocus(), - // underlayAttrs: attributes to set on underlay (when this widget is active) - // } - var ds = Dialog._dialogStack = [ - {dialog: null, focus: null, underlayAttrs: null} // entry for stuff at z-index: 0 - ]; - - // Back compat w/1.6, remove for 2.0 - if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/TooltipDialog"]; - require(requires); // use indirection so modules not rolled into a build - }); - } - - return Dialog; -}); - -}, -'dijit/_base/focus':function(){ -define("dijit/_base/focus", [ - "dojo/_base/array", // array.forEach - "dojo/dom", // dom.isDescendant - "dojo/_base/lang", // lang.isArray - "dojo/topic", // publish - "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal - "../focus", - "../main" // for exporting symbols to dijit -], function(array, dom, lang, topic, win, focus, dijit){ - - // module: - // dijit/_base/focus - - var exports = { - // summary: - // Deprecated module to monitor currently focused node and stack of currently focused widgets. - // New code should access dijit/focus directly. - - // _curFocus: DomNode - // Currently focused item on screen - _curFocus: null, - - // _prevFocus: DomNode - // Previously focused item on screen - _prevFocus: null, - - isCollapsed: function(){ - // summary: - // Returns true if there is no text selected - return dijit.getBookmark().isCollapsed; - }, - - getBookmark: function(){ - // summary: - // Retrieves a bookmark that can be used with moveToBookmark to return to the same range - var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode; - - if(win.global.getSelection){ - //W3C Range API for selections. - sel = win.global.getSelection(); - if(sel){ - if(sel.isCollapsed){ - tg = cf? cf.tagName : ""; - if(tg){ - //Create a fake rangelike item to restore selections. - tg = tg.toLowerCase(); - if(tg == "textarea" || - (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){ - sel = { - start: cf.selectionStart, - end: cf.selectionEnd, - node: cf, - pRange: true - }; - return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object. - } - } - bm = {isCollapsed:true}; - if(sel.rangeCount){ - bm.mark = sel.getRangeAt(0).cloneRange(); - } - }else{ - rg = sel.getRangeAt(0); - bm = {isCollapsed: false, mark: rg.cloneRange()}; - } - } - }else if(sel){ - // If the current focus was a input of some sort and no selection, don't bother saving - // a native bookmark. This is because it causes issues with dialog/page selection restore. - // So, we need to create psuedo bookmarks to work with. - tg = cf ? cf.tagName : ""; - tg = tg.toLowerCase(); - if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){ - if(sel.type && sel.type.toLowerCase() == "none"){ - return { - isCollapsed: true, - mark: null - } - }else{ - rg = sel.createRange(); - return { - isCollapsed: rg.text && rg.text.length?false:true, - mark: { - range: rg, - pRange: true - } - }; - } - } - bm = {}; - - //'IE' way for selections. - try{ - // createRange() throws exception when dojo in iframe - //and nothing selected, see #9632 - rg = sel.createRange(); - bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length); - }catch(e){ - bm.isCollapsed = true; - return bm; - } - if(sel.type.toUpperCase() == 'CONTROL'){ - if(rg.length){ - bm.mark=[]; - var i=0,len=rg.length; - while(i<len){ - bm.mark.push(rg.item(i++)); - } - }else{ - bm.isCollapsed = true; - bm.mark = null; - } - }else{ - bm.mark = rg.getBookmark(); - } - }else{ - console.warn("No idea how to store the current selection for this browser!"); - } - return bm; // Object - }, - - moveToBookmark: function(/*Object*/ bookmark){ - // summary: - // Moves current selection to a bookmark - // bookmark: - // This should be a returned object from dijit.getBookmark() - - var _doc = win.doc, - mark = bookmark.mark; - if(mark){ - if(win.global.getSelection){ - //W3C Rangi API (FF, WebKit, Opera, etc) - var sel = win.global.getSelection(); - if(sel && sel.removeAllRanges){ - if(mark.pRange){ - var n = mark.node; - n.selectionStart = mark.start; - n.selectionEnd = mark.end; - }else{ - sel.removeAllRanges(); - sel.addRange(mark); - } - }else{ - console.warn("No idea how to restore selection for this browser!"); - } - }else if(_doc.selection && mark){ - //'IE' way. - var rg; - if(mark.pRange){ - rg = mark.range; - }else if(lang.isArray(mark)){ - rg = _doc.body.createControlRange(); - //rg.addElement does not have call/apply method, so can not call it directly - //rg is not available in "range.addElement(item)", so can't use that either - array.forEach(mark, function(n){ - rg.addElement(n); - }); - }else{ - rg = _doc.body.createTextRange(); - rg.moveToBookmark(mark); - } - rg.select(); - } - } - }, - - getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){ - // summary: - // Called as getFocus(), this returns an Object showing the current focus - // and selected text. - // - // Called as getFocus(widget), where widget is a (widget representing) a button - // that was just pressed, it returns where focus was before that button - // was pressed. (Pressing the button may have either shifted focus to the button, - // or removed focus altogether.) In this case the selected text is not returned, - // since it can't be accurately determined. - // - // menu: dijit/_WidgetBase|{domNode: DomNode} structure - // The button that was just pressed. If focus has disappeared or moved - // to this button, returns the previous focus. In this case the bookmark - // information is already lost, and null is returned. - // - // openedForWindow: - // iframe in which menu was opened - // - // returns: - // A handle to restore focus/selection, to be passed to `dijit.focus` - var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode; - return { - node: node, - bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark), - openedForWindow: openedForWindow - }; // Object - }, - - // _activeStack: dijit/_WidgetBase[] - // List of currently active widgets (focused widget and it's ancestors) - _activeStack: [], - - registerIframe: function(/*DomNode*/ iframe){ - // summary: - // Registers listeners on the specified iframe so that any click - // or focus event on that iframe (or anything in it) is reported - // as a focus/click event on the `<iframe>` itself. - // description: - // Currently only used by editor. - // returns: - // Handle to pass to unregisterIframe() - return focus.registerIframe(iframe); - }, - - unregisterIframe: function(/*Object*/ handle){ - // summary: - // Unregisters listeners on the specified iframe created by registerIframe. - // After calling be sure to delete or null out the handle itself. - // handle: - // Handle returned by registerIframe() - - handle && handle.remove(); - }, - - registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){ - // summary: - // Registers listeners on the specified window (either the main - // window or an iframe's window) to detect when the user has clicked somewhere - // or focused somewhere. - // description: - // Users should call registerIframe() instead of this method. - // targetWindow: - // If specified this is the window associated with the iframe, - // i.e. iframe.contentWindow. - // effectiveNode: - // If specified, report any focus events inside targetWindow as - // an event on effectiveNode, rather than on evt.target. - // returns: - // Handle to pass to unregisterWin() - - return focus.registerWin(targetWindow, effectiveNode); - }, - - unregisterWin: function(/*Handle*/ handle){ - // summary: - // Unregisters listeners on the specified window (either the main - // window or an iframe's window) according to handle returned from registerWin(). - // After calling be sure to delete or null out the handle itself. - - handle && handle.remove(); - } - }; - - // Override focus singleton's focus function so that dijit.focus() - // has backwards compatible behavior of restoring selection (although - // probably no one is using that). - focus.focus = function(/*Object|DomNode */ handle){ - // summary: - // Sets the focused node and the selection according to argument. - // To set focus to an iframe's content, pass in the iframe itself. - // handle: - // object returned by get(), or a DomNode - - if(!handle){ return; } - - var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object - bookmark = handle.bookmark, - openedForWindow = handle.openedForWindow, - collapsed = bookmark ? bookmark.isCollapsed : false; - - // Set the focus - // Note that for iframe's we need to use the <iframe> to follow the parentNode chain, - // but we need to set focus to iframe.contentWindow - if(node){ - var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node; - if(focusNode && focusNode.focus){ - try{ - // Gecko throws sometimes if setting focus is impossible, - // node not displayed or something like that - focusNode.focus(); - }catch(e){/*quiet*/} - } - focus._onFocusNode(node); - } - - // set the selection - // do not need to restore if current selection is not empty - // (use keyboard to select a menu item) or if previous selection was collapsed - // as it may cause focus shift (Esp in IE). - if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){ - if(openedForWindow){ - openedForWindow.focus(); - } - try{ - win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]); - }catch(e2){ - /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */ - } - } - }; - - // For back compatibility, monitor changes to focused node and active widget stack, - // publishing events and copying changes from focus manager variables into dijit (top level) variables - focus.watch("curNode", function(name, oldVal, newVal){ - dijit._curFocus = newVal; - dijit._prevFocus = oldVal; - if(newVal){ - topic.publish("focusNode", newVal); // publish - } - }); - focus.watch("activeStack", function(name, oldVal, newVal){ - dijit._activeStack = newVal; - }); - - focus.on("widget-blur", function(widget, by){ - topic.publish("widgetBlur", widget, by); // publish - }); - focus.on("widget-focus", function(widget, by){ - topic.publish("widgetFocus", widget, by); // publish - }); - - lang.mixin(dijit, exports); - - /*===== return exports; =====*/ - return dijit; // for back compat :-( -}); - -}, -'dijit/tree/dndSource':function(){ -define("dijit/tree/dndSource", [ - "dojo/_base/array", // array.forEach array.indexOf array.map - "dojo/_base/connect", // isCopyKey - "dojo/_base/declare", // declare - "dojo/dom-class", // domClass.add - "dojo/dom-geometry", // domGeometry.position - "dojo/_base/lang", // lang.mixin lang.hitch - "dojo/on", // subscribe - "dojo/touch", - "dojo/topic", - "dojo/dnd/Manager", // DNDManager.manager - "./_dndSelector" -], function(array, connect, declare, domClass, domGeometry, lang, on, touch, topic, DNDManager, _dndSelector){ - -// module: -// dijit/tree/dndSource -// summary: -// Handles drag and drop operations (as a source or a target) for `dijit.Tree` - -/*===== -var __Item = { - // summary: - // New item to be added to the Tree, like: - // id: Anything - id: "", - // name: String - name: "" -}; -=====*/ - -var dndSource = declare("dijit.tree.dndSource", _dndSelector, { - // summary: - // Handles drag and drop operations (as a source or a target) for `dijit.Tree` - - // isSource: Boolean - // Can be used as a DnD source. - isSource: true, - - // accept: String[] - // List of accepted types (text strings) for the Tree; defaults to - // ["text"] - accept: ["text", "treeNode"], - - // copyOnly: [private] Boolean - // Copy items, if true, use a state of Ctrl key otherwise - copyOnly: false, - - // dragThreshold: Number - // The move delay in pixels before detecting a drag; 5 by default - dragThreshold: 5, - - // betweenThreshold: Integer - // Distance from upper/lower edge of node to allow drop to reorder nodes - betweenThreshold: 0, - - // Flag used by Avatar.js to signal to generate text node when dragging - generateText: true, - - constructor: function(/*dijit/Tree*/ tree, /*dijit/tree/dndSource*/ params){ - // summary: - // a constructor of the Tree DnD Source - // tags: - // private - if(!params){ params = {}; } - lang.mixin(this, params); - var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"]; - this.accept = null; - if(type.length){ - this.accept = {}; - for(var i = 0; i < type.length; ++i){ - this.accept[type[i]] = 1; - } - } - - // class-specific variables - this.isDragging = false; - this.mouseDown = false; - this.targetAnchor = null; // DOMNode corresponding to the currently moused over TreeNode - this.targetBox = null; // coordinates of this.targetAnchor - this.dropPosition = ""; // whether mouse is over/after/before this.targetAnchor - this._lastX = 0; - this._lastY = 0; - - // states - this.sourceState = ""; - if(this.isSource){ - domClass.add(this.node, "dojoDndSource"); - } - this.targetState = ""; - if(this.accept){ - domClass.add(this.node, "dojoDndTarget"); - } - - // set up events - this.topics = [ - topic.subscribe("/dnd/source/over", lang.hitch(this, "onDndSourceOver")), - topic.subscribe("/dnd/start", lang.hitch(this, "onDndStart")), - topic.subscribe("/dnd/drop", lang.hitch(this, "onDndDrop")), - topic.subscribe("/dnd/cancel", lang.hitch(this, "onDndCancel")) - ]; - }, - - // methods - checkAcceptance: function(/*===== source, nodes =====*/){ - // summary: - // Checks if the target can accept nodes from this source - // source: dijit/tree/dndSource - // The source which provides items - // nodes: DOMNode[] - // Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if - // source is a dijit/Tree. - // tags: - // extension - return true; // Boolean - }, - - copyState: function(keyPressed){ - // summary: - // Returns true, if we need to copy items, false to move. - // It is separated to be overwritten dynamically, if needed. - // keyPressed: Boolean - // The "copy" control key was pressed - // tags: - // protected - return this.copyOnly || keyPressed; // Boolean - }, - destroy: function(){ - // summary: - // Prepares the object to be garbage-collected. - this.inherited(arguments); - var h; - while(h = this.topics.pop()){ h.remove(); } - this.targetAnchor = null; - }, - - _onDragMouse: function(e, firstTime){ - // summary: - // Helper method for processing onmousemove/onmouseover events while drag is in progress. - // Keeps track of current drop target. - // e: Event - // The mousemove event. - // firstTime: Boolean? - // If this flag is set, this is the first mouse move event of the drag, so call m.canDrop() etc. - // even if newTarget == null because the user quickly dragged a node in the Tree to a position - // over Tree.containerNode but not over any TreeNode (#7971) - - var m = DNDManager.manager(), - oldTarget = this.targetAnchor, // the TreeNode corresponding to TreeNode mouse was previously over - newTarget = this.current, // TreeNode corresponding to TreeNode mouse is currently over - oldDropPosition = this.dropPosition; // the previous drop position (over/before/after) - - // calculate if user is indicating to drop the dragged node before, after, or over - // (i.e., to become a child of) the target node - var newDropPosition = "Over"; - if(newTarget && this.betweenThreshold > 0){ - // If mouse is over a new TreeNode, then get new TreeNode's position and size - if(!this.targetBox || oldTarget != newTarget){ - this.targetBox = domGeometry.position(newTarget.rowNode, true); - } - if((e.pageY - this.targetBox.y) <= this.betweenThreshold){ - newDropPosition = "Before"; - }else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){ - newDropPosition = "After"; - } - } - - if(firstTime || newTarget != oldTarget || newDropPosition != oldDropPosition){ - if(oldTarget){ - this._removeItemClass(oldTarget.rowNode, oldDropPosition); - } - if(newTarget){ - this._addItemClass(newTarget.rowNode, newDropPosition); - } - - // Check if it's ok to drop the dragged node on/before/after the target node. - if(!newTarget){ - m.canDrop(false); - }else if(newTarget == this.tree.rootNode && newDropPosition != "Over"){ - // Can't drop before or after tree's root node; the dropped node would just disappear (at least visually) - m.canDrop(false); - }else{ - // Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140) - var sameId = false; - if(m.source == this){ - for(var dragId in this.selection){ - var dragNode = this.selection[dragId]; - if(dragNode.item === newTarget.item){ - sameId = true; - break; - } - } - } - if(sameId){ - m.canDrop(false); - }else if(this.checkItemAcceptance(newTarget.rowNode, m.source, newDropPosition.toLowerCase()) - && !this._isParentChildDrop(m.source, newTarget.rowNode)){ - m.canDrop(true); - }else{ - m.canDrop(false); - } - } - - this.targetAnchor = newTarget; - this.dropPosition = newDropPosition; - } - }, - - onMouseMove: function(e){ - // summary: - // Called for any onmousemove/ontouchmove events over the Tree - // e: Event - // onmousemouse/ontouchmove event - // tags: - // private - if(this.isDragging && this.targetState == "Disabled"){ return; } - this.inherited(arguments); - var m = DNDManager.manager(); - if(this.isDragging){ - this._onDragMouse(e); - }else{ - if(this.mouseDown && this.isSource && - (Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){ - var nodes = this.getSelectedTreeNodes(); - if(nodes.length){ - if(nodes.length > 1){ - //filter out all selected items which has one of their ancestor selected as well - var seen = this.selection, i = 0, r = [], n, p; - nextitem: while((n = nodes[i++])){ - for(p = n.getParent(); p && p !== this.tree; p = p.getParent()){ - if(seen[p.id]){ //parent is already selected, skip this node - continue nextitem; - } - } - //this node does not have any ancestors selected, add it - r.push(n); - } - nodes = r; - } - nodes = array.map(nodes, function(n){return n.domNode}); - m.startDrag(this, nodes, this.copyState(connect.isCopyKey(e))); - this._onDragMouse(e, true); // because this may be the only mousemove event we get before the drop - } - } - } - }, - - onMouseDown: function(e){ - // summary: - // Event processor for onmousedown/ontouchstart - // e: Event - // onmousedown/ontouchend event - // tags: - // private - this.mouseDown = true; - this.mouseButton = e.button; - this._lastX = e.pageX; - this._lastY = e.pageY; - this.inherited(arguments); - }, - - onMouseUp: function(e){ - // summary: - // Event processor for onmouseup/ontouchend - // e: Event - // onmouseup/ontouchend event - // tags: - // private - if(this.mouseDown){ - this.mouseDown = false; - this.inherited(arguments); - } - }, - - onMouseOut: function(){ - // summary: - // Event processor for when mouse is moved away from a TreeNode - // tags: - // private - this.inherited(arguments); - this._unmarkTargetAnchor(); - }, - - checkItemAcceptance: function(/*===== target, source, position =====*/){ - // summary: - // Stub function to be overridden if one wants to check for the ability to drop at the node/item level - // description: - // In the base case, this is called to check if target can become a child of source. - // When betweenThreshold is set, position="before" or "after" means that we - // are asking if the source node can be dropped before/after the target node. - // target: DOMNode - // The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to - // Use dijit.getEnclosingWidget(target) to get the TreeNode. - // source: dijit/tree/dndSource - // The (set of) nodes we are dropping - // position: String - // "over", "before", or "after" - // tags: - // extension - return true; - }, - - // topic event processors - onDndSourceOver: function(source){ - // summary: - // Topic event processor for /dnd/source/over, called when detected a current source. - // source: Object - // The dijit/tree/dndSource / dojo/dnd/Source which has the mouse over it - // tags: - // private - if(this != source){ - this.mouseDown = false; - this._unmarkTargetAnchor(); - }else if(this.isDragging){ - var m = DNDManager.manager(); - m.canDrop(false); - } - }, - onDndStart: function(source, nodes, copy){ - // summary: - // Topic event processor for /dnd/start, called to initiate the DnD operation - // source: Object - // The dijit/tree/dndSource / dojo/dnd/Source which is providing the items - // nodes: DomNode[] - // The list of transferred items, dndTreeNode nodes if dragging from a Tree - // copy: Boolean - // Copy items, if true, move items otherwise - // tags: - // private - - if(this.isSource){ - this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : ""); - } - var accepted = this.checkAcceptance(source, nodes); - - this._changeState("Target", accepted ? "" : "Disabled"); - - if(this == source){ - DNDManager.manager().overSource(this); - } - - this.isDragging = true; - }, - - itemCreator: function(nodes /*===== , target, source =====*/){ - // summary: - // Returns objects passed to `Tree.model.newItem()` based on DnD nodes - // dropped onto the tree. Developer must override this method to enable - // dropping from external sources onto this Tree, unless the Tree.model's items - // happen to look like {id: 123, name: "Apple" } with no other attributes. - // description: - // For each node in nodes[], which came from source, create a hash of name/value - // pairs to be passed to Tree.model.newItem(). Returns array of those hashes. - // nodes: DomNode[] - // target: DomNode - // source: dojo/dnd/Source - // returns: __Item[] - // Array of name/value hashes for each new item to be added to the Tree - // tags: - // extension - - // TODO: for 2.0 refactor so itemCreator() is called once per drag node, and - // make signature itemCreator(sourceItem, node, target) (or similar). - - return array.map(nodes, function(node){ - return { - "id": node.id, - "name": node.textContent || node.innerText || "" - }; - }); // Object[] - }, - - onDndDrop: function(source, nodes, copy){ - // summary: - // Topic event processor for /dnd/drop, called to finish the DnD operation. - // description: - // Updates data store items according to where node was dragged from and dropped - // to. The tree will then respond to those data store updates and redraw itself. - // source: Object - // The dijit/tree/dndSource / dojo/dnd/Source which is providing the items - // nodes: DomNode[] - // The list of transferred items, dndTreeNode nodes if dragging from a Tree - // copy: Boolean - // Copy items, if true, move items otherwise - // tags: - // protected - if(this.containerState == "Over"){ - var tree = this.tree, - model = tree.model, - target = this.targetAnchor; - - this.isDragging = false; - - // Compute the new parent item - var newParentItem; - var insertIndex; - var before; // drop source before (aka previous sibling) of target - newParentItem = (target && target.item) || tree.item; - if(this.dropPosition == "Before" || this.dropPosition == "After"){ - // TODO: if there is no parent item then disallow the drop. - // Actually this should be checked during onMouseMove too, to make the drag icon red. - newParentItem = (target.getParent() && target.getParent().item) || tree.item; - // Compute the insert index for reordering - insertIndex = target.getIndexInParent(); - if(this.dropPosition == "After"){ - insertIndex = target.getIndexInParent() + 1; - before = target.getNextSibling() && target.getNextSibling().item; - }else{ - before = target.item; - } - }else{ - newParentItem = (target && target.item) || tree.item; - } - - // If necessary, use this variable to hold array of hashes to pass to model.newItem() - // (one entry in the array for each dragged node). - var newItemsParams; - - array.forEach(nodes, function(node, idx){ - // dojo/dnd/Item representing the thing being dropped. - // Don't confuse the use of item here (meaning a DnD item) with the - // uses below where item means dojo.data item. - var sourceItem = source.getItem(node.id); - - // Information that's available if the source is another Tree - // (possibly but not necessarily this tree, possibly but not - // necessarily the same model as this Tree) - if(array.indexOf(sourceItem.type, "treeNode") != -1){ - var childTreeNode = sourceItem.data, - childItem = childTreeNode.item, - oldParentItem = childTreeNode.getParent().item; - } - - if(source == this){ - // This is a node from my own tree, and we are moving it, not copying. - // Remove item from old parent's children attribute. - // TODO: dijit/tree/dndSelector should implement deleteSelectedNodes() - // and this code should go there. - - if(typeof insertIndex == "number"){ - if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){ - insertIndex -= 1; - } - } - model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex, before); - }else if(model.isItem(childItem)){ - // Item from same model - // (maybe we should only do this branch if the source is a tree?) - model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex, before); - }else{ - // Get the hash to pass to model.newItem(). A single call to - // itemCreator() returns an array of hashes, one for each drag source node. - if(!newItemsParams){ - newItemsParams = this.itemCreator(nodes, target.rowNode, source); - } - - // Create new item in the tree, based on the drag source. - model.newItem(newItemsParams[idx], newParentItem, insertIndex, before); - } - }, this); - - // Expand the target node (if it's currently collapsed) so the user can see - // where their node was dropped. In particular since that node is still selected. - this.tree._expandNode(target); - } - this.onDndCancel(); - }, - - onDndCancel: function(){ - // summary: - // Topic event processor for /dnd/cancel, called to cancel the DnD operation - // tags: - // private - this._unmarkTargetAnchor(); - this.isDragging = false; - this.mouseDown = false; - delete this.mouseButton; - this._changeState("Source", ""); - this._changeState("Target", ""); - }, - - // When focus moves in/out of the entire Tree - onOverEvent: function(){ - // summary: - // This method is called when mouse is moved over our container (like onmouseenter) - // tags: - // private - this.inherited(arguments); - DNDManager.manager().overSource(this); - }, - onOutEvent: function(){ - // summary: - // This method is called when mouse is moved out of our container (like onmouseleave) - // tags: - // private - this._unmarkTargetAnchor(); - var m = DNDManager.manager(); - if(this.isDragging){ - m.canDrop(false); - } - m.outSource(this); - - this.inherited(arguments); - }, - - _isParentChildDrop: function(source, targetRow){ - // summary: - // Checks whether the dragged items are parent rows in the tree which are being - // dragged into their own children. - // - // source: - // The DragSource object. - // - // targetRow: - // The tree row onto which the dragged nodes are being dropped. - // - // tags: - // private - - // If the dragged object is not coming from the tree this widget belongs to, - // it cannot be invalid. - if(!source.tree || source.tree != this.tree){ - return false; - } - - - var root = source.tree.domNode; - var ids = source.selection; - - var node = targetRow.parentNode; - - // Iterate up the DOM hierarchy from the target drop row, - // checking of any of the dragged nodes have the same ID. - while(node != root && !ids[node.id]){ - node = node.parentNode; - } - - return node.id && ids[node.id]; - }, - - _unmarkTargetAnchor: function(){ - // summary: - // Removes hover class of the current target anchor - // tags: - // private - if(!this.targetAnchor){ return; } - this._removeItemClass(this.targetAnchor.rowNode, this.dropPosition); - this.targetAnchor = null; - this.targetBox = null; - this.dropPosition = null; - }, - - _markDndStatus: function(copy){ - // summary: - // Changes source's state based on "copy" status - this._changeState("Source", copy ? "Copied" : "Moved"); - } -}); - -/*===== -dndSource.__Item = __Item; -=====*/ - -return dndSource; -}); - -}, -'dijit/a11y':function(){ -define("dijit/a11y", [ - "dojo/_base/array", // array.forEach array.map - "dojo/_base/config", // defaultDuration - "dojo/_base/declare", // declare - "dojo/dom", // dom.byId - "dojo/dom-attr", // domAttr.attr domAttr.has - "dojo/dom-style", // style.style - "dojo/sniff", // has("ie") - "./main" // for exporting methods to dijit namespace -], function(array, config, declare, dom, domAttr, domStyle, has, dijit){ - - // module: - // dijit/a11y - - var shown = (dijit._isElementShown = function(/*Element*/ elem){ - var s = domStyle.get(elem); - return (s.visibility != "hidden") - && (s.visibility != "collapsed") - && (s.display != "none") - && (domAttr.get(elem, "type") != "hidden"); - }); - - dijit.hasDefaultTabStop = function(/*Element*/ elem){ - // summary: - // Tests if element is tab-navigable even without an explicit tabIndex setting - - // No explicit tabIndex setting, need to investigate node type - switch(elem.nodeName.toLowerCase()){ - case "a": - // An <a> w/out a tabindex is only navigable if it has an href - return domAttr.has(elem, "href"); - case "area": - case "button": - case "input": - case "object": - case "select": - case "textarea": - // These are navigable by default - return true; - case "iframe": - // If it's an editor <iframe> then it's tab navigable. - var body; - try{ - // non-IE - var contentDocument = elem.contentDocument; - if("designMode" in contentDocument && contentDocument.designMode == "on"){ - return true; - } - body = contentDocument.body; - }catch(e1){ - // contentWindow.document isn't accessible within IE7/8 - // if the iframe.src points to a foreign url and this - // page contains an element, that could get focus - try{ - body = elem.contentWindow.document.body; - }catch(e2){ - return false; - } - } - return body && (body.contentEditable == 'true' || - (body.firstChild && body.firstChild.contentEditable == 'true')); - default: - return elem.contentEditable == 'true'; - } - }; - - var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){ - // summary: - // Tests if an element is tab-navigable - - // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable() - if(domAttr.get(elem, "disabled")){ - return false; - }else if(domAttr.has(elem, "tabIndex")){ - // Explicit tab index setting - return domAttr.get(elem, "tabIndex") >= 0; // boolean - }else{ - // No explicit tabIndex setting, so depends on node type - return dijit.hasDefaultTabStop(elem); - } - }); - - dijit._getTabNavigable = function(/*DOMNode*/ root){ - // summary: - // Finds descendants of the specified root node. - // description: - // Finds the following descendants of the specified root node: - // - // - the first tab-navigable element in document order - // without a tabIndex or with tabIndex="0" - // - the last tab-navigable element in document order - // without a tabIndex or with tabIndex="0" - // - the first element in document order with the lowest - // positive tabIndex value - // - the last element in document order with the highest - // positive tabIndex value - var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {}; - - function radioName(node){ - // If this element is part of a radio button group, return the name for that group. - return node && node.tagName.toLowerCase() == "input" && - node.type && node.type.toLowerCase() == "radio" && - node.name && node.name.toLowerCase(); - } - - var walkTree = function(/*DOMNode*/ parent){ - for(var child = parent.firstChild; child; child = child.nextSibling){ - // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE, - // since show() invokes getAttribute("type"), which crash on VML nodes in IE. - if(child.nodeType != 1 || (has("ie") <= 9 && child.scopeName !== "HTML") || !shown(child)){ - continue; - } - - if(isTabNavigable(child)){ - var tabindex = +domAttr.get(child, "tabIndex"); // + to convert string --> number - if(!domAttr.has(child, "tabIndex") || tabindex == 0){ - if(!first){ - first = child; - } - last = child; - }else if(tabindex > 0){ - if(!lowest || tabindex < lowestTabindex){ - lowestTabindex = tabindex; - lowest = child; - } - if(!highest || tabindex >= highestTabindex){ - highestTabindex = tabindex; - highest = child; - } - } - var rn = radioName(child); - if(domAttr.get(child, "checked") && rn){ - radioSelected[rn] = child; - } - } - if(child.nodeName.toUpperCase() != 'SELECT'){ - walkTree(child); - } - } - }; - if(shown(root)){ - walkTree(root); - } - function rs(node){ - // substitute checked radio button for unchecked one, if there is a checked one with the same name. - return radioSelected[radioName(node)] || node; - } - - return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) }; - }; - dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root, /*Document?*/ doc){ - // summary: - // Finds the descendant of the specified root node - // that is first in the tabbing order - var elems = dijit._getTabNavigable(dom.byId(root, doc)); - return elems.lowest ? elems.lowest : elems.first; // DomNode - }; - - dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root, /*Document?*/ doc){ - // summary: - // Finds the descendant of the specified root node - // that is last in the tabbing order - var elems = dijit._getTabNavigable(dom.byId(root, doc)); - return elems.last ? elems.last : elems.highest; // DomNode - }; - - return { - // summary: - // Accessibility utility functions (keyboard, tab stops, etc.) - - hasDefaultTabStop: dijit.hasDefaultTabStop, - isTabNavigable: dijit.isTabNavigable, - _getTabNavigable: dijit._getTabNavigable, - getFirstInTabbingOrder: dijit.getFirstInTabbingOrder, - getLastInTabbingOrder: dijit.getLastInTabbingOrder - }; -}); - -}, -'dijit/form/_ToggleButtonMixin':function(){ -define("dijit/form/_ToggleButtonMixin", [ - "dojo/_base/declare", // declare - "dojo/dom-attr" // domAttr.set -], function(declare, domAttr){ - -// module: -// dijit/form/_ToggleButtonMixin - -return declare("dijit.form._ToggleButtonMixin", null, { - // summary: - // A mixin to provide functionality to allow a button that can be in two states (checked or not). - - // checked: Boolean - // Corresponds to the native HTML `<input>` element's attribute. - // In markup, specified as "checked='checked'" or just "checked". - // True if the button is depressed, or the checkbox is checked, - // or the radio button is selected, etc. - checked: false, - - // aria-pressed for toggle buttons, and aria-checked for checkboxes - _aria_attr: "aria-pressed", - - _onClick: function(/*Event*/ evt){ - var original = this.checked; - this._set('checked', !original); // partially set the toggled value, assuming the toggle will work, so it can be overridden in the onclick handler - var ret = this.inherited(arguments); // the user could reset the value here - this.set('checked', ret ? this.checked : original); // officially set the toggled or user value, or reset it back - return ret; - }, - - _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){ - this._set("checked", value); - var node = this.focusNode || this.domNode; - domAttr.set(node, "checked", !!value); // "mixed" -> true - if(value){ - node.setAttribute("checked", ""); - }else{ - node.removeAttribute("checked"); - } - node.setAttribute(this._aria_attr, String(value)); // aria values should be strings - this._handleOnChange(value, priorityChange); - }, - - reset: function(){ - // summary: - // Reset the widget's value to what it was at initialization time - - this._hasBeenBlurred = false; - - // set checked state to original setting - this.set('checked', this.params.checked || false); - } -}); - -}); - -}, -'dijit/_Widget':function(){ -define("dijit/_Widget", [ - "dojo/aspect", // aspect.around - "dojo/_base/config", // config.isDebug - "dojo/_base/connect", // connect.connect - "dojo/_base/declare", // declare - "dojo/has", - "dojo/_base/kernel", // kernel.deprecated - "dojo/_base/lang", // lang.hitch - "dojo/query", - "dojo/ready", - "./registry", // registry.byNode - "./_WidgetBase", - "./_OnDijitClickMixin", - "./_FocusMixin", - "dojo/uacss", // browser sniffing (included for back-compat; subclasses may be using) - "./hccss" // high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused) -], function(aspect, config, connect, declare, has, kernel, lang, query, ready, - registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){ - - -// module: -// dijit/_Widget - - -function connectToDomNode(){ - // summary: - // If user connects to a widget method === this function, then they will - // instead actually be connecting the equivalent event on this.domNode -} - -// Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on() -function aroundAdvice(originalConnect){ - return function(obj, event, scope, method){ - if(obj && typeof event == "string" && obj[event] == connectToDomNode){ - return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method)); - } - return originalConnect.apply(connect, arguments); - }; -} -aspect.around(connect, "connect", aroundAdvice); -if(kernel.connect){ - aspect.around(kernel, "connect", aroundAdvice); -} - -var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], { - // summary: - // Old base class for widgets. New widgets should extend `dijit/_WidgetBase` instead - // description: - // Old Base class for Dijit widgets. - // - // Extends _WidgetBase, adding support for: - // - // - declaratively/programatically specifying widget initialization parameters like - // onMouseMove="foo" that call foo when this.domNode gets a mousemove event - // - ondijitclick: - // Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress - // - focus related functions: - // In particular, the onFocus()/onBlur() callbacks. Driven internally by - // dijit/_base/focus.js. - // - deprecated methods - // - onShow(), onHide(), onClose() - // - // Also, by loading code in dijit/_base, turns on: - // - // - browser sniffing (putting browser class like `dj_ie` on `<html>` node) - // - high contrast mode sniffing (add `dijit_a11y` class to `<body>` if machine is in high contrast mode) - - - ////////////////// DEFERRED CONNECTS /////////////////// - - onClick: connectToDomNode, - /*===== - onClick: function(event){ - // summary: - // Connect to this function to receive notifications of mouse click events. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onDblClick: connectToDomNode, - /*===== - onDblClick: function(event){ - // summary: - // Connect to this function to receive notifications of mouse double click events. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onKeyDown: connectToDomNode, - /*===== - onKeyDown: function(event){ - // summary: - // Connect to this function to receive notifications of keys being pressed down. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onKeyPress: connectToDomNode, - /*===== - onKeyPress: function(event){ - // summary: - // Connect to this function to receive notifications of printable keys being typed. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onKeyUp: connectToDomNode, - /*===== - onKeyUp: function(event){ - // summary: - // Connect to this function to receive notifications of keys being released. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onMouseDown: connectToDomNode, - /*===== - onMouseDown: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse button is pressed down. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseMove: connectToDomNode, - /*===== - onMouseMove: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseOut: connectToDomNode, - /*===== - onMouseOut: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseOver: connectToDomNode, - /*===== - onMouseOver: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseLeave: connectToDomNode, - /*===== - onMouseLeave: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse moves off of this widget. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseEnter: connectToDomNode, - /*===== - onMouseEnter: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse moves onto this widget. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onMouseUp: connectToDomNode, - /*===== - onMouseUp: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse button is released. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - - constructor: function(params /*===== ,srcNodeRef =====*/){ - // summary: - // Create the widget. - // params: Object|null - // Hash of initialization parameters for widget, including scalar values (like title, duration etc.) - // and functions, typically callbacks like onClick. - // The hash can contain any of the widget's properties, excluding read-only properties. - // srcNodeRef: DOMNode|String? - // If a srcNodeRef (DOM node) is specified: - // - // - use srcNodeRef.innerHTML as my contents - // - if this is a behavioral widget then apply behavior to that srcNodeRef - // - otherwise, replace srcNodeRef with my generated DOM tree - - // extract parameters like onMouseMove that should connect directly to this.domNode - this._toConnect = {}; - for(var name in params){ - if(this[name] === connectToDomNode){ - this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name]; - delete params[name]; - } - } - }, - - postCreate: function(){ - this.inherited(arguments); - - // perform connection from this.domNode to user specified handlers (ex: onMouseMove) - for(var name in this._toConnect){ - this.on(name, this._toConnect[name]); - } - delete this._toConnect; - }, - - on: function(/*String|Function*/ type, /*Function*/ func){ - if(this[this._onMap(type)] === connectToDomNode){ - // Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE, - // normalization of onkeypress/onkeydown to behave like firefox, etc. - // Also, need to specify context as "this" rather than the default context of the DOMNode - // Remove in 2.0. - return connect.connect(this.domNode, type.toLowerCase(), this, func); - } - return this.inherited(arguments); - }, - - _setFocusedAttr: function(val){ - // Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat - // (but since it's a private variable we aren't required to keep supporting it). - this._focused = val; - this._set("focused", val); - }, - - ////////////////// DEPRECATED METHODS /////////////////// - - setAttribute: function(/*String*/ attr, /*anything*/ value){ - // summary: - // Deprecated. Use set() instead. - // tags: - // deprecated - kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0"); - this.set(attr, value); - }, - - attr: function(/*String|Object*/name, /*Object?*/value){ - // summary: - // Set or get properties on a widget instance. - // name: - // The property to get or set. If an object is passed here and not - // a string, its keys are used as names of attributes to be set - // and the value of the object as values to set in the widget. - // value: - // Optional. If provided, attr() operates as a setter. If omitted, - // the current value of the named property is returned. - // description: - // This method is deprecated, use get() or set() directly. - - // Print deprecation warning but only once per calling function - if(config.isDebug){ - var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}), - caller = (arguments.callee.caller || "unknown caller").toString(); - if(!alreadyCalledHash[caller]){ - kernel.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " + - caller, "", "2.0"); - alreadyCalledHash[caller] = true; - } - } - - var args = arguments.length; - if(args >= 2 || typeof name === "object"){ // setter - return this.set.apply(this, arguments); - }else{ // getter - return this.get(name); - } - }, - - getDescendants: function(){ - // summary: - // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode. - // This method should generally be avoided as it returns widgets declared in templates, which are - // supposed to be internal/hidden, but it's left here for back-compat reasons. - - kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0"); - return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit/_WidgetBase[] - }, - - ////////////////// MISCELLANEOUS METHODS /////////////////// - - _onShow: function(){ - // summary: - // Internal method called when this widget is made visible. - // See `onShow` for details. - this.onShow(); - }, - - onShow: function(){ - // summary: - // Called when this widget becomes the selected pane in a - // `dijit/layout/TabContainer`, `dijit/layout/StackContainer`, - // `dijit/layout/AccordionContainer`, etc. - // - // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. - // tags: - // callback - }, - - onHide: function(){ - // summary: - // Called when another widget becomes the selected pane in a - // `dijit/layout/TabContainer`, `dijit/layout/StackContainer`, - // `dijit/layout/AccordionContainer`, etc. - // - // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`. - // tags: - // callback - }, - - onClose: function(){ - // summary: - // Called when this widget is being displayed as a popup (ex: a Calendar popped - // up from a DateTextBox), and it is hidden. - // This is called from the dijit.popup code, and should not be called directly. - // - // Also used as a parameter for children of `dijit/layout/StackContainer` or subclasses. - // Callback if a user tries to close the child. Child will be closed if this function returns true. - // tags: - // extension - - return true; // Boolean - } -}); - -// For back-compat, remove in 2.0. -if(has("dijit-legacy-requires")){ - ready(0, function(){ - var requires = ["dijit/_base"]; - require(requires); // use indirection so modules not rolled into a build - }); -} -return _Widget; -}); - -}, -'dojo/touch':function(){ -define("dojo/touch", ["./_base/kernel", "./aspect", "./dom", "./on", "./has", "./mouse", "./ready", "./_base/window"], -function(dojo, aspect, dom, on, has, mouse, ready, win){ - - // module: - // dojo/touch - - var hasTouch = has("touch"); - - // TODO: get iOS version from dojo/sniff after #15827 is fixed - var ios4 = false; - if(has("ios")){ - var ua = navigator.userAgent; - var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1"; - var os = parseFloat(v.replace(/_/, '.').replace(/_/g, '')); - ios4 = os < 5; - } - - var touchmove, hoveredNode; - - if(hasTouch){ - ready(function(){ - // Keep track of currently hovered node - hoveredNode = win.body(); // currently hovered node - - win.doc.addEventListener("touchstart", function(evt){ - // Precede touchstart event with touch.over event. DnD depends on this. - // Use addEventListener(cb, true) to run cb before any touchstart handlers on node run, - // and to ensure this code runs even if the listener on the node does event.stop(). - var oldNode = hoveredNode; - hoveredNode = evt.target; - on.emit(oldNode, "dojotouchout", { - target: oldNode, - relatedTarget: hoveredNode, - bubbles: true - }); - on.emit(hoveredNode, "dojotouchover", { - target: hoveredNode, - relatedTarget: oldNode, - bubbles: true - }); - }, true); - - // Fire synthetic touchover and touchout events on nodes since the browser won't do it natively. - on(win.doc, "touchmove", function(evt){ - var newNode = win.doc.elementFromPoint( - evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords - evt.pageY - (ios4 ? 0 : win.global.pageYOffset) - ); - if(newNode && hoveredNode !== newNode){ - // touch out on the old node - on.emit(hoveredNode, "dojotouchout", { - target: hoveredNode, - relatedTarget: newNode, - bubbles: true - }); - - // touchover on the new node - on.emit(newNode, "dojotouchover", { - target: newNode, - relatedTarget: hoveredNode, - bubbles: true - }); - - hoveredNode = newNode; - } - }); - }); - - // Define synthetic touch.move event that unlike the native touchmove, fires for the node the finger is - // currently dragging over rather than the node where the touch started. - touchmove = function(node, listener){ - return on(win.doc, "touchmove", function(evt){ - if(node === win.doc || dom.isDescendant(hoveredNode, node)){ - evt.target = hoveredNode; - listener.call(this, evt); - } - }); - }; - } - - - function _handle(type){ - // type: String - // press | move | release | cancel - - return function(node, listener){//called by on(), see dojo.on - return on(node, type, listener); - }; - } - - //device neutral events - touch.press|move|release|cancel/over/out - var touch = { - press: _handle(hasTouch ? "touchstart": "mousedown"), - move: hasTouch ? touchmove :_handle("mousemove"), - release: _handle(hasTouch ? "touchend": "mouseup"), - cancel: hasTouch ? _handle("touchcancel") : mouse.leave, - over: _handle(hasTouch ? "dojotouchover": "mouseover"), - out: _handle(hasTouch ? "dojotouchout": "mouseout"), - enter: mouse._eventHandler(hasTouch ? "dojotouchover" : "mouseover"), - leave: mouse._eventHandler(hasTouch ? "dojotouchout" : "mouseout") - }; - /*===== - touch = { - // summary: - // This module provides unified touch event handlers by exporting - // press, move, release and cancel which can also run well on desktop. - // Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html - // - // example: - // Used with dojo.on - // | define(["dojo/on", "dojo/touch"], function(on, touch){ - // | on(node, touch.press, function(e){}); - // | on(node, touch.move, function(e){}); - // | on(node, touch.release, function(e){}); - // | on(node, touch.cancel, function(e){}); - // example: - // Used with touch.* directly - // | touch.press(node, function(e){}); - // | touch.move(node, function(e){}); - // | touch.release(node, function(e){}); - // | touch.cancel(node, function(e){}); - - press: function(node, listener){ - // summary: - // Register a listener to 'touchstart'|'mousedown' for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - move: function(node, listener){ - // summary: - // Register a listener to 'touchmove'|'mousemove' for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - release: function(node, listener){ - // summary: - // Register a listener to 'touchend'|'mouseup' for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - cancel: function(node, listener){ - // summary: - // Register a listener to 'touchcancel'|'mouseleave' for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - over: function(node, listener){ - // summary: - // Register a listener to 'mouseover' or touch equivalent for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - out: function(node, listener){ - // summary: - // Register a listener to 'mouseout' or touch equivalent for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - enter: function(node, listener){ - // summary: - // Register a listener to mouse.enter or touch equivalent for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - }, - leave: function(node, listener){ - // summary: - // Register a listener to mouse.leave or touch equivalent for the given node - // node: Dom - // Target node to listen to - // listener: Function - // Callback function - // returns: - // A handle which will be used to remove the listener by handle.remove() - } - }; - =====*/ - - 1 && (dojo.touch = touch); - - return touch; -}); - -}, -'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"listbox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitInputField dijitButtonText\" data-dojo-attach-point=\"containerNode,_popupStateNode\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitValidationContainer\"\n\t\t\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t/></div\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td\n\t\t><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer\"\n\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t\t${_buttonInputDisabled}\n\t\t/></td\n\t></tr></tbody\n></table>\n", -'dojo/fx':function(){ -define("dojo/fx", [ - "./_base/lang", - "./Evented", - "./_base/kernel", - "./_base/array", - "./_base/connect", - "./_base/fx", - "./dom", - "./dom-style", - "./dom-geometry", - "./ready", - "require" // for context sensitive loading of Toggler -], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require){ - - // module: - // dojo/fx - - // For back-compat, remove in 2.0. - if(!dojo.isAsync){ - ready(0, function(){ - var requires = ["./fx/Toggler"]; - require(requires); // use indirection so modules not rolled into a build - }); - } - - var coreFx = dojo.fx = { - // summary: - // Effects library on top of Base animations - }; - - var _baseObj = { - _fire: function(evt, args){ - if(this[evt]){ - this[evt].apply(this, args||[]); - } - return this; - } - }; - - var _chain = function(animations){ - this._index = -1; - this._animations = animations||[]; - this._current = this._onAnimateCtx = this._onEndCtx = null; - - this.duration = 0; - arrayUtil.forEach(this._animations, function(a){ - this.duration += a.duration; - if(a.delay){ this.duration += a.delay; } - }, this); - }; - _chain.prototype = new Evented(); - lang.extend(_chain, { - _onAnimate: function(){ - this._fire("onAnimate", arguments); - }, - _onEnd: function(){ - connect.disconnect(this._onAnimateCtx); - connect.disconnect(this._onEndCtx); - this._onAnimateCtx = this._onEndCtx = null; - if(this._index + 1 == this._animations.length){ - this._fire("onEnd"); - }else{ - // switch animations - this._current = this._animations[++this._index]; - this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate"); - this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd"); - this._current.play(0, true); - } - }, - play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ - if(!this._current){ this._current = this._animations[this._index = 0]; } - if(!gotoStart && this._current.status() == "playing"){ return this; } - var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){ - this._fire("beforeBegin"); - }), - onBegin = connect.connect(this._current, "onBegin", this, function(arg){ - this._fire("onBegin", arguments); - }), - onPlay = connect.connect(this._current, "onPlay", this, function(arg){ - this._fire("onPlay", arguments); - connect.disconnect(beforeBegin); - connect.disconnect(onBegin); - connect.disconnect(onPlay); - }); - if(this._onAnimateCtx){ - connect.disconnect(this._onAnimateCtx); - } - this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate"); - if(this._onEndCtx){ - connect.disconnect(this._onEndCtx); - } - this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd"); - this._current.play.apply(this._current, arguments); - return this; - }, - pause: function(){ - if(this._current){ - var e = connect.connect(this._current, "onPause", this, function(arg){ - this._fire("onPause", arguments); - connect.disconnect(e); - }); - this._current.pause(); - } - return this; - }, - gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ - this.pause(); - var offset = this.duration * percent; - this._current = null; - arrayUtil.some(this._animations, function(a){ - if(a.duration <= offset){ - this._current = a; - return true; - } - offset -= a.duration; - return false; - }); - if(this._current){ - this._current.gotoPercent(offset / this._current.duration, andPlay); - } - return this; - }, - stop: function(/*boolean?*/ gotoEnd){ - if(this._current){ - if(gotoEnd){ - for(; this._index + 1 < this._animations.length; ++this._index){ - this._animations[this._index].stop(true); - } - this._current = this._animations[this._index]; - } - var e = connect.connect(this._current, "onStop", this, function(arg){ - this._fire("onStop", arguments); - connect.disconnect(e); - }); - this._current.stop(); - } - return this; - }, - status: function(){ - return this._current ? this._current.status() : "stopped"; - }, - destroy: function(){ - if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); } - if(this._onEndCtx){ connect.disconnect(this._onEndCtx); } - } - }); - lang.extend(_chain, _baseObj); - - coreFx.chain = function(/*dojo/_base/fx.Animation[]*/ animations){ - // summary: - // Chain a list of `dojo.Animation`s to run in sequence - // - // description: - // Return a `dojo.Animation` which will play all passed - // `dojo.Animation` instances in sequence, firing its own - // synthesized events simulating a single animation. (eg: - // onEnd of this animation means the end of the chain, - // not the individual animations within) - // - // example: - // Once `node` is faded out, fade in `otherNode` - // | fx.chain([ - // | dojo.fadeIn({ node:node }), - // | dojo.fadeOut({ node:otherNode }) - // | ]).play(); - // - return new _chain(animations); // dojo/_base/fx.Animation - }; - - var _combine = function(animations){ - this._animations = animations||[]; - this._connects = []; - this._finished = 0; - - this.duration = 0; - arrayUtil.forEach(animations, function(a){ - var duration = a.duration; - if(a.delay){ duration += a.delay; } - if(this.duration < duration){ this.duration = duration; } - this._connects.push(connect.connect(a, "onEnd", this, "_onEnd")); - }, this); - - this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration}); - var self = this; - arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"], - function(evt){ - self._connects.push(connect.connect(self._pseudoAnimation, evt, - function(){ self._fire(evt, arguments); } - )); - } - ); - }; - lang.extend(_combine, { - _doAction: function(action, args){ - arrayUtil.forEach(this._animations, function(a){ - a[action].apply(a, args); - }); - return this; - }, - _onEnd: function(){ - if(++this._finished > this._animations.length){ - this._fire("onEnd"); - } - }, - _call: function(action, args){ - var t = this._pseudoAnimation; - t[action].apply(t, args); - }, - play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ - this._finished = 0; - this._doAction("play", arguments); - this._call("play", arguments); - return this; - }, - pause: function(){ - this._doAction("pause", arguments); - this._call("pause", arguments); - return this; - }, - gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){ - var ms = this.duration * percent; - arrayUtil.forEach(this._animations, function(a){ - a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay); - }); - this._call("gotoPercent", arguments); - return this; - }, - stop: function(/*boolean?*/ gotoEnd){ - this._doAction("stop", arguments); - this._call("stop", arguments); - return this; - }, - status: function(){ - return this._pseudoAnimation.status(); - }, - destroy: function(){ - arrayUtil.forEach(this._connects, connect.disconnect); - } - }); - lang.extend(_combine, _baseObj); - - coreFx.combine = function(/*dojo/_base/fx.Animation[]*/ animations){ - // summary: - // Combine a list of `dojo.Animation`s to run in parallel - // - // description: - // Combine an array of `dojo.Animation`s to run in parallel, - // providing a new `dojo.Animation` instance encompasing each - // animation, firing standard animation events. - // - // example: - // Fade out `node` while fading in `otherNode` simultaneously - // | fx.combine([ - // | dojo.fadeIn({ node:node }), - // | dojo.fadeOut({ node:otherNode }) - // | ]).play(); - // - // example: - // When the longest animation ends, execute a function: - // | var anim = fx.combine([ - // | dojo.fadeIn({ node: n, duration:700 }), - // | dojo.fadeOut({ node: otherNode, duration: 300 }) - // | ]); - // | dojo.connect(anim, "onEnd", function(){ - // | // overall animation is done. - // | }); - // | anim.play(); // play the animation - // - return new _combine(animations); // dojo/_base/fx.Animation - }; - - coreFx.wipeIn = function(/*Object*/ args){ - // summary: - // Expand a node to it's natural height. - // - // description: - // Returns an animation that will expand the - // node defined in 'args' object from it's current height to - // it's natural height (with no scrollbar). - // Node must have no margin/border/padding. - // - // args: Object - // A hash-map of standard `dojo.Animation` constructor properties - // (such as easing: node: duration: and so on) - // - // example: - // | fx.wipeIn({ - // | node:"someId" - // | }).play() - var node = args.node = dom.byId(args.node), s = node.style, o; - - var anim = baseFx.animateProperty(lang.mixin({ - properties: { - height: { - // wrapped in functions so we wait till the last second to query (in case value has changed) - start: function(){ - // start at current [computed] height, but use 1px rather than 0 - // because 0 causes IE to display the whole panel - o = s.overflow; - s.overflow = "hidden"; - if(s.visibility == "hidden" || s.display == "none"){ - s.height = "1px"; - s.display = ""; - s.visibility = ""; - return 1; - }else{ - var height = domStyle.get(node, "height"); - return Math.max(height, 1); - } - }, - end: function(){ - return node.scrollHeight; - } - } - } - }, args)); - - var fini = function(){ - s.height = "auto"; - s.overflow = o; - }; - connect.connect(anim, "onStop", fini); - connect.connect(anim, "onEnd", fini); - - return anim; // dojo/_base/fx.Animation - }; - - coreFx.wipeOut = function(/*Object*/ args){ - // summary: - // Shrink a node to nothing and hide it. - // - // description: - // Returns an animation that will shrink node defined in "args" - // from it's current height to 1px, and then hide it. - // - // args: Object - // A hash-map of standard `dojo.Animation` constructor properties - // (such as easing: node: duration: and so on) - // - // example: - // | fx.wipeOut({ node:"someId" }).play() - - var node = args.node = dom.byId(args.node), s = node.style, o; - - var anim = baseFx.animateProperty(lang.mixin({ - properties: { - height: { - end: 1 // 0 causes IE to display the whole panel - } - } - }, args)); - - connect.connect(anim, "beforeBegin", function(){ - o = s.overflow; - s.overflow = "hidden"; - s.display = ""; - }); - var fini = function(){ - s.overflow = o; - s.height = "auto"; - s.display = "none"; - }; - connect.connect(anim, "onStop", fini); - connect.connect(anim, "onEnd", fini); - - return anim; // dojo/_base/fx.Animation - }; - - coreFx.slideTo = function(/*Object*/ args){ - // summary: - // Slide a node to a new top/left position - // - // description: - // Returns an animation that will slide "node" - // defined in args Object from its current position to - // the position defined by (args.left, args.top). - // - // args: Object - // A hash-map of standard `dojo.Animation` constructor properties - // (such as easing: node: duration: and so on). Special args members - // are `top` and `left`, which indicate the new position to slide to. - // - // example: - // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play() - - var node = args.node = dom.byId(args.node), - top = null, left = null; - - var init = (function(n){ - return function(){ - var cs = domStyle.getComputedStyle(n); - var pos = cs.position; - top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0); - left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0); - if(pos != 'absolute' && pos != 'relative'){ - var ret = geom.position(n, true); - top = ret.y; - left = ret.x; - n.style.position="absolute"; - n.style.top=top+"px"; - n.style.left=left+"px"; - } - }; - })(node); - init(); - - var anim = baseFx.animateProperty(lang.mixin({ - properties: { - top: args.top || 0, - left: args.left || 0 - } - }, args)); - connect.connect(anim, "beforeBegin", anim, init); - - return anim; // dojo/_base/fx.Animation - }; - - return coreFx; -}); - -}, -'dijit/_DialogMixin':function(){ -define("dijit/_DialogMixin", [ - "dojo/_base/declare", // declare - "./a11y" // _getTabNavigable -], function(declare, a11y){ - - // module: - // dijit/_DialogMixin - - return declare("dijit._DialogMixin", null, { - // summary: - // This provides functions useful to Dialog and TooltipDialog - - execute: function(/*Object*/ /*===== formContents =====*/){ - // summary: - // Callback when the user hits the submit button. - // Override this method to handle Dialog execution. - // description: - // After the user has pressed the submit button, the Dialog - // first calls onExecute() to notify the container to hide the - // dialog and restore focus to wherever it used to be. - // - // *Then* this method is called. - // type: - // callback - }, - - onCancel: function(){ - // summary: - // Called when user has pressed the Dialog's cancel button, to notify container. - // description: - // Developer shouldn't override or connect to this method; - // it's a private communication device between the TooltipDialog - // and the thing that opened it (ex: `dijit/form/DropDownButton`) - // type: - // protected - }, - - onExecute: function(){ - // summary: - // Called when user has pressed the dialog's OK button, to notify container. - // description: - // Developer shouldn't override or connect to this method; - // it's a private communication device between the TooltipDialog - // and the thing that opened it (ex: `dijit/form/DropDownButton`) - // type: - // protected - }, - - _onSubmit: function(){ - // summary: - // Callback when user hits submit button - // type: - // protected - this.onExecute(); // notify container that we are about to execute - this.execute(this.get('value')); - }, - - _getFocusItems: function(){ - // summary: - // Finds focusable items in dialog, - // and sets this._firstFocusItem and this._lastFocusItem - // tags: - // protected - - var elems = a11y._getTabNavigable(this.containerNode); - this._firstFocusItem = elems.lowest || elems.first || this.closeButtonNode || this.domNode; - this._lastFocusItem = elems.last || elems.highest || this._firstFocusItem; - } - }); -}); - -}, -'dijit/Tree':function(){ -require({cache:{ -'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow dijitInline\" role=\"presentation\"\n\t\t><div data-dojo-attach-point=\"indentNode\" class=\"dijitInline\"></div\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n", -'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n"}}); -define("dijit/Tree", [ - "dojo/_base/array", // array.filter array.forEach array.map - "dojo/_base/connect", // connect.isCopyKey() - "dojo/cookie", // cookie - "dojo/_base/declare", // declare - "dojo/Deferred", // Deferred - "dojo/DeferredList", // DeferredList - "dojo/dom", // dom.isDescendant - "dojo/dom-class", // domClass.add domClass.remove domClass.replace domClass.toggle - "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.position - "dojo/dom-style",// domStyle.set - "dojo/_base/event", // event.stop - "dojo/errors/create", // createError - "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut - "dojo/_base/kernel", // kernel.deprecated - "dojo/keys", // arrows etc. - "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch - "dojo/on", // on(), on.selector() - "dojo/topic", - "dojo/touch", - "dojo/when", - "./focus", - "./registry", // registry.byNode(), registry.getEnclosingWidget() - "./_base/manager", // manager.defaultDuration - "./_Widget", - "./_TemplatedMixin", - "./_Container", - "./_Contained", - "./_CssStateMixin", - "dojo/text!./templates/TreeNode.html", - "dojo/text!./templates/Tree.html", - "./tree/TreeStoreModel", - "./tree/ForestStoreModel", - "./tree/_dndSelector" -], function(array, connect, cookie, declare, Deferred, DeferredList, - dom, domClass, domGeometry, domStyle, event, createError, fxUtils, kernel, keys, lang, on, topic, touch, when, - focus, registry, manager, _Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin, - treeNodeTemplate, treeTemplate, TreeStoreModel, ForestStoreModel, _dndSelector){ - -// module: -// dijit/Tree - -// Back-compat shim -Deferred = declare(Deferred, { - addCallback: function(callback){ this.then(callback); }, - addErrback: function(errback){ this.then(null, errback); } -}); - -var TreeNode = declare( - "dijit._TreeNode", - [_Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin], -{ - // summary: - // Single node within a tree. This class is used internally - // by Tree and should not be accessed directly. - // tags: - // private - - // item: [const] Item - // the dojo.data entry this tree represents - item: null, - - // isTreeNode: [protected] Boolean - // Indicates that this is a TreeNode. Used by `dijit.Tree` only, - // should not be accessed directly. - isTreeNode: true, - - // label: String - // Text of this tree node - label: "", - _setLabelAttr: {node: "labelNode", type: "innerText"}, - - // isExpandable: [private] Boolean - // This node has children, so show the expando node (+ sign) - isExpandable: null, - - // isExpanded: [readonly] Boolean - // This node is currently expanded (ie, opened) - isExpanded: false, - - // state: [private] String - // Dynamic loading-related stuff. - // When an empty folder node appears, it is "UNCHECKED" first, - // then after dojo.data query it becomes "LOADING" and, finally "LOADED" - state: "UNCHECKED", - - templateString: treeNodeTemplate, - - baseClass: "dijitTreeNode", - - // For hover effect for tree node, and focus effect for label - cssStateNodes: { - rowNode: "dijitTreeRow" - }, - - // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here - _setTooltipAttr: {node: "rowNode", type: "attribute", attribute: "title"}, - - buildRendering: function(){ - this.inherited(arguments); - - // set expand icon for leaf - this._setExpando(); - - // set icon and label class based on item - this._updateItemClasses(this.item); - - if(this.isExpandable){ - this.labelNode.setAttribute("aria-expanded", this.isExpanded); - } - - //aria-selected should be false on all selectable elements. - this.setSelected(false); - }, - - _setIndentAttr: function(indent){ - // summary: - // Tell this node how many levels it should be indented - // description: - // 0 for top level nodes, 1 for their children, 2 for their - // grandchildren, etc. - - // Math.max() is to prevent negative padding on hidden root node (when indent == -1) - var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px"; - - domStyle.set(this.domNode, "backgroundPosition", pixels + " 0px"); // TODOC: what is this for??? - domStyle.set(this.indentNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels); - - array.forEach(this.getChildren(), function(child){ - child.set("indent", indent+1); - }); - - this._set("indent", indent); - }, - - markProcessing: function(){ - // summary: - // Visually denote that tree is loading data, etc. - // tags: - // private - this.state = "LOADING"; - this._setExpando(true); - }, - - unmarkProcessing: function(){ - // summary: - // Clear markup from markProcessing() call - // tags: - // private - this._setExpando(false); - }, - - _updateItemClasses: function(item){ - // summary: - // Set appropriate CSS classes for icon and label dom node - // (used to allow for item updates to change respective CSS) - // tags: - // private - var tree = this.tree, model = tree.model; - if(tree._v10Compat && item === model.root){ - // For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0) - item = null; - } - this._applyClassAndStyle(item, "icon", "Icon"); - this._applyClassAndStyle(item, "label", "Label"); - this._applyClassAndStyle(item, "row", "Row"); - - this.tree._startPaint(true); // signifies paint started and finished (synchronously) - }, - - _applyClassAndStyle: function(item, lower, upper){ - // summary: - // Set the appropriate CSS classes and styles for labels, icons and rows. - // - // item: - // The data item. - // - // lower: - // The lower case attribute to use, e.g. 'icon', 'label' or 'row'. - // - // upper: - // The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'. - // - // tags: - // private - - var clsName = "_" + lower + "Class"; - var nodeName = lower + "Node"; - var oldCls = this[clsName]; - - this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded); - domClass.replace(this[nodeName], this[clsName] || "", oldCls || ""); - - domStyle.set(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {}); - }, - - _updateLayout: function(){ - // summary: - // Set appropriate CSS classes for this.domNode - // tags: - // private - var parent = this.getParent(); - if(!parent || !parent.rowNode || parent.rowNode.style.display == "none"){ - /* if we are hiding the root node then make every first level child look like a root node */ - domClass.add(this.domNode, "dijitTreeIsRoot"); - }else{ - domClass.toggle(this.domNode, "dijitTreeIsLast", !this.getNextSibling()); - } - }, - - _setExpando: function(/*Boolean*/ processing){ - // summary: - // Set the right image for the expando node - // tags: - // private - - var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened", - "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"], - _a11yStates = ["*","-","+","*"], - idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3); - - // apply the appropriate class to the expando node - domClass.replace(this.expandoNode, styles[idx], styles); - - // provide a non-image based indicator for images-off mode - this.expandoNodeText.innerHTML = _a11yStates[idx]; - - }, - - expand: function(){ - // summary: - // Show my children - // returns: - // Deferred that fires when expansion is complete - - // If there's already an expand in progress or we are already expanded, just return - if(this._expandDeferred){ - return this._expandDeferred; // dojo/_base/Deferred - } - - // cancel in progress collapse operation - if(this._collapseDeferred){ - this._collapseDeferred.cancel(); - delete this._collapseDeferred; - } - - // All the state information for when a node is expanded, maybe this should be - // set when the animation completes instead - this.isExpanded = true; - this.labelNode.setAttribute("aria-expanded", "true"); - if(this.tree.showRoot || this !== this.tree.rootNode){ - this.containerNode.setAttribute("role", "group"); - } - domClass.add(this.contentNode,'dijitTreeContentExpanded'); - this._setExpando(); - this._updateItemClasses(this.item); - - if(this == this.tree.rootNode && this.tree.showRoot){ - this.tree.domNode.setAttribute("aria-expanded", "true"); - } - - var def, - wipeIn = fxUtils.wipeIn({ - node: this.containerNode, - duration: manager.defaultDuration, - onEnd: function(){ - def.resolve(true); - } - }); - - // Deferred that fires when expand is complete - def = (this._expandDeferred = new Deferred(function(){ - // Canceller - wipeIn.stop(); - })); - - wipeIn.play(); - - return def; // dojo/_base/Deferred - }, - - collapse: function(){ - // summary: - // Collapse this node (if it's expanded) - - if(this._collapseDeferred){ - // Node is already collapsed, or there's a collapse in progress, just return that Deferred - return this._collapseDeferred; - } - - // cancel in progress expand operation - if(this._expandDeferred){ - this._expandDeferred.cancel(); - delete this._expandDeferred; - } - - this.isExpanded = false; - this.labelNode.setAttribute("aria-expanded", "false"); - if(this == this.tree.rootNode && this.tree.showRoot){ - this.tree.domNode.setAttribute("aria-expanded", "false"); - } - domClass.remove(this.contentNode,'dijitTreeContentExpanded'); - this._setExpando(); - this._updateItemClasses(this.item); - - var def, - wipeOut = fxUtils.wipeOut({ - node: this.containerNode, - duration: manager.defaultDuration, - onEnd: function(){ - def.resolve(true); - } - }); - - // Deferred that fires when expand is complete - def = (this._collapseDeferred = new Deferred(function(){ - // Canceller - wipeOut.stop(); - })); - - wipeOut.play(); - - return def; // dojo/_base/Deferred - }, - - // indent: Integer - // Levels from this node to the root node - indent: 0, - - setChildItems: function(/* Object[] */ items){ - // summary: - // Sets the child items of this node, removing/adding nodes - // from current children to match specified items[] array. - // Also, if this.persist == true, expands any children that were previously - // opened. - // returns: - // Deferred object that fires after all previously opened children - // have been expanded again (or fires instantly if there are no such children). - - var tree = this.tree, - model = tree.model, - defs = []; // list of deferreds that need to fire before I am complete - - - // Orphan all my existing children. - // If items contains some of the same items as before then we will reattach them. - // Don't call this.removeChild() because that will collapse the tree etc. - var oldChildren = this.getChildren(); - array.forEach(oldChildren, function(child){ - _Container.prototype.removeChild.call(this, child); - }, this); - - // All the old children of this TreeNode are subject for destruction if - // 1) they aren't listed in the new children array (items) - // 2) they aren't immediately adopted by another node (DnD) - this.defer(function(){ - array.forEach(oldChildren, function(node){ - if(!node._destroyed && !node.getParent()){ - // If node is in selection then remove it. - tree.dndController.removeTreeNode(node); - - // Deregister mapping from item id --> this node - var id = model.getIdentity(node.item), - ary = tree._itemNodesMap[id]; - if(ary.length == 1){ - delete tree._itemNodesMap[id]; - }else{ - var index = array.indexOf(ary, node); - if(index != -1){ - ary.splice(index, 1); - } - } - - // And finally we can destroy the node - node.destroyRecursive(); - } - }); - }); - - this.state = "LOADED"; - - if(items && items.length > 0){ - this.isExpandable = true; - - // Create _TreeNode widget for each specified tree node, unless one already - // exists and isn't being used (presumably it's from a DnD move and was recently - // released - array.forEach(items, function(item){ // MARKER: REUSE NODE - var id = model.getIdentity(item), - existingNodes = tree._itemNodesMap[id], - node; - if(existingNodes){ - for(var i=0;i<existingNodes.length;i++){ - if(existingNodes[i] && !existingNodes[i].getParent()){ - node = existingNodes[i]; - node.set('indent', this.indent+1); - break; - } - } - } - if(!node){ - node = this.tree._createTreeNode({ - item: item, - tree: tree, - isExpandable: model.mayHaveChildren(item), - label: tree.getLabel(item), - tooltip: tree.getTooltip(item), - ownerDocument: tree.ownerDocument, - dir: tree.dir, - lang: tree.lang, - textDir: tree.textDir, - indent: this.indent + 1 - }); - if(existingNodes){ - existingNodes.push(node); - }else{ - tree._itemNodesMap[id] = [node]; - } - } - this.addChild(node); - - // If node was previously opened then open it again now (this may trigger - // more data store accesses, recursively) - if(this.tree.autoExpand || this.tree._state(node)){ - defs.push(tree._expandNode(node)); - } - }, this); - - // note that updateLayout() needs to be called on each child after - // _all_ the children exist - array.forEach(this.getChildren(), function(child){ - child._updateLayout(); - }); - }else{ - this.isExpandable=false; - } - - if(this._setExpando){ - // change expando to/from dot or + icon, as appropriate - this._setExpando(false); - } - - // Set leaf icon or folder icon, as appropriate - this._updateItemClasses(this.item); - - // On initial tree show, make the selected TreeNode as either the root node of the tree, - // or the first child, if the root node is hidden - if(this == tree.rootNode){ - var fc = this.tree.showRoot ? this : this.getChildren()[0]; - if(fc){ - fc.setFocusable(true); - tree.lastFocused = fc; - }else{ - // fallback: no nodes in tree so focus on Tree <div> itself - tree.domNode.setAttribute("tabIndex", "0"); - } - } - - var def = new DeferredList(defs); - this.tree._startPaint(def); // to reset TreeNode widths after an item is added/removed from the Tree - return def; // dojo/_base/Deferred - }, - - getTreePath: function(){ - var node = this; - var path = []; - while(node && node !== this.tree.rootNode){ - path.unshift(node.item); - node = node.getParent(); - } - path.unshift(this.tree.rootNode.item); - - return path; - }, - - getIdentity: function(){ - return this.tree.model.getIdentity(this.item); - }, - - removeChild: function(/* treeNode */ node){ - this.inherited(arguments); - - var children = this.getChildren(); - if(children.length == 0){ - this.isExpandable = false; - this.collapse(); - } - - array.forEach(children, function(child){ - child._updateLayout(); - }); - }, - - makeExpandable: function(){ - // summary: - // if this node wasn't already showing the expando node, - // turn it into one and call _setExpando() - - // TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0 - - this.isExpandable = true; - this._setExpando(false); - }, - - setSelected: function(/*Boolean*/ selected){ - // summary: - // A Tree has a (single) currently selected node. - // Mark that this node is/isn't that currently selected node. - // description: - // In particular, setting a node as selected involves setting tabIndex - // so that when user tabs to the tree, focus will go to that node (only). - this.labelNode.setAttribute("aria-selected", selected ? "true" : "false"); - domClass.toggle(this.rowNode, "dijitTreeRowSelected", selected); - }, - - setFocusable: function(/*Boolean*/ selected){ - // summary: - // A Tree has a (single) node that's focusable. - // Mark that this node is/isn't that currently focsuable node. - // description: - // In particular, setting a node as selected involves setting tabIndex - // so that when user tabs to the tree, focus will go to that node (only). - - this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1"); - }, - - - _setTextDirAttr: function(textDir){ - if(textDir &&((this.textDir != textDir) || !this._created)){ - this._set("textDir", textDir); - this.applyTextDir(this.labelNode, this.labelNode.innerText || this.labelNode.textContent || ""); - array.forEach(this.getChildren(), function(childNode){ - childNode.set("textDir", textDir); - }, this); - } - } -}); - -var Tree = declare("dijit.Tree", [_Widget, _TemplatedMixin], { - // summary: - // This widget displays hierarchical data from a store. - - // store: [deprecated] String|dojo/data/Store - // Deprecated. Use "model" parameter instead. - // The store to get data to display in the tree. - store: null, - - // model: dijit/tree/model - // Interface to read tree data, get notifications of changes to tree data, - // and for handling drop operations (i.e drag and drop onto the tree) - model: null, - - // query: [deprecated] anything - // Deprecated. User should specify query to the model directly instead. - // Specifies datastore query to return the root item or top items for the tree. - query: null, - - // label: [deprecated] String - // Deprecated. Use dijit/tree/ForestStoreModel directly instead. - // Used in conjunction with query parameter. - // If a query is specified (rather than a root node id), and a label is also specified, - // then a fake root node is created and displayed, with this label. - label: "", - - // showRoot: [const] Boolean - // Should the root node be displayed, or hidden? - showRoot: true, - - // childrenAttr: [deprecated] String[] - // Deprecated. This information should be specified in the model. - // One ore more attributes that holds children of a tree node - childrenAttr: ["children"], - - // paths: String[][] or Item[][] - // Full paths from rootNode to selected nodes expressed as array of items or array of ids. - // Since setting the paths may be asynchronous (because of waiting on dojo.data), set("paths", ...) - // returns a Deferred to indicate when the set is complete. - paths: [], - - // path: String[] or Item[] - // Backward compatible singular variant of paths. - path: [], - - // selectedItems: [readonly] Item[] - // The currently selected items in this tree. - // This property can only be set (via set('selectedItems', ...)) when that item is already - // visible in the tree. (I.e. the tree has already been expanded to show that node.) - // Should generally use `paths` attribute to set the selected items instead. - selectedItems: null, - - // selectedItem: [readonly] Item - // Backward compatible singular variant of selectedItems. - selectedItem: null, - - // openOnClick: Boolean - // If true, clicking a folder node's label will open it, rather than calling onClick() - openOnClick: false, - - // openOnDblClick: Boolean - // If true, double-clicking a folder node's label will open it, rather than calling onDblClick() - openOnDblClick: false, - - templateString: treeTemplate, - - // persist: Boolean - // Enables/disables use of cookies for state saving. - persist: true, - - // autoExpand: Boolean - // Fully expand the tree on load. Overrides `persist`. - autoExpand: false, - - // dndController: [protected] Function|String - // Class to use as as the dnd controller. Specifying this class enables DnD. - // Generally you should specify this as dijit/tree/dndSource. - // Setting of dijit/tree/_dndSelector handles selection only (no actual DnD). - dndController: _dndSelector, - - // parameters to pull off of the tree and pass on to the dndController as its params - dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"], - - //declare the above items so they can be pulled from the tree's markup - - // onDndDrop: [protected] Function - // Parameter to dndController, see `dijit/tree/dndSource.onDndDrop()`. - // Generally this doesn't need to be set. - onDndDrop: null, - - itemCreator: null, - /*===== - itemCreator: function(nodes, target, source){ - // summary: - // Returns objects passed to `Tree.model.newItem()` based on DnD nodes - // dropped onto the tree. Developer must override this method to enable - // dropping from external sources onto this Tree, unless the Tree.model's items - // happen to look like {id: 123, name: "Apple" } with no other attributes. - // - // For each node in nodes[], which came from source, create a hash of name/value - // pairs to be passed to Tree.model.newItem(). Returns array of those hashes. - // nodes: DomNode[] - // The DOMNodes dragged from the source container - // target: DomNode - // The target TreeNode.rowNode - // source: dojo/dnd/Source - // The source container the nodes were dragged from, perhaps another Tree or a plain dojo/dnd/Source - // returns: Object[] - // Array of name/value hashes for each new item to be added to the Tree, like: - // | [ - // | { id: 123, label: "apple", foo: "bar" }, - // | { id: 456, label: "pear", zaz: "bam" } - // | ] - // tags: - // extension - return [{}]; - }, - =====*/ - - // onDndCancel: [protected] Function - // Parameter to dndController, see `dijit/tree/dndSource.onDndCancel()`. - // Generally this doesn't need to be set. - onDndCancel: null, - -/*===== - checkAcceptance: function(source, nodes){ - // summary: - // Checks if the Tree itself can accept nodes from this source - // source: dijit/tree/dndSource - // The source which provides items - // nodes: DOMNode[] - // Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if - // source is a dijit/Tree. - // tags: - // extension - return true; // Boolean - }, -=====*/ - checkAcceptance: null, - -/*===== - checkItemAcceptance: function(target, source, position){ - // summary: - // Stub function to be overridden if one wants to check for the ability to drop at the node/item level - // description: - // In the base case, this is called to check if target can become a child of source. - // When betweenThreshold is set, position="before" or "after" means that we - // are asking if the source node can be dropped before/after the target node. - // target: DOMNode - // The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to - // Use registry.getEnclosingWidget(target) to get the TreeNode. - // source: dijit/tree/dndSource - // The (set of) nodes we are dropping - // position: String - // "over", "before", or "after" - // tags: - // extension - return true; // Boolean - }, -=====*/ - checkItemAcceptance: null, - - // dragThreshold: Integer - // Number of pixels mouse moves before it's considered the start of a drag operation - dragThreshold: 5, - - // betweenThreshold: Integer - // Set to a positive value to allow drag and drop "between" nodes. - // - // If during DnD mouse is over a (target) node but less than betweenThreshold - // pixels from the bottom edge, dropping the the dragged node will make it - // the next sibling of the target node, rather than the child. - // - // Similarly, if mouse is over a target node but less that betweenThreshold - // pixels from the top edge, dropping the dragged node will make it - // the target node's previous sibling rather than the target node's child. - betweenThreshold: 0, - - // _nodePixelIndent: Integer - // Number of pixels to indent tree nodes (relative to parent node). - // Default is 19 but can be overridden by setting CSS class dijitTreeIndent - // and calling resize() or startup() on tree after it's in the DOM. - _nodePixelIndent: 19, - - _publish: function(/*String*/ topicName, /*Object*/ message){ - // summary: - // Publish a message for this widget/topic - topic.publish(this.id, lang.mixin({tree: this, event: topicName}, message || {})); // publish - }, - - postMixInProperties: function(){ - this.tree = this; - - if(this.autoExpand){ - // There's little point in saving opened/closed state of nodes for a Tree - // that initially opens all it's nodes. - this.persist = false; - } - - this._itemNodesMap = {}; - - if(!this.cookieName && this.id){ - this.cookieName = this.id + "SaveStateCookie"; - } - - // Deferred that fires when all the children have loaded. - this.expandChildrenDeferred = new Deferred(); - - // Deferred that fires when all pending operations complete. - this.pendingCommandsDeferred = this.expandChildrenDeferred; - - this.inherited(arguments); - }, - - postCreate: function(){ - this._initState(); - - // Catch events on TreeNodes - var self = this; - this.own( - on(this.domNode, on.selector(".dijitTreeNode", touch.enter), function(evt){ - self._onNodeMouseEnter(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeNode", touch.leave), function(evt){ - self._onNodeMouseLeave(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeNode", "click"), function(evt){ - self._onClick(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeNode", "dblclick"), function(evt){ - self._onDblClick(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeNode", "keypress"), function(evt){ - self._onKeyPress(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeNode", "keydown"), function(evt){ - self._onKeyDown(registry.byNode(this), evt); - }), - on(this.domNode, on.selector(".dijitTreeRow", "focusin"), function(evt){ - self._onNodeFocus(registry.getEnclosingWidget(this), evt); - }) - ); - - // Create glue between store and Tree, if not specified directly by user - if(!this.model){ - this._store2model(); - } - - // monitor changes to items - this.connect(this.model, "onChange", "_onItemChange"); - this.connect(this.model, "onChildrenChange", "_onItemChildrenChange"); - this.connect(this.model, "onDelete", "_onItemDelete"); - - this.inherited(arguments); - - if(this.dndController){ - if(lang.isString(this.dndController)){ - this.dndController = lang.getObject(this.dndController); - } - var params={}; - for(var i=0; i<this.dndParams.length;i++){ - if(this[this.dndParams[i]]){ - params[this.dndParams[i]] = this[this.dndParams[i]]; - } - } - this.dndController = new this.dndController(this, params); - } - - this._load(); - - // If no path was specified to the constructor, use path saved in cookie - if(!this.params.path && !this.params.paths && this.persist){ - this.set("paths", this.dndController._getSavedPaths()); - } - - // onLoadDeferred should fire when all commands that are part of initialization have completed. - // It will include all the set("paths", ...) commands that happen during initialization. - this.onLoadDeferred = this.pendingCommandsDeferred; - - this.onLoadDeferred.then(lang.hitch(this, "onLoad")); - }, - - _store2model: function(){ - // summary: - // User specified a store&query rather than model, so create model from store/query - this._v10Compat = true; - kernel.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query"); - - var modelParams = { - id: this.id + "_ForestStoreModel", - store: this.store, - query: this.query, - childrenAttrs: this.childrenAttr - }; - - // Only override the model's mayHaveChildren() method if the user has specified an override - if(this.params.mayHaveChildren){ - modelParams.mayHaveChildren = lang.hitch(this, "mayHaveChildren"); - } - - if(this.params.getItemChildren){ - modelParams.getChildren = lang.hitch(this, function(item, onComplete, onError){ - this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError); - }); - } - this.model = new ForestStoreModel(modelParams); - - // For backwards compatibility, the visibility of the root node is controlled by - // whether or not the user has specified a label - this.showRoot = Boolean(this.label); - }, - - onLoad: function(){ - // summary: - // Called when tree finishes loading and expanding. - // description: - // If persist == true the loading may encompass many levels of fetches - // from the data store, each asynchronous. Waits for all to finish. - // tags: - // callback - }, - - _load: function(){ - // summary: - // Initial load of the tree. - // Load root node (possibly hidden) and it's children. - this.model.getRoot( - lang.hitch(this, function(item){ - var rn = (this.rootNode = this.tree._createTreeNode({ - item: item, - tree: this, - isExpandable: true, - label: this.label || this.getLabel(item), - textDir: this.textDir, - indent: this.showRoot ? 0 : -1 - })); - - if(!this.showRoot){ - rn.rowNode.style.display="none"; - // if root is not visible, move tree role to the invisible - // root node's containerNode, see #12135 - this.domNode.setAttribute("role", "presentation"); - this.domNode.removeAttribute("aria-expanded"); - this.domNode.removeAttribute("aria-multiselectable"); - - rn.labelNode.setAttribute("role", "presentation"); - rn.containerNode.setAttribute("role", "tree"); - rn.containerNode.setAttribute("aria-expanded","true"); - rn.containerNode.setAttribute("aria-multiselectable", !this.dndController.singular); - }else{ - this.domNode.setAttribute("aria-multiselectable", !this.dndController.singular); - } - - this.domNode.appendChild(rn.domNode); - var identity = this.model.getIdentity(item); - if(this._itemNodesMap[identity]){ - this._itemNodesMap[identity].push(rn); - }else{ - this._itemNodesMap[identity] = [rn]; - } - - rn._updateLayout(); // sets "dijitTreeIsRoot" CSS classname - - // Load top level children, and if persist==true, all nodes that were previously opened - this._expandNode(rn).then(lang.hitch(this, function(){ - // Then, select the nodes that were selected last time, or - // the ones specified by params.paths[]. - - this.expandChildrenDeferred.resolve(true); - })); - }), - lang.hitch(this, function(err){ - console.error(this, ": error loading root: ", err); - }) - ); - }, - - getNodesByItem: function(/*Item or id*/ item){ - // summary: - // Returns all tree nodes that refer to an item - // returns: - // Array of tree nodes that refer to passed item - - if(!item){ return []; } - var identity = lang.isString(item) ? item : this.model.getIdentity(item); - // return a copy so widget don't get messed up by changes to returned array - return [].concat(this._itemNodesMap[identity]); - }, - - _setSelectedItemAttr: function(/*Item or id*/ item){ - this.set('selectedItems', [item]); - }, - - _setSelectedItemsAttr: function(/*Items or ids*/ items){ - // summary: - // Select tree nodes related to passed items. - // WARNING: if model use multi-parented items or desired tree node isn't already loaded - // behavior is undefined. Use set('paths', ...) instead. - var tree = this; - return this.pendingCommandsDeferred = this.pendingCommandsDeferred.then( lang.hitch(this, function(){ - var identities = array.map(items, function(item){ - return (!item || lang.isString(item)) ? item : tree.model.getIdentity(item); - }); - var nodes = []; - array.forEach(identities, function(id){ - nodes = nodes.concat(tree._itemNodesMap[id] || []); - }); - this.set('selectedNodes', nodes); - })); - }, - - _setPathAttr: function(/*Item[]|String[]*/ path){ - // summary: - // Singular variant of _setPathsAttr - if(path.length){ - return this.set("paths", [path]); - }else{ - // Empty list is interpreted as "select nothing" - return this.set("paths", []); - } - }, - - _setPathsAttr: function(/*Item[][]|String[][]*/ paths){ - // summary: - // Select the tree nodes identified by passed paths. - // paths: - // Array of arrays of items or item id's - // returns: - // Deferred to indicate when the set is complete - - var tree = this; - - // Let any previous set("path", ...) commands complete before this one starts. - return this.pendingCommandsDeferred = this.pendingCommandsDeferred.then(function(){ - // We may need to wait for some nodes to expand, so setting - // each path will involve a Deferred. We bring those deferreds - // together with a DeferredList. - return new DeferredList(array.map(paths, function(path){ - var d = new Deferred(); - - // normalize path to use identity - path = array.map(path, function(item){ - return lang.isString(item) ? item : tree.model.getIdentity(item); - }); - - if(path.length){ - // Wait for the tree to load, if it hasn't already. - selectPath(path, [tree.rootNode], d); - }else{ - d.reject(new Tree.PathError("Empty path")); - } - return d; - })); - }).then(setNodes); - - function selectPath(path, nodes, def){ - // Traverse path; the next path component should be among "nodes". - var nextPath = path.shift(); - var nextNode = array.filter(nodes, function(node){ - return node.getIdentity() == nextPath; - })[0]; - if(!!nextNode){ - if(path.length){ - tree._expandNode(nextNode).then(function(){ selectPath(path, nextNode.getChildren(), def); }); - }else{ - // Successfully reached the end of this path - def.resolve(nextNode); - } - }else{ - def.reject(new Tree.PathError("Could not expand path at " + nextPath)); - } - } - - function setNodes(newNodes){ - // After all expansion is finished, set the selection to - // the set of nodes successfully found. - tree.set("selectedNodes", array.map( - array.filter(newNodes,function(x){return x[0];}), - function(x){return x[1];})); - } - }, - - _setSelectedNodeAttr: function(node){ - this.set('selectedNodes', [node]); - }, - _setSelectedNodesAttr: function(nodes){ - // summary: - // Marks the specified TreeNodes as selected. - // nodes: TreeNode[] - // TreeNodes to mark. - this.dndController.setSelection(nodes); - }, - - - expandAll: function(){ - // summary: - // Expand all nodes in the tree - // returns: - // Deferred that fires when all nodes have expanded - - var _this = this; - - function expand(node){ - var def = new dojo.Deferred(); - - // Expand the node - _this._expandNode(node).then(function(){ - // When node has expanded, call expand() recursively on each non-leaf child - var childBranches = array.filter(node.getChildren() || [], function(node){ - return node.isExpandable; - }), - defs = array.map(childBranches, expand); - - // And when all those recursive calls finish, signal that I'm finished - new dojo.DeferredList(defs).then(function(){ - def.resolve(true); - }); - }); - - return def; - } - - return expand(this.rootNode); - }, - - collapseAll: function(){ - // summary: - // Collapse all nodes in the tree - // returns: - // Deferred that fires when all nodes have collapsed - - var _this = this; - - function collapse(node){ - var def = new dojo.Deferred(); - def.label = "collapseAllDeferred"; - - // Collapse children first - var childBranches = array.filter(node.getChildren() || [], function(node){ - return node.isExpandable; - }), - defs = array.map(childBranches, collapse); - - // And when all those recursive calls finish, collapse myself, unless I'm the invisible root node, - // in which case collapseAll() is finished - new dojo.DeferredList(defs).then(function(){ - if(!node.isExpanded || (node == _this.rootNode && !_this.showRoot)){ - def.resolve(true); - }else{ - _this._collapseNode(node).then(function(){ - // When node has collapsed, signal that call is finished - def.resolve(true); - }); - } - }); - - - return def; - } - - return collapse(this.rootNode); - }, - - ////////////// Data store related functions ////////////////////// - // These just get passed to the model; they are here for back-compat - - mayHaveChildren: function(/*dojo/data/Item*/ /*===== item =====*/){ - // summary: - // Deprecated. This should be specified on the model itself. - // - // Overridable function to tell if an item has or may have children. - // Controls whether or not +/- expando icon is shown. - // (For efficiency reasons we may not want to check if an element actually - // has children until user clicks the expando node) - // tags: - // deprecated - }, - - getItemChildren: function(/*===== parentItem, onComplete =====*/){ - // summary: - // Deprecated. This should be specified on the model itself. - // - // Overridable function that return array of child items of given parent item, - // or if parentItem==null then return top items in tree - // tags: - // deprecated - }, - - /////////////////////////////////////////////////////// - // Functions for converting an item to a TreeNode - getLabel: function(/*dojo/data/Item*/ item){ - // summary: - // Overridable function to get the label for a tree node (given the item) - // tags: - // extension - return this.model.getLabel(item); // String - }, - - getIconClass: function(/*dojo/data/Item*/ item, /*Boolean*/ opened){ - // summary: - // Overridable function to return CSS class name to display icon - // tags: - // extension - return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf" - }, - - getLabelClass: function(/*===== item, opened =====*/){ - // summary: - // Overridable function to return CSS class name to display label - // item: dojo/data/Item - // opened: Boolean - // returns: String - // CSS class name - // tags: - // extension - }, - - getRowClass: function(/*===== item, opened =====*/){ - // summary: - // Overridable function to return CSS class name to display row - // item: dojo/data/Item - // opened: Boolean - // returns: String - // CSS class name - // tags: - // extension - }, - - getIconStyle: function(/*===== item, opened =====*/){ - // summary: - // Overridable function to return CSS styles to display icon - // item: dojo/data/Item - // opened: Boolean - // returns: Object - // Object suitable for input to dojo.style() like {backgroundImage: "url(...)"} - // tags: - // extension - }, - - getLabelStyle: function(/*===== item, opened =====*/){ - // summary: - // Overridable function to return CSS styles to display label - // item: dojo/data/Item - // opened: Boolean - // returns: - // Object suitable for input to dojo.style() like {color: "red", background: "green"} - // tags: - // extension - }, - - getRowStyle: function(/*===== item, opened =====*/){ - // summary: - // Overridable function to return CSS styles to display row - // item: dojo/data/Item - // opened: Boolean - // returns: - // Object suitable for input to dojo.style() like {background-color: "#bbb"} - // tags: - // extension - }, - - getTooltip: function(/*dojo/data/Item*/ /*===== item =====*/){ - // summary: - // Overridable function to get the tooltip for a tree node (given the item) - // tags: - // extension - return ""; // String - }, - - /////////// Keyboard and Mouse handlers //////////////////// - - _onKeyPress: function(/*TreeNode*/ treeNode, /*Event*/ e){ - // summary: - // Handles keystrokes for printable keys, doing search navigation - - if(e.charCode <= 32){ - // Avoid duplicate events on firefox (this is an arrow key that will be handled by keydown handler) - return; - } - - if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){ - var c = String.fromCharCode(e.charCode); - this._onLetterKeyNav( { node: treeNode, key: c.toLowerCase() } ); - event.stop(e); - } - }, - - _onKeyDown: function(/*TreeNode*/ treeNode, /*Event*/ e){ - // summary: - // Handles arrow, space, and enter keys - - var key = e.keyCode; - - var map = this._keyHandlerMap; - if(!map){ - // Setup table mapping keys to events. - // On WebKit based browsers, the combination ctrl-enter does not get passed through. To allow accessible - // multi-select on those browsers, the space key is also used for selection. - // Therefore, also allow space key for keyboard "click" operation. - map = {}; - map[keys.ENTER] = map[keys.SPACE] = map[" "] = "_onEnterKey"; - map[this.isLeftToRight() ? keys.LEFT_ARROW : keys.RIGHT_ARROW] = "_onLeftArrow"; - map[this.isLeftToRight() ? keys.RIGHT_ARROW : keys.LEFT_ARROW] = "_onRightArrow"; - map[keys.UP_ARROW] = "_onUpArrow"; - map[keys.DOWN_ARROW] = "_onDownArrow"; - map[keys.HOME] = "_onHomeKey"; - map[keys.END] = "_onEndKey"; - this._keyHandlerMap = map; - } - - if(this._keyHandlerMap[key]){ - // clear record of recent printables (being saved for multi-char letter navigation), - // because "a", down-arrow, "b" shouldn't search for "ab" - if(this._curSearch){ - this._curSearch.timer.remove(); - delete this._curSearch; - } - - this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } ); - event.stop(e); - } - }, - - _onEnterKey: function(/*Object*/ message){ - this._publish("execute", { item: message.item, node: message.node } ); - this.dndController.userSelect(message.node, connect.isCopyKey( message.evt ), message.evt.shiftKey); - this.onClick(message.item, message.node, message.evt); - }, - - _onDownArrow: function(/*Object*/ message){ - // summary: - // down arrow pressed; get next visible node, set focus there - var node = this._getNextNode(message.node); - if(node && node.isTreeNode){ - this.focusNode(node); - } - }, - - _onUpArrow: function(/*Object*/ message){ - // summary: - // Up arrow pressed; move to previous visible node - - var node = message.node; - - // if younger siblings - var previousSibling = node.getPreviousSibling(); - if(previousSibling){ - node = previousSibling; - // if the previous node is expanded, dive in deep - while(node.isExpandable && node.isExpanded && node.hasChildren()){ - // move to the last child - var children = node.getChildren(); - node = children[children.length-1]; - } - }else{ - // if this is the first child, return the parent - // unless the parent is the root of a tree with a hidden root - var parent = node.getParent(); - if(!(!this.showRoot && parent === this.rootNode)){ - node = parent; - } - } - - if(node && node.isTreeNode){ - this.focusNode(node); - } - }, - - _onRightArrow: function(/*Object*/ message){ - // summary: - // Right arrow pressed; go to child node - var node = message.node; - - // if not expanded, expand, else move to 1st child - if(node.isExpandable && !node.isExpanded){ - this._expandNode(node); - }else if(node.hasChildren()){ - node = node.getChildren()[0]; - if(node && node.isTreeNode){ - this.focusNode(node); - } - } - }, - - _onLeftArrow: function(/*Object*/ message){ - // summary: - // Left arrow pressed. - // If not collapsed, collapse, else move to parent. - - var node = message.node; - - if(node.isExpandable && node.isExpanded){ - this._collapseNode(node); - }else{ - var parent = node.getParent(); - if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){ - this.focusNode(parent); - } - } - }, - - _onHomeKey: function(){ - // summary: - // Home key pressed; get first visible node, and set focus there - var node = this._getRootOrFirstNode(); - if(node){ - this.focusNode(node); - } - }, - - _onEndKey: function(){ - // summary: - // End key pressed; go to last visible node. - - var node = this.rootNode; - while(node.isExpanded){ - var c = node.getChildren(); - node = c[c.length - 1]; - } - - if(node && node.isTreeNode){ - this.focusNode(node); - } - }, - - // multiCharSearchDuration: Number - // If multiple characters are typed where each keystroke happens within - // multiCharSearchDuration of the previous keystroke, - // search for nodes matching all the keystrokes. - // - // For example, typing "ab" will search for entries starting with - // "ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration. - multiCharSearchDuration: 250, - - _onLetterKeyNav: function(message){ - // summary: - // Called when user presses a prinatable key; search for node starting with recently typed letters. - // message: Object - // Like { node: TreeNode, key: 'a' } where key is the key the user pressed. - - // Branch depending on whether this key starts a new search, or modifies an existing search - var cs = this._curSearch; - if(cs){ - // We are continuing a search. Ex: user has pressed 'a', and now has pressed - // 'b', so we want to search for nodes starting w/"ab". - cs.pattern = cs.pattern + message.key; - cs.timer.remove(); - }else{ - // We are starting a new search - cs = this._curSearch = { - pattern: message.key, - startNode: message.node - }; - } - - // set/reset timer to forget recent keystrokes - cs.timer = this.defer(function(){ - delete this._curSearch; - }, this.multiCharSearchDuration); - - // Navigate to TreeNode matching keystrokes [entered so far]. - var node = cs.startNode; - do{ - node = this._getNextNode(node); - //check for last node, jump to first node if necessary - if(!node){ - node = this._getRootOrFirstNode(); - } - }while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern)); - if(node && node.isTreeNode){ - // no need to set focus if back where we started - if(node !== cs.startNode){ - this.focusNode(node); - } - } - }, - - isExpandoNode: function(node, widget){ - // summary: - // check whether a dom node is the expandoNode for a particular TreeNode widget - return dom.isDescendant(node, widget.expandoNode) || dom.isDescendant(node, widget.expandoNodeText); - }, - - _onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){ - // summary: - // Translates click events into commands for the controller to process - - var domElement = e.target, - isExpandoClick = this.isExpandoNode(domElement, nodeWidget); - - if( (this.openOnClick && nodeWidget.isExpandable) || isExpandoClick ){ - // expando node was clicked, or label of a folder node was clicked; open it - if(nodeWidget.isExpandable){ - this._onExpandoClick({node:nodeWidget}); - } - }else{ - this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } ); - this.onClick(nodeWidget.item, nodeWidget, e); - this.focusNode(nodeWidget); - } - event.stop(e); - }, - _onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){ - // summary: - // Translates double-click events into commands for the controller to process - - var domElement = e.target, - isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText); - - if( (this.openOnDblClick && nodeWidget.isExpandable) ||isExpandoClick ){ - // expando node was clicked, or label of a folder node was clicked; open it - if(nodeWidget.isExpandable){ - this._onExpandoClick({node:nodeWidget}); - } - }else{ - this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } ); - this.onDblClick(nodeWidget.item, nodeWidget, e); - this.focusNode(nodeWidget); - } - event.stop(e); - }, - - _onExpandoClick: function(/*Object*/ message){ - // summary: - // User clicked the +/- icon; expand or collapse my children. - var node = message.node; - - // If we are collapsing, we might be hiding the currently focused node. - // Also, clicking the expando node might have erased focus from the current node. - // For simplicity's sake just focus on the node with the expando. - this.focusNode(node); - - if(node.isExpanded){ - this._collapseNode(node); - }else{ - this._expandNode(node); - } - }, - - onClick: function(/*===== item, node, evt =====*/){ - // summary: - // Callback when a tree node is clicked - // item: Object - // Object from the dojo/store corresponding to this TreeNode - // node: TreeNode - // The TreeNode itself - // evt: Event - // The event - // tags: - // callback - }, - onDblClick: function(/*===== item, node, evt =====*/){ - // summary: - // Callback when a tree node is double-clicked - // item: Object - // Object from the dojo/store corresponding to this TreeNode - // node: TreeNode - // The TreeNode itself - // evt: Event - // The event - // tags: - // callback - }, - onOpen: function(/*===== item, node =====*/){ - // summary: - // Callback when a node is opened - // item: dojo/data/Item - // node: TreeNode - // tags: - // callback - }, - onClose: function(/*===== item, node =====*/){ - // summary: - // Callback when a node is closed - // item: Object - // Object from the dojo/store corresponding to this TreeNode - // node: TreeNode - // The TreeNode itself - // tags: - // callback - }, - - _getNextNode: function(node){ - // summary: - // Get next visible node - - if(node.isExpandable && node.isExpanded && node.hasChildren()){ - // if this is an expanded node, get the first child - return node.getChildren()[0]; // TreeNode - }else{ - // find a parent node with a sibling - while(node && node.isTreeNode){ - var returnNode = node.getNextSibling(); - if(returnNode){ - return returnNode; // TreeNode - } - node = node.getParent(); - } - return null; - } - }, - - _getRootOrFirstNode: function(){ - // summary: - // Get first visible node - return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0]; - }, - - _collapseNode: function(/*TreeNode*/ node){ - // summary: - // Called when the user has requested to collapse the node - // returns: - // Deferred that fires when the node is closed - - if(node._expandNodeDeferred){ - delete node._expandNodeDeferred; - } - - if(node.state == "LOADING"){ - // ignore clicks while we are in the process of loading data - return; - } - - if(node.isExpanded){ - var ret = node.collapse(); - - this.onClose(node.item, node); - this._state(node, false); - - this._startPaint(ret); // after this finishes, need to reset widths of TreeNodes - - return ret; - } - }, - - _expandNode: function(/*TreeNode*/ node){ - // summary: - // Called when the user has requested to expand the node - // returns: - // Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants - // that were previously opened too - - // Signal that this call is complete - var def = new Deferred(); - - if(node._expandNodeDeferred){ - // there's already an expand in progress, or completed, so just return - return node._expandNodeDeferred; // dojo/_base/Deferred - } - - var model = this.model, - item = node.item, - _this = this; - - // Load data if it's not already loaded - if(!node._loadDeferred){ - // need to load all the children before expanding - node.markProcessing(); - - // Setup deferred to signal when the load and expand are finished. - // Save that deferred in this._expandDeferred as a flag that operation is in progress. - node._loadDeferred = new Deferred(); - - // Get the children - model.getChildren( - item, - function(items){ - node.unmarkProcessing(); - - // Display the children and also start expanding any children that were previously expanded - // (if this.persist == true). The returned Deferred will fire when those expansions finish. - node.setChildItems(items).then(function(){ - node._loadDeferred.resolve(items); - }); - }, - function(err){ - console.error(_this, ": error loading " + node.label + " children: ", err); - node._loadDeferred.reject(err); - } - ); - } - - // Expand the node after data has loaded - node._loadDeferred.then(lang.hitch(this, function(){ - node.expand().then(function(){ - def.resolve(true); // signal that this _expandNode() call is complete - }); - - // seems like these should be inside of then(), but left here for back-compat about - // when this.isOpen flag gets set (ie, at the beginning of the animation) - this.onOpen(node.item, node); - this._state(node, true); - })); - - this._startPaint(def); // after this finishes, need to reset widths of TreeNodes - - return def; // dojo/_base/Deferred - }, - - ////////////////// Miscellaneous functions //////////////// - - focusNode: function(/* _tree.Node */ node){ - // summary: - // Focus on the specified node (which must be visible) - // tags: - // protected - - // set focus so that the label will be voiced using screen readers - focus.focus(node.labelNode); - }, - - _onNodeFocus: function(/*dijit/_WidgetBase*/ node){ - // summary: - // Called when a TreeNode gets focus, either by user clicking - // it, or programatically by arrow key handling code. - // description: - // It marks that the current node is the selected one, and the previously - // selected node no longer is. - - if(node && node != this.lastFocused){ - if(this.lastFocused && !this.lastFocused._destroyed){ - // mark that the previously focsable node is no longer focusable - this.lastFocused.setFocusable(false); - } - - // mark that the new node is the currently selected one - node.setFocusable(true); - this.lastFocused = node; - } - }, - - _onNodeMouseEnter: function(/*dijit/_WidgetBase*/ /*===== node =====*/){ - // summary: - // Called when mouse is over a node (onmouseenter event), - // this is monitored by the DND code - }, - - _onNodeMouseLeave: function(/*dijit/_WidgetBase*/ /*===== node =====*/){ - // summary: - // Called when mouse leaves a node (onmouseleave event), - // this is monitored by the DND code - }, - - //////////////// Events from the model ////////////////////////// - - _onItemChange: function(/*Item*/ item){ - // summary: - // Processes notification of a change to an item's scalar values like label - var model = this.model, - identity = model.getIdentity(item), - nodes = this._itemNodesMap[identity]; - - if(nodes){ - var label = this.getLabel(item), - tooltip = this.getTooltip(item); - array.forEach(nodes, function(node){ - node.set({ - item: item, // theoretically could be new JS Object representing same item - label: label, - tooltip: tooltip - }); - node._updateItemClasses(item); - }); - } - }, - - _onItemChildrenChange: function(/*dojo/data/Item*/ parent, /*dojo/data/Item[]*/ newChildrenList){ - // summary: - // Processes notification of a change to an item's children - var model = this.model, - identity = model.getIdentity(parent), - parentNodes = this._itemNodesMap[identity]; - - if(parentNodes){ - array.forEach(parentNodes,function(parentNode){ - parentNode.setChildItems(newChildrenList); - }); - } - }, - - _onItemDelete: function(/*Item*/ item){ - // summary: - // Processes notification of a deletion of an item. - // Not called from new dojo.store interface but there's cleanup code in setChildItems() instead. - - var model = this.model, - identity = model.getIdentity(item), - nodes = this._itemNodesMap[identity]; - - if(nodes){ - array.forEach(nodes,function(node){ - // Remove node from set of selected nodes (if it's selected) - this.dndController.removeTreeNode(node); - - var parent = node.getParent(); - if(parent){ - // if node has not already been orphaned from a _onSetItem(parent, "children", ..) call... - parent.removeChild(node); - } - node.destroyRecursive(); - }, this); - delete this._itemNodesMap[identity]; - } - }, - - /////////////// Miscellaneous funcs - - _initState: function(){ - // summary: - // Load in which nodes should be opened automatically - this._openedNodes = {}; - if(this.persist && this.cookieName){ - var oreo = cookie(this.cookieName); - if(oreo){ - array.forEach(oreo.split(','), function(item){ - this._openedNodes[item] = true; - }, this); - } - } - }, - _state: function(node, expanded){ - // summary: - // Query or set expanded state for an node - if(!this.persist){ - return false; - } - var path = array.map(node.getTreePath(), function(item){ - return this.model.getIdentity(item); - }, this).join("/"); - if(arguments.length === 1){ - return this._openedNodes[path]; - }else{ - if(expanded){ - this._openedNodes[path] = true; - }else{ - delete this._openedNodes[path]; - } - if(this.persist && this.cookieName){ - var ary = []; - for(var id in this._openedNodes){ - ary.push(id); - } - cookie(this.cookieName, ary.join(","), {expires:365}); - } - } - }, - - destroy: function(){ - if(this._curSearch){ - this._curSearch.timer.remove(); - delete this._curSearch; - } - if(this.rootNode){ - this.rootNode.destroyRecursive(); - } - if(this.dndController && !lang.isString(this.dndController)){ - this.dndController.destroy(); - } - this.rootNode = null; - this.inherited(arguments); - }, - - destroyRecursive: function(){ - // A tree is treated as a leaf, not as a node with children (like a grid), - // but defining destroyRecursive for back-compat. - this.destroy(); - }, - - resize: function(changeSize){ - if(changeSize){ - domGeometry.setMarginBox(this.domNode, changeSize); - } - - // The main JS sizing involved w/tree is the indentation, which is specified - // in CSS and read in through this dummy indentDetector node (tree must be - // visible and attached to the DOM to read this). - // If the Tree is hidden domGeometry.position(this.tree.indentDetector).w will return 0, in which case just - // keep the default value. - this._nodePixelIndent = domGeometry.position(this.tree.indentDetector).w || this._nodePixelIndent; - - // resize() may be called before this.rootNode is created, so wait until it's available - this.expandChildrenDeferred.then(lang.hitch(this, function(){ - // If tree has already loaded, then reset indent for all the nodes - this.rootNode.set('indent', this.showRoot ? 0 : -1); - - // Also, adjust widths of all rows to match width of Tree - this._adjustWidths(); - })); - }, - - _outstandingPaintOperations: 0, - _startPaint: function(/*Promise|Boolean*/ p){ - // summary: - // Called at the start of an operation that will change what's displayed. - // p: - // Promise that tells when the operation will complete. Alternately, if it's just a Boolean, it signifies - // that the operation was synchronous, and already completed. - - this._outstandingPaintOperations++; - if(this._adjustWidthsTimer){ - this._adjustWidthsTimer.remove(); - delete this._adjustWidthsTimer; - } - - var oc = lang.hitch(this, function(){ - this._outstandingPaintOperations--; - - if(this._outstandingPaintOperations <= 0 && !this._adjustWidthsTimer && this._started){ - // Use defer() to avoid a width adjustment when another operation will immediately follow, - // such as a sequence of opening a node, then it's children, then it's grandchildren, etc. - this._adjustWidthsTimer = this.defer("_adjustWidths"); - } - }); - when(p, oc, oc); - }, - - _adjustWidths: function(){ - // summary: - // Get width of widest TreeNode, or the width of the Tree itself, whichever is greater, - // and then set all TreeNodes to that width, so that selection/hover highlighting - // extends to the edge of the Tree (#13141) - - if(this._adjustWidthsTimer){ - this._adjustWidthsTimer.remove(); - delete this._adjustWidthsTimer; - } - - var maxWidth = 0, - nodes = []; - function collect(/*TreeNode*/ parent){ - var node = parent.rowNode; - node.style.width = "auto"; // erase setting from previous run - maxWidth = Math.max(maxWidth, node.clientWidth); - nodes.push(node); - if(parent.isExpanded){ - array.forEach(parent.getChildren(), collect); - } - } - collect(this.rootNode); - maxWidth = Math.max(maxWidth, domGeometry.getContentBox(this.domNode).w); // do after node.style.width="auto" - array.forEach(nodes, function(node){ - node.style.width = maxWidth + "px"; // assumes no horizontal padding, border, or margin on rowNode - }); - }, - - _createTreeNode: function(/*Object*/ args){ - // summary: - // creates a TreeNode - // description: - // Developers can override this method to define their own TreeNode class; - // However it will probably be removed in a future release in favor of a way - // of just specifying a widget for the label, rather than one that contains - // the children too. - return new TreeNode(args); - }, - - _setTextDirAttr: function(textDir){ - if(textDir && this.textDir!= textDir){ - this._set("textDir",textDir); - this.rootNode.set("textDir", textDir); - } - } -}); - -Tree.PathError = createError("TreePathError"); -Tree._TreeNode = TreeNode; // for monkey patching or creating subclasses of TreeNode - -return Tree; -}); - -}, -'dijit/form/_FormValueWidget':function(){ -define("dijit/form/_FormValueWidget", [ - "dojo/_base/declare", // declare - "dojo/sniff", // has("ie") - "./_FormWidget", - "./_FormValueMixin" -], function(declare, has, _FormWidget, _FormValueMixin){ - -// module: -// dijit/form/_FormValueWidget - -return declare("dijit.form._FormValueWidget", [_FormWidget, _FormValueMixin], -{ - // summary: - // Base class for widgets corresponding to native HTML elements such as `<input>` or `<select>` - // that have user changeable values. - // description: - // Each _FormValueWidget represents a single input value, and has a (possibly hidden) `<input>` element, - // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?) - // works as expected. - - // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared - // directly in the template as read by the parser in order to function. IE is known to specifically - // require the 'name' attribute at element creation time. See #8484, #8660. - - _layoutHackIE7: function(){ - // summary: - // Work around table sizing bugs on IE7 by forcing redraw - - if(has("ie") == 7){ // fix IE7 layout bug when the widget is scrolled out of sight - var domNode = this.domNode; - var parent = domNode.parentNode; - var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter - var origFilter = pingNode.style.filter; // save custom filter, most likely nothing - var _this = this; - while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet - (function ping(){ - var disconnectHandle = _this.connect(parent, "onscroll", - function(){ - _this.disconnect(disconnectHandle); // only call once - pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique - _this.defer(function(){ pingNode.style.filter = origFilter; }); // restore custom filter, if any - } - ); - })(); - parent = parent.parentNode; - } - } - } -}); - -}); - -}, -'*now':function(r){r(['dojo/i18n!*preload*dojo/nls/tt-rss-layer*["ar","ca","cs","da","de","el","en-gb","en-us","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn","ROOT"]']);} -}}); -define("dojo/tt-rss-layer", [], 1); |