e28798334aee079c4f6f38b45afb8d7ec97040c9.svn-base 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. if (!dojo._hasResource["dojo._base.NodeList"]) { // _hasResource checks added
  2. // by build. Do not use
  3. // _hasResource directly in
  4. // your code.
  5. dojo._hasResource["dojo._base.NodeList"] = true;
  6. dojo.provide("dojo._base.NodeList");
  7. dojo.require("dojo._base.lang");
  8. dojo.require("dojo._base.array");
  9. (function() {
  10. var d = dojo;
  11. var tnl = function(arr) {
  12. arr.constructor = dojo.NodeList;
  13. dojo._mixin(arr, dojo.NodeList.prototype);
  14. return arr;
  15. }
  16. dojo.NodeList = function() {
  17. // summary:
  18. // dojo.NodeList is as subclass of Array which adds syntactic
  19. // sugar for chaining, common iteration operations, animation,
  20. // and node manipulation. NodeLists are most often returned as
  21. // the result of dojo.query() calls.
  22. // example:
  23. // create a node list from a node
  24. // | new dojo.NodeList(dojo.byId("foo"));
  25. return tnl(Array.apply(null, arguments));
  26. }
  27. dojo.NodeList._wrap = tnl;
  28. dojo.extend(dojo.NodeList, {
  29. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
  30. // FIXME: handle return values for #3244
  31. // http://trac.dojotoolkit.org/ticket/3244
  32. // FIXME:
  33. // need to wrap or implement:
  34. // join (perhaps w/ innerHTML/outerHTML overload for toString() of
  35. // items?)
  36. // reduce
  37. // reduceRight
  38. slice : function(/* ===== begin, end ===== */) {
  39. // summary:
  40. // Returns a new NodeList, maintaining this one in place
  41. // description:
  42. // This method behaves exactly like the Array.slice method
  43. // with the caveat that it returns a dojo.NodeList and not a
  44. // raw Array. For more details, see:
  45. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:slice
  46. // begin: Integer
  47. // Can be a positive or negative integer, with positive
  48. // integers noting the offset to begin at, and negative
  49. // integers denoting an offset from the end (i.e., to the left
  50. // of the end)
  51. // end: Integer?
  52. // Optional parameter to describe what position relative to
  53. // the NodeList's zero index to end the slice at. Like begin,
  54. // can be positive or negative.
  55. var a = dojo._toArray(arguments);
  56. return tnl(a.slice.apply(this, a));
  57. },
  58. splice : function(/* ===== index, howmany, item ===== */) {
  59. // summary:
  60. // Returns a new NodeList, manipulating this NodeList based on
  61. // the arguments passed, potentially splicing in new elements
  62. // at an offset, optionally deleting elements
  63. // description:
  64. // This method behaves exactly like the Array.splice method
  65. // with the caveat that it returns a dojo.NodeList and not a
  66. // raw Array. For more details, see:
  67. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:splice
  68. // index: Integer
  69. // begin can be a positive or negative integer, with positive
  70. // integers noting the offset to begin at, and negative
  71. // integers denoting an offset from the end (i.e., to the left
  72. // of the end)
  73. // howmany: Integer?
  74. // Optional parameter to describe what position relative to
  75. // the NodeList's zero index to end the slice at. Like begin,
  76. // can be positive or negative.
  77. // item: Object...?
  78. // Any number of optional parameters may be passed in to be
  79. // spliced into the NodeList
  80. // returns:
  81. // dojo.NodeList
  82. var a = dojo._toArray(arguments);
  83. return tnl(a.splice.apply(this, a));
  84. },
  85. concat : function(/* ===== item ===== */) {
  86. // summary:
  87. // Returns a new NodeList comprised of items in this NodeList
  88. // as well as items passed in as parameters
  89. // description:
  90. // This method behaves exactly like the Array.concat method
  91. // with the caveat that it returns a dojo.NodeList and not a
  92. // raw Array. For more details, see:
  93. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:concat
  94. // item: Object...?
  95. // Any number of optional parameters may be passed in to be
  96. // spliced into the NodeList
  97. // returns:
  98. // dojo.NodeList
  99. var a = dojo._toArray(arguments, 0, [this]);
  100. return tnl(a.concat.apply([], a));
  101. },
  102. indexOf : function(/* Object */value, /* Integer? */fromIndex) {
  103. // summary:
  104. // see dojo.indexOf(). The primary difference is that the
  105. // acted-on
  106. // array is implicitly this NodeList
  107. // value:
  108. // The value to search for.
  109. // fromIndex:
  110. // The loction to start searching from. Optional. Defaults to 0.
  111. // description:
  112. // For more details on the behavior of indexOf, see:
  113. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
  114. // returns:
  115. // Positive Integer or 0 for a match, -1 of not found.
  116. return d.indexOf(this, value, fromIndex); // Integer
  117. },
  118. lastIndexOf : function(/* ===== value, fromIndex ===== */) {
  119. // summary:
  120. // see dojo.lastIndexOf(). The primary difference is that the
  121. // acted-on array is implicitly this NodeList
  122. // description:
  123. // For more details on the behavior of lastIndexOf, see:
  124. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
  125. // value: Object
  126. // The value to search for.
  127. // fromIndex: Integer?
  128. // The loction to start searching from. Optional. Defaults to 0.
  129. // returns:
  130. // Positive Integer or 0 for a match, -1 of not found.
  131. return d.lastIndexOf.apply(d, d._toArray(arguments, 0, [this])); // Integer
  132. },
  133. every : function(/* Function */callback, /* Object? */thisObject) {
  134. // summary:
  135. // see dojo.every() and:
  136. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
  137. // Takes the same structure of arguments and returns as
  138. // dojo.every() with the caveat that the passed array is
  139. // implicitly this NodeList
  140. return d.every(this, callback, thisObject); // Boolean
  141. },
  142. some : function(/* Function */callback, /* Object? */thisObject) {
  143. // summary:
  144. // see dojo.some() and:
  145. // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
  146. // Takes the same structure of arguments and returns as
  147. // dojo.some() with the caveat that the passed array is
  148. // implicitly this NodeList
  149. return d.some(this, callback, thisObject); // Boolean
  150. },
  151. map : function(/* Function */func, /* Function? */obj) {
  152. // summary:
  153. // see dojo.map(). The primary difference is that the acted-on
  154. // array is implicitly this NodeList and the return is a
  155. // dojo.NodeList (a subclass of Array)
  156. return d.map(this, func, obj, d.NodeList); // dojo.NodeList
  157. },
  158. forEach : function(callback, thisObj) {
  159. // summary:
  160. // see dojo.forEach(). The primary difference is that the
  161. // acted-on
  162. // array is implicitly this NodeList
  163. d.forEach(this, callback, thisObj);
  164. return this; // dojo.NodeList non-standard return to allow
  165. // easier chaining
  166. },
  167. // custom methods
  168. coords : function() {
  169. // summary:
  170. // Returns the box objects all elements in a node list as
  171. // an Array (*not* a NodeList)
  172. return d.map(this, d.coords);
  173. },
  174. style : function(/* ===== property, value ===== */) {
  175. // summary:
  176. // gets or sets the CSS property for every element in the
  177. // NodeList
  178. // property: String
  179. // the CSS property to get/set, in JavaScript notation
  180. // ("lineHieght" instead of "line-height")
  181. // value: String?
  182. // optional. The value to set the property to
  183. // return:
  184. // if no value is passed, the result is an array of strings.
  185. // If a value is passed, the return is this NodeList
  186. var aa = d._toArray(arguments, 0, [null]);
  187. var s = this.map(function(i) {
  188. aa[0] = i;
  189. return d.style.apply(d, aa);
  190. });
  191. return (arguments.length > 1) ? this : s; // String||dojo.NodeList
  192. },
  193. styles : function(/* ===== property, value ===== */) {
  194. // summary:
  195. // Deprecated. Use NodeList.style instead. Will be removed in
  196. // Dojo 1.1. Gets or sets the CSS property for every element
  197. // in the NodeList
  198. // property: String
  199. // the CSS property to get/set, in JavaScript notation
  200. // ("lineHieght" instead of "line-height")
  201. // value: String?
  202. // optional. The value to set the property to
  203. // return:
  204. // if no value is passed, the result is an array of strings.
  205. // If a value is passed, the return is this NodeList
  206. d.deprecated("NodeList.styles", "use NodeList.style instead",
  207. "1.1");
  208. return this.style.apply(this, arguments);
  209. },
  210. addClass : function(/* String */className) {
  211. // summary:
  212. // adds the specified class to every node in the list
  213. //
  214. this.forEach(function(i) {
  215. d.addClass(i, className);
  216. });
  217. return this;
  218. },
  219. removeClass : function(/* String */className) {
  220. this.forEach(function(i) {
  221. d.removeClass(i, className);
  222. });
  223. return this;
  224. },
  225. // FIXME: toggleClass()? connectPublisher()? connectRunOnce()?
  226. place : function(/* String||Node */queryOrNode, /* String */position) {
  227. // summary:
  228. // places elements of this node list relative to the first
  229. // element matched
  230. // by queryOrNode. Returns the original NodeList.
  231. // queryOrNode:
  232. // may be a string representing any valid CSS3 selector or a DOM
  233. // node.
  234. // In the selector case, only the first matching element will be
  235. // used
  236. // for relative positioning.
  237. // position:
  238. // can be one of:
  239. // "last"||"end" (default)
  240. // "first||"start"
  241. // "before"
  242. // "after"
  243. // or an offset in the childNodes property
  244. var item = d.query(queryOrNode)[0];
  245. position = position || "last";
  246. for (var x = 0; x < this.length; x++) {
  247. d.place(this[x], item, position);
  248. }
  249. return this; // dojo.NodeList
  250. },
  251. connect : function(/* String */methodName, /* Object||Function||String */
  252. objOrFunc, /* String? */funcName) {
  253. // summary:
  254. // attach event handlers to every item of the NodeList. Uses
  255. // dojo.connect()
  256. // so event properties are normalized
  257. // methodName:
  258. // the name of the method to attach to. For DOM events, this
  259. // should be
  260. // the lower-case name of the event
  261. // objOrFunc:
  262. // if 2 arguments are passed (methodName, objOrFunc), objOrFunc
  263. // should
  264. // reference a function or be the name of the function in the
  265. // global
  266. // namespace to attach. If 3 arguments are provided
  267. // (methodName, objOrFunc, funcName), objOrFunc must be the
  268. // scope to
  269. // locate the bound function in
  270. // funcName:
  271. // optional. A string naming the function in objOrFunc to bind
  272. // to the
  273. // event. May also be a function reference.
  274. // example:
  275. // add an onclick handler to every button on the page
  276. // | dojo.query("onclick", function(e){
  277. // | console.debug("clicked!");
  278. // | });
  279. // example:
  280. // attach foo.bar() to every odd div's onmouseover
  281. // | dojo.query("div:nth-child(odd)").onclick("onmouseover",
  282. // foo, "bar");
  283. this.forEach(function(item) {
  284. d.connect(item, methodName, objOrFunc, funcName);
  285. });
  286. return this; // dojo.NodeList
  287. },
  288. orphan : function(/* String? */simpleFilter) {
  289. // summary:
  290. // removes elements in this list that match the simple
  291. // filter from their parents and returns them as a new
  292. // NodeList.
  293. // simpleFilter: single-expression CSS filter
  294. // return: a dojo.NodeList of all of the elements orpahned
  295. var orphans = (simpleFilter) ? d._filterQueryResult(this,
  296. simpleFilter) : this;
  297. orphans.forEach(function(item) {
  298. if (item["parentNode"]) {
  299. item.parentNode.removeChild(item);
  300. }
  301. });
  302. return orphans; // dojo.NodeList
  303. },
  304. adopt : function(/* String||Array||DomNode */queryOrListOrNode, /* String? */
  305. position) {
  306. // summary:
  307. // places any/all elements in queryOrListOrNode at a
  308. // position relative to the first element in this list.
  309. // Returns a dojo.NodeList of the adopted elements.
  310. // queryOrListOrNode:
  311. // a DOM node or a query string or a query result.
  312. // Represents the nodes to be adopted relative to the
  313. // first element of this NodeList.
  314. // position:
  315. // optional. One of:
  316. // "last"||"end" (default)
  317. // "first||"start"
  318. // "before"
  319. // "after"
  320. // or an offset in the childNodes property
  321. var item = this[0];
  322. return d.query(queryOrListOrNode).forEach(function(ai) {
  323. d.place(ai, item, (position || "last"));
  324. }); // dojo.NodeList
  325. },
  326. // FIXME: do we need this?
  327. query : function(/* String */queryStr) {
  328. // summary:
  329. // Returns a new, flattened NodeList. Elements of the new list
  330. // satisfy the passed query but use elements of the
  331. // current NodeList as query roots.
  332. queryStr = queryStr || "";
  333. // FIXME: probably slow
  334. var ret = d.NodeList();
  335. this.forEach(function(item) {
  336. d.query(queryStr, item).forEach(function(subItem) {
  337. if (typeof subItem != "undefined") {
  338. ret.push(subItem);
  339. }
  340. });
  341. });
  342. return ret; // dojo.NodeList
  343. },
  344. filter : function(/* String */simpleQuery) {
  345. // summary:
  346. // "masks" the built-in javascript filter() method to support
  347. // passing a simple string filter in addition to supporting
  348. // filtering function objects.
  349. // example:
  350. // "regular" JS filter syntax as exposed in dojo.filter:
  351. // | dojo.query("*").filter(function(item){
  352. // | // highlight every paragraph
  353. // | return (item.nodeName == "p");
  354. // | }).styles("backgroundColor", "yellow");
  355. // example:
  356. // the same filtering using a CSS selector
  357. // | dojo.query("*").filter("p").styles("backgroundColor",
  358. // "yellow");
  359. var items = this;
  360. var _a = arguments;
  361. var r = d.NodeList();
  362. var rp = function(t) {
  363. if (typeof t != "undefined") {
  364. r.push(t);
  365. }
  366. }
  367. if (d.isString(simpleQuery)) {
  368. items = d._filterQueryResult(this, _a[0]);
  369. if (_a.length == 1) {
  370. // if we only got a string query, pass back the filtered
  371. // results
  372. return items; // dojo.NodeList
  373. }
  374. // if we got a callback, run it over the filtered items
  375. d.forEach(d.filter(items, _a[1], _a[2]), rp);
  376. return r; // dojo.NodeList
  377. }
  378. // handle the (callback, [thisObject]) case
  379. d.forEach(d.filter(items, _a[0], _a[1]), rp);
  380. return r; // dojo.NodeList
  381. },
  382. /*
  383. * // FIXME: should this be "copyTo" and include parenting info?
  384. * clone: function(){ // summary: // creates node clones of each
  385. * element of this list // and returns a new list containing the
  386. * clones },
  387. */
  388. addContent : function(/* String */content, /* String||Integer? */
  389. position) {
  390. // summary:
  391. // add a node or some HTML as a string to every item in the
  392. // list.
  393. // Returns the original list.
  394. // content:
  395. // the HTML in string format to add at position to every item
  396. // position:
  397. // One of:
  398. // "last"||"end" (default)
  399. // "first||"start"
  400. // "before"
  401. // "after"
  402. // or an integer offset in the childNodes property
  403. var ta = d.doc.createElement("span");
  404. if (d.isString(content)) {
  405. ta.innerHTML = content;
  406. } else {
  407. ta.appendChild(content);
  408. }
  409. var ct = ((position == "first") || (position == "after"))
  410. ? "lastChild"
  411. : "firstChild";
  412. this.forEach(function(item) {
  413. var tn = ta.cloneNode(true);
  414. while (tn[ct]) {
  415. d.place(tn[ct], item, position);
  416. }
  417. });
  418. return this; // dojo.NodeList
  419. }
  420. });
  421. // syntactic sugar for DOM events
  422. d.forEach(["blur", "click", "keydown", "keypress", "keyup",
  423. "mousedown", "mouseenter", "mouseleave", "mousemove",
  424. "mouseout", "mouseover", "mouseup"], function(evt) {
  425. var _oe = "on" + evt;
  426. dojo.NodeList.prototype[_oe] = function(a, b) {
  427. return this.connect(_oe, a, b);
  428. }
  429. // FIXME: should these events trigger publishes?
  430. /*
  431. * return (a ? this.connect(_oe, a, b) :
  432. * this.forEach(function(n){ // FIXME: // listeners get buried
  433. * by // addEventListener and can't be dug back // out to be
  434. * triggered externally. // see: //
  435. * http://developer.mozilla.org/en/docs/DOM:element
  436. *
  437. * console.debug(n, evt, _oe);
  438. * // FIXME: need synthetic event support! var _e = { target:
  439. * n, faux: true, type: evt }; //
  440. * dojo._event_listener._synthesizeEvent({}, { target: n, faux:
  441. * true, type: evt }); try{ n[evt](_e); }catch(e){
  442. * console.debug(e); } try{ n[_oe](_e); }catch(e){
  443. * console.debug(e); } }) ); }
  444. */
  445. });
  446. })();
  447. }