summaryrefslogtreecommitdiff
path: root/lib/dojo/_base/html.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dojo/_base/html.js')
-rw-r--r--lib/dojo/_base/html.js266
1 files changed, 134 insertions, 132 deletions
diff --git a/lib/dojo/_base/html.js b/lib/dojo/_base/html.js
index be5fd2aaa..8661b2b12 100644
--- a/lib/dojo/_base/html.js
+++ b/lib/dojo/_base/html.js
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
+ Copyright (c) 2004-2011, 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
*/
@@ -7,8 +7,9 @@
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");
+dojo.require("dojo._base.lang");
+
// FIXME: need to add unit tests for all the semi-public methods
@@ -53,13 +54,13 @@ dojo.byId = function(id, doc){
// | }
=====*/
-if(dojo.isIE || dojo.isOpera){
+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
+ // 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;
@@ -80,8 +81,9 @@ if(dojo.isIE || dojo.isOpera){
};
}else{
dojo.byId = function(id, doc){
- // inline'd type check
- return (typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id; // DomNode
+ // 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
};
}
/*=====
@@ -164,16 +166,16 @@ if(dojo.isIE || dojo.isOpera){
};
dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
- // summary:
+ // 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
+ // state to put the node in. false indicates unselectable, true
// allows selection.
// example:
// Make the node id="bar" unselectable
- // | dojo.setSelectable("bar");
+ // | dojo.setSelectable("bar");
// example:
// Make the node id="bar" selectable
// | dojo.setSelectable("bar", true);
@@ -256,7 +258,7 @@ if(dojo.isIE || dojo.isOpera){
refNode = byId(refNode);
if(typeof node == "string"){ // inline'd type check
- node = node.charAt(0) == "<" ? d._toDom(node, refNode.ownerDocument) : byId(node);
+ node = /^\s*</.test(node) ? d._toDom(node, refNode.ownerDocument) : byId(node);
}
if(typeof position == "number"){ // inline'd type check
var cn = refNode.childNodes;
@@ -291,7 +293,7 @@ if(dojo.isIE || dojo.isOpera){
}
}
return node; // DomNode
- }
+ };
// Box functions will assume this model.
// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
@@ -303,7 +305,7 @@ if(dojo.isIE || dojo.isOpera){
dojo.boxModel = "content-box";
// We punt per-node box mode testing completely.
- // If anybody cares, we can provide an additional (optional) unit
+ // 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.
@@ -323,10 +325,10 @@ if(dojo.isIE || dojo.isOpera){
// getComputedStyle drives most of the style code.
// Wherever possible, reuse the returned object.
//
- // API functions below that need to access computed styles accept an
+ // 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
+ // This way, calling code can access computedStyle once, and then pass the reference to
// multiple API functions.
/*=====
@@ -365,7 +367,7 @@ if(dojo.isIE || dojo.isOpera){
// Although we normally eschew argument validation at this
// level, here we test argument 'node' for (duck)type,
// by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
- // it is frequently sent to this function even
+ // it is frequently sent to this function even
// though it is not Element.
var gcs;
if(d.isWebKit){
@@ -426,7 +428,7 @@ if(dojo.isIE || dojo.isOpera){
runtimeStyle.left = rsLeft;
}
return avalue;
- }
+ };
}
var px = d._toPixelValue;
@@ -454,7 +456,7 @@ if(dojo.isIE || dojo.isOpera){
};
dojo._getOpacity =
- d.isIE ? function(node){
+ d.isIE < 9 ? function(node){
try{
return af(node).Opacity / 100; // Number
}catch(e){
@@ -481,7 +483,7 @@ if(dojo.isIE || dojo.isOpera){
=====*/
dojo._setOpacity =
- d.isIE ? function(/*DomNode*/node, /*Number*/opacity){
+ d.isIE < 9 ? function(/*DomNode*/node, /*Number*/opacity){
var ov = opacity * 100, opaque = opacity == 1;
node.style.zoom = opaque ? "" : 1;
@@ -553,7 +555,7 @@ if(dojo.isIE || dojo.isOpera){
// 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()`,
+ // 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
@@ -622,7 +624,7 @@ if(dojo.isIE || dojo.isOpera){
return s;
}
return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */
- }
+ };
// =============================
// Box Functions
@@ -635,13 +637,13 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ // | 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
+ var
s = computedStyle||gcs(n),
l = px(n, s.paddingLeft),
t = px(n, s.paddingTop);
@@ -651,7 +653,7 @@ if(dojo.isIE || dojo.isOpera){
w: l+px(n, s.paddingRight),
h: t+px(n, s.paddingBottom)
};
- }
+ };
dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
// summary:
@@ -665,7 +667,7 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ var
ne = "none",
s = computedStyle||gcs(n),
bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0),
@@ -676,7 +678,7 @@ if(dojo.isIE || dojo.isOpera){
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:
@@ -690,7 +692,7 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ var
s = computedStyle||gcs(n),
p = d._getPadExtents(n, s),
b = d._getBorderExtents(n, s);
@@ -700,7 +702,7 @@ if(dojo.isIE || dojo.isOpera){
w: p.w + b.w,
h: p.h + b.h
};
- }
+ };
dojo._getMarginExtents = function(n, computedStyle){
// summary:
@@ -714,7 +716,7 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ var
s = computedStyle||gcs(n),
l = px(n, s.marginLeft),
t = px(n, s.marginTop),
@@ -722,9 +724,9 @@ if(dojo.isIE || dojo.isOpera){
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
+ // 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
+ // 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;
@@ -735,7 +737,7 @@ if(dojo.isIE || dojo.isOpera){
w: l+r,
h: t+b
};
- }
+ };
// Box getters work in any box context because offsetWidth/clientWidth
// are invariant wrt box context
@@ -743,10 +745,10 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ // 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
+ // 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)
@@ -790,9 +792,23 @@ if(dojo.isIE || dojo.isOpera){
l: l,
t: t,
w: node.offsetWidth + me.w,
- h: node.offsetHeight + me.h
+ 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:
@@ -821,7 +837,7 @@ if(dojo.isIE || dojo.isOpera){
w: w - pe.w - be.w,
h: h - pe.h - be.h
};
- }
+ };
dojo._getBorderBox = function(node, computedStyle){
var s = computedStyle || gcs(node),
@@ -834,7 +850,7 @@ if(dojo.isIE || dojo.isOpera){
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.
@@ -845,12 +861,12 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ // 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
+ // 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){
@@ -876,14 +892,14 @@ if(dojo.isIE || dojo.isOpera){
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:
@@ -898,7 +914,7 @@ if(dojo.isIE || dojo.isOpera){
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:
@@ -910,7 +926,7 @@ if(dojo.isIE || dojo.isOpera){
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,
@@ -942,7 +958,7 @@ if(dojo.isIE || dojo.isOpera){
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 };
@@ -977,7 +993,7 @@ if(dojo.isIE || dojo.isOpera){
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:
@@ -1002,14 +1018,14 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ // Positioning
// =============================
var _sumAncestorProperties = function(node, prop){
- if(!(node = (node||0).parentNode)){return 0}
+ if(!(node = (node||0).parentNode)){return 0;}
var val, retVal = 0, _b = d.body();
while(node && node.style){
if(gcs(node).position == "fixed"){
@@ -1025,19 +1041,19 @@ if(dojo.isIE || dojo.isOpera){
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.doc.documentElement, n.clientHeight? { x:d._fixIeBiDiScrollLeft(n.scrollLeft), y:n.scrollTop } :
- (n=d.body(), { x:n.scrollLeft||0, y:n.scrollTop||0 }));
+ 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
- }
+ d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
+ };
dojo._getIeDocumentElementOffset = function(){
// summary:
@@ -1058,7 +1074,7 @@ if(dojo.isIE || dojo.isOpera){
//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
+ 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+
@@ -1083,18 +1099,22 @@ if(dojo.isIE || dojo.isOpera){
};
dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){
- // In RTL direction, scrollLeft should be a negative value, but IE < 8
+ // 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 < 8 && !d._isBodyLtr()){
- var de = d.isQuirks ? dd.body : dd.documentElement;
- return scrollLeft + de.clientWidth - de.scrollWidth; // Integer
+ 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){
@@ -1112,10 +1132,9 @@ if(dojo.isIE || dojo.isOpera){
// Uses the border-box model (inclusive of border and padding but
// not margin). Does not act as a setter.
- var db = d.body(), dh = db.parentNode, ret;
node = byId(node);
- if(node["getBoundingClientRect"]){
- // IE6+, FF3+, super-modern WebKit, and Opera 9.6+ all take this branch
+ 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){
@@ -1132,60 +1151,7 @@ if(dojo.isIE || dojo.isOpera){
ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth);
ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth);
}
- }else{
- // FF2 and older WebKit
- ret = {
- x: 0,
- y: 0,
- w: node.offsetWidth,
- h: node.offsetHeight
- };
- if(node["offsetParent"]){
- ret.x -= _sumAncestorProperties(node, "scrollLeft");
- ret.y -= _sumAncestorProperties(node, "scrollTop");
-
- var curnode = node;
- do{
- var n = curnode.offsetLeft,
- t = curnode.offsetTop;
- ret.x += isNaN(n) ? 0 : n;
- ret.y += isNaN(t) ? 0 : t;
-
- cs = gcs(curnode);
- if(curnode != node){
- if(d.isMoz){
- // tried left+right with differently sized left/right borders
- // it really is 2xleft border in FF, not left+right, even in RTL!
- ret.x += 2 * px(curnode,cs.borderLeftWidth);
- ret.y += 2 * px(curnode,cs.borderTopWidth);
- }else{
- ret.x += px(curnode, cs.borderLeftWidth);
- ret.y += px(curnode, cs.borderTopWidth);
- }
- }
- // static children in a static div in FF2 are affected by the div's border as well
- // but offsetParent will skip this div!
- if(d.isMoz && cs.position=="static"){
- var parent=curnode.parentNode;
- while(parent!=curnode.offsetParent){
- var pcs=gcs(parent);
- if(pcs.position=="static"){
- ret.x += px(curnode,pcs.borderLeftWidth);
- ret.y += px(curnode,pcs.borderTopWidth);
- }
- parent=parent.parentNode;
- }
- }
- curnode = curnode.offsetParent;
- }while((curnode != dh) && 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
+ // account for document scrolling
if(includeScroll){
var scroll = d._docScroll();
ret.x += scroll.x;
@@ -1193,7 +1159,7 @@ if(dojo.isIE || dojo.isOpera){
}
return ret; // Object
- }
+ };
dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
// summary:
@@ -1215,7 +1181,7 @@ if(dojo.isIE || dojo.isOpera){
mb.x = abs.x;
mb.y = abs.y;
return mb;
- }
+ };
// =============================
// Element attribute Functions
@@ -1277,7 +1243,7 @@ if(dojo.isIE || dojo.isOpera){
// 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",
@@ -1447,7 +1413,7 @@ if(dojo.isIE || dojo.isOpera){
// 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:
@@ -1457,7 +1423,7 @@ if(dojo.isIE || dojo.isOpera){
// name:
// the name of the attribute to remove
byId(node).removeAttribute(_fixAttrName(name));
- }
+ };
dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){
// summary:
@@ -1476,7 +1442,7 @@ if(dojo.isIE || dojo.isOpera){
// 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:
@@ -1491,7 +1457,7 @@ if(dojo.isIE || dojo.isOpera){
// 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
+ // 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
@@ -1529,7 +1495,7 @@ if(dojo.isIE || dojo.isOpera){
// | 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
+ // 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"];
@@ -1559,7 +1525,7 @@ if(dojo.isIE || dojo.isOpera){
if(attrs){ d.attr(tag, attrs); }
if(refNode){ d.place(tag, refNode, pos); }
return tag; // DomNode
- }
+ };
/*=====
dojo.empty = function(node){
@@ -1627,11 +1593,13 @@ if(dojo.isIE || dojo.isOpera){
// generate start/end tag strings to use
// for the injection for each special tag wrap case.
for(var param in tagWrap){
- var tw = tagWrap[param];
- tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
- tw.post = "</" + tw.reverse().join("></") + ">";
- // the last line is destructive: it reverses the array,
- // but we don't care at this point
+ if(tagWrap.hasOwnProperty(param)){
+ var tw = tagWrap[param];
+ tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
+ tw.post = "</" + tw.reverse().join("></") + ">";
+ // the last line is destructive: it reverses the array,
+ // but we don't care at this point
+ }
}
d._toDom = function(frag, doc){
@@ -1674,7 +1642,7 @@ if(dojo.isIE || dojo.isOpera){
df.appendChild(fc);
}
return df; // DOMNode
- }
+ };
// =============================
// (CSS) Class Functions
@@ -1700,6 +1668,7 @@ if(dojo.isIE || dojo.isOpera){
};
var spaces = /\s+/, a1 = [""],
+ fakeNode = {},
str2array = function(s){
if(typeof s == "string" || s instanceof String){
if(s.indexOf(" ") < 0){
@@ -1805,6 +1774,39 @@ if(dojo.isIE || dojo.isOpera){
if(node[_className] != cls){ node[_className] = cls; }
};
+ dojo.replaceClass = function(/*DomNode|String*/node, /*String|Array*/addClassStr, /*String|Array?*/removeClassStr){
+ // summary:
+ // Replaces one or more classes on a node if not present.
+ // Operates more quickly than calling dojo.removeClass and dojo.addClass
+ // node:
+ // String ID or DomNode reference to remove the class from.
+ // addClassStr:
+ // A String class name to add, or several space-separated class names,
+ // or an array of class names.
+ // removeClassStr:
+ // A String class name to remove, or several space-separated class names,
+ // or an array of class names.
+ //
+ // example:
+ // | dojo.replaceClass("someNode", "add1 add2", "remove1 remove2");
+ //
+ // example:
+ // Replace all classes with addMe
+ // | dojo.replaceClass("someNode", "addMe");
+ //
+ // example:
+ // Available in `dojo.NodeList()` for multiple toggles
+ // | dojo.query(".findMe").replaceClass("addMe", "removeMe");
+
+ node = byId(node);
+ fakeNode.className = node.className;
+ dojo.removeClass(fakeNode, removeClassStr);
+ dojo.addClass(fakeNode, addClassStr);
+ if(node.className !== fakeNode.className){
+ node.className = fakeNode.className;
+ }
+ };
+
dojo.toggleClass = function(/*DomNode|String*/node, /*String|Array*/classStr, /*Boolean?*/condition){
// summary:
// Adds a class to node if not present, or removes if present.