diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/dijit.js.uncompressed.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/dijit.js.uncompressed.js')
-rw-r--r-- | lib/dijit/dijit.js.uncompressed.js | 5961 |
1 files changed, 0 insertions, 5961 deletions
diff --git a/lib/dijit/dijit.js.uncompressed.js b/lib/dijit/dijit.js.uncompressed.js deleted file mode 100644 index 076a03208..000000000 --- a/lib/dijit/dijit.js.uncompressed.js +++ /dev/null @@ -1,5961 +0,0 @@ -/* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. - Available via Academic Free License >= 2.1 OR the modified BSD license. - see: http://dojotoolkit.org/license for details -*/ - -/* - This is an optimized version of Dojo, built for deployment and not for - development. To get sources and documentation, please visit: - - http://dojotoolkit.org -*/ - -if(!dojo._hasResource["dojo.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.window"] = true; -dojo.provide("dojo.window"); - -dojo.window.getBox = function(){ - // summary: - // Returns the dimensions and scroll position of the viewable area of a browser window - - var scrollRoot = (dojo.doc.compatMode == 'BackCompat') ? dojo.body() : dojo.doc.documentElement; - - // get scroll position - var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work - return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y }; -}; - -dojo.window.get = function(doc){ - // summary: - // Get window object associated with document doc - - // 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(dojo.isIE && 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 -}; - -dojo.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 = dojo.byId(node); - var doc = node.ownerDocument || dojo.doc, - body = doc.body || dojo.body(), - html = doc.documentElement || body.parentNode, - isIE = dojo.isIE, isWK = dojo.isWebKit; - // if an untested browser, then use the native method - if((!(dojo.isMoz || isIE || isWK || dojo.isOpera) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){ - node.scrollIntoView(false); // short-circuit to native if possible - return; - } - var backCompat = doc.compatMode == 'BackCompat', - clientAreaRoot = backCompat? body : html, - scrollRoot = isWK ? body : clientAreaRoot, - rootWidth = clientAreaRoot.clientWidth, - rootHeight = clientAreaRoot.clientHeight, - rtl = !dojo._isBodyLtr(), - nodePos = pos || dojo.position(node), - el = node.parentNode, - isFixed = function(el){ - return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed")); - }; - if(isFixed(node)){ return; } // nothing to do - - while(el){ - if(el == body){ el = scrollRoot; } - var elPos = dojo.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 = dojo._getPadBorderExtents(el); - elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; - } - - if(el != scrollRoot){ // body, html sizes already have the scrollbar removed - var clientSize = el.clientWidth, - scrollBarSize = elPos.w - clientSize; - if(clientSize > 0 && scrollBarSize > 0){ - elPos.w = clientSize; - if(isIE && rtl){ elPos.x += scrollBarSize; } - } - 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); - nodePos.x += el.scrollLeft; - el.scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : 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); - } -}; - -} - -if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.manager"] = true; -dojo.provide("dijit._base.manager"); - -dojo.declare("dijit.WidgetSet", null, { - // summary: - // A set of widgets indexed by id. A default instance of this class is - // available as `dijit.registry` - // - // example: - // Create a small list of widgets: - // | var ws = new dijit.WidgetSet(); - // | ws.add(dijit.byId("one")); - // | ws.add(dijit.byId("two")); - // | // destroy both: - // | ws.forEach(function(w){ w.destroy(); }); - // - // example: - // Using dijit.registry: - // | dijit.registry.forEach(function(w){ /* do something */ }); - - constructor: function(){ - this._hash = {}; - this.length = 0; - }, - - add: function(/*dijit._Widget*/ widget){ - // summary: - // Add a widget to this list. If a duplicate ID is detected, a error is thrown. - // - // widget: dijit._Widget - // Any dijit._Widget 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 `dojo.forEach`. - // - // thisObj: - // An optional scope parameter - // - // example: - // Using the default `dijit.registry` instance: - // | dijit.registry.forEach(function(widget){ - // | console.log(widget.declaredClass); - // | }); - // - // returns: - // Returns self, in order to allow for further chaining. - - thisObj = thisObj || dojo.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 `dojo.filter` and `dojo.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 - // | dijit.registry.filter(function(w, i){ - // | return i % 2 == 0; - // | }).forEach(function(w){ /* odd ones */ }); - - thisObj = thisObj || dojo.global; - var res = new dijit.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 - // | var ws = new dijit.WidgetSet(); - // | ws.add(dijit.byId("bar")); - // | var t = ws.byId("bar") // returns a widget - // | var x = ws.byId("foo"); // returns undefined - - return this._hash[id]; // dijit._Widget - }, - - 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: - // | dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); }); - - var res = new dijit.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 - // | dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; }); - - var ar = []; - for(var id in this._hash){ - ar.push(this._hash[id]); - } - return ar; // dijit._Widget[] -}, - - map: function(/* Function */func, /* Object? */thisObj){ - // summary: - // Create a new Array from this WidgetSet, following the same rules as `dojo.map` - // example: - // | var nodes = dijit.registry.map(function(w){ return w.domNode; }); - // - // returns: - // A new array of the returned values. - return dojo.map(this.toArray(), func, thisObj); // Array - }, - - every: function(func, thisObj){ - // summary: - // A synthetic clone of `dojo.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 || dojo.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 `dojo.some` acting explictly 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 || dojo.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 - } - -}); - -(function(){ - - /*===== - dijit.registry = { - // summary: - // A list of widgets on a page. - // description: - // Is an instance of `dijit.WidgetSet` - }; - =====*/ - dijit.registry = new dijit.WidgetSet(); - - var hash = dijit.registry._hash, - attr = dojo.attr, - hasAttr = dojo.hasAttr, - style = dojo.style; - - dijit.byId = function(/*String|dijit._Widget*/ id){ - // summary: - // Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId()) - return typeof id == "string" ? hash[id] : id; // dijit._Widget - }; - - var _widgetTypeCtr = {}; - dijit.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 - }; - - dijit.findWidgets = function(/*DomNode*/ root){ - // summary: - // Search subtree under root returning widgets found. - // Doesn't search for nested widgets (ie, widgets inside other widgets). - - 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){ - outAry.push(hash[widgetId]); - }else{ - getChildrenHelper(node); - } - } - } - } - - getChildrenHelper(root); - return outAry; - }; - - dijit._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 - dojo.forEach(dijit.findWidgets(dojo.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(); - } - } - }); - }; - - if(dojo.isIE){ - // Only run _destroyAll() for IE because we think it's only necessary in that case, - // and because it causes problems on FF. See bug #3531 for details. - dojo.addOnWindowUnload(function(){ - dijit._destroyAll(); - }); - } - - dijit.byNode = function(/*DOMNode*/ node){ - // summary: - // Returns the widget corresponding to the given DOMNode - return hash[node.getAttribute("widgetId")]; // dijit._Widget - }; - - dijit.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.getAttribute && node.getAttribute("widgetId"); - if(id){ - return hash[id]; - } - node = node.parentNode; - } - return null; - }; - - var shown = (dijit._isElementShown = function(/*Element*/ elem){ - var s = style(elem); - return (s.visibility != "hidden") - && (s.visibility != "collapsed") - && (s.display != "none") - && (attr(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 hasAttr(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. - //TODO: feature detect "designMode" in elem.contentDocument? - if(dojo.isMoz){ - try{ - return elem.contentDocument.designMode == "on"; - }catch(err){ - return false; - } - }else if(dojo.isWebKit){ - var doc = elem.contentDocument, - body = doc && doc.body; - return body && body.contentEditable == 'true'; - }else{ - // 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{ - doc = elem.contentWindow.document; - body = doc && doc.body; - return body && body.firstChild && body.firstChild.contentEditable == 'true'; - }catch(e){ - return false; - } - } - 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(attr(elem, "disabled")){ - return false; - }else if(hasAttr(elem, "tabIndex")){ - // Explicit tab index setting - return attr(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; - var walkTree = function(/*DOMNode*/parent){ - dojo.query("> *", parent).forEach(function(child){ - // Skip 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((dojo.isIE && child.scopeName!=="HTML") || !shown(child)){ - return; - } - - if(isTabNavigable(child)){ - var tabindex = attr(child, "tabIndex"); - if(!hasAttr(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; - } - } - } - if(child.nodeName.toUpperCase() != 'SELECT'){ - walkTree(child); - } - }); - }; - if(shown(root)){ walkTree(root) } - return { first: first, last: last, lowest: lowest, highest: highest }; - } - dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){ - // summary: - // Finds the descendant of the specified root node - // that is first in the tabbing order - var elems = dijit._getTabNavigable(dojo.byId(root)); - return elems.lowest ? elems.lowest : elems.first; // DomNode - }; - - dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){ - // summary: - // Finds the descendant of the specified root node - // that is last in the tabbing order - var elems = dijit._getTabNavigable(dojo.byId(root)); - return elems.last ? elems.last : elems.highest; // DomNode - }; - - /*===== - dojo.mixin(dijit, { - // defaultDuration: Integer - // The default animation speed (in ms) to use for all Dijit - // transitional animations, unless otherwise specified - // on a per-instance basis. Defaults to 200, overrided by - // `djConfig.defaultDuration` - defaultDuration: 200 - }); - =====*/ - - dijit.defaultDuration = dojo.config["defaultDuration"] || 200; - -})(); - -} - -if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.focus"] = true; -dojo.provide("dijit._base.focus"); - - - // for dijit.isTabNavigable() - -// summary: -// These functions are used to query or set the focus and selection. -// -// Also, they trace when widgets become activated/deactivated, -// so that the widget can fire _onFocus/_onBlur events. -// "Active" here means something similar to "focused", but -// "focus" isn't quite the right word because we keep track of -// a whole stack of "active" widgets. Example: ComboButton --> Menu --> -// MenuItem. The onBlur event for ComboButton doesn't fire due to focusing -// on the Menu or a MenuItem, since they are considered part of the -// ComboButton widget. It only happens when focus is shifted -// somewhere completely different. - -dojo.mixin(dijit, { - // _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 = dojo.doc.selection, cf = dijit._curFocus; - - if(dojo.global.getSelection){ - //W3C Range API for selections. - sel = dojo.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}; - }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 = dojo.doc, - mark = bookmark.mark; - if(mark){ - if(dojo.global.getSelection){ - //W3C Rangi API (FF, WebKit, Opera, etc) - var sel = dojo.global.getSelection(); - if(sel && sel.removeAllRanges){ - if(mark.pRange){ - var r = mark; - var n = r.node; - n.selectionStart = r.start; - n.selectionEnd = r.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(dojo.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 - dojo.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._Widget or {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 = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus; - return { - node: node, - bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark), - openedForWindow: openedForWindow - }; // Object - }, - - 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*/} - } - dijit._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 && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){ - if(openedForWindow){ - openedForWindow.focus(); - } - try{ - dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]); - }catch(e2){ - /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */ - } - } - }, - - // _activeStack: dijit._Widget[] - // 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 dijit.registerWin(iframe.contentWindow, 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() - - dijit.unregisterWin(handle); - }, - - 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() - - // TODO: make this function private in 2.0; Editor/users should call registerIframe(), - - var mousedownListener = function(evt){ - dijit._justMouseDowned = true; - setTimeout(function(){ dijit._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(dojo.isIE && evt && evt.srcElement && evt.srcElement.parentNode == null){ - return; - } - - dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse"); - }; - //dojo.connect(targetWindow, "onscroll", ???); - - // Listen for blur and focus events on targetWindow's document. - // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble - // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers - // fire. - // 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 = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document; - if(doc){ - if(dojo.isIE){ - doc.attachEvent('onmousedown', mousedownListener); - var activateListener = function(evt){ - // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1, - // Should consider those more like a mouse-click than a focus.... - if(evt.srcElement.tagName.toLowerCase() != "#document" && - dijit.isTabNavigable(evt.srcElement)){ - dijit._onFocusNode(effectiveNode || evt.srcElement); - }else{ - dijit._onTouchNode(effectiveNode || evt.srcElement); - } - }; - doc.attachEvent('onactivate', activateListener); - var deactivateListener = function(evt){ - dijit._onBlurNode(effectiveNode || evt.srcElement); - }; - doc.attachEvent('ondeactivate', deactivateListener); - - return function(){ - doc.detachEvent('onmousedown', mousedownListener); - doc.detachEvent('onactivate', activateListener); - doc.detachEvent('ondeactivate', deactivateListener); - doc = null; // prevent memory leak (apparent circular reference via closure) - }; - }else{ - doc.addEventListener('mousedown', mousedownListener, true); - var focusListener = function(evt){ - dijit._onFocusNode(effectiveNode || evt.target); - }; - doc.addEventListener('focus', focusListener, true); - var blurListener = function(evt){ - dijit._onBlurNode(effectiveNode || evt.target); - }; - doc.addEventListener('blur', blurListener, true); - - return function(){ - doc.removeEventListener('mousedown', mousedownListener, true); - doc.removeEventListener('focus', focusListener, true); - doc.removeEventListener('blur', blurListener, true); - doc = null; // prevent memory leak (apparent circular reference via closure) - }; - } - } - }, - - 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. - - // Currently our handle is actually a function - handle && handle(); - }, - - _onBlurNode: function(/*DomNode*/ node){ - // summary: - // Called when focus leaves a node. - // Usually ignored, _unless_ it *isn't* follwed by touching another node, - // which indicates that we tabbed off the last field on the page, - // in which case every widget is marked inactive - dijit._prevFocus = dijit._curFocus; - dijit._curFocus = null; - - if(dijit._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 event then mark all widgets as inactive. - if(dijit._clearActiveWidgetsTimer){ - clearTimeout(dijit._clearActiveWidgetsTimer); - } - dijit._clearActiveWidgetsTimer = setTimeout(function(){ - delete dijit._clearActiveWidgetsTimer; - dijit._setStack([]); - dijit._prevFocus = null; - }, 100); - }, - - _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(dijit._clearActiveWidgetsTimer){ - clearTimeout(dijit._clearActiveWidgetsTimer); - delete dijit._clearActiveWidgetsTimer; - } - - // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem) - var newStack=[]; - try{ - while(node){ - var popupParent = dojo.attr(node, "dijitPopupParent"); - if(popupParent){ - node=dijit.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 === dojo.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=dojo.window.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 && dijit.byId(id); - if(widget && !(by == "mouse" && widget.get("disabled"))){ - newStack.unshift(id); - } - node=node.parentNode; - } - } - }catch(e){ /* squelch */ } - - dijit._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; - } - - dijit._onTouchNode(node); - - if(node == dijit._curFocus){ return; } - if(dijit._curFocus){ - dijit._prevFocus = dijit._curFocus; - } - dijit._curFocus = node; - dojo.publish("focusNode", [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 = dijit._activeStack; - dijit._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, send blur event - for(var i=oldStack.length-1; i>=nCommon; i--){ - widget = dijit.byId(oldStack[i]); - if(widget){ - widget._focused = false; - widget._hasBeenBlurred = true; - if(widget._onBlur){ - widget._onBlur(by); - } - dojo.publish("widgetBlur", [widget, by]); - } - } - - // for all element that have come into focus, send focus event - for(i=nCommon; i<newStack.length; i++){ - widget = dijit.byId(newStack[i]); - if(widget){ - widget._focused = true; - if(widget._onFocus){ - widget._onFocus(by); - } - dojo.publish("widgetFocus", [widget, by]); - } - } - } -}); - -// register top window and all the iframes it contains -dojo.addOnLoad(function(){ - var handle = dijit.registerWin(window); - if(dojo.isIE){ - dojo.addOnWindowUnload(function(){ - dijit.unregisterWin(handle); - handle = null; - }) - } -}); - -} - -if(!dojo._hasResource["dojo.AdapterRegistry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.AdapterRegistry"] = true; -dojo.provide("dojo.AdapterRegistry"); - -dojo.AdapterRegistry = function(/*Boolean?*/ returnWrappers){ - // summary: - // A registry to make contextual calling/searching easier. - // description: - // Objects of this class keep list of arrays in the form [name, check, - // wrap, directReturn] that are used to determine what the contextual - // result of a set of checked arguments is. All check/wrap functions - // in this registry should be of the same arity. - // example: - // | // create a new registry - // | var reg = new dojo.AdapterRegistry(); - // | reg.register("handleString", - // | dojo.isString, - // | function(str){ - // | // do something with the string here - // | } - // | ); - // | reg.register("handleArr", - // | dojo.isArray, - // | function(arr){ - // | // do something with the array here - // | } - // | ); - // | - // | // now we can pass reg.match() *either* an array or a string and - // | // the value we pass will get handled by the right function - // | reg.match("someValue"); // will call the first function - // | reg.match(["someValue"]); // will call the second - - this.pairs = []; - this.returnWrappers = returnWrappers || false; // Boolean -} - -dojo.extend(dojo.AdapterRegistry, { - register: function(/*String*/ name, /*Function*/ check, /*Function*/ wrap, /*Boolean?*/ directReturn, /*Boolean?*/ override){ - // summary: - // register a check function to determine if the wrap function or - // object gets selected - // name: - // a way to identify this matcher. - // check: - // a function that arguments are passed to from the adapter's - // match() function. The check function should return true if the - // given arguments are appropriate for the wrap function. - // directReturn: - // If directReturn is true, the value passed in for wrap will be - // returned instead of being called. Alternately, the - // AdapterRegistry can be set globally to "return not call" using - // the returnWrappers property. Either way, this behavior allows - // the registry to act as a "search" function instead of a - // function interception library. - // override: - // If override is given and true, the check function will be given - // highest priority. Otherwise, it will be the lowest priority - // adapter. - this.pairs[((override) ? "unshift" : "push")]([name, check, wrap, directReturn]); - }, - - match: function(/* ... */){ - // summary: - // Find an adapter for the given arguments. If no suitable adapter - // is found, throws an exception. match() accepts any number of - // arguments, all of which are passed to all matching functions - // from the registered pairs. - for(var i = 0; i < this.pairs.length; i++){ - var pair = this.pairs[i]; - if(pair[1].apply(this, arguments)){ - if((pair[3])||(this.returnWrappers)){ - return pair[2]; - }else{ - return pair[2].apply(this, arguments); - } - } - } - throw new Error("No match found"); - }, - - unregister: function(name){ - // summary: Remove a named adapter from the registry - - // FIXME: this is kind of a dumb way to handle this. On a large - // registry this will be slow-ish and we can use the name as a lookup - // should we choose to trade memory for speed. - for(var i = 0; i < this.pairs.length; i++){ - var pair = this.pairs[i]; - if(pair[0] == name){ - this.pairs.splice(i, 1); - return true; - } - } - return false; - } -}); - -} - -if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.place"] = true; -dojo.provide("dijit._base.place"); - - - - - -dijit.getViewport = function(){ - // summary: - // Returns the dimensions and scroll position of the viewable area of a browser window - - return dojo.window.getBox(); -}; - -/*===== -dijit.__Position = function(){ - // x: Integer - // horizontal coordinate in pixels, relative to document body - // y: Integer - // vertical coordinate in pixels, relative to document body - - thix.x = x; - this.y = y; -} -=====*/ - - -dijit.placeOnScreen = function( - /* DomNode */ node, - /* dijit.__Position */ pos, - /* String[] */ corners, - /* dijit.__Position? */ 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. - // pos: - // Object like {x: 10, y: 20} - // corners: - // 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: - // 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). - // | placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"]) - - var choices = dojo.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 dijit._place(node, choices); -} - -dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){ - // 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) - // 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. - - // get {x: 10, y: 10, w: 100, h:100} type obj representing position of - // viewport over document - var view = dojo.window.getBox(); - - // This won't work if the node is inside a <div style="position: relative">, - // so reattach it to dojo.doc.body. (Otherwise, the positioning will be wrong - // and also it might get cutoff) - if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){ - dojo.body().appendChild(node); - } - - var best = null; - dojo.some(choices, function(choice){ - var corner = choice.corner; - var pos = choice.pos; - - // 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 tooltips size changes based on position, due to triangle) - if(layoutNode){ - layoutNode(node, choice.aroundCorner, corner); - } - - // get node's size - var style = node.style; - var oldDisplay = style.display; - var oldVis = style.visibility; - style.visibility = "hidden"; - style.display = ""; - var mb = dojo.marginBox(node); - style.display = oldDisplay; - style.visibility = oldVis; - - // coordinates and size of node with specified corner placed at pos, - // and clipped by viewport - var startX = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)), - startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)), - endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x), - endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (startY + mb.h) : pos.y), - width = endX - startX, - height = endY - startY, - overflow = (mb.w - width) + (mb.h - height); - - if(best == null || overflow < best.overflow){ - best = { - corner: corner, - aroundCorner: choice.aroundCorner, - x: startX, - y: startY, - w: width, - h: height, - overflow: overflow - }; - } - return !overflow; - }); - - node.style.left = best.x + "px"; - node.style.top = best.y + "px"; - if(best.overflow && layoutNode){ - layoutNode(node, best.aroundCorner, best.corner); - } - return best; -} - -dijit.placeOnScreenAroundNode = function( - /* DomNode */ node, - /* DomNode */ aroundNode, - /* Object */ aroundCorners, - /* Function? */ layoutNode){ - - // summary: - // Position node adjacent or kitty-corner to aroundNode - // 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. - // - // aroundCorners: - // Ordered list of pairs of corners to try matching up. - // Each pair of corners is represented as a key/value in the hash, - // where the key corresponds to the aroundNode's corner, and - // the value corresponds to the node's corner: - // - // | { aroundNodeCorner1: nodeCorner1, aroundNodeCorner2: nodeCorner2, ...} - // - // The following strings are used to represent the four corners: - // * "BL" - bottom left - // * "BR" - bottom right - // * "TL" - top left - // * "TR" - top right - // - // 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. - // - // example: - // | dijit.placeOnScreenAroundNode(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) - // - - // get coordinates of aroundNode - aroundNode = dojo.byId(aroundNode); - var oldDisplay = aroundNode.style.display; - aroundNode.style.display=""; - // #3172: use the slightly tighter border box instead of marginBox - var aroundNodePos = dojo.position(aroundNode, true); - aroundNode.style.display=oldDisplay; - - // place the node around the calculated rectangle - return dijit._placeOnScreenAroundRect(node, - aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h, // rectangle - aroundCorners, layoutNode); -}; - -/*===== -dijit.__Rectangle = function(){ - // x: Integer - // horizontal offset in pixels, relative to document body - // y: Integer - // vertical offset in pixels, relative to document body - // width: Integer - // width in pixels - // height: Integer - // height in pixels - - this.x = x; - this.y = y; - this.width = width; - this.height = height; -} -=====*/ - - -dijit.placeOnScreenAroundRectangle = function( - /* DomNode */ node, - /* dijit.__Rectangle */ aroundRect, - /* Object */ aroundCorners, - /* Function */ 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. - - return dijit._placeOnScreenAroundRect(node, - aroundRect.x, aroundRect.y, aroundRect.width, aroundRect.height, // rectangle - aroundCorners, layoutNode); -}; - -dijit._placeOnScreenAroundRect = function( - /* DomNode */ node, - /* Number */ x, - /* Number */ y, - /* Number */ width, - /* Number */ height, - /* Object */ aroundCorners, - /* Function */ layoutNode){ - - // summary: - // Like dijit.placeOnScreenAroundNode(), except it accepts coordinates - // of a rectangle to place node adjacent to. - - // TODO: combine with placeOnScreenAroundRectangle() - - // Generate list of possible positions for node - var choices = []; - for(var nodeCorner in aroundCorners){ - choices.push( { - aroundCorner: nodeCorner, - corner: aroundCorners[nodeCorner], - pos: { - x: x + (nodeCorner.charAt(1) == 'L' ? 0 : width), - y: y + (nodeCorner.charAt(0) == 'T' ? 0 : height) - } - }); - } - - return dijit._place(node, choices, layoutNode); -}; - -dijit.placementRegistry= new dojo.AdapterRegistry(); -dijit.placementRegistry.register("node", - function(n, x){ - return typeof x == "object" && - typeof x.offsetWidth != "undefined" && typeof x.offsetHeight != "undefined"; - }, - dijit.placeOnScreenAroundNode); -dijit.placementRegistry.register("rect", - function(n, x){ - return typeof x == "object" && - "x" in x && "y" in x && "width" in x && "height" in x; - }, - dijit.placeOnScreenAroundRectangle); - -dijit.placeOnScreenAroundElement = function( - /* DomNode */ node, - /* Object */ aroundElement, - /* Object */ aroundCorners, - /* Function */ layoutNode){ - - // summary: - // Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object - // for the "around" argument and finds a proper processor to place a node. - - return dijit.placementRegistry.match.apply(dijit.placementRegistry, arguments); -}; - -dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){ - // summary: - // Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.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 = {}; - dojo.forEach(position, function(pos){ - switch(pos){ - case "after": - align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR"; - break; - case "before": - align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL"; - break; - case "below": - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR"; - align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL"; - break; - case "above": - default: - // first try to align left borders, next try to align right borders (or reverse for RTL mode) - align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR"; - align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL"; - break; - } - }); - return align; -}; - -} - -if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.window"] = true; -dojo.provide("dijit._base.window"); - - - -dijit.getDocumentWindow = function(doc){ - return dojo.window.get(doc); -}; - -} - -if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.popup"] = true; -dojo.provide("dijit._base.popup"); - - - - - -/*===== -dijit.popup.__OpenArgs = function(){ - // 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 an - // ordered list of tuples of the form (around-node-corner, popup-node-corner). - // dijit.popup.open() tries to position the popup according to each tuple in the list, in order, - // until the popup appears fully within the viewport. - // - // The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples: - // 1. (BL, TL) - // 2. (TL, BL) - // where BL means "bottom left" and "TL" means "top left". - // So by default, it first tries putting the popup below the around node, left-aligning them, - // and then tries to put it above the around node, still left-aligning them. Note that the - // default is horizontally reversed when in RTL mode. - // - // 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: dijit.__Position - // adding a buffer around the opening position. This is only useful when around is not set. - this.popup = popup; - this.parent = parent; - this.around = around; - this.x = x; - this.y = y; - this.orient = orient; - this.onCancel = onCancel; - this.onClose = onClose; - this.onExecute = onExecute; - this.padding = padding; -} -=====*/ - -dijit.popup = { - // summary: - // This singleton is used to show/hide widgets as popups. - - // _stack: dijit._Widget[] - // 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, - - moveOffScreen: function(/*DomNode*/ node){ - // summary: - // Initialization for nodes that will be used as popups - // - // description: - // Puts node inside a wrapper <div>, and - // positions wrapper div off screen, but not display:none, so that - // the widget doesn't appear in the page flow and/or cause a blank - // area at the bottom of the viewport (making scrollbar longer), but - // initialization of contained widgets works correctly - - var wrapper = node.parentNode; - - // Create a wrapper widget for when this node (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 - if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){ - wrapper = dojo.create("div",{ - "class":"dijitPopup", - style:{ - visibility:"hidden", - top: "-9999px" - } - }, dojo.body()); - dijit.setWaiRole(wrapper, "presentation"); - wrapper.appendChild(node); - } - - - var s = node.style; - s.display = ""; - s.visibility = ""; - s.position = ""; - s.top = "0px"; - - dojo.style(wrapper, { - visibility: "hidden", - // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111) - top: "-9999px" - }); - }, - - 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(/*dijit.popup.__OpenArgs*/ args){ - // summary: - // Popup the widget at the specified position - // - // example: - // opening at the mouse position - // | dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY}); - // - // example: - // opening the widget as a dropdown - // | dijit.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 || ( - (args.parent ? args.parent.isLeftToRight() : dojo._isBodyLtr()) ? - {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} : - {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'} - ), - around = args.around, - id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++); - - - // The wrapper may have already been created, but in case it wasn't, create here - var wrapper = widget.domNode.parentNode; - if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){ - this.moveOffScreen(widget.domNode); - wrapper = widget.domNode.parentNode; - } - - dojo.attr(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(dojo.isIE || dojo.isMoz){ - var iframe = wrapper.childNodes[1]; - if(!iframe){ - iframe = new dijit.BackgroundIframe(wrapper); - } - } - - // position the wrapper node and make it visible - var best = around ? - dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) : - dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding); - - 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(dojo.connect(wrapper, "onkeypress", this, function(evt){ - if(evt.charOrCode == dojo.keys.ESCAPE && args.onCancel){ - dojo.stopEvent(evt); - args.onCancel(); - }else if(evt.charOrCode === dojo.keys.TAB){ - dojo.stopEvent(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){ - handlers.push(dojo.connect(widget, "onCancel", args.onCancel)); - } - - handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", this, function(){ - var topPopup = this.getTopPopup(); - if(topPopup && topPopup.onExecute){ - topPopup.onExecute(); - } - })); - - stack.push({ - wrapper: wrapper, - iframe: iframe, - 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(/*dijit._Widget*/ popup){ - // summary: - // Close specified popup and any popups that it parented - - 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(dojo.some(stack, function(elem){return elem.widget == popup;})){ - var top = stack.pop(), - wrapper = top.wrapper, - iframe = top.iframe, - widget = top.widget, - onClose = top.onClose; - - if(widget.onClose){ - // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here) - widget.onClose(); - } - dojo.forEach(top.handlers, dojo.disconnect); - - // Move the widget plus it's wrapper off screen, unless it has already been destroyed in above onClose() etc. - if(widget && widget.domNode){ - this.moveOffScreen(widget.domNode); - }else{ - dojo.destroy(wrapper); - } - - if(onClose){ - onClose(); - } - } - } -}; - -dijit._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(dojo.isIE){ - var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"") || "javascript:\"\""; - var html="<iframe src='" + burl + "'" - + " style='position: absolute; left: 0px; top: 0px;" - + "z-index: -1; filter:Alpha(Opacity=\"0\");'>"; - iframe = dojo.doc.createElement(html); - }else{ - iframe = dojo.create("iframe"); - iframe.src = 'javascript:""'; - iframe.className = "dijitBackgroundIframe"; - dojo.style(iframe, "opacity", 0.1); - } - iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work. - dijit.setWaiRole(iframe,"presentation"); - } - 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(dojo.isIE || dojo.isMoz){ - var iframe = dijit._frames.pop(); - node.appendChild(iframe); - if(dojo.isIE<7){ - this.resize(node); - this._conn = dojo.connect(node, 'onresize', this, function(){ - this.resize(node); - }); - }else{ - dojo.style(iframe, { - width: '100%', - height: '100%' - }); - } - this.iframe = iframe; - } -}; - -dojo.extend(dijit.BackgroundIframe, { - resize: function(node){ - // summary: - // resize the iframe so its the same size as node - // description: - // this function is a no-op in all browsers except - // IE6, which does not support 100% width/height - // of absolute positioned iframes - if(this.iframe && dojo.isIE<7){ - dojo.style(this.iframe, { - width: node.offsetWidth + 'px', - height: node.offsetHeight + 'px' - }); - } - }, - destroy: function(){ - // summary: - // destroy the iframe - if(this._conn){ - dojo.disconnect(this._conn); - this._conn = null; - } - if(this.iframe){ - dijit._frames.push(this.iframe); - delete this.iframe; - } - } -}); - -} - -if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.scroll"] = true; -dojo.provide("dijit._base.scroll"); - - - -dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){ - // summary: - // Scroll the passed node into view, if it is not already. - // Deprecated, use `dojo.window.scrollIntoView` instead. - - dojo.window.scrollIntoView(node, pos); -}; - -} - -if(!dojo._hasResource["dojo.uacss"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.uacss"] = true; -dojo.provide("dojo.uacss"); - -(function(){ - // 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. - - var d = dojo, - html = d.doc.documentElement, - ie = d.isIE, - opera = d.isOpera, - maj = Math.floor, - ff = d.isFF, - boxModel = d.boxModel.replace(/-/,''), - - classes = { - dj_ie: ie, - dj_ie6: maj(ie) == 6, - dj_ie7: maj(ie) == 7, - dj_ie8: maj(ie) == 8, - dj_quirks: d.isQuirks, - dj_iequirks: ie && d.isQuirks, - - // NOTE: Opera not supported by dijit - dj_opera: opera, - - dj_khtml: d.isKhtml, - - dj_webkit: d.isWebKit, - dj_safari: d.isSafari, - dj_chrome: d.isChrome, - - dj_gecko: d.isMozilla, - dj_ff3: maj(ff) == 3 - }; // no dojo unsupported browsers - - 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 = d.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). - // Unshift() is to run sniff code before the parser. - dojo._loaders.unshift(function(){ - if(!dojo._isBodyLtr()){ - var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ") - html.className = d.trim(html.className + " " + rtlClassStr); - } - }); -})(); - -} - -if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.sniff"] = true; -// summary: -// Applies pre-set CSS classes to the top-level HTML node, see -// `dojo.uacss` for details. -// -// Simply doing a require on this module will -// establish this CSS. Modified version of Morris' CSS hack. - -dojo.provide("dijit._base.sniff"); - - - -} - -if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.typematic"] = true; -dojo.provide("dijit._base.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(dojo.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 (optional): - // 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 (optional): - // the number of milliseconds until the 2nd event occurs, default=500ms - // minDelay (optional): - // 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._evt = evt; - this._node = node; - this._currentTimeout = -1; - this._count = -1; - this._callback = dojo.hitch(_this, callback); - this._fireEventAndReload(); - this._evt = dojo.mixin({faux: true}, evt); - } - }, - - 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: - // an array of dojo.connect handles - if(keyObject.keyCode){ - keyObject.charOrCode = keyObject.keyCode; - dojo.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); - dojo.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0"); - } - return [ - dojo.connect(node, "onkeypress", 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)){ - dojo.stopEvent(evt); - dijit.typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay); - }else if(dijit.typematic._obj == keyObject){ - dijit.typematic.stop(); - } - }), - dojo.connect(node, "onkeyup", this, function(evt){ - if(dijit.typematic._obj == keyObject){ - dijit.typematic.stop(); - } - }) - ]; - }, - - 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: - // an array of dojo.connect handles - var dc = dojo.connect; - return [ - dc(node, "mousedown", this, function(evt){ - dojo.stopEvent(evt); - dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); - }), - dc(node, "mouseup", this, function(evt){ - dojo.stopEvent(evt); - dijit.typematic.stop(); - }), - dc(node, "mouseout", this, function(evt){ - dojo.stopEvent(evt); - dijit.typematic.stop(); - }), - dc(node, "mousemove", this, function(evt){ - evt.preventDefault(); - }), - dc(node, "dblclick", this, function(evt){ - dojo.stopEvent(evt); - if(dojo.isIE){ - dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay); - setTimeout(dojo.hitch(this, dijit.typematic.stop), 50); - } - }) - ]; - }, - - 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: - // an array of dojo.connect handles - return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay).concat( - this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay)); - } -}; - -} - -if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base.wai"] = true; -dojo.provide("dijit._base.wai"); - -dijit.wai = { - onload: function(){ - // summary: - // Detects if we are in high-contrast mode or not - - // This must be a named function and not an anonymous - // function, so that the widget parsing code can make sure it - // registers its onload function after this function. - // DO NOT USE "this" within this function. - - // create div for testing if high contrast mode is on or images are turned off - var div = dojo.create("div",{ - id: "a11yTestNode", - style:{ - cssText:'border: 1px solid;' - + 'border-color:red green;' - + 'position: absolute;' - + 'height: 5px;' - + 'top: -999px;' - + 'background-image: url("' + (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")) + '");' - } - }, dojo.body()); - - // test it - var cs = dojo.getComputedStyle(div); - if(cs){ - var bkImg = cs.backgroundImage; - var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" )); - dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y"); - if(dojo.isIE){ - div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014 - }else{ - dojo.body().removeChild(div); - } - } - } -}; - -// Test if computer is in high contrast mode. -// Make sure the a11y test runs first, before widgets are instantiated. -if(dojo.isIE || dojo.isMoz){ // NOTE: checking in Safari messes things up - dojo._loaders.unshift(dijit.wai.onload); -} - -dojo.mixin(dijit, { - _XhtmlRoles: /banner|contentinfo|definition|main|navigation|search|note|secondary|seealso/, - - hasWaiRole: function(/*Element*/ elem, /*String*/ role){ - // summary: - // Determines if an element has a particular non-XHTML role. - // returns: - // True if elem has the specific non-XHTML role attribute and false if not. - // For backwards compatibility if role parameter not provided, - // returns true if has non XHTML role - var waiRole = this.getWaiRole(elem); - return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0); - }, - - getWaiRole: function(/*Element*/ elem){ - // summary: - // Gets the non-XHTML role for an element (which should be a wai role). - // returns: - // The non-XHTML role of elem or an empty string if elem - // does not have a role. - return dojo.trim((dojo.attr(elem, "role") || "").replace(this._XhtmlRoles,"").replace("wairole:","")); - }, - - setWaiRole: function(/*Element*/ elem, /*String*/ role){ - // summary: - // Sets the role on an element. - // description: - // Replace existing role attribute with new role. - // If elem already has an XHTML role, append this role to XHTML role - // and remove other ARIA roles. - - var curRole = dojo.attr(elem, "role") || ""; - if(!this._XhtmlRoles.test(curRole)){ - dojo.attr(elem, "role", role); - }else{ - if((" "+ curRole +" ").indexOf(" " + role + " ") < 0){ - var clearXhtml = dojo.trim(curRole.replace(this._XhtmlRoles, "")); - var cleanRole = dojo.trim(curRole.replace(clearXhtml, "")); - dojo.attr(elem, "role", cleanRole + (cleanRole ? ' ' : '') + role); - } - } - }, - - removeWaiRole: function(/*Element*/ elem, /*String*/ role){ - // summary: - // Removes the specified non-XHTML role from an element. - // Removes role attribute if no specific role provided (for backwards compat.) - - var roleValue = dojo.attr(elem, "role"); - if(!roleValue){ return; } - if(role){ - var t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " ")); - dojo.attr(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); - } -}); - -} - -if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._base"] = true; -dojo.provide("dijit._base"); - - - - - - - - - - - -} - -if(!dojo._hasResource["dojo.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.date.stamp"] = true; -dojo.provide("dojo.date.stamp"); - -// Methods to convert dates to or from a wire (string) format using well-known conventions - -dojo.date.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(!dojo.date.stamp._isoRegExp){ - dojo.date.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 = dojo.date.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); - dojo.forEach(dojo.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 -} - -/*===== - dojo.date.stamp.__Options = function(){ - // 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 - this.selector = selector; - this.zulu = zulu; - this.milliseconds = milliseconds; - } -=====*/ - -dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__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 -} - -} - -if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.parser"] = true; -dojo.provide("dojo.parser"); - - -new Date("X"); // workaround for #11279, new Date("") == NaN - -dojo.parser = new function(){ - // summary: The Dom/Widget parsing package - - var d = dojo; - this._attrName = d._scopeName + "Type"; - this._query = "[" + this._attrName + "]"; - - function val2type(/*Object*/ value){ - // summary: - // Returns name of type of given value. - - if(d.isString(value)){ return "string"; } - if(typeof value == "number"){ return "number"; } - if(typeof value == "boolean"){ return "boolean"; } - if(d.isFunction(value)){ return "function"; } - if(d.isArray(value)){ return "array"; } // typeof [] == "object" - if(value instanceof Date) { return "date"; } // assume timestamp - if(value instanceof d._Url){ return "url"; } - return "object"; - } - - function str2obj(/*String*/ value, /*String*/ type){ - // summary: - // Convert given string value to given type - switch(type){ - case "string": - return value; - case "number": - return value.length ? Number(value) : NaN; - case "boolean": - // for checked/disabled value might be "" or "checked". interpret as true. - return typeof value == "boolean" ? value : !(value.toLowerCase()=="false"); - case "function": - if(d.isFunction(value)){ - // IE gives us a function, even when we say something like onClick="foo" - // (in which case it gives us an invalid function "function(){ foo }"). - // Therefore, convert to string - value=value.toString(); - value=d.trim(value.substring(value.indexOf('{')+1, value.length-1)); - } - try{ - if(value === "" || value.search(/[^\w\.]+/i) != -1){ - // The user has specified some text for a function like "return x+5" - return new Function(value); - }else{ - // The user has specified the name of a function like "myOnClick" - // or a single word function "return" - return d.getObject(value, false) || new Function(value); - } - }catch(e){ return new Function(); } - case "array": - return value ? value.split(/\s*,\s*/) : []; - case "date": - switch(value){ - case "": return new Date(""); // the NaN of dates - case "now": return new Date(); // current date - default: return d.date.stamp.fromISOString(value); - } - case "url": - return d.baseUrl + value; - default: - return d.fromJson(value); - } - } - - var instanceClasses = { - // map from fully qualified name (like "dijit.Button") to structure like - // { cls: dijit.Button, params: {label: "string", disabled: "boolean"} } - }; - - // 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). - dojo.connect(dojo, "extend", function(){ - instanceClasses = {}; - }); - - function getClassInfo(/*String*/ className){ - // className: - // fully qualified name (like "dijit.form.Button") - // returns: - // structure like - // { - // cls: dijit.Button, - // params: { label: "string", disabled: "boolean"} - // } - - if(!instanceClasses[className]){ - // get pointer to widget class - var cls = d.getObject(className); - if(!cls){ return null; } // class not defined [yet] - - var proto = cls.prototype; - - // get table of parameter names & types - var params = {}, dummyClass = {}; - for(var name in proto){ - if(name.charAt(0)=="_"){ continue; } // skip internal properties - if(name in dummyClass){ continue; } // skip "constructor" and "toString" - var defVal = proto[name]; - params[name]=val2type(defVal); - } - - instanceClasses[className] = { cls: cls, params: params }; - } - return instanceClasses[className]; - } - - this._functionFromScript = function(script){ - var preamble = ""; - var suffix = ""; - var argsStr = script.getAttribute("args"); - if(argsStr){ - d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){ - preamble += "var "+part+" = arguments["+idx+"]; "; - }); - } - var withStr = script.getAttribute("with"); - if(withStr && withStr.length){ - d.forEach(withStr.split(/\s*,\s*/), function(part){ - preamble += "with("+part+"){"; - suffix += "}"; - }); - } - return new Function(preamble+script.innerHTML+suffix); - } - - this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){ - // 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 nodes or objects like - // | { - // | type: "dijit.form.Button", - // | 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. - // args: Object? - // An object used to hold kwArgs for instantiation. - // Supports 'noStart' and inherited. - var thelist = [], dp = dojo.parser; - mixin = mixin||{}; - args = args||{}; - - d.forEach(nodes, function(obj){ - if(!obj){ return; } - - // Get pointers to DOMNode, dojoType string, and clsInfo (metadata about the dojoType), etc.s - var node, type, clsInfo, clazz, scripts; - if(obj.node){ - // new format of nodes[] array, object w/lots of properties pre-computed for me - node = obj.node; - type = obj.type; - clsInfo = obj.clsInfo || (type && getClassInfo(type)); - clazz = clsInfo && clsInfo.cls; - scripts = obj.scripts; - }else{ - // old (backwards compatible) format of nodes[] array, simple array of DOMNodes - node = obj; - type = dp._attrName in mixin ? mixin[dp._attrName] : node.getAttribute(dp._attrName); - clsInfo = type && getClassInfo(type); - clazz = clsInfo && clsInfo.cls; - scripts = (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] : - d.query("> script[type^='dojo/']", node)); - } - if(!clsInfo){ - throw new Error("Could not load class '" + type); - } - - // 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 = {}, - attributes = node.attributes; - if(args.defaults){ - // settings for the document itself (or whatever subtree is being parsed) - dojo.mixin(params, args.defaults); - } - if(obj.inherited){ - // settings from dir=rtl or lang=... on a node above this node - dojo.mixin(params, obj.inherited); - } - - // read parameters (ie, attributes) specified on DOMNode - // clsInfo.params lists expected params like {"checked": "boolean", "n": "number"} - for(var name in clsInfo.params){ - var item = name in mixin?{value:mixin[name],specified:true}:attributes.getNamedItem(name); - if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; } - var value = item.value; - // Deal with IE quirks for 'class' and 'style' - switch(name){ - case "class": - value = "className" in mixin?mixin.className:node.className; - break; - case "style": - value = "style" in mixin?mixin.style:(node.style && node.style.cssText); // FIXME: Opera? - } - var _type = clsInfo.params[name]; - if(typeof value == "string"){ - params[name] = str2obj(value, _type); - }else{ - params[name] = value; - } - } - - // 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" event="foo"> tags are dojo.connected after instantiation - // note: dojo/* script tags cannot exist in self closing widgets, like <input /> - var connects = [], // functions to connect after instantiation - calls = []; // functions to call after instantiation - - d.forEach(scripts, function(script){ - node.removeChild(script); - var event = script.getAttribute("event"), - type = script.getAttribute("type"), - nf = d.parser._functionFromScript(script); - if(event){ - if(type == "dojo/connect"){ - connects.push({event: event, func: nf}); - }else{ - params[event] = nf; - } - }else{ - calls.push(nf); - } - }); - - var markupFactory = clazz.markupFactory || clazz.prototype && clazz.prototype.markupFactory; - // create the instance - var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node); - thelist.push(instance); - - // map it to the JS namespace if that makes sense - var jsname = node.getAttribute("jsId"); - if(jsname){ - d.setObject(jsname, instance); - } - - // process connections and startup functions - d.forEach(connects, function(connect){ - d.connect(instance, connect.event, null, connect.func); - }); - d.forEach(calls, function(func){ - func.call(instance); - }); - }); - - // 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){ - // TODO: for 2.0, when old instantiate() API is desupported, store parent-child - // relationships in the nodes[] array so that no getParent() call is needed. - // Note that will require a parse() call from ContentPane setting a param that the - // ContentPane is the parent widget (so that the parse doesn't call startup() on the - // ContentPane's children) - d.forEach(thelist, function(instance){ - if( !args.noStart && instance && - instance.startup && - !instance._started && - (!instance.getParent || !instance.getParent()) - ){ - instance.startup(); - } - }); - } - return thelist; - }; - - this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){ - // 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 - // dojoType="qualified.class.name" - // - // rootNode: DomNode? - // A default starting root node from which to start the parsing. Can be - // omitted, defaulting to the entire document. If omitted, the `args` - // object can be passed in this place. If the `args` object has a - // `rootNode` member, that is used. - // - // args: - // a kwArgs object passed along to instantiate() - // - // * 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 `args object. - // * 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 - // - // - // example: - // Parse all widgets on a page: - // | dojo.parser.parse(); - // - // example: - // Parse all classes within the node with id="foo" - // | dojo.parser.parse(dojo.byId(foo)); - // - // example: - // Parse all classes in a page, but do not call .startup() on any - // child - // | dojo.parser.parse({ noStart: true }) - // - // example: - // Parse all classes in a node, but do not call .startup() - // | dojo.parser.parse(someNode, { noStart:true }); - // | // or - // | dojo.parser.parse({ noStart:true, rootNode: someNode }); - - // determine the root node based on the passed arguments. - var root; - if(!args && rootNode && rootNode.rootNode){ - args = rootNode; - root = args.rootNode; - }else{ - root = rootNode; - } - - var attrName = this._attrName; - function scan(parent, list){ - // summary: - // Parent is an Object representing a DOMNode, with or without a dojoType specified. - // Scan parent's children looking for nodes with dojoType specified, storing in list[]. - // If parent has a dojoType, also collects <script type=dojo/*> children and stores in parent.scripts[]. - // parent: Object - // Object representing the parent node, like - // | { - // | node: DomNode, // scan children of this node - // | inherited: {dir: "rtl"}, // dir/lang setting inherited from above node - // | - // | // attributes only set if node has dojoType specified - // | scripts: [], // empty array, put <script type=dojo/*> in here - // | clsInfo: { cls: dijit.form.Button, ...} - // | } - // list: DomNode[] - // Output array of objects (same format as parent) representing nodes to be turned into widgets - - // Effective dir and lang settings on parent node, either set directly or inherited from grandparent - var inherited = dojo.clone(parent.inherited); - dojo.forEach(["dir", "lang"], function(name){ - var val = parent.node.getAttribute(name); - if(val){ - inherited[name] = val; - } - }); - - // if parent is a widget, then search for <script type=dojo/*> tags and put them in scripts[]. - var scripts = parent.scripts; - - // unless parent is a widget with the stopParser flag set, continue search for dojoType, recursively - var recurse = !parent.clsInfo || !parent.clsInfo.cls.prototype.stopParser; - - // scan parent's children looking for dojoType and <script type=dojo/*> - for(var child = parent.node.firstChild; child; child = child.nextSibling){ - if(child.nodeType == 1){ - var type = recurse && child.getAttribute(attrName); - if(type){ - // if dojoType specified, add to output array of nodes to instantiate - var params = { - "type": type, - clsInfo: getClassInfo(type), // note: won't find classes declared via dojo.Declaration - node: child, - scripts: [], // <script> nodes that are parent's children - inherited: inherited // dir & lang attributes inherited from parent - }; - list.push(params); - - // Recurse, collecting <script type="dojo/..."> children, and also looking for - // descendant nodes with dojoType specified (unless the widget has the stopParser flag), - scan(params, list); - }else if(scripts && child.nodeName.toLowerCase() == "script"){ - // if <script type="dojo/...">, save in scripts[] - type = child.getAttribute("type"); - if (type && /^dojo\//i.test(type)) { - scripts.push(child); - } - }else if(recurse){ - // Recurse, looking for grandchild nodes with dojoType specified - scan({ - node: child, - inherited: inherited - }, list); - } - } - } - } - - // Make list of all nodes on page w/dojoType specified - var list = []; - scan({ - node: root ? dojo.byId(root) : dojo.body(), - inherited: (args && args.inherited) || { - dir: dojo._isBodyLtr() ? "ltr" : "rtl" - } - }, list); - - // go build the object instances - return this.instantiate(list, null, args); // Array - }; -}(); - -//Register the parser callback. It should be the first callback -//after the a11y test. - -(function(){ - var parseRunner = function(){ - if(dojo.config.parseOnLoad){ - dojo.parser.parse(); - } - }; - - // FIXME: need to clobber cross-dependency!! - if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){ - dojo._loaders.splice(1, 0, parseRunner); - }else{ - dojo._loaders.unshift(parseRunner); - } -})(); - -} - -if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._Widget"] = true; -dojo.provide("dijit._Widget"); - -dojo.require( "dijit._base" ); - - -// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets' -// DOM nodes) until someone actually needs to monitor that event. -dojo.connect(dojo, "_connect", - function(/*dijit._Widget*/ widget, /*String*/ event){ - if(widget && dojo.isFunction(widget._onConnect)){ - widget._onConnect(event); - } - }); - -dijit._connectOnUseEventHandler = function(/*Event*/ event){}; - -// 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 -dijit._lastKeyDownNode = null; -if(dojo.isIE){ - (function(){ - var keydownCallback = function(evt){ - dijit._lastKeyDownNode = evt.srcElement; - }; - dojo.doc.attachEvent('onkeydown', keydownCallback); - dojo.addOnWindowUnload(function(){ - dojo.doc.detachEvent('onkeydown', keydownCallback); - }); - })(); -}else{ - dojo.doc.addEventListener('keydown', function(evt){ - dijit._lastKeyDownNode = evt.target; - }, true); -} - -(function(){ - -var _attrReg = {}, // cached results from getSetterAttributes - getSetterAttributes = function(widget){ - // summary: - // Returns list of attributes with custom setters for specified widget - var dc = widget.declaredClass; - if(!_attrReg[dc]){ - var r = [], - attrs, - proto = widget.constructor.prototype; - for(var fxName in proto){ - if(dojo.isFunction(proto[fxName]) && (attrs = fxName.match(/^_set([a-zA-Z]*)Attr$/)) && attrs[1]){ - r.push(attrs[1].charAt(0).toLowerCase() + attrs[1].substr(1)); - } - } - _attrReg[dc] = r; - } - return _attrReg[dc] || []; // String[] - }; - -dojo.declare("dijit._Widget", null, { - // summary: - // Base class for all Dijit widgets. - - // 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: "", - - // 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: "", - - // 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: "", - - // class: String - // HTML class attribute - "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 dojoAttachPoint 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 dojoType=myWidget> - // | <b> here's a plain DOM node - // | <span dojoType=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 dojoType=subWidget>and a widget</span> - // | <i> and another plain DOM node </i> - // - // In templated widgets, "containerNode" is set via a - // dojoAttachPoint 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, - -/*===== - // _started: Boolean - // startup() has completed. - _started: false, -=====*/ - - // attributeMap: [protected] Object - // 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 attr('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: {id:"", dir:"", lang:"", "class":"", style:"", title:""}, - - // _deferredConnects: [protected] Object - // attributeMap addendum for event handlers that should be connected only on first use - _deferredConnects: { - onClick: "", - onDblClick: "", - onKeyDown: "", - onKeyPress: "", - onKeyUp: "", - onMouseMove: "", - onMouseDown: "", - onMouseOut: "", - onMouseOver: "", - onMouseLeave: "", - onMouseEnter: "", - onMouseUp: "" - }, - - onClick: dijit._connectOnUseEventHandler, - /*===== - onClick: function(event){ - // summary: - // Connect to this function to receive notifications of mouse click events. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onDblClick: dijit._connectOnUseEventHandler, - /*===== - onDblClick: function(event){ - // summary: - // Connect to this function to receive notifications of mouse double click events. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - onKeyDown: dijit._connectOnUseEventHandler, - /*===== - onKeyDown: function(event){ - // summary: - // Connect to this function to receive notifications of keys being pressed down. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onKeyPress: dijit._connectOnUseEventHandler, - /*===== - onKeyPress: function(event){ - // summary: - // Connect to this function to receive notifications of printable keys being typed. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onKeyUp: dijit._connectOnUseEventHandler, - /*===== - onKeyUp: function(event){ - // summary: - // Connect to this function to receive notifications of keys being released. - // event: - // key Event - // tags: - // callback - }, - =====*/ - onMouseDown: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - 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: dijit._connectOnUseEventHandler, - /*===== - onMouseUp: function(event){ - // summary: - // Connect to this function to receive notifications of when the mouse button is released. - // event: - // mouse Event - // tags: - // callback - }, - =====*/ - - // Constants used in templates - - // _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: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(), - - //////////// INITIALIZATION METHODS /////////////////////////////////////// - - postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){ - // summary: - // Kicks off widget instantiation. See create() for details. - // tags: - // private - this.create(params, srcNodeRef); - }, - - create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){ - // summary: - // Kick off the life-cycle of a widget - // params: - // Hash of initialization parameters for widget, including - // scalar values (like title, duration etc.) and functions, - // typically callbacks like onClick. - // srcNodeRef: - // 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 - // description: - // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate, - // etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget - // 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. - // tags: - // private - - // store pointer to original DOM tree - this.srcNodeRef = dojo.byId(srcNodeRef); - - // For garbage collection. An array of handles returned by Widget.connect() - // Each handle returned from Widget.connect() is an array of handles from dojo.connect() - this._connects = []; - - // For garbage collection. An array of handles returned by Widget.subscribe() - // The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe() - this._subscribes = []; - - // To avoid double-connects, remove entries from _deferredConnects - // that have been setup manually by a subclass (ex, by dojoAttachEvent). - // If a subclass has redefined a callback (ex: onClick) then assume it's being - // connected to manually. - this._deferredConnects = dojo.clone(this._deferredConnects); - for(var attr in this.attributeMap){ - delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects - } - for(attr in this._deferredConnects){ - if(this[attr] !== dijit._connectOnUseEventHandler){ - delete this._deferredConnects[attr]; // redefined, probably dojoAttachEvent exists - } - } - - //mixin our passed parameters - if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; } - if(params){ - this.params = params; - dojo.mixin(this,params); - } - this.postMixInProperties(); - - // generate an id for the widget if one wasn't specified - // (be sure to do this before buildRendering() because that function might - // expect the id to be there.) - if(!this.id){ - this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_")); - } - dijit.registry.add(this); - - this.buildRendering(); - - if(this.domNode){ - // Copy attributes listed in attributeMap into the [newly created] DOM for the widget. - this._applyAttributes(); - - var source = this.srcNodeRef; - if(source && source.parentNode){ - source.parentNode.replaceChild(this.domNode, source); - } - - // If the developer has specified a handler as a widget parameter - // (ex: new Button({onClick: ...}) - // then naturally need to connect from DOM node to that handler immediately, - for(attr in this.params){ - this._onConnect(attr); - } - } - - if(this.domNode){ - 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. - if(this.srcNodeRef && !this.srcNodeRef.parentNode){ - delete this.srcNodeRef; - } - - this._created = true; - }, - - _applyAttributes: function(){ - // summary: - // Step during widget creation to copy all widget attributes to the - // DOM as per attributeMap and _setXXXAttr functions. - // description: - // 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. - // - // It processes the attributes in the attribute map first, and then - // it goes through and processes the attributes for the _setXXXAttr - // functions that have been specified - // tags: - // private - var condAttrApply = function(attr, scope){ - if((scope.params && attr in scope.params) || scope[attr]){ - scope.set(attr, scope[attr]); - } - }; - - // Do the attributes in attributeMap - for(var attr in this.attributeMap){ - condAttrApply(attr, this); - } - - // And also any attributes with custom setters - dojo.forEach(getSetterAttributes(this), function(a){ - if(!(a in this.attributeMap)){ - condAttrApply(a, this); - } - }, this); - }, - - 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 - // description: - // Most widgets will mixin `dijit._Templated`, which implements this - // method. - // tags: - // protected - this.domNode = this.srcNodeRef || dojo.create('div'); - }, - - 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 - - // baseClass is a single class name or occasionally a space-separated list of names. - // Add those classes to the DOMNod. If RTL mode then also add with Rtl suffix. - if(this.baseClass){ - var classes = this.baseClass.split(" "); - if(!this.isLeftToRight()){ - classes = classes.concat( dojo.map(classes, function(name){ return name+"Rtl"; })); - } - dojo.addClass(this.domNode, classes); - } - }, - - 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. - this._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(); - var d = dojo, - dfe = d.forEach, - dun = d.unsubscribe; - dfe(this._connects, function(array){ - dfe(array, d.disconnect); - }); - dfe(this._subscribes, function(handle){ - dun(handle); - }); - - // destroy widgets created as part of template, etc. - dfe(this._supportingWidgets || [], function(w){ - if(w.destroyRecursive){ - w.destroyRecursive(); - }else if(w.destroy){ - w.destroy(); - } - }); - - this.destroyRendering(preserveDom); - dijit.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){ - dojo.removeAttr(this.domNode, "widgetId"); - }else{ - dojo.destroy(this.domNode); - } - delete this.domNode; - } - - if(this.srcNodeRef){ - if(!preserveDom){ - dojo.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 - dojo.forEach(this.getChildren(), function(widget){ - if(widget.destroyRecursive){ - widget.destroyRecursive(preserveDom); - } - }); - }, - - - uninitialize: function(){ - // summary: - // Stub function. Override to implement custom widget tear-down - // behavior. - // tags: - // protected - return false; - }, - - ////////////////// MISCELLANEOUS METHODS /////////////////// - - 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(e){ - // 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(); - }, - - _onConnect: function(/*String*/ event){ - // summary: - // Called when someone connects to one of my handlers. - // "Turn on" that handler if it isn't active yet. - // - // This is also called for every single initialization parameter - // so need to do nothing for parameters like "id". - // tags: - // private - if(event in this._deferredConnects){ - var mapNode = this[this._deferredConnects[event] || 'domNode']; - this.connect(mapNode, event.toLowerCase(), event); - delete this._deferredConnects[event]; - } - }, - - _setClassAttr: function(/*String*/ value){ - // summary: - // Custom setter for the CSS "class" attribute - // tags: - // protected - var mapNode = this[this.attributeMap["class"] || 'domNode']; - dojo.removeClass(mapNode, this["class"]) - this["class"] = value; - dojo.addClass(mapNode, value); - }, - - _setStyleAttr: function(/*String||Object*/ value){ - // summary: - // Sets the style attribut 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[this.attributeMap.style || '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(dojo.isObject(value)){ - dojo.style(mapNode, value); - }else{ - if(mapNode.style.cssText){ - mapNode.style.cssText += "; " + value; - }else{ - mapNode.style.cssText = value; - } - } - - this.style = value; - }, - - setAttribute: function(/*String*/ attr, /*anything*/ value){ - // summary: - // Deprecated. Use set() instead. - // tags: - // deprecated - dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0"); - this.set(attr, value); - }, - - _attrToDom: function(/*String*/ attr, /*String*/ value){ - // summary: - // Reflect a widget attribute (title, tabIndex, duration etc.) to - // the widget DOM, as specified in attributeMap. - // - // description: - // Also sets this["attr"] to the new value. - // Note some attributes like "type" - // cannot be processed this way as they are not mutable. - // - // tags: - // private - - var commands = this.attributeMap[attr]; - dojo.forEach(dojo.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(dojo.isFunction(value)){ // functions execute in the context of the widget - value = dojo.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); - - dojo.attr(mapNode, attrName, value); - break; - case "innerText": - mapNode.innerHTML = ""; - mapNode.appendChild(dojo.doc.createTextNode(value)); - break; - case "innerHTML": - mapNode.innerHTML = value; - break; - case "class": - dojo.removeClass(mapNode, this[attr]); - dojo.addClass(mapNode, value); - break; - } - }, this); - this[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(dojo.config.isDebug){ - var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}), - caller = (arguments.callee.caller || "unknown caller").toString(); - if(!alreadyCalledHash[caller]){ - dojo.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); - } - }, - - 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 a properties "foo" - // and "bar" and a method named "_getFooAttr", calling: - // | myWidget.get("foo"); - // would be equivalent to writing: - // | widget._getFooAttr(); - // and: - // | myWidget.get("bar"); - // would be equivalent to writing: - // | widget.bar; - 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 a properties "foo" - // and "bar" and a method named "_setFooAttr", calling: - // | myWidget.set("foo", "Howdy!"); - // would be equivalent to writing: - // | widget._setFooAttr("Howdy!"); - // and: - // | myWidget.set("bar", 3); - // would be equivalent to writing: - // | 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); - if(this[names.s]){ - // use the explicit setter - var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1)); - }else{ - // if param is specified as DOM node attribute, copy it - if(name in this.attributeMap){ - this._attrToDom(name, value); - } - var oldValue = this[name]; - // FIXME: what about function assignments? Any way to connect() here? - this[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.charAt(0).toUpperCase() + name.substr(1); - return (apn[name] = { - n: name+"Node", - s: "_set"+uc+"Attr", - g: "_get"+uc+"Attr" - }); - }, - - 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 - }, - - 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. - - return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[] - }, - - 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 ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[] - }, - - // nodesWithKeyClick: [private] String[] - // List of nodes that correctly handle click events via native browser support, - // and don't need dijit's help - nodesWithKeyClick: ["input", "button"], - - 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 dojo.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 - // returns: - // A handle that can be passed to `disconnect` in order to disconnect before - // the widget is destroyed. - // example: - // | var btn = new dijit.form.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 - - var d = dojo, - dc = d._connect, - handles = []; - if(event == "ondijitclick"){ - // add key based click activation for unsupported nodes. - // do all processing onkey up to prevent spurious clicks - // for details see comments at top of this file where _lastKeyDownNode is defined - if(dojo.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button - var m = d.hitch(this, method); - handles.push( - dc(obj, "onkeydown", this, function(e){ - //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode)); - if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) && - !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ - // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work - dijit._lastKeyDownNode = e.target; - e.preventDefault(); // stop event to prevent scrolling on space key in IE - } - }), - dc(obj, "onkeyup", this, function(e){ - //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode)); - if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) && - e.target === dijit._lastKeyDownNode && - !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){ - //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert - dijit._lastKeyDownNode = null; - return m(e); - } - }) - ); - } - event = "onclick"; - } - handles.push(dc(obj, event, this, method)); - - this._connects.push(handles); - return handles; // _Widget.Handle - }, - - disconnect: function(/* _Widget.Handle */ handles){ - // summary: - // Disconnects handle created by `connect`. - // Also removes handle from this widget's list of connects. - // tags: - // protected - for(var i=0; i<this._connects.length; i++){ - if(this._connects[i] == handles){ - dojo.forEach(handles, dojo.disconnect); - this._connects.splice(i, 1); - return; - } - } - }, - - subscribe: function( - /*String*/ topic, - /*String|Function*/ method){ - // summary: - // Subscribes to the specified topic and calls the specified method - // of this object and registers for unsubscribe() on widget destroy. - // description: - // Provide widget-specific analog to dojo.subscribe, except with the - // implicit use of this widget as the target object. - // example: - // | var btn = new dijit.form.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); - // | }); - var d = dojo, - handle = d.subscribe(topic, this, method); - - // return handles for Any widget that may need them - this._subscribes.push(handle); - return handle; - }, - - unsubscribe: function(/*Object*/ handle){ - // summary: - // Unsubscribes handle created by this.subscribe. - // Also removes handle from this widget's list of subscriptions - for(var i=0; i<this._subscribes.length; i++){ - if(this._subscribes[i] == handle){ - dojo.unsubscribe(handle); - this._subscribes.splice(i, 1); - return; - } - } - }, - - 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") : dojo._isBodyLtr(); //Boolean - }, - - isFocusable: function(){ - // summary: - // Return true if this widget can currently be focused - // and false if not - return this.focus && (dojo.style(this.domNode, "display") != "none"); - }, - - placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){ - // summary: - // Place this widget's domNode reference somewhere in the DOM based - // on standard dojo.place conventions, or passing a Widget reference that - // contains and addChild member. - // - // 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: - // The String id of a domNode, a domNode reference, or a reference to a Widget posessing - // an addChild method. - // - // position: - // If passed a string or domNode reference, the position argument - // accepts a string just as dojo.place does, one of: "first", "last", - // "before", or "after". - // - // If passed a _Widget reference, and that widget reference has an ".addChild" method, - // it will be called passing this widget instance into that method, supplying the optional - // position index passed. - // - // returns: - // dijit._Widget - // 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 dijit.form.Button({ label:"click" }).placeAt(dojo.body()); - // | // now, 'button' is still the widget reference to the newly created button - // | dojo.connect(button, "onClick", 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 dijit.form.Button({},"src").placeAt("wrapper"); - // - // example: - // | // place a new button as the first element of some div - // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first"); - // - // example: - // | // create a contentpane and add it to a TabContainer - // | var tc = dijit.byId("myTabs"); - // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc) - - if(reference.declaredClass && reference.addChild){ - reference.addChild(this, position); - }else{ - dojo.place(this.domNode, reference, position); - } - return this; - }, - - _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 - } -}); - -})(); - -} - -if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.string"] = true; -dojo.provide("dojo.string"); - -/*===== -dojo.string = { - // summary: String utilities for Dojo -}; -=====*/ - -dojo.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 -}; - -dojo.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++++++". - // | dojo.string.pad("Dojo", 10, "+", true); - - if(!ch){ - ch = '0'; - } - var out = String(text), - pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length)); - return end ? out + pad : pad + out; // String -}; - -dojo.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 - // | dojo.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. - // | dojo.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'." - // | dojo.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" - // | dojo.string.substitute( - // | "${0:postfix}", ["thinger"], null, { - // | postfix: function(value, key){ - // | return value + " -- howdy"; - // | } - // | } - // | ); - - thisObject = thisObject || dojo.global; - transform = transform ? - dojo.hitch(thisObject, transform) : function(v){ return v; }; - - return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, - function(match, key, format){ - var value = dojo.getObject(key, false, map); - if(format){ - value = dojo.getObject(format, false, thisObject).call(thisObject, value, key); - } - return transform(value, key).toString(); - }); // String -}; - -/*===== -dojo.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 -} -=====*/ - -dojo.string.trim = String.prototype.trim ? - dojo.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; - }; - -} - -if(!dojo._hasResource["dojo.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo.cache"] = true; -dojo.provide("dojo.cache"); - -/*===== -dojo.cache = { - // summary: - // A way to cache string content that is fetchable via `dojo.moduleUrl`. -}; -=====*/ - -(function(){ - var cache = {}; - 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: - // module and url are used to call `dojo.moduleUrl()` to generate a module URL. - // 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, 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 demostrates 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}); - - //Module could be a string, or an object that has a toString() method - //that will return a useful path. If it is an object, then the "url" argument - //will actually be the value argument. - if(typeof module == "string"){ - var pathObj = dojo.moduleUrl(module, url); - }else{ - pathObj = module; - value = url; - } - var key = pathObj.toString(); - - var val = value; - if(value != undefined && !dojo.isString(value)){ - val = ("value" in value ? value.value : undefined); - } - - var sanitize = value && value.sanitize ? true : false; - - if(typeof val == "string"){ - //We have a string, set cache value - val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val; - }else if(val === null){ - //Remove cached value - delete cache[key]; - }else{ - //Allow cache values to be empty strings. If key property does - //not exist, fetch it. - if(!(key in cache)){ - val = dojo._getText(key); - cache[key] = sanitize ? dojo.cache._sanitize(val) : val; - } - val = cache[key]; - } - return val; //String - }; - - dojo.cache._sanitize = function(/*String*/val){ - // summary: - // 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. - // description: - // Copied from dijit._Templated._sanitizeTemplateString. - if(val){ - val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, ""); - var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im); - if(matches){ - val = matches[1]; - } - }else{ - val = ""; - } - return val; //String - }; -})(); - -} - -if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._Templated"] = true; -dojo.provide("dijit._Templated"); - - - - - - -dojo.declare("dijit._Templated", - null, - { - // summary: - // Mixin for widgets that are instantiated from a template - - // templateString: [protected] String - // A string that represents the widget template. Pre-empts the - // templatePath. In builds that have their strings "interned", the - // templatePath is converted to an inline templateString, thereby - // preventing a synchronous network call. - // - // 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 dojo.cache() instead. - templatePath: null, - - // widgetsInTemplate: [protected] Boolean - // Should we parse the template to find widgets that might be - // declared in markup inside it? False by default. - widgetsInTemplate: false, - - // skipNodeCache: [protected] Boolean - // If using a cached widget template node 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 dojoAttachPoint=... in the - // template, ex: ["containerNode", "labelNode"] -/*===== - _attachPoints: [], - =====*/ - - constructor: function(){ - this._attachPoints = []; - }, - - _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 dojo.string.substitute(tmpl, this, function(value, key){ - if(key.charAt(0) == '!'){ value = dojo.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); - }, - - // method over-ride - buildRendering: function(){ - // summary: - // Construct the UI for this widget from a template, setting this.domNode. - // tags: - // protected - - // 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 = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache); - - var node; - if(dojo.isString(cached)){ - node = dojo._toDom(this._stringRepl(cached)); - 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; - - // 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); - - if(this.widgetsInTemplate){ - // Make sure dojoType is used for parsing widgets in template. - // The dojo.parser.query could be changed from multiversion support. - var parser = dojo.parser, qry, attr; - if(parser._query != "[dojoType]"){ - qry = parser._query; - attr = parser._attrName; - parser._query = "[dojoType]"; - parser._attrName = "dojoType"; - } - - // Store widgets that we need to start at a later point in time - var cw = (this._startupWidgets = dojo.parser.parse(node, { - noStart: !this._earlyTemplatedStartup, - inherited: {dir: this.dir, lang: this.lang} - })); - - // Restore the query. - if(qry){ - parser._query = qry; - parser._attrName = attr; - } - - this._supportingWidgets = dijit.findWidgets(node); - - this._attachTemplateNodes(cw, function(n,p){ - return n[p]; - }); - } - - this._fillContent(this.srcNodeRef); - }, - - _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. - // 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 - // * dojoAttachEvent - // * waiRole - // * waiState - // rootNode: DomNode|Array[Widgets] - // 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 - - getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); }; - - var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*")); - var x = dojo.isArray(rootNode) ? 0 : -1; - for(; x<nodes.length; x++){ - var baseNode = (x == -1) ? rootNode : nodes[x]; - if(this.widgetsInTemplate && getAttrFunc(baseNode, "dojoType")){ - continue; - } - // Process dojoAttachPoint - var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint"); - if(attachPoint){ - var point, points = attachPoint.split(/\s*,\s*/); - while((point = points.shift())){ - if(dojo.isArray(this[point])){ - this[point].push(baseNode); - }else{ - this[point]=baseNode; - } - this._attachPoints.push(point); - } - } - - // Process dojoAttachEvent - var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent"); - if(attachEvent){ - // NOTE: we want to support attributes that have the form - // "domEvent: nativeEvent; ..." - var event, events = attachEvent.split(/\s*,\s*/); - var trim = dojo.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; - } - this.connect(baseNode, event, thisFunc); - } - } - } - - // waiRole, waiState - var role = getAttrFunc(baseNode, "waiRole"); - if(role){ - dijit.setWaiRole(baseNode, role); - } - var values = getAttrFunc(baseNode, "waiState"); - if(values){ - dojo.forEach(values.split(/\s*,\s*/), function(stateValue){ - if(stateValue.indexOf('-') != -1){ - var pair = stateValue.split('-'); - dijit.setWaiState(baseNode, pair[0], pair[1]); - } - }); - } - } - }, - - startup: function(){ - dojo.forEach(this._startupWidgets, function(w){ - if(w && !w._started && w.startup){ - w.startup(); - } - }); - this.inherited(arguments); - }, - - destroyRendering: function(){ - // Delete all attach points to prevent IE6 memory leaks. - dojo.forEach(this._attachPoints, function(point){ - delete this[point]; - }, this); - this._attachPoints = []; - - this.inherited(arguments); - } - } -); - -// key is either templatePath or templateString; object is either string or DOM tree -dijit._Templated._templateCache = {}; - -dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){ - // summary: - // Static method to get a template based on the templatePath or - // templateString key - // templatePath: String||dojo.uri.Uri - // The URL to get the template from. - // templateString: String? - // a string to use in lieu of fetching the template from a URL. Takes precedence - // over templatePath - // 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 = dijit._Templated._templateCache; - var key = templateString || templatePath; - 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 == dojo.doc){ - // string or node of the same document - return cached; - } - }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded - dojo.destroy(cached); - } - - // If necessary, load template string from template path - if(!templateString){ - templateString = dojo.cache(templatePath, {sanitize: true}); - } - templateString = dojo.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 = dojo._toDom(templateString); - if(node.nodeType != 1){ - throw new Error("Invalid template: " + templateString); - } - return (tmplts[key] = node); //Node - } -}; - -if(dojo.isIE){ - dojo.addOnWindowUnload(function(){ - var cache = dijit._Templated._templateCache; - for(var key in cache){ - var value = cache[key]; - if(typeof value == "object"){ // value is either a string or a DOM node template - dojo.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.) -dojo.extend(dijit._Widget,{ - dojoAttachEvent: "", - dojoAttachPoint: "", - waiRole: "", - waiState:"" -}); - -} - -if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._Container"] = true; -dojo.provide("dijit._Container"); - -dojo.declare("dijit._Container", - null, - { - // summary: - // Mixin for widgets that contain a set of widget children. - // description: - // Use this mixin for widgets that needs to know about and - // keep track of their widget children. Suitable for widgets like BorderContainer - // and TabContainer which contain (only) a set of child widgets. - // - // It's not suitable for widgets like ContentPane - // which contains mixed HTML (plain DOM nodes in addition to widgets), - // and where contained widgets are not necessarily directly below - // this.containerNode. In that case calls like addChild(node, position) - // wouldn't make sense. - - // isContainer: [protected] Boolean - // Indicates that this widget acts as a "parent" to the descendant widgets. - // When the parent is started it will call startup() on the child widgets. - // See also `isLayoutContainer`. - isContainer: true, - - buildRendering: function(){ - this.inherited(arguments); - if(!this.containerNode){ - // all widgets with descendants must set containerNode - this.containerNode = this.domNode; - } - }, - - addChild: function(/*dijit._Widget*/ 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). - - 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"; - } - } - dojo.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 or 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 - - if(typeof widget == "number" && widget > 0){ - 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 children, i.e. if this.containerNode contains something. - return this.getChildren().length > 0; // Boolean - }, - - destroyDescendants: function(/*Boolean*/ preserveDom){ - // summary: - // Destroys all the widgets inside this.containerNode, - // but not this widget itself - dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); }); - }, - - _getSiblingOfChild: function(/*dijit._Widget*/ 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 node = child.domNode, - which = (dir>0 ? "nextSibling" : "previousSibling"); - do{ - node = node[which]; - }while(node && (node.nodeType != 1 || !dijit.byNode(node))); - return node && dijit.byNode(node); // dijit._Widget - }, - - getIndexOfChild: function(/*dijit._Widget*/ child){ - // summary: - // Gets the index of the child in this container or -1 if not found - return dojo.indexOf(this.getChildren(), child); // int - }, - - startup: function(){ - // summary: - // Called after all the widgets have been instantiated and their - // dom nodes have been inserted somewhere under dojo.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; } - - // Startup all children of this widget - dojo.forEach(this.getChildren(), function(child){ child.startup(); }); - - this.inherited(arguments); - } - } -); - -} - -if(!dojo._hasResource["dijit._Contained"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._Contained"] = true; -dojo.provide("dijit._Contained"); - -dojo.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 - // | dojo.declare("my.customClass",[dijit._Widget,dijit._Contained],{}); - - getParent: function(){ - // summary: - // Returns the parent widget of this widget, assuming the parent - // specifies isContainer - var parent = dijit.getEnclosingWidget(this.domNode.parentNode); - return parent && parent.isContainer ? parent : null; - }, - - _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 && dijit.byNode(node); // dijit._Widget - }, - - 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._Widget - }, - - 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._Widget - }, - - 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 - } - } - ); - - -} - -if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit.layout._LayoutWidget"] = true; -dojo.provide("dijit.layout._LayoutWidget"); - - - - - -dojo.declare("dijit.layout._LayoutWidget", - [dijit._Widget, dijit._Container, dijit._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, - - postCreate: function(){ - dojo.addClass(this.domNode, "dijitContainer"); - - this.inherited(arguments); - }, - - startup: function(){ - // summary: - // Called after all the widgets have been instantiated and their - // dom nodes have been inserted somewhere under dojo.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 my size changes so that I can re-layout. - // For browsers where I can't directly monitor when my size changes, - // monitor when the viewport changes size, which *may* indicate a size change for me. - this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){ - // Using function(){} closure to ensure no arguments to resize. - 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 relayout 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 relayout 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){ - dojo.marginBox(node, changeSize); - - // set offset of the node - if(changeSize.t){ node.style.top = changeSize.t + "px"; } - if(changeSize.l){ node.style.left = changeSize.l + "px"; } - } - - // 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 || {}; - dojo.mixin(mb, changeSize || {}); // changeSize overrides resultSize - if( !("h" in mb) || !("w" in mb) ){ - mb = dojo.mixin(dojo.marginBox(node), mb); // just use dojo.marginBox() to fill in missing values - } - - // Compute and save the size of my border box and content box - // (w/out calling dojo.contentBox() since that may fail if size was recently set) - var cs = dojo.getComputedStyle(node); - var me = dojo._getMarginExtents(node, cs); - var be = dojo._getBorderExtents(node, cs); - var bb = (this._borderBox = { - w: mb.w - (me.w + be.w), - h: mb.h - (me.h + be.h) - }); - var pe = dojo._getPadExtents(node, cs); - this._contentBox = { - l: dojo._toPixelValue(node, cs.paddingLeft), - t: dojo._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._Widget*/child){ - // summary: - // Common setup for initial children and children which are added after startup - // tags: - // protected extension - - dojo.addClass(child.domNode, this.baseClass+"-child"); - if(child.baseClass){ - dojo.addClass(child.domNode, this.baseClass+"-"+child.baseClass); - } - }, - - addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){ - // Overrides _Container.addChild() to call _setupChild() - this.inherited(arguments); - if(this._started){ - this._setupChild(child); - } - }, - - removeChild: function(/*dijit._Widget*/ child){ - // Overrides _Container.removeChild() to remove class added by _setupChild() - dojo.removeClass(child.domNode, this.baseClass+"-child"); - if(child.baseClass){ - dojo.removeClass(child.domNode, this.baseClass+"-"+child.baseClass); - } - this.inherited(arguments); - } - } -); - -dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){ - // summary: - // Given the margin-box size of a node, return its content box size. - // Functions like dojo.contentBox() but is more reliable since it doesn't have - // to wait for the browser to compute sizes. - var cs = dojo.getComputedStyle(node); - var me = dojo._getMarginExtents(node, cs); - var pb = dojo._getPadBorderExtents(node, cs); - return { - l: dojo._toPixelValue(node, cs.paddingLeft), - t: dojo._toPixelValue(node, cs.paddingTop), - w: mb.w - (me.w + pb.w), - h: mb.h - (me.h + pb.h) - }; -}; - -(function(){ - var capitalize = function(word){ - return word.substring(0,1).toUpperCase() + word.substring(1); - }; - - var size = function(widget, dim){ - // size the child - widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim); - - // record child's size, but favor our own numbers when we have them. - // the browser lies sometimes - dojo.mixin(widget, dojo.marginBox(widget.domNode)); - dojo.mixin(widget, dim); - }; - - dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){ - // 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 like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ] - - // copy dim because we are going to modify it - dim = dojo.mixin({}, dim); - - dojo.addClass(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. - children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; }) - .concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; })); - - // set positions/sizes - dojo.forEach(children, function(child){ - var elm = child.domNode, - pos = child.layoutAlign; - - // 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.bottom = elmStyle.right = "auto"; - - dojo.addClass(elm, "dijitAlign" + capitalize(pos)); - - // set size && adjust record of remaining space. - // note that setting the width of a <div> may affect its height. - if(pos == "top" || pos == "bottom"){ - size(child, { w: dim.w }); - 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"){ - size(child, { h: dim.h }); - dim.w -= child.w; - if(pos == "left"){ - dim.l += child.w; - }else{ - elmStyle.left = dim.l + dim.w + "px"; - } - }else if(pos == "client"){ - size(child, dim); - } - }); - }; - -})(); - -} - -if(!dojo._hasResource["dijit._CssStateMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._CssStateMixin"] = true; -dojo.provide("dijit._CssStateMixin"); - - -dojo.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: {}, - - postCreate: function(){ - this.inherited(arguments); - - // Automatically monitor mouse events (essentially :hover and :active) on this.domNode - dojo.forEach(["onmouseenter", "onmouseleave", "onmousedown"], function(e){ - this.connect(this.domNode, e, "_cssMouseEvent"); - }, this); - - // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node - this.connect(this, "set", function(name, value){ - if(arguments.length >= 2 && {disabled: true, readOnly: true, checked:true, selected:true}[name]){ - this._setStateClass(); - } - }); - - // The widget coming in/out of the focus change affects it's state - dojo.forEach(["_onFocus", "_onBlur"], function(ap){ - this.connect(this, ap, "_setStateClass"); - }, this); - - // Events on sub nodes within the widget - for(var ap in this.cssStateNodes){ - this._trackMouseState(this[ap], this.cssStateNodes[ap]); - } - // Set state initially; there's probably no hover/active/focus state but widget might be - // disabled/readonly so we want to set CSS classes for those conditions. - this._setStateClass(); - }, - - _cssMouseEvent: function(/*Event*/ event){ - // summary: - // Sets _hovering and _active properties depending on mouse state, - // then calls _setStateClass() to set appropriate CSS classes for this.domNode. - - if(!this.disabled){ - switch(event.type){ - case "mouseenter": - case "mouseover": // generated on non-IE browsers even though we connected to mouseenter - this._hovering = true; - this._active = this._mouseDown; - break; - - case "mouseleave": - case "mouseout": // generated on non-IE browsers even though we connected to mouseleave - this._hovering = false; - this._active = false; - break; - - case "mousedown" : - this._active = true; - this._mouseDown = true; - // Set a global event to handle mouseup, so it fires properly - // even if the cursor leaves this.domNode before the mouse up event. - // Alternately could set active=false on mouseout. - var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){ - this._active = false; - this._mouseDown = false; - this._setStateClass(); - this.disconnect(mouseUpConnector); - }); - break; - } - this._setStateClass(); - } - }, - - _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 - // - 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, 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(dojo.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"); - } - - if(this.checked){ - multiply("Checked"); - } - if(this.state){ - multiply(this.state); - } - if(this.selected){ - multiply("Selected"); - } - - 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 - - dojo.forEach(tn.className.split(" "), function(c){ classHash[c] = true; }); - - if("_stateClasses" in this){ - dojo.forEach(this._stateClasses, function(c){ delete classHash[c]; }); - } - - dojo.forEach(newStateClasses, function(c){ classHash[c] = true; }); - - var newClasses = []; - for(var c in classHash){ - newClasses.push(c); - } - tn.className = newClasses.join(" "); - - this._stateClasses = newStateClasses; - }, - - _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). - - // Current state of node (initially false) - // NB: setting specifically to false because dojo.toggleClass() needs true boolean as third arg - var hovering=false, active=false, focused=false; - - var self = this, - cn = dojo.hitch(this, "connect", node); - - function setClass(){ - var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly); - dojo.toggleClass(node, clazz+"Hover", hovering && !active && !disabled); - dojo.toggleClass(node, clazz+"Active", active && !disabled); - dojo.toggleClass(node, clazz+"Focused", focused && !disabled); - } - - // Mouse - cn("onmouseenter", function(){ - hovering = true; - setClass(); - }); - cn("onmouseleave", function(){ - hovering = false; - active = false; - setClass(); - }); - cn("onmousedown", function(){ - active = true; - setClass(); - }); - cn("onmouseup", function(){ - active = false; - setClass(); - }); - - // Focus - cn("onfocus", function(){ - focused = true; - setClass(); - }); - cn("onblur", function(){ - focused = false; - setClass(); - }); - - // Just in case widget is enabled/disabled while it has focus/hover/active state. - // Maybe this is overkill. - this.connect(this, "set", function(name, value){ - if(name == "disabled" || name == "readOnly"){ - setClass(); - } - }); - } -}); - -} - -if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit.form._FormWidget"] = true; -dojo.provide("dijit.form._FormWidget"); - - - - - - - -dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated, dijit._CssStateMixin], - { - // 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._Widget.attr`. - // - // They also share some common methods. - - // name: 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: String - // Corresponds to the native HTML <input> element's attribute. - type: "text", - - // tabIndex: Integer - // Order fields are traversed when user hits the tab key - tabIndex: "0", - - // 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, - - // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are. - attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, { - value: "focusNode", - id: "focusNode", - tabIndex: "focusNode", - alt: "focusNode", - title: "focusNode" - }), - - 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 attributeMap to set the name due to IE limitations, see #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); - }, - - postCreate: function(){ - this.inherited(arguments); - this.connect(this.domNode, "onmousedown", "_onMouseDown"); - }, - - _setDisabledAttr: function(/*Boolean*/ value){ - this.disabled = value; - dojo.attr(this.focusNode, 'disabled', value); - if(this.valueNode){ - dojo.attr(this.valueNode, 'disabled', value); - } - dijit.setWaiState(this.focusNode, "disabled", value); - - if(value){ - // reset these, because after the domNode is disabled, we can no longer receive - // mouse related events, see #4200 - this._hovering = false; - this._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 : "focusNode"; - dojo.forEach(dojo.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){ - var node = this[attachPointName]; - // complex code because tabIndex=-1 on a <div> doesn't work on FF - if(dojo.isWebKit || dijit.hasDefaultTabStop(node)){ // see #11064 about webkit bug - node.setAttribute('tabIndex', "-1"); - }else{ - node.removeAttribute('tabIndex'); - } - }, this); - }else{ - this.focusNode.setAttribute('tabIndex', this.tabIndex); - } - }, - - setDisabled: function(/*Boolean*/ disabled){ - // summary: - // Deprecated. Use set('disabled', ...) instead. - dojo.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0"); - this.set('disabled', disabled); - }, - - _onFocus: function(e){ - if(this.scrollOnFocus){ - dojo.window.scrollIntoView(this.domNode); - } - this.inherited(arguments); - }, - - isFocusable: function(){ - // summary: - // Tells if this widget is focusable or not. Used internally by dijit. - // tags: - // protected - return !this.disabled && !this.readOnly && this.focusNode && (dojo.style(this.domNode, "display") != "none"); - }, - - focus: function(){ - // summary: - // Put focus on this widget - dijit.focus(this.focusNode); - }, - - compare: function(/*anything*/val1, /*anything*/val2){ - // summary: - // Compare 2 values (as returned by attr('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==true, - // onChange is only called form priorityChange=true events. - // tags: - // private - this._lastValue = newValue; - 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; - } - if((this.intermediateChanges || priorityChange || priorityChange === undefined) && - ((typeof newValue != typeof this._lastValueReported) || - this.compare(newValue, this._lastValueReported) != 0)){ - this._lastValueReported = newValue; - if(this._onChangeActive){ - if(this._onChangeHandle){ - clearTimeout(this._onChangeHandle); - } - // setTimout allows hidden value processing to run and - // also the onChange handler can safely adjust focus, etc - this._onChangeHandle = setTimeout(dojo.hitch(this, - function(){ - this._onChangeHandle = null; - this.onChange(newValue); - }), 0); // 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 - clearTimeout(this._onChangeHandle); - this.onChange(this._lastValueReported); - } - this.inherited(arguments); - }, - - setValue: function(/*String*/ value){ - // summary: - // Deprecated. Use set('value', ...) instead. - dojo.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. - dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0"); - return this.get('value'); - }, - - _onMouseDown: function(e){ - // If user clicks on the button, even if the mouse is released outside of it, - // this button should get focus (to mimics native browser buttons). - // This is also needed on chrome because otherwise buttons won't get focus at all, - // which leads to bizarre focus restore on Dialog close etc. - if(!e.ctrlKey && this.isFocusable()){ // !e.ctrlKey to ignore right-click on mac - // 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(dojo.body(), "onmouseup", function(){ - if (this.isFocusable()) { - this.focus(); - } - this.disconnect(mouseUpConnector); - }); - } - } -}); - -dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget, -{ - // 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. - // TODO: unclear what that {value: ""} is for; FormWidget.attributeMap copies value to focusNode, - // so maybe {value: ""} is so the value *doesn't* get copied to focusNode? - // Seems like we really want value removed from attributeMap altogether - // (although there's no easy way to do that now) - - // 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, - - attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, { - value: "", - readOnly: "focusNode" - }), - - _setReadOnlyAttr: function(/*Boolean*/ value){ - this.readOnly = value; - dojo.attr(this.focusNode, 'readOnly', value); - dijit.setWaiState(this.focusNode, "readonly", value); - }, - - postCreate: function(){ - this.inherited(arguments); - - if(dojo.isIE){ // 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._resetValue = this.value; - } - }, - - _setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){ - // summary: - // Hook so attr('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.value = newValue; - this._handleOnChange(newValue, priorityChange); - }, - - _getValueAttr: function(){ - // summary: - // Hook so attr('value') works. - return this._lastValue; - }, - - 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 == dojo.keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){ - var te; - if(dojo.isIE){ - e.preventDefault(); // default behavior needs to be stopped here since keypress is too late - te = document.createEventObject(); - te.keyCode = dojo.keys.ESCAPE; - te.shiftKey = e.shiftKey; - e.srcElement.fireEvent('onkeypress', te); - } - } - }, - - _layoutHackIE7: function(){ - // summary: - // Work around table sizing bugs on IE7 by forcing redraw - - if(dojo.isIE == 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(e){ - _this.disconnect(disconnectHandle); // only call once - pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique - setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any - } - ); - })(); - parent = parent.parentNode; - } - } - } -}); - -} - -if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit.dijit"] = true; -dojo.provide("dijit.dijit"); - -/*===== -dijit.dijit = { - // summary: - // A roll-up for common dijit methods - // description: - // A rollup file for the build system including the core and common - // dijit files. - // - // example: - // | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script> - // -}; -=====*/ - -// 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 - - - - - - - -} - |