diff options
Diffstat (limited to 'lib/dojo/NodeList-traverse.js')
-rw-r--r-- | lib/dojo/NodeList-traverse.js | 628 |
1 files changed, 507 insertions, 121 deletions
diff --git a/lib/dojo/NodeList-traverse.js b/lib/dojo/NodeList-traverse.js index 4fda2e7ea..b5314eed6 100644 --- a/lib/dojo/NodeList-traverse.js +++ b/lib/dojo/NodeList-traverse.js @@ -5,127 +5,513 @@ */ -if(!dojo._hasResource["dojo.NodeList-traverse"]){ -dojo._hasResource["dojo.NodeList-traverse"]=true; +if(!dojo._hasResource["dojo.NodeList-traverse"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.NodeList-traverse"] = true; dojo.provide("dojo.NodeList-traverse"); -dojo.extend(dojo.NodeList,{_buildArrayFromCallback:function(_1){ -var _2=[]; -for(var i=0;i<this.length;i++){ -var _3=_1.call(this[i],this[i],_2); -if(_3){ -_2=_2.concat(_3); -} -} -return _2; -},_filterQueryResult:function(_4,_5){ -var _6=dojo.filter(_4,function(_7){ -return dojo.query(_5,_7.parentNode).indexOf(_7)!=-1; -}); -var _8=this._wrap(_6); -return _8; -},_getUniqueAsNodeList:function(_9){ -var _a=[]; -for(var i=0,_b;_b=_9[i];i++){ -if(_b.nodeType==1&&dojo.indexOf(_a,_b)==-1){ -_a.push(_b); -} -} -return this._wrap(_a,null,this._NodeListCtor); -},_getUniqueNodeListWithParent:function(_c,_d){ -var _e=this._getUniqueAsNodeList(_c); -_e=(_d?this._filterQueryResult(_e,_d):_e); -return _e._stash(this); -},_getRelatedUniqueNodes:function(_f,_10){ -return this._getUniqueNodeListWithParent(this._buildArrayFromCallback(_10),_f); -},children:function(_11){ -return this._getRelatedUniqueNodes(_11,function(_12,ary){ -return dojo._toArray(_12.childNodes); -}); -},closest:function(_13){ -var _14=this; -return this._getRelatedUniqueNodes(_13,function(_15,ary){ -do{ -if(_14._filterQueryResult([_15],_13).length){ -return _15; -} -}while((_15=_15.parentNode)&&_15.nodeType==1); -return null; -}); -},parent:function(_16){ -return this._getRelatedUniqueNodes(_16,function(_17,ary){ -return _17.parentNode; -}); -},parents:function(_18){ -return this._getRelatedUniqueNodes(_18,function(_19,ary){ -var _1a=[]; -while(_19.parentNode){ -_19=_19.parentNode; -_1a.push(_19); -} -return _1a; -}); -},siblings:function(_1b){ -return this._getRelatedUniqueNodes(_1b,function(_1c,ary){ -var _1d=[]; -var _1e=(_1c.parentNode&&_1c.parentNode.childNodes); -for(var i=0;i<_1e.length;i++){ -if(_1e[i]!=_1c){ -_1d.push(_1e[i]); -} -} -return _1d; -}); -},next:function(_1f){ -return this._getRelatedUniqueNodes(_1f,function(_20,ary){ -var _21=_20.nextSibling; -while(_21&&_21.nodeType!=1){ -_21=_21.nextSibling; -} -return _21; -}); -},nextAll:function(_22){ -return this._getRelatedUniqueNodes(_22,function(_23,ary){ -var _24=[]; -var _25=_23; -while((_25=_25.nextSibling)){ -if(_25.nodeType==1){ -_24.push(_25); -} -} -return _24; -}); -},prev:function(_26){ -return this._getRelatedUniqueNodes(_26,function(_27,ary){ -var _28=_27.previousSibling; -while(_28&&_28.nodeType!=1){ -_28=_28.previousSibling; -} -return _28; -}); -},prevAll:function(_29){ -return this._getRelatedUniqueNodes(_29,function(_2a,ary){ -var _2b=[]; -var _2c=_2a; -while((_2c=_2c.previousSibling)){ -if(_2c.nodeType==1){ -_2b.push(_2c); -} -} -return _2b; -}); -},andSelf:function(){ -return this.concat(this._parent); -},first:function(){ -return this._wrap(((this[0]&&[this[0]])||[]),this); -},last:function(){ -return this._wrap((this.length?[this[this.length-1]]:[]),this); -},even:function(){ -return this.filter(function(_2d,i){ -return i%2!=0; -}); -},odd:function(){ -return this.filter(function(_2e,i){ -return i%2==0; + +/*===== +dojo["NodeList-traverse"] = { + // summary: Adds a chainable methods to dojo.query() / Nodelist instances for traversing the DOM +}; +=====*/ + +dojo.extend(dojo.NodeList, { + _buildArrayFromCallback: function(/*Function*/callback){ + // summary: + // builds a new array of possibly differing size based on the input list. + // Since the returned array is likely of different size than the input array, + // the array's map function cannot be used. + var ary = []; + for(var i = 0; i < this.length; i++){ + var items = callback.call(this[i], this[i], ary); + if(items){ + ary = ary.concat(items); + } + } + return ary; + }, + + _filterQueryResult: function(nodeList, query){ + // summmary: + // Replacement for dojo._filterQueryResult that does a full + // query. Slower, but allows for more types of queries. + var filter = dojo.filter(nodeList, function(node){ + return dojo.query(query, node.parentNode).indexOf(node) != -1; + }); + var result = this._wrap(filter); + return result; + }, + + _getUniqueAsNodeList: function(nodes){ + // summary: + // given a list of nodes, make sure only unique + // elements are returned as our NodeList object. + // Does not call _stash(). + var ary = []; + //Using for loop for better speed. + for(var i = 0, node; node = nodes[i]; i++){ + //Should be a faster way to do this. dojo.query has a private + //_zip function that may be inspirational, but there are pathways + //in query that force nozip? + if(node.nodeType == 1 && dojo.indexOf(ary, node) == -1){ + ary.push(node); + } + } + return this._wrap(ary, null, this._NodeListCtor); //dojo.NodeList + }, + + _getUniqueNodeListWithParent: function(nodes, query){ + // summary: + // gets unique element nodes, filters them further + // with an optional query and then calls _stash to track parent NodeList. + var ary = this._getUniqueAsNodeList(nodes); + ary = (query ? this._filterQueryResult(ary, query) : ary); + return ary._stash(this); //dojo.NodeList + }, + + _getRelatedUniqueNodes: function(/*String?*/query, /*Function*/callback){ + // summary: + // cycles over all the nodes and calls a callback + // to collect nodes for a possible inclusion in a result. + // The callback will get two args: callback(node, ary), + // where ary is the array being used to collect the nodes. + return this._getUniqueNodeListWithParent(this._buildArrayFromCallback(callback), query); //dojo.NodeList + }, + + children: function(/*String?*/query){ + // summary: + // Returns all immediate child elements for nodes in this dojo.NodeList. + // Optionally takes a query to filter the child elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, all immediate child elements for the nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".container").children(); + // returns the four divs that are children of the container div. + // Running this code: + // | dojo.query(".container").children(".red"); + // returns the two divs that have the class "red". + return this._getRelatedUniqueNodes(query, function(node, ary){ + return dojo._toArray(node.childNodes); + }); //dojo.NodeList + }, + + closest: function(/*String*/query){ + // summary: + // Returns closest parent that matches query, including current node in this + // dojo.NodeList if it matches the query. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, the closest parent that matches the query, including the current + // node in this dojo.NodeList if it matches the query. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".red").closest(".container"); + // returns the div with class "container". + var self = this; + return this._getRelatedUniqueNodes(query, function(node, ary){ + do{ + if(self._filterQueryResult([node], query).length){ + return node; + } + }while((node = node.parentNode) && node.nodeType == 1); + return null; //To make rhino strict checking happy. + }); //dojo.NodeList + }, + + parent: function(/*String?*/query){ + // summary: + // Returns immediate parent elements for nodes in this dojo.NodeList. + // Optionally takes a query to filter the parent elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, immediate parent elements for nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | <div class="blue first"><span class="text">Blue One</span></div> + // | <div class="red">Red Two</div> + // | <div class="blue"><span class="text">Blue Two</span></div> + // | </div> + // Running this code: + // | dojo.query(".text").parent(); + // returns the two divs with class "blue". + // Running this code: + // | dojo.query(".text").parent(".first"); + // returns the one div with class "blue" and "first". + return this._getRelatedUniqueNodes(query, function(node, ary){ + return node.parentNode; + }); //dojo.NodeList + }, + + parents: function(/*String?*/query){ + // summary: + // Returns all parent elements for nodes in this dojo.NodeList. + // Optionally takes a query to filter the child elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, all parent elements for nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | <div class="blue first"><span class="text">Blue One</span></div> + // | <div class="red">Red Two</div> + // | <div class="blue"><span class="text">Blue Two</span></div> + // | </div> + // Running this code: + // | dojo.query(".text").parents(); + // returns the two divs with class "blue", the div with class "container", + // | the body element and the html element. + // Running this code: + // | dojo.query(".text").parents(".container"); + // returns the one div with class "container". + return this._getRelatedUniqueNodes(query, function(node, ary){ + var pary = [] + while(node.parentNode){ + node = node.parentNode; + pary.push(node); + } + return pary; + }); //dojo.NodeList + }, + + siblings: function(/*String?*/query){ + // summary: + // Returns all sibling elements for nodes in this dojo.NodeList. + // Optionally takes a query to filter the sibling elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, all sibling elements for nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue first">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".first").siblings(); + // returns the two divs with class "red" and the other div + // | with class "blue" that does not have "first". + // Running this code: + // | dojo.query(".first").siblings(".red"); + // returns the two div with class "red". + return this._getRelatedUniqueNodes(query, function(node, ary){ + var pary = [] + var nodes = (node.parentNode && node.parentNode.childNodes); + for(var i = 0; i < nodes.length; i++){ + if(nodes[i] != node){ + pary.push(nodes[i]); + } + } + return pary; + }); //dojo.NodeList + }, + + next: function(/*String?*/query){ + // summary: + // Returns the next element for nodes in this dojo.NodeList. + // Optionally takes a query to filter the next elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, the next element for nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue first">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue last">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".first").next(); + // returns the div with class "red" and has innerHTML of "Red Two". + // Running this code: + // | dojo.query(".last").next(".red"); + // does not return any elements. + return this._getRelatedUniqueNodes(query, function(node, ary){ + var next = node.nextSibling; + while(next && next.nodeType != 1){ + next = next.nextSibling; + } + return next; + }); //dojo.NodeList + }, + + nextAll: function(/*String?*/query){ + // summary: + // Returns all sibling elements that come after the nodes in this dojo.NodeList. + // Optionally takes a query to filter the sibling elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, all sibling elements that come after the nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue first">Blue One</div> + // | <div class="red next">Red Two</div> + // | <div class="blue next">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".first").nextAll(); + // returns the two divs with class of "next". + // Running this code: + // | dojo.query(".first").nextAll(".red"); + // returns the one div with class "red" and innerHTML "Red Two". + return this._getRelatedUniqueNodes(query, function(node, ary){ + var pary = [] + var next = node; + while((next = next.nextSibling)){ + if(next.nodeType == 1){ + pary.push(next); + } + } + return pary; + }); //dojo.NodeList + }, + + prev: function(/*String?*/query){ + // summary: + // Returns the previous element for nodes in this dojo.NodeList. + // Optionally takes a query to filter the previous elements. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, the previous element for nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | Some Text + // | <div class="blue first">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".first").prev(); + // returns the div with class "red" and has innerHTML of "Red One". + // Running this code: + // | dojo.query(".first").prev(".blue"); + // does not return any elements. + return this._getRelatedUniqueNodes(query, function(node, ary){ + var prev = node.previousSibling; + while(prev && prev.nodeType != 1){ + prev = prev.previousSibling; + } + return prev; + }); //dojo.NodeList + }, + + prevAll: function(/*String?*/query){ + // summary: + // Returns all sibling elements that come before the nodes in this dojo.NodeList. + // Optionally takes a query to filter the sibling elements. + // description: + // The returned nodes will be in reverse DOM order -- the first node in the list will + // be the node closest to the original node/NodeList. + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // query: + // a CSS selector. + // returns: + // dojo.NodeList, all sibling elements that come before the nodes in this dojo.NodeList. + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red prev">Red One</div> + // | Some Text + // | <div class="blue prev">Blue One</div> + // | <div class="red second">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".second").prevAll(); + // returns the two divs with class of "prev". + // Running this code: + // | dojo.query(".first").prevAll(".red"); + // returns the one div with class "red prev" and innerHTML "Red One". + return this._getRelatedUniqueNodes(query, function(node, ary){ + var pary = [] + var prev = node; + while((prev = prev.previousSibling)){ + if(prev.nodeType == 1){ + pary.push(prev); + } + } + return pary; + }); //dojo.NodeList + }, + + andSelf: function(){ + // summary: + // Adds the nodes from the previous dojo.NodeList to the current dojo.NodeList. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // returns: + // dojo.NodeList + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red prev">Red One</div> + // | Some Text + // | <div class="blue prev">Blue One</div> + // | <div class="red second">Red Two</div> + // | <div class="blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".second").prevAll().andSelf(); + // returns the two divs with class of "prev", as well as the div with class "second". + return this.concat(this._parent); + }, + + //Alternate methods for the :first/:last/:even/:odd pseudos. + first: function(){ + // summary: + // Returns the first node in this dojo.NodeList as a dojo.NodeList. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // returns: + // dojo.NodeList, with the first node in this dojo.NodeList + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | <div class="blue first">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue last">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".blue").first(); + // returns the div with class "blue" and "first". + return this._wrap(((this[0] && [this[0]]) || []), this); //dojo.NodeList + }, + + last: function(){ + // summary: + // Returns the last node in this dojo.NodeList as a dojo.NodeList. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // returns: + // dojo.NodeList, with the last node in this dojo.NodeList + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="red">Red One</div> + // | <div class="blue first">Blue One</div> + // | <div class="red">Red Two</div> + // | <div class="blue last">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".blue").last(); + // returns the last div with class "blue", + return this._wrap((this.length ? [this[this.length - 1]] : []), this); //dojo.NodeList + }, + + even: function(){ + // summary: + // Returns the even nodes in this dojo.NodeList as a dojo.NodeList. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // returns: + // dojo.NodeList, with the even nodes in this dojo.NodeList + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="interior red">Red One</div> + // | <div class="interior blue">Blue One</div> + // | <div class="interior red">Red Two</div> + // | <div class="interior blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".interior").even(); + // returns the two divs with class "blue" + return this.filter(function(item, i){ + return i % 2 != 0; + }); //dojo.NodeList + }, + + odd: function(){ + // summary: + // Returns the odd nodes in this dojo.NodeList as a dojo.NodeList. + // description: + // .end() can be used on the returned dojo.NodeList to get back to the + // original dojo.NodeList. + // returns: + // dojo.NodeList, with the odd nodes in this dojo.NodeList + // example: + // assume a DOM created by this markup: + // | <div class="container"> + // | <div class="interior red">Red One</div> + // | <div class="interior blue">Blue One</div> + // | <div class="interior red">Red Two</div> + // | <div class="interior blue">Blue Two</div> + // | </div> + // Running this code: + // | dojo.query(".interior").odd(); + // returns the two divs with class "red" + return this.filter(function(item, i){ + return i % 2 == 0; + }); //dojo.NodeList + } }); -}}); + } |