]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/NodeList-manipulate.js
build custom layer of Dojo to speed up loading of tt-rss (refs #293)
[tt-rss.git] / lib / dojo / NodeList-manipulate.js
1 /*
2 Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5 */
6
7
8 if(!dojo._hasResource["dojo.NodeList-manipulate"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9 dojo._hasResource["dojo.NodeList-manipulate"] = true;
10 dojo.provide("dojo.NodeList-manipulate");
11
12 /*=====
13 dojo["NodeList-manipulate"] = {
14 // summary: Adds a chainable methods to dojo.query() / Nodelist instances for manipulating HTML
15 // and DOM nodes and their properties.
16 };
17 =====*/
18
19 //TODO: add a way to parse for widgets in the injected markup?
20
21 (function(){
22 function getText(/*DOMNode*/node){
23 // summary:
24 // recursion method for text() to use. Gets text value for a node.
25 // description:
26 // Juse uses nodedValue so things like <br/> tags do not end up in
27 // the text as any sort of line return.
28 var text = "", ch = node.childNodes;
29 for(var i = 0, n; n = ch[i]; i++){
30 //Skip comments.
31 if(n.nodeType != 8){
32 if(n.nodeType == 1){
33 text += getText(n);
34 }else{
35 text += n.nodeValue;
36 }
37 }
38 }
39 return text;
40 }
41
42 function getWrapInsertion(/*DOMNode*/node){
43 // summary:
44 // finds the innermost element to use for wrap insertion.
45
46 //Make it easy, assume single nesting, no siblings.
47 while(node.childNodes[0] && node.childNodes[0].nodeType == 1){
48 node = node.childNodes[0];
49 }
50 return node; //DOMNode
51 }
52
53 function makeWrapNode(/*DOMNode||String*/html, /*DOMNode*/refNode){
54 // summary:
55 // convert HTML into nodes if it is not already a node.
56 if(typeof html == "string"){
57 html = dojo._toDom(html, (refNode && refNode.ownerDocument));
58 if(html.nodeType == 11){
59 //DocumentFragment cannot handle cloneNode, so choose first child.
60 html = html.childNodes[0];
61 }
62 }else if(html.nodeType == 1 && html.parentNode){
63 //This element is already in the DOM clone it, but not its children.
64 html = html.cloneNode(false);
65 }
66 return html; /*DOMNode*/
67 }
68
69 dojo.extend(dojo.NodeList, {
70 _placeMultiple: function(/*String||Node||NodeList*/query, /*String*/position){
71 // summary:
72 // private method for inserting queried nodes into all nodes in this NodeList
73 // at different positions. Differs from NodeList.place because it will clone
74 // the nodes in this NodeList if the query matches more than one element.
75 var nl2 = typeof query == "string" || query.nodeType ? dojo.query(query) : query;
76 var toAdd = [];
77 for(var i = 0; i < nl2.length; i++){
78 //Go backwards in DOM to make dom insertions easier via insertBefore
79 var refNode = nl2[i];
80 var length = this.length;
81 for(var j = length - 1, item; item = this[j]; j--){
82 if(i > 0){
83 //Need to clone the item. This also means
84 //it needs to be added to the current NodeList
85 //so it can also be the target of other chaining operations.
86 item = this._cloneNode(item);
87 toAdd.unshift(item);
88 }
89 if(j == length - 1){
90 dojo.place(item, refNode, position);
91 }else{
92 refNode.parentNode.insertBefore(item, refNode);
93 }
94 refNode = item;
95 }
96 }
97
98 if(toAdd.length){
99 //Add the toAdd items to the current NodeList. Build up list of args
100 //to pass to splice.
101 toAdd.unshift(0);
102 toAdd.unshift(this.length - 1);
103 Array.prototype.splice.apply(this, toAdd);
104 }
105
106 return this; //dojo.NodeList
107 },
108
109 innerHTML: function(/*String?||DOMNode?|NodeList?*/value){
110 // summary:
111 // allows setting the innerHTML of each node in the NodeList,
112 // if there is a value passed in, otherwise, reads the innerHTML value of the first node.
113 // description:
114 // This method is simpler than the dojo.NodeList.html() method provided by
115 // `dojo.NodeList-html`. This method just does proper innerHTML insertion of HTML fragments,
116 // and it allows for the innerHTML to be read for the first node in the node list.
117 // Since dojo.NodeList-html already took the "html" name, this method is called
118 // "innerHTML". However, if dojo.NodeList-html has not been loaded yet, this
119 // module will define an "html" method that can be used instead. Be careful if you
120 // are working in an environment where it is possible that dojo.NodeList-html could
121 // have been loaded, since its definition of "html" will take precedence.
122 // The nodes represented by the value argument will be cloned if more than one
123 // node is in this NodeList. The nodes in this NodeList are returned in the "set"
124 // usage of this method, not the HTML that was inserted.
125 // returns:
126 // if no value is passed, the result is String, the innerHTML of the first node.
127 // If a value is passed, the return is this dojo.NodeList
128 // example:
129 // assume a DOM created by this markup:
130 // | <div id="foo"></div>
131 // | <div id="bar"></div>
132 // This code inserts <p>Hello World</p> into both divs:
133 // | dojo.query("div").innerHTML("<p>Hello World</p>");
134 // example:
135 // assume a DOM created by this markup:
136 // | <div id="foo"><p>Hello Mars</p></div>
137 // | <div id="bar"><p>Hello World</p></div>
138 // This code returns "<p>Hello Mars</p>":
139 // | var message = dojo.query("div").innerHTML();
140 if(arguments.length){
141 return this.addContent(value, "only"); //dojo.NodeList
142 }else{
143 return this[0].innerHTML; //String
144 }
145 },
146
147 /*=====
148 html: function(value){
149 // summary:
150 // see the information for "innerHTML". "html" is an alias for "innerHTML", but is
151 // only defined if dojo.NodeList-html has not been loaded.
152 // description:
153 // An alias for the "innerHTML" method, but only defined if there is not an existing
154 // "html" method on dojo.NodeList. Be careful if you are working in an environment
155 // where it is possible that dojo.NodeList-html could have been loaded, since its
156 // definition of "html" will take precedence. If you are not sure if dojo.NodeList-html
157 // could be loaded, use the "innerHTML" method.
158 // value: String?||DOMNode?||NodeList?
159 // optional. The HTML fragment to use as innerHTML. If value is not passed, then the innerHTML
160 // of the first element in this NodeList is returned.
161 // returns:
162 // if no value is passed, the result is String, the innerHTML of the first node.
163 // If a value is passed, the return is this dojo.NodeList
164 return; // dojo.NodeList
165 return; // String
166 },
167 =====*/
168
169 text: function(/*String*/value){
170 // summary:
171 // allows setting the text value of each node in the NodeList,
172 // if there is a value passed in, otherwise, returns the text value for all the
173 // nodes in the NodeList in one string.
174 // example:
175 // assume a DOM created by this markup:
176 // | <div id="foo"></div>
177 // | <div id="bar"></div>
178 // This code inserts "Hello World" into both divs:
179 // | dojo.query("div").text("Hello World");
180 // example:
181 // assume a DOM created by this markup:
182 // | <div id="foo"><p>Hello Mars <span>today</span></p></div>
183 // | <div id="bar"><p>Hello World</p></div>
184 // This code returns "Hello Mars today":
185 // | var message = dojo.query("div").text();
186 // returns:
187 // if no value is passed, the result is String, the text value of the first node.
188 // If a value is passed, the return is this dojo.NodeList
189 if(arguments.length){
190 for(var i = 0, node; node = this[i]; i++){
191 if(node.nodeType == 1){
192 dojo.empty(node);
193 node.appendChild(node.ownerDocument.createTextNode(value));
194 }
195 }
196 return this; //dojo.NodeList
197 }else{
198 var result = "";
199 for(i = 0; node = this[i]; i++){
200 result += getText(node);
201 }
202 return result; //String
203 }
204 },
205
206 val: function(/*String||Array*/value){
207 // summary:
208 // If a value is passed, allows seting the value property of form elements in this
209 // NodeList, or properly selecting/checking the right value for radio/checkbox/select
210 // elements. If no value is passed, the value of the first node in this NodeList
211 // is returned.
212 // returns:
213 // if no value is passed, the result is String or an Array, for the value of the
214 // first node.
215 // If a value is passed, the return is this dojo.NodeList
216 // example:
217 // assume a DOM created by this markup:
218 // | <input type="text" value="foo">
219 // | <select multiple>
220 // | <option value="red" selected>Red</option>
221 // | <option value="blue">Blue</option>
222 // | <option value="yellow" selected>Yellow</option>
223 // | </select>
224 // This code gets and sets the values for the form fields above:
225 // | dojo.query('[type="text"]').val(); //gets value foo
226 // | dojo.query('[type="text"]').val("bar"); //sets the input's value to "bar"
227 // | dojo.query("select").val() //gets array value ["red", "yellow"]
228 // | dojo.query("select").val(["blue", "yellow"]) //Sets the blue and yellow options to selected.
229
230 //Special work for input elements.
231 if(arguments.length){
232 var isArray = dojo.isArray(value);
233 for(var index = 0, node; node = this[index]; index++){
234 var name = node.nodeName.toUpperCase();
235 var type = node.type;
236 var newValue = isArray ? value[index] : value;
237
238 if(name == "SELECT"){
239 var opts = node.options;
240 for(var i = 0; i < opts.length; i++){
241 var opt = opts[i];
242 if(node.multiple){
243 opt.selected = (dojo.indexOf(value, opt.value) != -1);
244 }else{
245 opt.selected = (opt.value == newValue);
246 }
247 }
248 }else if(type == "checkbox" || type == "radio"){
249 node.checked = (node.value == newValue);
250 }else{
251 node.value = newValue;
252 }
253 }
254 return this; //dojo.NodeList
255 }else{
256 //node already declared above.
257 node = this[0];
258 if(!node || node.nodeType != 1){
259 return undefined;
260 }
261 value = node.value || "";
262 if(node.nodeName.toUpperCase() == "SELECT" && node.multiple){
263 //A multivalued selectbox. Do the pain.
264 value = [];
265 //opts declared above in if block.
266 opts = node.options;
267 //i declared above in if block;
268 for(i = 0; i < opts.length; i++){
269 //opt declared above in if block
270 opt = opts[i];
271 if(opt.selected){
272 value.push(opt.value);
273 }
274 }
275 if(!value.length){
276 value = null;
277 }
278 }
279 return value; //String||Array
280 }
281 },
282
283 append: function(/*String||DOMNode||NodeList*/content){
284 // summary:
285 // appends the content to every node in the NodeList.
286 // description:
287 // The content will be cloned if the length of NodeList
288 // is greater than 1. Only the DOM nodes are cloned, not
289 // any attached event handlers.
290 // returns:
291 // dojo.NodeList, the nodes currently in this NodeList will be returned,
292 // not the appended content.
293 // example:
294 // assume a DOM created by this markup:
295 // | <div id="foo"><p>Hello Mars</p></div>
296 // | <div id="bar"><p>Hello World</p></div>
297 // Running this code:
298 // | dojo.query("div").append("<span>append</span>");
299 // Results in this DOM structure:
300 // | <div id="foo"><p>Hello Mars</p><span>append</span></div>
301 // | <div id="bar"><p>Hello World</p><span>append</span></div>
302 return this.addContent(content, "last"); //dojo.NodeList
303 },
304
305 appendTo: function(/*String*/query){
306 // summary:
307 // appends nodes in this NodeList to the nodes matched by
308 // the query passed to appendTo.
309 // description:
310 // The nodes in this NodeList will be cloned if the query
311 // matches more than one element. Only the DOM nodes are cloned, not
312 // any attached event handlers.
313 // returns:
314 // dojo.NodeList, the nodes currently in this NodeList will be returned,
315 // not the matched nodes from the query.
316 // example:
317 // assume a DOM created by this markup:
318 // | <span>append</span>
319 // | <p>Hello Mars</p>
320 // | <p>Hello World</p>
321 // Running this code:
322 // | dojo.query("span").appendTo("p");
323 // Results in this DOM structure:
324 // | <p>Hello Mars<span>append</span></p>
325 // | <p>Hello World<span>append</span></p>
326 return this._placeMultiple(query, "last"); //dojo.NodeList
327 },
328
329 prepend: function(/*String||DOMNode||NodeList*/content){
330 // summary:
331 // prepends the content to every node in the NodeList.
332 // description:
333 // The content will be cloned if the length of NodeList
334 // is greater than 1. Only the DOM nodes are cloned, not
335 // any attached event handlers.
336 // returns:
337 // dojo.NodeList, the nodes currently in this NodeList will be returned,
338 // not the appended content.
339 // assume a DOM created by this markup:
340 // | <div id="foo"><p>Hello Mars</p></div>
341 // | <div id="bar"><p>Hello World</p></div>
342 // Running this code:
343 // | dojo.query("div").prepend("<span>prepend</span>");
344 // Results in this DOM structure:
345 // | <div id="foo"><span>prepend</span><p>Hello Mars</p></div>
346 // | <div id="bar"><span>prepend</span><p>Hello World</p></div>
347 return this.addContent(content, "first"); //dojo.NodeList
348 },
349
350 prependTo: function(/*String*/query){
351 // summary:
352 // prepends nodes in this NodeList to the nodes matched by
353 // the query passed to prependTo.
354 // description:
355 // The nodes in this NodeList will be cloned if the query
356 // matches more than one element. Only the DOM nodes are cloned, not
357 // any attached event handlers.
358 // returns:
359 // dojo.NodeList, the nodes currently in this NodeList will be returned,
360 // not the matched nodes from the query.
361 // example:
362 // assume a DOM created by this markup:
363 // | <span>prepend</span>
364 // | <p>Hello Mars</p>
365 // | <p>Hello World</p>
366 // Running this code:
367 // | dojo.query("span").prependTo("p");
368 // Results in this DOM structure:
369 // | <p><span>prepend</span>Hello Mars</p>
370 // | <p><span>prepend</span>Hello World</p>
371 return this._placeMultiple(query, "first"); //dojo.NodeList
372 },
373
374 after: function(/*String||Element||NodeList*/content){
375 // summary:
376 // Places the content after every node in the NodeList.
377 // description:
378 // The content will be cloned if the length of NodeList
379 // is greater than 1. Only the DOM nodes are cloned, not
380 // any attached event handlers.
381 // returns:
382 // dojo.NodeList, the nodes currently in this NodeList will be returned,
383 // not the appended content.
384 // example:
385 // assume a DOM created by this markup:
386 // | <div id="foo"><p>Hello Mars</p></div>
387 // | <div id="bar"><p>Hello World</p></div>
388 // Running this code:
389 // | dojo.query("div").after("<span>after</span>");
390 // Results in this DOM structure:
391 // | <div id="foo"><p>Hello Mars</p></div><span>after</span>
392 // | <div id="bar"><p>Hello World</p></div><span>after</span>
393 return this.addContent(content, "after"); //dojo.NodeList
394 },
395
396 insertAfter: function(/*String*/query){
397 // summary:
398 // The nodes in this NodeList will be placed after the nodes
399 // matched by the query passed to insertAfter.
400 // description:
401 // The nodes in this NodeList will be cloned if the query
402 // matches more than one element. Only the DOM nodes are cloned, not
403 // any attached event handlers.
404 // returns:
405 // dojo.NodeList, the nodes currently in this NodeList will be returned,
406 // not the matched nodes from the query.
407 // example:
408 // assume a DOM created by this markup:
409 // | <span>after</span>
410 // | <p>Hello Mars</p>
411 // | <p>Hello World</p>
412 // Running this code:
413 // | dojo.query("span").insertAfter("p");
414 // Results in this DOM structure:
415 // | <p>Hello Mars</p><span>after</span>
416 // | <p>Hello World</p><span>after</span>
417 return this._placeMultiple(query, "after"); //dojo.NodeList
418 },
419
420 before: function(/*String||DOMNode||NodeList*/content){
421 // summary:
422 // Places the content before every node in the NodeList.
423 // description:
424 // The content will be cloned if the length of NodeList
425 // is greater than 1. Only the DOM nodes are cloned, not
426 // any attached event handlers.
427 // returns:
428 // dojo.NodeList, the nodes currently in this NodeList will be returned,
429 // not the appended content.
430 // example:
431 // assume a DOM created by this markup:
432 // | <div id="foo"><p>Hello Mars</p></div>
433 // | <div id="bar"><p>Hello World</p></div>
434 // Running this code:
435 // | dojo.query("div").before("<span>before</span>");
436 // Results in this DOM structure:
437 // | <span>before</span><div id="foo"><p>Hello Mars</p></div>
438 // | <span>before</span><div id="bar"><p>Hello World</p></div>
439 return this.addContent(content, "before"); //dojo.NodeList
440 },
441
442 insertBefore: function(/*String*/query){
443 // summary:
444 // The nodes in this NodeList will be placed after the nodes
445 // matched by the query passed to insertAfter.
446 // description:
447 // The nodes in this NodeList will be cloned if the query
448 // matches more than one element. Only the DOM nodes are cloned, not
449 // any attached event handlers.
450 // returns:
451 // dojo.NodeList, the nodes currently in this NodeList will be returned,
452 // not the matched nodes from the query.
453 // example:
454 // assume a DOM created by this markup:
455 // | <span>before</span>
456 // | <p>Hello Mars</p>
457 // | <p>Hello World</p>
458 // Running this code:
459 // | dojo.query("span").insertBefore("p");
460 // Results in this DOM structure:
461 // | <span>before</span><p>Hello Mars</p>
462 // | <span>before</span><p>Hello World</p>
463 return this._placeMultiple(query, "before"); //dojo.NodeList
464 },
465
466 /*=====
467 remove: function(simpleFilter){
468 // summary:
469 // alias for dojo.NodeList's orphan method. Removes elements
470 // in this list that match the simple filter from their parents
471 // and returns them as a new NodeList.
472 // simpleFilter: String
473 // single-expression CSS rule. For example, ".thinger" or
474 // "#someId[attrName='value']" but not "div > span". In short,
475 // anything which does not invoke a descent to evaluate but
476 // can instead be used to test a single node is acceptable.
477 // returns:
478 // dojo.NodeList
479 return; // dojo.NodeList
480 },
481 =====*/
482 remove: dojo.NodeList.prototype.orphan,
483
484 wrap: function(/*String||DOMNode*/html){
485 // summary:
486 // Wrap each node in the NodeList with html passed to wrap.
487 // description:
488 // html will be cloned if the NodeList has more than one
489 // element. Only DOM nodes are cloned, not any attached
490 // event handlers.
491 // returns:
492 // dojo.NodeList, the nodes in the current NodeList will be returned,
493 // not the nodes from html argument.
494 // example:
495 // assume a DOM created by this markup:
496 // | <b>one</b>
497 // | <b>two</b>
498 // Running this code:
499 // | dojo.query("b").wrap("<div><span></span></div>");
500 // Results in this DOM structure:
501 // | <div><span><b>one</b></span></div>
502 // | <div><span><b>two</b></span></div>
503 if(this[0]){
504 html = makeWrapNode(html, this[0]);
505
506 //Now cycle through the elements and do the insertion.
507 for(var i = 0, node; node = this[i]; i++){
508 //Always clone because if html is used to hold one of
509 //the "this" nodes, then on the clone of html it will contain
510 //that "this" node, and that would be bad.
511 var clone = this._cloneNode(html);
512 if(node.parentNode){
513 node.parentNode.replaceChild(clone, node);
514 }
515 //Find deepest element and insert old node in it.
516 var insertion = getWrapInsertion(clone);
517 insertion.appendChild(node);
518 }
519 }
520 return this; //dojo.NodeList
521 },
522
523 wrapAll: function(/*String||DOMNode*/html){
524 // summary:
525 // Insert html where the first node in this NodeList lives, then place all
526 // nodes in this NodeList as the child of the html.
527 // returns:
528 // dojo.NodeList, the nodes in the current NodeList will be returned,
529 // not the nodes from html argument.
530 // example:
531 // assume a DOM created by this markup:
532 // | <div class="container">
533 // | <div class="red">Red One</div>
534 // | <div class="blue">Blue One</div>
535 // | <div class="red">Red Two</div>
536 // | <div class="blue">Blue Two</div>
537 // | </div>
538 // Running this code:
539 // | dojo.query(".red").wrapAll('<div class="allRed"></div>');
540 // Results in this DOM structure:
541 // | <div class="container">
542 // | <div class="allRed">
543 // | <div class="red">Red One</div>
544 // | <div class="red">Red Two</div>
545 // | </div>
546 // | <div class="blue">Blue One</div>
547 // | <div class="blue">Blue Two</div>
548 // | </div>
549 if(this[0]){
550 html = makeWrapNode(html, this[0]);
551
552 //Place the wrap HTML in place of the first node.
553 this[0].parentNode.replaceChild(html, this[0]);
554
555 //Now cycle through the elements and move them inside
556 //the wrap.
557 var insertion = getWrapInsertion(html);
558 for(var i = 0, node; node = this[i]; i++){
559 insertion.appendChild(node);
560 }
561 }
562 return this; //dojo.NodeList
563 },
564
565 wrapInner: function(/*String||DOMNode*/html){
566 // summary:
567 // For each node in the NodeList, wrap all its children with the passed in html.
568 // description:
569 // html will be cloned if the NodeList has more than one
570 // element. Only DOM nodes are cloned, not any attached
571 // event handlers.
572 // returns:
573 // dojo.NodeList, the nodes in the current NodeList will be returned,
574 // not the nodes from html argument.
575 // example:
576 // assume a DOM created by this markup:
577 // | <div class="container">
578 // | <div class="red">Red One</div>
579 // | <div class="blue">Blue One</div>
580 // | <div class="red">Red Two</div>
581 // | <div class="blue">Blue Two</div>
582 // | </div>
583 // Running this code:
584 // | dojo.query(".red").wrapInner('<span class="special"></span>');
585 // Results in this DOM structure:
586 // | <div class="container">
587 // | <div class="red"><span class="special">Red One</span></div>
588 // | <div class="blue">Blue One</div>
589 // | <div class="red"><span class="special">Red Two</span></div>
590 // | <div class="blue">Blue Two</div>
591 // | </div>
592 if(this[0]){
593 html = makeWrapNode(html, this[0]);
594 for(var i = 0; i < this.length; i++){
595 //Always clone because if html is used to hold one of
596 //the "this" nodes, then on the clone of html it will contain
597 //that "this" node, and that would be bad.
598 var clone = this._cloneNode(html);
599
600 //Need to convert the childNodes to an array since wrapAll modifies the
601 //DOM and can change the live childNodes NodeList.
602 this._wrap(dojo._toArray(this[i].childNodes), null, this._NodeListCtor).wrapAll(clone);
603 }
604 }
605 return this; //dojo.NodeList
606 },
607
608 replaceWith: function(/*String||DOMNode||NodeList*/content){
609 // summary:
610 // Replaces each node in ths NodeList with the content passed to replaceWith.
611 // description:
612 // The content will be cloned if the length of NodeList
613 // is greater than 1. Only the DOM nodes are cloned, not
614 // any attached event handlers.
615 // returns:
616 // The nodes currently in this NodeList will be returned, not the replacing content.
617 // Note that the returned nodes have been removed from the DOM.
618 // example:
619 // assume a DOM created by this markup:
620 // | <div class="container">
621 // | <div class="red">Red One</div>
622 // | <div class="blue">Blue One</div>
623 // | <div class="red">Red Two</div>
624 // | <div class="blue">Blue Two</div>
625 // | </div>
626 // Running this code:
627 // | dojo.query(".red").replaceWith('<div class="green">Green</div>');
628 // Results in this DOM structure:
629 // | <div class="container">
630 // | <div class="green">Green</div>
631 // | <div class="blue">Blue One</div>
632 // | <div class="green">Green</div>
633 // | <div class="blue">Blue Two</div>
634 // | </div>
635 content = this._normalize(content, this[0]);
636 for(var i = 0, node; node = this[i]; i++){
637 this._place(content, node, "before", i > 0);
638 node.parentNode.removeChild(node);
639 }
640 return this; //dojo.NodeList
641 },
642
643 replaceAll: function(/*String*/query){
644 // summary:
645 // replaces nodes matched by the query passed to replaceAll with the nodes
646 // in this NodeList.
647 // description:
648 // The nodes in this NodeList will be cloned if the query
649 // matches more than one element. Only the DOM nodes are cloned, not
650 // any attached event handlers.
651 // returns:
652 // The nodes currently in this NodeList will be returned, not the matched nodes
653 // from the query. The nodes currently in this NodeLIst could have
654 // been cloned, so the returned NodeList will include the cloned nodes.
655 // example:
656 // assume a DOM created by this markup:
657 // | <div class="container">
658 // | <div class="spacer">___</div>
659 // | <div class="red">Red One</div>
660 // | <div class="spacer">___</div>
661 // | <div class="blue">Blue One</div>
662 // | <div class="spacer">___</div>
663 // | <div class="red">Red Two</div>
664 // | <div class="spacer">___</div>
665 // | <div class="blue">Blue Two</div>
666 // | </div>
667 // Running this code:
668 // | dojo.query(".red").replaceAll(".blue");
669 // Results in this DOM structure:
670 // | <div class="container">
671 // | <div class="spacer">___</div>
672 // | <div class="spacer">___</div>
673 // | <div class="red">Red One</div>
674 // | <div class="red">Red Two</div>
675 // | <div class="spacer">___</div>
676 // | <div class="spacer">___</div>
677 // | <div class="red">Red One</div>
678 // | <div class="red">Red Two</div>
679 // | </div>
680 var nl = dojo.query(query);
681 var content = this._normalize(this, this[0]);
682 for(var i = 0, node; node = nl[i]; i++){
683 this._place(content, node, "before", i > 0);
684 node.parentNode.removeChild(node);
685 }
686 return this; //dojo.NodeList
687 },
688
689 clone: function(){
690 // summary:
691 // Clones all the nodes in this NodeList and returns them as a new NodeList.
692 // description:
693 // Only the DOM nodes are cloned, not any attached event handlers.
694 // returns:
695 // dojo.NodeList, a cloned set of the original nodes.
696 // example:
697 // assume a DOM created by this markup:
698 // | <div class="container">
699 // | <div class="red">Red One</div>
700 // | <div class="blue">Blue One</div>
701 // | <div class="red">Red Two</div>
702 // | <div class="blue">Blue Two</div>
703 // | </div>
704 // Running this code:
705 // | dojo.query(".red").clone().appendTo(".container");
706 // Results in this DOM structure:
707 // | <div class="container">
708 // | <div class="red">Red One</div>
709 // | <div class="blue">Blue One</div>
710 // | <div class="red">Red Two</div>
711 // | <div class="blue">Blue Two</div>
712 // | <div class="red">Red One</div>
713 // | <div class="red">Red Two</div>
714 // | </div>
715
716 //TODO: need option to clone events?
717 var ary = [];
718 for(var i = 0; i < this.length; i++){
719 ary.push(this._cloneNode(this[i]));
720 }
721 return this._wrap(ary, this, this._NodeListCtor); //dojo.NodeList
722 }
723 });
724
725 //set up html method if one does not exist
726 if(!dojo.NodeList.prototype.html){
727 dojo.NodeList.prototype.html = dojo.NodeList.prototype.innerHTML;
728 }
729 })();
730
731 }