diff options
Diffstat (limited to 'includes/js/dojo/_base/html.js')
-rw-r--r-- | includes/js/dojo/_base/html.js | 1227 |
1 files changed, 0 insertions, 1227 deletions
diff --git a/includes/js/dojo/_base/html.js b/includes/js/dojo/_base/html.js deleted file mode 100644 index d673eb1..0000000 --- a/includes/js/dojo/_base/html.js +++ /dev/null @@ -1,1227 +0,0 @@ -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.require("dojo._base.lang"); -dojo.provide("dojo._base.html"); - -// 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, similar to "$" function in another library. - // 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. -=====*/ -if(dojo.isIE || dojo.isOpera){ - dojo.byId = function(id, doc){ - if(dojo.isString(id)){ - var _d = doc || dojo.doc; - var 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){ - return te; - }else{ - var eles = _d.all[id]; - if(!eles || !eles.length){ return eles; } - // if more than 1, choose first with the correct id - var i=0; - while((te=eles[i++])){ - if(te.attributes.id.value == id){ return te; } - } - } - }else{ - return id; // DomNode - } - } -}else{ - dojo.byId = function(id, doc){ - return dojo.isString(id) ? (doc || dojo.doc).getElementById(id) : id; // DomNode - } -} -/*===== -} -=====*/ - -(function(){ - /* - dojo.createElement = function(obj, parent, position){ - // TODO: need to finish this! - } - */ - - var d = dojo; - - var _destroyContainer = null; - dojo.addOnUnload(function(){ - _destroyContainer=null; //prevent IE leak - }); - dojo._destroyElement = function(/*String||DomNode*/node){ - // summary: - // removes node from its parent, clobbers it and all of its - // children. - // node: - // the element to be destroyed, either as an ID or a reference - - node = d.byId(node); - try{ - if(!_destroyContainer){ - _destroyContainer = document.createElement("div"); - } - _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: id or node reference to test - // ancestor: id or node reference of potential parent to test against - try{ - node = d.byId(node); - ancestor = d.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: - node = d.byId(node); - if(d.isMozilla){ - node.style.MozUserSelect = selectable ? "" : "none"; - }else if(d.isKhtml){ - node.style.KhtmlUserSelect = selectable ? "auto" : "none"; - }else if(d.isIE){ - node.unselectable = selectable ? "" : "on"; - d.query("*", node).forEach(function(descendant){ - descendant.unselectable = selectable ? "" : "on"; - }); - } - //FIXME: else? Opera? - }; - - var _insertBefore = function(/*Node*/node, /*Node*/ref){ - ref.parentNode.insertBefore(node, ref); - return true; // boolean - } - - var _insertAfter = function(/*Node*/node, /*Node*/ref){ - // summary: - // Try to insert node after ref - var pn = ref.parentNode; - if(ref == pn.lastChild){ - pn.appendChild(node); - }else{ - return _insertBefore(node, ref.nextSibling); // boolean - } - return true; // boolean - } - - dojo.place = function(/*String|DomNode*/node, /*String|DomNode*/refNode, /*String|Number*/position){ - // summary: - // Attempt to insert node into the DOM, choosing from various positioning options. - // Returns true if successful, false otherwise. - // node: - // id or node reference to place relative to refNode - // refNode: - // id or node reference to use as basis for placement - // position: - // 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 - // * first - // * last - // - // "first" and "last" indicate positions as children of refNode. - - // FIXME: need to write tests for this!!!! - if(!node || !refNode || position === undefined){ - return false; // boolean - } - node = d.byId(node); - refNode = d.byId(refNode); - if(typeof position == "number"){ - var cn = refNode.childNodes; - if((position == 0 && cn.length == 0) || - cn.length == position){ - refNode.appendChild(node); return true; - } - if(position == 0){ - return _insertBefore(node, refNode.firstChild); - } - return _insertAfter(node, cn[position-1]); - } - switch(position.toLowerCase()){ - case "before": - return _insertBefore(node, refNode); // boolean - case "after": - return _insertAfter(node, refNode); // boolean - case "first": - if(refNode.firstChild){ - return _insertBefore(node, refNode.firstChild); // boolean - } - // else fallthrough... - default: // aka: last - refNode.appendChild(node); - return true; // boolean - } - } - - // Box functions will assume this model. - // On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode. - // Can be set to change behavior of box setters. - - // can be either: - // "border-box" - // "content-box" (default) - dojo.boxModel = "content-box"; - - // We punt per-node box mode testing completely. - // If anybody cares, we can provide an additional (optional) unit - // that overrides existing code to include per-node box sensitivity. - - // Opera documentation claims that Opera 9 uses border-box in BackCompat mode. - // but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box. - // IIRC, earlier versions of Opera did in fact use border-box. - // Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault. - - if(d.isIE /*|| dojo.isOpera*/){ - var _dcm = document.compatMode; - // client code may have to adjust if compatMode varies across iframes - d.boxModel = _dcm == "BackCompat" || _dcm == "QuirksMode" || d.isIE<6 ? "border-box" : "content-box"; // FIXME: remove IE < 6 support? - } - - // ============================= - // Style Functions - // ============================= - - // getComputedStyle drives most of the style code. - // Wherever possible, reuse the returned object. - // - // API functions below that need to access computed styles accept an - // optional computedStyle parameter. - // If this parameter is omitted, the functions will call getComputedStyle themselves. - // This way, calling code can access computedStyle once, and then pass the reference to - // multiple API functions. - -/*===== - dojo.getComputedStyle = function(node){ - // summary: - // Returns a "computed style" object. - // - // description: - // Gets a "computed style" object which can be used to gather - // information about the current state of the rendered node. - // - // Note that this may behave differently on different browsers. - // Values may have different formats and value encodings across - // browsers. - // - // Note also that this method is expensive. Wherever possible, - // reuse the returned object. - // - // Use the dojo.style() method for more consistent (pixelized) - // return values. - // - // node: DOMNode - // A reference to a DOM node. Does NOT support taking an - // ID string for speed reasons. - // example: - // | dojo.getComputedStyle(dojo.byId('foo')).borderWidth; - return; // CSS2Properties - } -=====*/ - - var gcs, dv = document.defaultView; - if(d.isSafari){ - gcs = function(/*DomNode*/node){ - var s = dv.getComputedStyle(node, null); - if(!s && node.style){ - node.style.display = ""; - s = dv.getComputedStyle(node, null); - } - return s || {}; - }; - }else if(d.isIE){ - gcs = function(node){ - return node.currentStyle; - }; - }else{ - gcs = function(node){ - return dv.getComputedStyle(node, null); - }; - } - dojo.getComputedStyle = gcs; - - if(!d.isIE){ - dojo._toPixelValue = function(element, value){ - // style values can be floats, client code may want - // to round for integer pixels. - return parseFloat(value) || 0; - } - }else{ - dojo._toPixelValue = function(element, avalue){ - if(!avalue){ return 0; } - // on IE7, medium is usually 4 pixels - if(avalue=="medium"){ return 4; } - // style values can be floats, client code may - // want to round this value for integer pixels. - if(avalue.slice && (avalue.slice(-2)=='px')){ return parseFloat(avalue); } - with(element){ - var sLeft = style.left; - var rsLeft = runtimeStyle.left; - runtimeStyle.left = currentStyle.left; - try{ - // 'avalue' may be incompatible with style.left, which can cause IE to throw - // this has been observed for border widths using "thin", "medium", "thick" constants - // those particular constants could be trapped by a lookup - // but perhaps there are more - style.left = avalue; - avalue = style.pixelLeft; - }catch(e){ - avalue = 0; - } - style.left = sLeft; - runtimeStyle.left = rsLeft; - } - return avalue; - } - } - var px = d._toPixelValue; - - // FIXME: there opacity quirks on FF that we haven't ported over. Hrm. - /*===== - dojo._getOpacity = function(node){ - // summary: - // Returns the current opacity of the passed node as a - // floating-point value between 0 and 1. - // node: DomNode - // a reference to a DOM node. Does NOT support taking an - // ID string for speed reasons. - // return: Number between 0 and 1 - } - =====*/ - - dojo._getOpacity = d.isIE ? function(node){ - try{ - return node.filters.alpha.opacity / 100; // Number - }catch(e){ - return 1; // Number - } - } : function(node){ - return gcs(node).opacity; - }; - - /*===== - dojo._setOpacity = function(node, opacity){ - // summary: - // set the opacity of the passed node portably. Returns the - // new opacity of the node. - // node: DOMNode - // a reference to a DOM node. Does NOT support taking an - // ID string for performance reasons. - // opacity: Number - // A Number between 0 and 1. 0 specifies transparent. - // return: Number between 0 and 1 - } - =====*/ - - dojo._setOpacity = d.isIE ? function(/*DomNode*/node, /*Number*/opacity){ - if(opacity == 1){ - // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so remove it altogether (bug #2661) - var filterRE = /FILTER:[^;]*;?/i; - node.style.cssText = node.style.cssText.replace(filterRE, ""); - if(node.nodeName.toLowerCase() == "tr"){ - d.query("> td", node).forEach(function(i){ - i.style.cssText = i.style.cssText.replace(filterRE, ""); - }); - } - }else{ - var o = "Alpha(Opacity="+ opacity * 100 +")"; - node.style.filter = o; - } - if(node.nodeName.toLowerCase() == "tr"){ - d.query("> td", node).forEach(function(i){ - i.style.filter = o; - }); - } - 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(); - if(d.isIE && value == "auto"){ - if(type == "height"){ return node.offsetHeight; } - if(type == "width"){ return node.offsetWidth; } - } - if(!(type in _pixelNamesCache)){ - // if(dojo.isOpera && type == "cssText"){ - // FIXME: add workaround for #2855 here - // } - _pixelNamesCache[type] = _pixelRegExp.test(type); - } - return _pixelNamesCache[type] ? px(node, value) : value; - } - - var _floatStyle = d.isIE ? "styleFloat" : "cssFloat"; - var _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. - // 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. - // 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": 300 - // | }); - // - // 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 = d.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 && !d.isString(style)){ - for(var x in style){ - d.style(node, x, style[x]); - } - return s; - } - return (args == 1) ? s : _toStyleValue(n, style, s[style]); /* CSS2Properties||String||Number */ - } - - // ============================= - // Box Functions - // ============================= - - dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // Returns object with special values specifically useful for node - // fitting. - // - // * 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. - // - // * 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. - // - // * 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.isSafari && (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; - 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. - var p = node.parentNode; - 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){ - // On Opera, offsetLeft includes the parent's border - var p = node.parentNode; - if(p){ - var 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._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: optional. left offset from parent. - // t: optional. top offset from parent. - // w: optional. width in current box model. - // h: optional. width in current box model. - // u: optional. 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._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. - var n = node.tagName; - // For whatever reason, TABLE and BUTTON are always border-box by default. - // If you have assigned a different box to either one via CSS then - // box functions will break. - return d.boxModel=="border-box" || n=="TABLE" || n=="BUTTON"; // 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. - var bb=d._usesBorderBox(node), - pb=bb ? _nilExtents : d._getPadBorderExtents(node, s), - 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: - // 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. - var n=d.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. - // 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. All properties are optional if passed. - var n=dojo.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 - _b = d.body(), - _w = d.global, - de = d.doc.documentElement; - return { - y: (_w.pageYOffset || de.scrollTop || _b.scrollTop || 0), - x: (_w.pageXOffset || d._fixIeBiDiScrollLeft(de.scrollLeft) || _b.scrollLeft || 0) - }; - }; - - dojo._isBodyLtr = function(){ - //FIXME: could check html and body tags directly instead of computed style? need to ignore case, accept empty values - return !("_bodyLtr" in d) ? - d._bodyLtr = gcs(d.body()).direction == "ltr" : - d._bodyLtr; // Boolean - } - - dojo._getIeDocumentElementOffset = function(){ - // summary - // 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; - //FIXME: use this instead? var de = d.compatMode == "BackCompat" ? d.body : d.documentElement; - - return (d.isIE >= 7) ? - {x: de.getBoundingClientRect().left, y: de.getBoundingClientRect().top} - : - // IE 6.0 - {x: d._isBodyLtr() || window.parent == window ? - de.clientLeft : de.offsetWidth - de.clientWidth - de.clientLeft, - y: de.clientTop}; // Object - }; - - 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 dd = d.doc; - if(d.isIE && !dojo._isBodyLtr()){ - var de = dd.compatMode == "BackCompat" ? dd.body : dd.documentElement; - return scrollLeft + de.clientWidth - de.scrollWidth; // Integer - } - return scrollLeft; // Integer - } - - dojo._abs = function(/*DomNode*/node, /*Boolean?*/includeScroll){ - // summary: - // Gets the position of the passed element relative to - // the viewport (if includeScroll==false), or relative to the - // document root (if includeScroll==true). - // - // Returns an object of the form: - // { x: 100, y: 300 } - // if includeScroll is passed, the x and y values will include any - // document offsets that may affect the position relative to the - // viewport. - - // FIXME: need to decide in the brave-new-world if we're going to be - // margin-box or border-box. - var ownerDocument = node.ownerDocument; - var ret = { - x: 0, - y: 0 - }; - - // targetBoxType == "border-box" - var db = d.body(); - if(d.isIE || (d.isFF >= 3)){ - var client = node.getBoundingClientRect(); - var offset = (d.isIE) ? d._getIeDocumentElementOffset() : { x: 0, y: 0}; - ret.x = client.left - offset.x; - ret.y = client.top - offset.y; - }else if(ownerDocument["getBoxObjectFor"]){ - // mozilla - var bo = ownerDocument.getBoxObjectFor(node), - b = d._getBorderExtents(node); - ret.x = bo.x - b.l - _sumAncestorProperties(node, "scrollLeft"); - ret.y = bo.y - b.t - _sumAncestorProperties(node, "scrollTop"); - }else{ - if(node["offsetParent"]){ - var endNode; - // in Safari, if the node is an absolutely positioned child of - // the body and the body has a margin the offset of the child - // and the body contain the body's margins, so we need to end - // at the body - // FIXME: getting contrary results to the above in latest WebKit. - if(d.isSafari && - //(node.style.getPropertyValue("position") == "absolute") && - (gcs(node).position == "absolute") && - (node.parentNode == db)){ - endNode = db; - }else{ - endNode = db.parentNode; - } - if(node.parentNode != db){ - var nd = node; - if(d.isOpera){ nd = db; } - ret.x -= _sumAncestorProperties(nd, "scrollLeft"); - ret.y -= _sumAncestorProperties(nd, "scrollTop"); - } - var curnode = node; - do{ - var n = curnode.offsetLeft; - //FIXME: ugly hack to workaround the submenu in - //popupmenu2 does not shown up correctly in opera. - //Someone have a better workaround? - if(!d.isOpera || n > 0){ - ret.x += isNaN(n) ? 0 : n; - } - var t = curnode.offsetTop; - ret.y += isNaN(t) ? 0 : t; - if(d.isSafari && curnode != node){ - var cs = gcs(curnode); - ret.x += px(curnode, cs.borderLeftWidth); - ret.y += px(curnode, cs.borderTopWidth); - } - curnode = curnode.offsetParent; - }while((curnode != endNode) && curnode); - }else if(node.x && node.y){ - ret.x += isNaN(node.x) ? 0 : node.x; - ret.y += isNaN(node.y) ? 0 : node.y; - } - } - // account for document scrolling - // if offsetParent is used, ret value already includes scroll position - // so we may have to actually remove that value if !includeScroll - if(includeScroll){ - var scroll = d._docScroll(); - ret.y += scroll.y; - ret.x += scroll.x; - } - - return ret; // object - } - - // FIXME: need a setter for coords or a moveTo!! - dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){ - // summary: - // Returns an object that measures margin box width/height and - // absolute positioning data from dojo._abs(). - // - // description: - // Returns an object that measures margin box width/height and - // absolute positioning data from dojo._abs(). - // 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._abs(). - var n=d.byId(node), s=gcs(n), mb=d._getMarginBox(n, s); - var abs = d._abs(n, includeScroll); - mb.x = abs.x; - mb.y = abs.y; - return mb; - } - - // ============================= - // Element attribute Functions - // ============================= - - var _fixAttrName = function(/*String*/name){ - switch(name.toLowerCase()){ - case "tabindex": - // Internet Explorer will only set or remove tabindex - // if it is spelled "tabIndex" - // console.debug((dojo.isIE && dojo.isIE < 8)? "tabIndex" : "tabindex"); - return (d.isIE && d.isIE < 8) ? "tabIndex" : "tabindex"; - default: - return name; - } - } - - // non-deprecated HTML4 attributes with default values - // http://www.w3.org/TR/html401/index/attributes.html - // FF and Safari will return the default values if you - // access the attributes via a property but not - // via getAttribute() - var _attrProps = { - colspan: "colSpan", - enctype: "enctype", - frameborder: "frameborder", - method: "method", - rowspan: "rowSpan", - scrolling: "scrolling", - shape: "shape", - span: "span", - type: "type", - valuetype: "valueType" - } - - 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 attr = d.byId(node).getAttributeNode(_fixAttrName(name)); - return attr ? attr.specified : false; // Boolean - } - - var _evtHdlrMap = { - - } - - var _ctr = 0; - var _attrId = dojo._scopeName + "attrid"; - - 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 argumnt 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 user as a setter, undefined - // example: - // | // get the current value of the "foo" attribute on a node - // | dojo.attr(dojo.byId("nodeId"), "foo"); - // | - // | // we can just pass the id: - // | dojo.attr("nodeId", "foo"); - // | - // | // use attr() to set the tab index - // | dojo.attr("nodeId", "tabindex", 3); - // | - // | // 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" }); - // | } - // | }); - - var args = arguments.length; - if(args == 2 && !d.isString(name)){ - for(var x in name){ d.attr(node, x, name[x]); } - return; - } - node = d.byId(node); - name = _fixAttrName(name); - if(args == 3){ - if(d.isFunction(value)){ - // 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][name]; - if(h){ - d.disconnect(h); - }else{ - try{ - delete node[name]; - }catch(e){} - } - - // ensure that event objects are normalized, etc. - _evtHdlrMap[attrId][name] = d.connect(node, name, value); - - }else if(typeof value == "boolean"){ // e.g. onsubmit, disabled - // if a function, we should normalize the event object here!!! - node[name] = value; - }else{ - node.setAttribute(name, value); - } - return; - }else{ - // should we access this attribute via a property or - // via getAttribute()? - var prop = _attrProps[name.toLowerCase()]; - if(prop){ - return node[prop]; - }else{ - var value = node[name]; - return (typeof value == 'boolean' || typeof value == 'function') ? value : (d.hasAttr(node, name) ? node.getAttribute(name) : null); - } - } - } - - 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 - d.byId(node).removeAttribute(_fixAttrName(name)); - } -})(); - -// ============================= -// (CSS) Class Functions -// ============================= - -dojo.hasClass = function(/*DomNode|String*/node, /*String*/classStr){ - // summary: - // Returns whether or not the specified classes are a portion of the - // class list currently applied to the node. - return ((" "+dojo.byId(node).className+" ").indexOf(" "+classStr+" ") >= 0); // Boolean -}; - -dojo.addClass = function(/*DomNode|String*/node, /*String*/classStr){ - // summary: - // Adds the specified classes to the end of the class list on the - // passed node. - node = dojo.byId(node); - var cls = node.className; - if((" "+cls+" ").indexOf(" "+classStr+" ") < 0){ - node.className = cls + (cls ? ' ' : '') + classStr; - } -}; - -dojo.removeClass = function(/*DomNode|String*/node, /*String*/classStr){ - // summary: Removes the specified classes from node. - node = dojo.byId(node); - var t = dojo.trim((" " + node.className + " ").replace(" " + classStr + " ", " ")); - if(node.className != t){ node.className = t; } -}; - -dojo.toggleClass = function(/*DomNode|String*/node, /*String*/classStr, /*Boolean?*/condition){ - // summary: - // Adds a class to node if not present, or removes if present. - // Pass a boolean condition if you want to explicitly add or remove. - // condition: - // If passed, true means to add the class, false means to remove. - if(condition === undefined){ - condition = !dojo.hasClass(node, classStr); - } - dojo[condition ? "addClass" : "removeClass"](node, classStr); -}; - -} |