From 1354d17270961fff662d40f90521223f8fd0d73b Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 14 Aug 2012 18:59:10 +0400 Subject: update dojo to 1.7.3 --- lib/dojo/_base/html.js | 1832 +----------------------------------------------- 1 file changed, 2 insertions(+), 1830 deletions(-) (limited to 'lib/dojo/_base/html.js') diff --git a/lib/dojo/_base/html.js b/lib/dojo/_base/html.js index 8661b2b12..89f6a5192 100644 --- a/lib/dojo/_base/html.js +++ b/lib/dojo/_base/html.js @@ -4,1833 +4,5 @@ see: http://dojotoolkit.org/license for details */ - -if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base.html"] = true; -dojo.provide("dojo._base.html"); -dojo.require("dojo._base.lang"); - - -// FIXME: need to add unit tests for all the semi-public methods - -try{ - document.execCommand("BackgroundImageCache", false, true); -}catch(e){ - // sane browsers don't have cache "issues" -} - -// ============================= -// DOM Functions -// ============================= - -/*===== -dojo.byId = function(id, doc){ - // summary: - // Returns DOM node with matching `id` attribute or `null` - // if not found. If `id` is a DomNode, this function is a no-op. - // - // id: String|DOMNode - // A string to match an HTML id attribute or a reference to a DOM Node - // - // doc: Document? - // Document to work in. Defaults to the current value of - // dojo.doc. Can be used to retrieve - // node references from other documents. - // - // example: - // Look up a node by ID: - // | var n = dojo.byId("foo"); - // - // example: - // Check if a node exists, and use it. - // | var n = dojo.byId("bar"); - // | if(n){ doStuff() ... } - // - // example: - // Allow string or DomNode references to be passed to a custom function: - // | var foo = function(nodeOrId){ - // | nodeOrId = dojo.byId(nodeOrId); - // | // ... more stuff - // | } -=====*/ - -if(dojo.isIE){ - dojo.byId = function(id, doc){ - if(typeof id != "string"){ - return id; - } - var _d = doc || dojo.doc, te = _d.getElementById(id); - // attributes.id.value is better than just id in case the - // user has a name=id inside a form - if(te && (te.attributes.id.value == id || te.id == id)){ - return te; - }else{ - var eles = _d.all[id]; - if(!eles || eles.nodeName){ - eles = [eles]; - } - // if more than 1, choose first with the correct id - var i=0; - while((te=eles[i++])){ - if((te.attributes && te.attributes.id && te.attributes.id.value == id) - || te.id == id){ - return te; - } - } - } - }; -}else{ - dojo.byId = function(id, doc){ - // inline'd type check. - // be sure to return null per documentation, to match IE branch. - return ((typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id) || null; // DomNode - }; -} -/*===== -}; -=====*/ - -(function(){ - var d = dojo; - var byId = d.byId; - - var _destroyContainer = null, - _destroyDoc; - d.addOnWindowUnload(function(){ - _destroyContainer = null; //prevent IE leak - }); - -/*===== - dojo._destroyElement = function(node){ - // summary: - // Existing alias for `dojo.destroy`. Deprecated, will be removed - // in 2.0 - } -=====*/ - dojo._destroyElement = dojo.destroy = function(/*String|DomNode*/node){ - // summary: - // Removes a node from its parent, clobbering it and all of its - // children. - // - // description: - // Removes a node from its parent, clobbering it and all of its - // children. Function only works with DomNodes, and returns nothing. - // - // node: - // A String ID or DomNode reference of the element to be destroyed - // - // example: - // Destroy a node byId: - // | dojo.destroy("someId"); - // - // example: - // Destroy all nodes in a list by reference: - // | dojo.query(".someNode").forEach(dojo.destroy); - - node = byId(node); - try{ - var doc = node.ownerDocument; - // cannot use _destroyContainer.ownerDocument since this can throw an exception on IE - if(!_destroyContainer || _destroyDoc != doc){ - _destroyContainer = doc.createElement("div"); - _destroyDoc = doc; - } - _destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node); - // NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature - _destroyContainer.innerHTML = ""; - }catch(e){ - /* squelch */ - } - }; - - dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){ - // summary: - // Returns true if node is a descendant of ancestor - // node: string id or node reference to test - // ancestor: string id or node reference of potential parent to test against - // - // example: - // Test is node id="bar" is a descendant of node id="foo" - // | if(dojo.isDescendant("bar", "foo")){ ... } - try{ - node = byId(node); - ancestor = byId(ancestor); - while(node){ - if(node == ancestor){ - return true; // Boolean - } - node = node.parentNode; - } - }catch(e){ /* squelch, return false */ } - return false; // Boolean - }; - - dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){ - // summary: - // Enable or disable selection on a node - // node: - // id or reference to node - // selectable: - // state to put the node in. false indicates unselectable, true - // allows selection. - // example: - // Make the node id="bar" unselectable - // | dojo.setSelectable("bar"); - // example: - // Make the node id="bar" selectable - // | dojo.setSelectable("bar", true); - node = byId(node); - if(d.isMozilla){ - node.style.MozUserSelect = selectable ? "" : "none"; - }else if(d.isKhtml || d.isWebKit){ - node.style.KhtmlUserSelect = selectable ? "auto" : "none"; - }else if(d.isIE){ - var v = (node.unselectable = selectable ? "" : "on"); - d.query("*", node).forEach("item.unselectable = '"+v+"'"); - } - //FIXME: else? Opera? - }; - - var _insertBefore = function(/*DomNode*/node, /*DomNode*/ref){ - var parent = ref.parentNode; - if(parent){ - parent.insertBefore(node, ref); - } - }; - - var _insertAfter = function(/*DomNode*/node, /*DomNode*/ref){ - // summary: - // Try to insert node after ref - var parent = ref.parentNode; - if(parent){ - if(parent.lastChild == ref){ - parent.appendChild(node); - }else{ - parent.insertBefore(node, ref.nextSibling); - } - } - }; - - dojo.place = function(node, refNode, position){ - // summary: - // Attempt to insert node into the DOM, choosing from various positioning options. - // Returns the first argument resolved to a DOM node. - // - // node: String|DomNode - // id or node reference, or HTML fragment starting with "<" to place relative to refNode - // - // refNode: String|DomNode - // id or node reference to use as basis for placement - // - // position: String|Number? - // string noting the position of node relative to refNode or a - // number indicating the location in the childNodes collection of refNode. - // Accepted string values are: - // | * before - // | * after - // | * replace - // | * only - // | * first - // | * last - // "first" and "last" indicate positions as children of refNode, "replace" replaces refNode, - // "only" replaces all children. position defaults to "last" if not specified - // - // returns: DomNode - // Returned values is the first argument resolved to a DOM node. - // - // .place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups. - // - // example: - // Place a node by string id as the last child of another node by string id: - // | dojo.place("someNode", "anotherNode"); - // - // example: - // Place a node by string id before another node by string id - // | dojo.place("someNode", "anotherNode", "before"); - // - // example: - // Create a Node, and place it in the body element (last child): - // | dojo.place("
", dojo.body()); - // - // example: - // Put a new LI as the first child of a list by id: - // | dojo.place("
  • ", "someUl", "first"); - - refNode = byId(refNode); - if(typeof node == "string"){ // inline'd type check - node = /^\s* td", node).forEach(function(i){ - d._setOpacity(i, opacity); - }); - } - return opacity; - } : - function(node, opacity){ - return node.style.opacity = opacity; - }; - - var _pixelNamesCache = { - left: true, top: true - }; - var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border - var _toStyleValue = function(node, type, value){ - type = type.toLowerCase(); // FIXME: should we really be doing string case conversion here? Should we cache it? Need to profile! - if(d.isIE){ - if(value == "auto"){ - if(type == "height"){ return node.offsetHeight; } - if(type == "width"){ return node.offsetWidth; } - } - if(type == "fontweight"){ - switch(value){ - case 700: return "bold"; - case 400: - default: return "normal"; - } - } - } - if(!(type in _pixelNamesCache)){ - _pixelNamesCache[type] = _pixelRegExp.test(type); - } - return _pixelNamesCache[type] ? px(node, value) : value; - }; - - var _floatStyle = d.isIE ? "styleFloat" : "cssFloat", - _floatAliases = { "cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle } - ; - - // public API - - dojo.style = function( /*DomNode|String*/ node, - /*String?|Object?*/ style, - /*String?*/ value){ - // summary: - // Accesses styles on a node. If 2 arguments are - // passed, acts as a getter. If 3 arguments are passed, acts - // as a setter. - // description: - // Getting the style value uses the computed style for the node, so the value - // will be a calculated value, not just the immediate node.style value. - // Also when getting values, use specific style names, - // like "borderBottomWidth" instead of "border" since compound values like - // "border" are not necessarily reflected as expected. - // If you want to get node dimensions, use `dojo.marginBox()`, - // `dojo.contentBox()` or `dojo.position()`. - // node: - // id or reference to node to get/set style for - // style: - // the style property to set in DOM-accessor format - // ("borderWidth", not "border-width") or an object with key/value - // pairs suitable for setting each property. - // value: - // If passed, sets value on the node for style, handling - // cross-browser concerns. When setting a pixel value, - // be sure to include "px" in the value. For instance, top: "200px". - // Otherwise, in some cases, some browsers will not apply the style. - // example: - // Passing only an ID or node returns the computed style object of - // the node: - // | dojo.style("thinger"); - // example: - // Passing a node and a style property returns the current - // normalized, computed value for that property: - // | dojo.style("thinger", "opacity"); // 1 by default - // - // example: - // Passing a node, a style property, and a value changes the - // current display of the node and returns the new computed value - // | dojo.style("thinger", "opacity", 0.5); // == 0.5 - // - // example: - // Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node: - // | dojo.style("thinger", { - // | "opacity": 0.5, - // | "border": "3px solid black", - // | "height": "300px" - // | }); - // - // example: - // When the CSS style property is hyphenated, the JavaScript property is camelCased. - // font-size becomes fontSize, and so on. - // | dojo.style("thinger",{ - // | fontSize:"14pt", - // | letterSpacing:"1.2em" - // | }); - // - // example: - // dojo.NodeList implements .style() using the same syntax, omitting the "node" parameter, calling - // dojo.style() on every element of the list. See: `dojo.query()` and `dojo.NodeList()` - // | dojo.query(".someClassName").style("visibility","hidden"); - // | // or - // | dojo.query("#baz > div").style({ - // | opacity:0.75, - // | fontSize:"13pt" - // | }); - - var n = byId(node), args = arguments.length, op = (style == "opacity"); - style = _floatAliases[style] || style; - if(args == 3){ - return op ? d._setOpacity(n, value) : n.style[style] = value; /*Number*/ - } - if(args == 2 && op){ - return d._getOpacity(n); - } - var s = gcs(n); - if(args == 2 && typeof style != "string"){ // inline'd type check - for(var x in style){ - d.style(node, x, style[x]); - } - return s; - } - return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */ - }; - - // ============================= - // Box Functions - // ============================= - - dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // Returns object with special values specifically useful for node - // fitting. - // description: - // Returns an object with `w`, `h`, `l`, `t` properties: - // | l/t = left/top padding (respectively) - // | w = the total of the left and right padding - // | h = the total of the top and bottom padding - // If 'node' has position, l/t forms the origin for child nodes. - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - s = computedStyle||gcs(n), - l = px(n, s.paddingLeft), - t = px(n, s.paddingTop); - return { - l: l, - t: t, - w: l+px(n, s.paddingRight), - h: t+px(n, s.paddingBottom) - }; - }; - - dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // returns an object with properties useful for noting the border - // dimensions. - // description: - // * l/t = the sum of left/top border (respectively) - // * w = the sum of the left and right border - // * h = the sum of the top and bottom border - // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - ne = "none", - s = computedStyle||gcs(n), - bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0), - bt = (s.borderTopStyle != ne ? px(n, s.borderTopWidth) : 0); - return { - l: bl, - t: bt, - w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0), - h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0) - }; - }; - - dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // Returns object with properties useful for box fitting with - // regards to padding. - // description: - // * l/t = the sum of left/top padding and left/top border (respectively) - // * w = the sum of the left and right padding and border - // * h = the sum of the top and bottom padding and border - // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - s = computedStyle||gcs(n), - p = d._getPadExtents(n, s), - b = d._getBorderExtents(n, s); - return { - l: p.l + b.l, - t: p.t + b.t, - w: p.w + b.w, - h: p.h + b.h - }; - }; - - dojo._getMarginExtents = function(n, computedStyle){ - // summary: - // returns object with properties useful for box fitting with - // regards to box margins (i.e., the outer-box). - // - // * l/t = marginLeft, marginTop, respectively - // * w = total width, margin inclusive - // * h = total height, margin inclusive - // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - s = computedStyle||gcs(n), - l = px(n, s.marginLeft), - t = px(n, s.marginTop), - r = px(n, s.marginRight), - b = px(n, s.marginBottom); - if(d.isWebKit && (s.position != "absolute")){ - // FIXME: Safari's version of the computed right margin - // is the space between our right edge and the right edge - // of our offsetParent. - // What we are looking for is the actual margin value as - // determined by CSS. - // Hack solution is to assume left/right margins are the same. - r = l; - } - return { - l: l, - t: t, - w: l+r, - h: t+b - }; - }; - - // Box getters work in any box context because offsetWidth/clientWidth - // are invariant wrt box context - // - // They do *not* work for display: inline objects that have padding styles - // because the user agent ignores padding (it's bogus styling in any case) - // - // Be careful with IMGs because they are inline or block depending on - // browser and browser mode. - - // Although it would be easier to read, there are not separate versions of - // _getMarginBox for each browser because: - // 1. the branching is not expensive - // 2. factoring the shared code wastes cycles (function call overhead) - // 3. duplicating the shared code wastes bytes - - dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){ - // summary: - // returns an object that encodes the width, height, left and top - // positions of the node's margin box. - var s = computedStyle || gcs(node), me = d._getMarginExtents(node, s); - var l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode; - if(d.isMoz){ - // Mozilla: - // If offsetParent has a computed overflow != visible, the offsetLeft is decreased - // by the parent's border. - // We don't want to compute the parent's style, so instead we examine node's - // computed left/top which is more stable. - var sl = parseFloat(s.left), st = parseFloat(s.top); - if(!isNaN(sl) && !isNaN(st)){ - l = sl, t = st; - }else{ - // If child's computed left/top are not parseable as a number (e.g. "auto"), we - // have no choice but to examine the parent's computed style. - if(p && p.style){ - var pcs = gcs(p); - if(pcs.overflow != "visible"){ - var be = d._getBorderExtents(p, pcs); - l += be.l, t += be.t; - } - } - } - }else if(d.isOpera || (d.isIE > 7 && !d.isQuirks)){ - // On Opera and IE 8, offsetLeft/Top includes the parent's border - if(p){ - be = d._getBorderExtents(p); - l -= be.l; - t -= be.t; - } - } - return { - l: l, - t: t, - w: node.offsetWidth + me.w, - h: node.offsetHeight + me.h - }; - } - - dojo._getMarginSize = function(/*DomNode*/node, /*Object*/computedStyle){ - // summary: - // returns an object that encodes the width and height of - // the node's margin box - node = byId(node); - var me = d._getMarginExtents(node, computedStyle || gcs(node)); - - var size = node.getBoundingClientRect(); - return { - w: (size.right - size.left) + me.w, - h: (size.bottom - size.top) + me.h - } - } - - dojo._getContentBox = function(node, computedStyle){ - // summary: - // Returns an object that encodes the width, height, left and top - // positions of the node's content box, irrespective of the - // current box model. - - // clientWidth/Height are important since the automatically account for scrollbars - // fallback to offsetWidth/Height for special cases (see #3378) - var s = computedStyle || gcs(node), - pe = d._getPadExtents(node, s), - be = d._getBorderExtents(node, s), - w = node.clientWidth, - h - ; - if(!w){ - w = node.offsetWidth, h = node.offsetHeight; - }else{ - h = node.clientHeight, be.w = be.h = 0; - } - // On Opera, offsetLeft includes the parent's border - if(d.isOpera){ pe.l += be.l; pe.t += be.t; }; - return { - l: pe.l, - t: pe.t, - w: w - pe.w - be.w, - h: h - pe.h - be.h - }; - }; - - dojo._getBorderBox = function(node, computedStyle){ - var s = computedStyle || gcs(node), - pe = d._getPadExtents(node, s), - cb = d._getContentBox(node, s) - ; - return { - l: cb.l - pe.l, - t: cb.t - pe.t, - w: cb.w + pe.w, - h: cb.h + pe.h - }; - }; - - // Box setters depend on box context because interpretation of width/height styles - // vary wrt box context. - // - // The value of dojo.boxModel is used to determine box context. - // dojo.boxModel can be set directly to change behavior. - // - // Beware of display: inline objects that have padding styles - // because the user agent ignores padding (it's a bogus setup anyway) - // - // Be careful with IMGs because they are inline or block depending on - // browser and browser mode. - // - // Elements other than DIV may have special quirks, like built-in - // margins or padding, or values not detectable via computedStyle. - // In particular, margins on TABLE do not seems to appear - // at all in computedStyle on Mozilla. - - dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){ - // summary: - // sets width/height/left/top in the current (native) box-model - // dimentions. Uses the unit passed in u. - // node: - // DOM Node reference. Id string not supported for performance - // reasons. - // l: - // left offset from parent. - // t: - // top offset from parent. - // w: - // width in current box model. - // h: - // width in current box model. - // u: - // unit measure to use for other measures. Defaults to "px". - u = u || "px"; - var s = node.style; - if(!isNaN(l)){ s.left = l + u; } - if(!isNaN(t)){ s.top = t + u; } - if(w >= 0){ s.width = w + u; } - if(h >= 0){ s.height = h + u; } - }; - - dojo._isButtonTag = function(/*DomNode*/node) { - // summary: - // True if the node is BUTTON or INPUT.type="button". - return node.tagName == "BUTTON" - || node.tagName=="INPUT" && (node.getAttribute("type")||'').toUpperCase() == "BUTTON"; // boolean - }; - - dojo._usesBorderBox = function(/*DomNode*/node){ - // summary: - // True if the node uses border-box layout. - - // We could test the computed style of node to see if a particular box - // has been specified, but there are details and we choose not to bother. - - // TABLE and BUTTON (and INPUT type=button) are always border-box by default. - // If you have assigned a different box to either one via CSS then - // box functions will break. - - var n = node.tagName; - return d.boxModel=="border-box" || n=="TABLE" || d._isButtonTag(node); // boolean - }; - - dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){ - // summary: - // Sets the size of the node's contents, irrespective of margins, - // padding, or borders. - if(d._usesBorderBox(node)){ - var pb = d._getPadBorderExtents(node, computedStyle); - if(widthPx >= 0){ widthPx += pb.w; } - if(heightPx >= 0){ heightPx += pb.h; } - } - d._setBox(node, NaN, NaN, widthPx, heightPx); - }; - - dojo._setMarginBox = function(/*DomNode*/node, /*Number?*/leftPx, /*Number?*/topPx, - /*Number?*/widthPx, /*Number?*/heightPx, - /*Object*/computedStyle){ - // summary: - // sets the size of the node's margin box and placement - // (left/top), irrespective of box model. Think of it as a - // passthrough to dojo._setBox that handles box-model vagaries for - // you. - - var s = computedStyle || gcs(node), - // Some elements have special padding, margin, and box-model settings. - // To use box functions you may need to set padding, margin explicitly. - // Controlling box-model is harder, in a pinch you might set dojo.boxModel. - bb = d._usesBorderBox(node), - pb = bb ? _nilExtents : d._getPadBorderExtents(node, s) - ; - if(d.isWebKit){ - // on Safari (3.1.2), button nodes with no explicit size have a default margin - // setting an explicit size eliminates the margin. - // We have to swizzle the width to get correct margin reading. - if(d._isButtonTag(node)){ - var ns = node.style; - if(widthPx >= 0 && !ns.width) { ns.width = "4px"; } - if(heightPx >= 0 && !ns.height) { ns.height = "4px"; } - } - } - var mb = d._getMarginExtents(node, s); - if(widthPx >= 0){ widthPx = Math.max(widthPx - pb.w - mb.w, 0); } - if(heightPx >= 0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); } - d._setBox(node, leftPx, topPx, widthPx, heightPx); - }; - - var _nilExtents = { l:0, t:0, w:0, h:0 }; - - // public API - - dojo.marginBox = function(/*DomNode|String*/node, /*Object?*/box){ - // summary: - // Getter/setter for the margin-box of node. - // description: - // Getter/setter for the margin-box of node. - // Returns an object in the expected format of box (regardless - // if box is passed). The object might look like: - // `{ l: 50, t: 200, w: 300: h: 150 }` - // for a node offset from its parent 50px to the left, 200px from - // the top with a margin width of 300px and a margin-height of - // 150px. - // node: - // id or reference to DOM Node to get/set box for - // box: - // If passed, denotes that dojo.marginBox() should - // update/set the margin box for node. Box is an object in the - // above format. All properties are optional if passed. - // example: - // Retrieve the marginbox of a passed node - // | var box = dojo.marginBox("someNodeId"); - // | console.dir(box); - // - // example: - // Set a node's marginbox to the size of another node - // | var box = dojo.marginBox("someNodeId"); - // | dojo.marginBox("someOtherNode", box); - - var n = byId(node), s = gcs(n), b = box; - return !b ? d._getMarginBox(n, s) : d._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object - }; - - dojo.contentBox = function(/*DomNode|String*/node, /*Object?*/box){ - // summary: - // Getter/setter for the content-box of node. - // description: - // Returns an object in the expected format of box (regardless if box is passed). - // The object might look like: - // `{ l: 50, t: 200, w: 300: h: 150 }` - // for a node offset from its parent 50px to the left, 200px from - // the top with a content width of 300px and a content-height of - // 150px. Note that the content box may have a much larger border - // or margin box, depending on the box model currently in use and - // CSS values set/inherited for node. - // While the getter will return top and left values, the - // setter only accepts setting the width and height. - // node: - // id or reference to DOM Node to get/set box for - // box: - // If passed, denotes that dojo.contentBox() should - // update/set the content box for node. Box is an object in the - // above format, but only w (width) and h (height) are supported. - // All properties are optional if passed. - var n = byId(node), s = gcs(n), b = box; - return !b ? d._getContentBox(n, s) : d._setContentSize(n, b.w, b.h, s); // Object - }; - - // ============================= - // Positioning - // ============================= - - var _sumAncestorProperties = function(node, prop){ - if(!(node = (node||0).parentNode)){return 0;} - var val, retVal = 0, _b = d.body(); - while(node && node.style){ - if(gcs(node).position == "fixed"){ - return 0; - } - val = node[prop]; - if(val){ - retVal += val - 0; - // opera and khtml #body & #html has the same values, we only - // need one value - if(node == _b){ break; } - } - node = node.parentNode; - } - return retVal; // integer - }; - - dojo._docScroll = function(){ - var n = d.global; - return "pageXOffset" in n - ? { x:n.pageXOffset, y:n.pageYOffset } - : (n = d.isQuirks? d.doc.body : d.doc.documentElement, { x:d._fixIeBiDiScrollLeft(n.scrollLeft || 0), y:n.scrollTop || 0 }); - }; - - dojo._isBodyLtr = function(){ - return "_bodyLtr" in d? d._bodyLtr : - d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean - }; - - dojo._getIeDocumentElementOffset = function(){ - // summary: - // returns the offset in x and y from the document body to the - // visual edge of the page - // description: - // The following values in IE contain an offset: - // | event.clientX - // | event.clientY - // | node.getBoundingClientRect().left - // | node.getBoundingClientRect().top - // But other position related values do not contain this offset, - // such as node.offsetLeft, node.offsetTop, node.style.left and - // node.style.top. The offset is always (2, 2) in LTR direction. - // When the body is in RTL direction, the offset counts the width - // of left scroll bar's width. This function computes the actual - // offset. - - //NOTE: assumes we're being called in an IE browser - - var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks - - if(d.isIE < 8){ - var r = de.getBoundingClientRect(); // works well for IE6+ - //console.debug('rect left,top = ' + r.left+','+r.top + ', html client left/top = ' + de.clientLeft+','+de.clientTop + ', rtl = ' + (!d._isBodyLtr()) + ', quirks = ' + d.isQuirks); - var l = r.left, - t = r.top; - if(d.isIE < 7){ - l += de.clientLeft; // scrollbar size in strict/RTL, or, - t += de.clientTop; // HTML border size in strict - } - return { - x: l < 0? 0 : l, // FRAME element border size can lead to inaccurate negative values - y: t < 0? 0 : t - }; - }else{ - return { - x: 0, - y: 0 - }; - } - - }; - - dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){ - // In RTL direction, scrollLeft should be a negative value, but IE - // returns a positive one. All codes using documentElement.scrollLeft - // must call this function to fix this error, otherwise the position - // will offset to right when there is a horizontal scrollbar. - - var ie = d.isIE; - if(ie && !d._isBodyLtr()){ - var qk = d.isQuirks, - de = qk ? d.doc.body : d.doc.documentElement; - if(ie == 6 && !qk && d.global.frameElement && de.scrollHeight > de.clientHeight){ - scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels - } - return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer - } - return scrollLeft; // Integer - }; - - // FIXME: need a setter for coords or a moveTo!! - dojo._abs = dojo.position = function(/*DomNode*/node, /*Boolean?*/includeScroll){ - // summary: - // Gets the position and size of the passed element relative to - // the viewport (if includeScroll==false), or relative to the - // document root (if includeScroll==true). - // - // description: - // Returns an object of the form: - // { x: 100, y: 300, w: 20, h: 15 } - // If includeScroll==true, the x and y values will include any - // document offsets that may affect the position relative to the - // viewport. - // Uses the border-box model (inclusive of border and padding but - // not margin). Does not act as a setter. - - node = byId(node); - var db = d.body(), - dh = db.parentNode, - ret = node.getBoundingClientRect(); - ret = { x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top }; - if(d.isIE){ - // On IE there's a 2px offset that we need to adjust for, see _getIeDocumentElementOffset() - var offset = d._getIeDocumentElementOffset(); - - // fixes the position in IE, quirks mode - ret.x -= offset.x + (d.isQuirks ? db.clientLeft+db.offsetLeft : 0); - ret.y -= offset.y + (d.isQuirks ? db.clientTop+db.offsetTop : 0); - }else if(d.isFF == 3){ - // In FF3 you have to subtract the document element margins. - // Fixed in FF3.5 though. - var cs = gcs(dh); - ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth); - ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth); - } - // account for document scrolling - if(includeScroll){ - var scroll = d._docScroll(); - ret.x += scroll.x; - ret.y += scroll.y; - } - - return ret; // Object - }; - - dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){ - // summary: - // Deprecated: Use position() for border-box x/y/w/h - // or marginBox() for margin-box w/h/l/t. - // Returns an object representing a node's size and position. - // - // description: - // Returns an object that measures margin-box (w)idth/(h)eight - // and absolute position x/y of the border-box. Also returned - // is computed (l)eft and (t)op values in pixels from the - // node's offsetParent as returned from marginBox(). - // Return value will be in the form: - //| { l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 } - // Does not act as a setter. If includeScroll is passed, the x and - // y params are affected as one would expect in dojo.position(). - var n = byId(node), s = gcs(n), mb = d._getMarginBox(n, s); - var abs = d.position(n, includeScroll); - mb.x = abs.x; - mb.y = abs.y; - return mb; - }; - - // ============================= - // Element attribute Functions - // ============================= - - // dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/ - - var _propNames = { - // properties renamed to avoid clashes with reserved words - "class": "className", - "for": "htmlFor", - // properties written as camelCase - tabindex: "tabIndex", - readonly: "readOnly", - colspan: "colSpan", - frameborder: "frameBorder", - rowspan: "rowSpan", - valuetype: "valueType" - }, - _attrNames = { - // original attribute names - classname: "class", - htmlfor: "for", - // for IE - tabindex: "tabIndex", - readonly: "readOnly" - }, - _forcePropNames = { - innerHTML: 1, - className: 1, - htmlFor: d.isIE, - value: 1 - }; - - var _fixAttrName = function(/*String*/ name){ - return _attrNames[name.toLowerCase()] || name; - }; - - var _hasAttr = function(node, name){ - var attr = node.getAttributeNode && node.getAttributeNode(name); - return attr && attr.specified; // Boolean - }; - - // There is a difference in the presence of certain properties and their default values - // between browsers. For example, on IE "disabled" is present on all elements, - // but it is value is "false"; "tabIndex" of
    returns 0 by default on IE, yet other browsers - // can return -1. - - dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){ - // summary: - // Returns true if the requested attribute is specified on the - // given element, and false otherwise. - // node: - // id or reference to the element to check - // name: - // the name of the attribute - // returns: - // true if the requested attribute is specified on the - // given element, and false otherwise - var lc = name.toLowerCase(); - return _forcePropNames[_propNames[lc] || name] || _hasAttr(byId(node), _attrNames[lc] || name); // Boolean - }; - - var _evtHdlrMap = {}, _ctr = 0, - _attrId = dojo._scopeName + "attrid", - // the next dictionary lists elements with read-only innerHTML on IE - _roInnerHtml = {col: 1, colgroup: 1, - // frameset: 1, head: 1, html: 1, style: 1, - table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}; - - dojo.attr = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){ - // summary: - // Gets or sets an attribute on an HTML element. - // description: - // Handles normalized getting and setting of attributes on DOM - // Nodes. If 2 arguments are passed, and a the second argumnt is a - // string, acts as a getter. - // - // If a third argument is passed, or if the second argument is a - // map of attributes, acts as a setter. - // - // When passing functions as values, note that they will not be - // directly assigned to slots on the node, but rather the default - // behavior will be removed and the new behavior will be added - // using `dojo.connect()`, meaning that event handler properties - // will be normalized and that some caveats with regards to - // non-standard behaviors for onsubmit apply. Namely that you - // should cancel form submission using `dojo.stopEvent()` on the - // passed event object instead of returning a boolean value from - // the handler itself. - // node: - // id or reference to the element to get or set the attribute on - // name: - // the name of the attribute to get or set. - // value: - // The value to set for the attribute - // returns: - // when used as a getter, the value of the requested attribute - // or null if that attribute does not have a specified or - // default value; - // - // when used as a setter, the DOM node - // - // example: - // | // get the current value of the "foo" attribute on a node - // | dojo.attr(dojo.byId("nodeId"), "foo"); - // | // or we can just pass the id: - // | dojo.attr("nodeId", "foo"); - // - // example: - // | // use attr() to set the tab index - // | dojo.attr("nodeId", "tabIndex", 3); - // | - // - // example: - // Set multiple values at once, including event handlers: - // | dojo.attr("formId", { - // | "foo": "bar", - // | "tabIndex": -1, - // | "method": "POST", - // | "onsubmit": function(e){ - // | // stop submitting the form. Note that the IE behavior - // | // of returning true or false will have no effect here - // | // since our handler is connect()ed to the built-in - // | // onsubmit behavior and so we need to use - // | // dojo.stopEvent() to ensure that the submission - // | // doesn't proceed. - // | dojo.stopEvent(e); - // | - // | // submit the form with Ajax - // | dojo.xhrPost({ form: "formId" }); - // | } - // | }); - // - // example: - // Style is s special case: Only set with an object hash of styles - // | dojo.attr("someNode",{ - // | id:"bar", - // | style:{ - // | width:"200px", height:"100px", color:"#000" - // | } - // | }); - // - // example: - // Again, only set style as an object hash of styles: - // | var obj = { color:"#fff", backgroundColor:"#000" }; - // | dojo.attr("someNode", "style", obj); - // | - // | // though shorter to use `dojo.style()` in this case: - // | dojo.style("someNode", obj); - - node = byId(node); - var args = arguments.length, prop; - if(args == 2 && typeof name != "string"){ // inline'd type check - // the object form of setter: the 2nd argument is a dictionary - for(var x in name){ - d.attr(node, x, name[x]); - } - return node; // DomNode - } - var lc = name.toLowerCase(), - propName = _propNames[lc] || name, - forceProp = _forcePropNames[propName], - attrName = _attrNames[lc] || name; - if(args == 3){ - // setter - do{ - if(propName == "style" && typeof value != "string"){ // inline'd type check - // special case: setting a style - d.style(node, value); - break; - } - if(propName == "innerHTML"){ - // special case: assigning HTML - if(d.isIE && node.tagName.toLowerCase() in _roInnerHtml){ - d.empty(node); - node.appendChild(d._toDom(value, node.ownerDocument)); - }else{ - node[propName] = value; - } - break; - } - if(d.isFunction(value)){ - // special case: assigning an event handler - // clobber if we can - var attrId = d.attr(node, _attrId); - if(!attrId){ - attrId = _ctr++; - d.attr(node, _attrId, attrId); - } - if(!_evtHdlrMap[attrId]){ - _evtHdlrMap[attrId] = {}; - } - var h = _evtHdlrMap[attrId][propName]; - if(h){ - d.disconnect(h); - }else{ - try{ - delete node[propName]; - }catch(e){} - } - // ensure that event objects are normalized, etc. - _evtHdlrMap[attrId][propName] = d.connect(node, propName, value); - break; - } - if(forceProp || typeof value == "boolean"){ - // special case: forcing assignment to the property - // special case: setting boolean to a property instead of attribute - node[propName] = value; - break; - } - // node's attribute - node.setAttribute(attrName, value); - }while(false); - return node; // DomNode - } - // getter - // should we access this attribute via a property or - // via getAttribute()? - value = node[propName]; - if(forceProp && typeof value != "undefined"){ - // node's property - return value; // Anything - } - if(propName != "href" && (typeof value == "boolean" || d.isFunction(value))){ - // node's property - return value; // Anything - } - // node's attribute - // we need _hasAttr() here to guard against IE returning a default value - return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything - }; - - dojo.removeAttr = function(/*DomNode|String*/ node, /*String*/ name){ - // summary: - // Removes an attribute from an HTML element. - // node: - // id or reference to the element to remove the attribute from - // name: - // the name of the attribute to remove - byId(node).removeAttribute(_fixAttrName(name)); - }; - - dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){ - // summary: - // Returns an effective value of a property or an attribute. - // node: - // id or reference to the element to remove the attribute from - // name: - // the name of the attribute - node = byId(node); - var lc = name.toLowerCase(), - propName = _propNames[lc] || name; - if((propName in node) && propName != "href"){ - // node's property - return node[propName]; // Anything - } - // node's attribute - var attrName = _attrNames[lc] || name; - return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything - }; - - dojo.create = function(tag, attrs, refNode, pos){ - // summary: - // Create an element, allowing for optional attribute decoration - // and placement. - // - // description: - // A DOM Element creation function. A shorthand method for creating a node or - // a fragment, and allowing for a convenient optional attribute setting step, - // as well as an optional DOM placement reference. - //| - // Attributes are set by passing the optional object through `dojo.attr`. - // See `dojo.attr` for noted caveats and nuances, and API if applicable. - //| - // Placement is done via `dojo.place`, assuming the new node to be the action - // node, passing along the optional reference node and position. - // - // tag: String|DomNode - // A string of the element to create (eg: "div", "a", "p", "li", "script", "br"), - // or an existing DOM node to process. - // - // attrs: Object - // An object-hash of attributes to set on the newly created node. - // Can be null, if you don't want to set any attributes/styles. - // See: `dojo.attr` for a description of available attributes. - // - // refNode: String?|DomNode? - // Optional reference node. Used by `dojo.place` to place the newly created - // node somewhere in the dom relative to refNode. Can be a DomNode reference - // or String ID of a node. - // - // pos: String? - // Optional positional reference. Defaults to "last" by way of `dojo.place`, - // though can be set to "first","after","before","last", "replace" or "only" - // to further control the placement of the new node relative to the refNode. - // 'refNode' is required if a 'pos' is specified. - // - // returns: DomNode - // - // example: - // Create a DIV: - // | var n = dojo.create("div"); - // - // example: - // Create a DIV with content: - // | var n = dojo.create("div", { innerHTML:"

    hi

    " }); - // - // example: - // Place a new DIV in the BODY, with no attributes set - // | var n = dojo.create("div", null, dojo.body()); - // - // example: - // Create an UL, and populate it with LI's. Place the list as the first-child of a - // node with id="someId": - // | var ul = dojo.create("ul", null, "someId", "first"); - // | var items = ["one", "two", "three", "four"]; - // | dojo.forEach(items, function(data){ - // | dojo.create("li", { innerHTML: data }, ul); - // | }); - // - // example: - // Create an anchor, with an href. Place in BODY: - // | dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body()); - // - // example: - // Create a `dojo.NodeList()` from a new element (for syntatic sugar): - // | dojo.query(dojo.create('div')) - // | .addClass("newDiv") - // | .onclick(function(e){ console.log('clicked', e.target) }) - // | .place("#someNode"); // redundant, but cleaner. - - var doc = d.doc; - if(refNode){ - refNode = byId(refNode); - doc = refNode.ownerDocument; - } - if(typeof tag == "string"){ // inline'd type check - tag = doc.createElement(tag); - } - if(attrs){ d.attr(tag, attrs); } - if(refNode){ d.place(tag, refNode, pos); } - return tag; // DomNode - }; - - /*===== - dojo.empty = function(node){ - // summary: - // safely removes all children of the node. - // node: DOMNode|String - // a reference to a DOM node or an id. - // example: - // Destroy node's children byId: - // | dojo.empty("someId"); - // - // example: - // Destroy all nodes' children in a list by reference: - // | dojo.query(".someNode").forEach(dojo.empty); - } - =====*/ - - d.empty = - d.isIE ? function(node){ - node = byId(node); - for(var c; c = node.lastChild;){ // intentional assignment - d.destroy(c); - } - } : - function(node){ - byId(node).innerHTML = ""; - }; - - /*===== - dojo._toDom = function(frag, doc){ - // summary: - // instantiates an HTML fragment returning the corresponding DOM. - // frag: String - // the HTML fragment - // doc: DocumentNode? - // optional document to use when creating DOM nodes, defaults to - // dojo.doc if not specified. - // returns: DocumentFragment - // - // example: - // Create a table row: - // | var tr = dojo._toDom("First!"); - } - =====*/ - - // support stuff for dojo._toDom - var tagWrap = { - option: ["select"], - tbody: ["table"], - thead: ["table"], - tfoot: ["table"], - tr: ["table", "tbody"], - td: ["table", "tbody", "tr"], - th: ["table", "thead", "tr"], - legend: ["fieldset"], - caption: ["table"], - colgroup: ["table"], - col: ["table", "colgroup"], - li: ["ul"] - }, - reTag = /<\s*([\w\:]+)/, - masterNode = {}, masterNum = 0, - masterName = "__" + d._scopeName + "ToDomId"; - - // generate start/end tag strings to use - // for the injection for each special tag wrap case. - for(var param in tagWrap){ - if(tagWrap.hasOwnProperty(param)){ - var tw = tagWrap[param]; - tw.pre = param == "option" ? '