NodeList-manipulate.js 26 KB

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