NodeList-manipulate.js 27 KB

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