NodeList-manipulate.js 27 KB

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