]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/NodeList-dom.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dojo / NodeList-dom.js.uncompressed.js
1 define("dojo/NodeList-dom", ["./_base/kernel", "./query", "./_base/array", "./_base/lang", "./dom-class", "./dom-construct", "./dom-geometry", "./dom-attr", "./dom-style"], function(dojo, query, array, lang, domCls, domCtr, domGeom, domAttr, domStyle){
2 /*===== var NodeList = dojo.NodeList; =====*/
3 var magicGuard = function(a){
4 // summary:
5 // the guard function for dojo.attr() and dojo.style()
6 return a.length == 1 && (typeof a[0] == "string"); // inline'd type check
7 };
8
9 var orphan = function(node){
10 // summary:
11 // function to orphan nodes
12 var p = node.parentNode;
13 if(p){
14 p.removeChild(node);
15 }
16 };
17 // FIXME: should we move orphan() to dojo.html?
18
19 var NodeList = query.NodeList,
20 awc = NodeList._adaptWithCondition,
21 aafe = NodeList._adaptAsForEach,
22 aam = NodeList._adaptAsMap;
23
24 function getSet(module){
25 return function(node, name, value){
26 if(arguments.length == 2){
27 return module[typeof name == "string" ? "get" : "set"](node, name);
28 }
29 // setter
30 return module.set(node, name, value);
31 };
32 }
33
34 lang.extend(NodeList, {
35 _normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){
36 // summary:
37 // normalizes data to an array of items to insert.
38 // description:
39 // If content is an object, it can have special properties "template" and
40 // "parse". If "template" is defined, then the template value is run through
41 // dojo.string.substitute (if dojo.string.substitute has been dojo.required elsewhere),
42 // or if templateFunc is a function on the content, that function will be used to
43 // transform the template into a final string to be used for for passing to dojo._toDom.
44 // If content.parse is true, then it is remembered for later, for when the content
45 // nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
46 // (if dojo.parser has been dojo.required elsewhere).
47
48 //Wanted to just use a DocumentFragment, but for the array/NodeList
49 //case that meant using cloneNode, but we may not want that.
50 //Cloning should only happen if the node operations span
51 //multiple refNodes. Also, need a real array, not a NodeList from the
52 //DOM since the node movements could change those NodeLists.
53
54 var parse = content.parse === true;
55
56 //Do we have an object that needs to be run through a template?
57 if(typeof content.template == "string"){
58 var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute);
59 content = templateFunc ? templateFunc(content.template, content) : content;
60 }
61
62 var type = (typeof content);
63 if(type == "string" || type == "number"){
64 content = domCtr.toDom(content, (refNode && refNode.ownerDocument));
65 if(content.nodeType == 11){
66 //DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
67 content = lang._toArray(content.childNodes);
68 }else{
69 content = [content];
70 }
71 }else if(!lang.isArrayLike(content)){
72 content = [content];
73 }else if(!lang.isArray(content)){
74 //To get to this point, content is array-like, but
75 //not an array, which likely means a DOM NodeList. Convert it now.
76 content = lang._toArray(content);
77 }
78
79 //Pass around the parse info
80 if(parse){
81 content._runParse = true;
82 }
83 return content; //Array
84 },
85
86 _cloneNode: function(/*DOMNode*/ node){
87 // summary:
88 // private utility to clone a node. Not very interesting in the vanilla
89 // dojo.NodeList case, but delegates could do interesting things like
90 // clone event handlers if that is derivable from the node.
91 return node.cloneNode(true);
92 },
93
94 _place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){
95 // summary:
96 // private utility to handle placing an array of nodes relative to another node.
97 // description:
98 // Allows for cloning the nodes in the array, and for
99 // optionally parsing widgets, if ary._runParse is true.
100
101 //Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
102 if(refNode.nodeType != 1 && position == "only"){
103 return;
104 }
105 var rNode = refNode, tempNode;
106
107 //Always cycle backwards in case the array is really a
108 //DOM NodeList and the DOM operations take it out of the live collection.
109 var length = ary.length;
110 for(var i = length - 1; i >= 0; i--){
111 var node = (useClone ? this._cloneNode(ary[i]) : ary[i]);
112
113 //If need widget parsing, use a temp node, instead of waiting after inserting into
114 //real DOM because we need to start widget parsing at one node up from current node,
115 //which could cause some already parsed widgets to be parsed again.
116 if(ary._runParse && dojo.parser && dojo.parser.parse){
117 if(!tempNode){
118 tempNode = rNode.ownerDocument.createElement("div");
119 }
120 tempNode.appendChild(node);
121 dojo.parser.parse(tempNode);
122 node = tempNode.firstChild;
123 while(tempNode.firstChild){
124 tempNode.removeChild(tempNode.firstChild);
125 }
126 }
127
128 if(i == length - 1){
129 domCtr.place(node, rNode, position);
130 }else{
131 rNode.parentNode.insertBefore(node, rNode);
132 }
133 rNode = node;
134 }
135 },
136
137 /*=====
138 position: function(){
139 // summary:
140 // Returns border-box objects (x/y/w/h) of all elements in a node list
141 // as an Array (*not* a NodeList). Acts like `dojo.position`, though
142 // assumes the node passed is each node in this list.
143
144 return dojo.map(this, dojo.position); // Array
145 },
146
147 attr: function(property, value){
148 // summary:
149 // gets or sets the DOM attribute for every element in the
150 // NodeList. See also `dojo.attr`
151 // property: String
152 // the attribute to get/set
153 // value: String?
154 // optional. The value to set the property to
155 // returns:
156 // if no value is passed, the result is an array of attribute values
157 // If a value is passed, the return is this NodeList
158 // example:
159 // Make all nodes with a particular class focusable:
160 // | dojo.query(".focusable").attr("tabIndex", -1);
161 // example:
162 // Disable a group of buttons:
163 // | dojo.query("button.group").attr("disabled", true);
164 // example:
165 // innerHTML can be assigned or retrieved as well:
166 // | // get the innerHTML (as an array) for each list item
167 // | var ih = dojo.query("li.replaceable").attr("innerHTML");
168 return; // dojo.NodeList
169 return; // Array
170 },
171
172 style: function(property, value){
173 // summary:
174 // gets or sets the CSS property for every element in the NodeList
175 // property: String
176 // the CSS property to get/set, in JavaScript notation
177 // ("lineHieght" instead of "line-height")
178 // value: String?
179 // optional. The value to set the property to
180 // returns:
181 // if no value is passed, the result is an array of strings.
182 // If a value is passed, the return is this NodeList
183 return; // dojo.NodeList
184 return; // Array
185 },
186
187 addClass: function(className){
188 // summary:
189 // adds the specified class to every node in the list
190 // className: String|Array
191 // A String class name to add, or several space-separated class names,
192 // or an array of class names.
193 return; // dojo.NodeList
194 },
195
196 removeClass: function(className){
197 // summary:
198 // removes the specified class from every node in the list
199 // className: String|Array?
200 // An optional String class name to remove, or several space-separated
201 // class names, or an array of class names. If omitted, all class names
202 // will be deleted.
203 // returns:
204 // dojo.NodeList, this list
205 return; // dojo.NodeList
206 },
207
208 toggleClass: function(className, condition){
209 // summary:
210 // Adds a class to node if not present, or removes if present.
211 // Pass a boolean condition if you want to explicitly add or remove.
212 // condition: Boolean?
213 // If passed, true means to add the class, false means to remove.
214 // className: String
215 // the CSS class to add
216 return; // dojo.NodeList
217 },
218
219 empty: function(){
220 // summary:
221 // clears all content from each node in the list. Effectively
222 // equivalent to removing all child nodes from every item in
223 // the list.
224 return this.forEach("item.innerHTML='';"); // dojo.NodeList
225 // FIXME: should we be checking for and/or disposing of widgets below these nodes?
226 },
227 =====*/
228
229 // useful html methods
230 attr: awc(getSet(domAttr), magicGuard),
231 style: awc(getSet(domStyle), magicGuard),
232
233 addClass: aafe(domCls.add),
234 removeClass: aafe(domCls.remove),
235 replaceClass: aafe(domCls.replace),
236 toggleClass: aafe(domCls.toggle),
237
238 empty: aafe(domCtr.empty),
239 removeAttr: aafe(domAttr.remove),
240
241 position: aam(domGeom.position),
242 marginBox: aam(domGeom.getMarginBox),
243
244 // FIXME: connectPublisher()? connectRunOnce()?
245
246 /*
247 destroy: function(){
248 // summary:
249 // destroys every item in the list.
250 this.forEach(d.destroy);
251 // FIXME: should we be checking for and/or disposing of widgets below these nodes?
252 },
253 */
254
255 place: function(/*String||Node*/ queryOrNode, /*String*/ position){
256 // summary:
257 // places elements of this node list relative to the first element matched
258 // by queryOrNode. Returns the original NodeList. See: `dojo.place`
259 // queryOrNode:
260 // may be a string representing any valid CSS3 selector or a DOM node.
261 // In the selector case, only the first matching element will be used
262 // for relative positioning.
263 // position:
264 // can be one of:
265 // | "last" (default)
266 // | "first"
267 // | "before"
268 // | "after"
269 // | "only"
270 // | "replace"
271 // or an offset in the childNodes property
272 var item = query(queryOrNode)[0];
273 return this.forEach(function(node){ domCtr.place(node, item, position); }); // dojo.NodeList
274 },
275
276 orphan: function(/*String?*/ filter){
277 // summary:
278 // removes elements in this list that match the filter
279 // from their parents and returns them as a new NodeList.
280 // filter:
281 // CSS selector like ".foo" or "div > span"
282 // returns:
283 // `dojo.NodeList` containing the orphaned elements
284 return (filter ? query._filterResult(this, filter) : this).forEach(orphan); // dojo.NodeList
285 },
286
287 adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
288 // summary:
289 // places any/all elements in queryOrListOrNode at a
290 // position relative to the first element in this list.
291 // Returns a dojo.NodeList of the adopted elements.
292 // queryOrListOrNode:
293 // a DOM node or a query string or a query result.
294 // Represents the nodes to be adopted relative to the
295 // first element of this NodeList.
296 // position:
297 // can be one of:
298 // | "last" (default)
299 // | "first"
300 // | "before"
301 // | "after"
302 // | "only"
303 // | "replace"
304 // or an offset in the childNodes property
305 return query(queryOrListOrNode).place(this[0], position)._stash(this); // dojo.NodeList
306 },
307
308 // FIXME: do we need this?
309 query: function(/*String*/ queryStr){
310 // summary:
311 // Returns a new list whose members match the passed query,
312 // assuming elements of the current NodeList as the root for
313 // each search.
314 // example:
315 // assume a DOM created by this markup:
316 // | <div id="foo">
317 // | <p>
318 // | bacon is tasty, <span>dontcha think?</span>
319 // | </p>
320 // | </div>
321 // | <div id="bar">
322 // | <p>great comedians may not be funny <span>in person</span></p>
323 // | </div>
324 // If we are presented with the following definition for a NodeList:
325 // | var l = new dojo.NodeList(dojo.byId("foo"), dojo.byId("bar"));
326 // it's possible to find all span elements under paragraphs
327 // contained by these elements with this sub-query:
328 // | var spans = l.query("p span");
329
330 // FIXME: probably slow
331 if(!queryStr){ return this; }
332 var ret = new NodeList;
333 this.map(function(node){
334 // FIXME: why would we ever get undefined here?
335 query(queryStr, node).forEach(function(subNode){
336 if(subNode !== undefined){
337 ret.push(subNode);
338 }
339 });
340 });
341 return ret._stash(this); // dojo.NodeList
342 },
343
344 filter: function(/*String|Function*/ filter){
345 // summary:
346 // "masks" the built-in javascript filter() method (supported
347 // in Dojo via `dojo.filter`) to support passing a simple
348 // string filter in addition to supporting filtering function
349 // objects.
350 // filter:
351 // If a string, a CSS rule like ".thinger" or "div > span".
352 // example:
353 // "regular" JS filter syntax as exposed in dojo.filter:
354 // | dojo.query("*").filter(function(item){
355 // | // highlight every paragraph
356 // | return (item.nodeName == "p");
357 // | }).style("backgroundColor", "yellow");
358 // example:
359 // the same filtering using a CSS selector
360 // | dojo.query("*").filter("p").styles("backgroundColor", "yellow");
361
362 var a = arguments, items = this, start = 0;
363 if(typeof filter == "string"){ // inline'd type check
364 items = query._filterResult(this, a[0]);
365 if(a.length == 1){
366 // if we only got a string query, pass back the filtered results
367 return items._stash(this); // dojo.NodeList
368 }
369 // if we got a callback, run it over the filtered items
370 start = 1;
371 }
372 return this._wrap(array.filter(items, a[start], a[start + 1]), this); // dojo.NodeList
373 },
374
375 /*
376 // FIXME: should this be "copyTo" and include parenting info?
377 clone: function(){
378 // summary:
379 // creates node clones of each element of this list
380 // and returns a new list containing the clones
381 },
382 */
383
384 addContent: function(/*String||DomNode||Object||dojo.NodeList*/ content, /*String||Integer?*/ position){
385 // summary:
386 // add a node, NodeList or some HTML as a string to every item in the
387 // list. Returns the original list.
388 // description:
389 // a copy of the HTML content is added to each item in the
390 // list, with an optional position argument. If no position
391 // argument is provided, the content is appended to the end of
392 // each item.
393 // content:
394 // DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
395 // NodeList, the content will be cloned if the current NodeList has more than one
396 // element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
397 // it should be an object with at "template" String property that has the HTML string
398 // to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
399 // will be used on the "template" to generate the final HTML string. Other allowed
400 // properties on the object are: "parse" if the HTML
401 // string should be parsed for widgets (dojo.require("dojo.parser") to get that
402 // option to work), and "templateFunc" if a template function besides dojo.string.substitute
403 // should be used to transform the "template".
404 // position:
405 // can be one of:
406 // | "last"||"end" (default)
407 // | "first||"start"
408 // | "before"
409 // | "after"
410 // | "replace" (replaces nodes in this NodeList with new content)
411 // | "only" (removes other children of the nodes so new content is the only child)
412 // or an offset in the childNodes property
413 // example:
414 // appends content to the end if the position is omitted
415 // | dojo.query("h3 > p").addContent("hey there!");
416 // example:
417 // add something to the front of each element that has a
418 // "thinger" property:
419 // | dojo.query("[thinger]").addContent("...", "first");
420 // example:
421 // adds a header before each element of the list
422 // | dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
423 // example:
424 // add a clone of a DOM node to the end of every element in
425 // the list, removing it from its existing parent.
426 // | dojo.query(".note").addContent(dojo.byId("foo"));
427 // example:
428 // Append nodes from a templatized string.
429 // dojo.require("dojo.string");
430 // dojo.query(".note").addContent({
431 // template: '<b>${id}: </b><span>${name}</span>',
432 // id: "user332",
433 // name: "Mr. Anderson"
434 // });
435 // example:
436 // Append nodes from a templatized string that also has widgets parsed.
437 // dojo.require("dojo.string");
438 // dojo.require("dojo.parser");
439 // var notes = dojo.query(".note").addContent({
440 // template: '<button dojoType="dijit.form.Button">${text}</button>',
441 // parse: true,
442 // text: "Send"
443 // });
444 content = this._normalize(content, this[0]);
445 for(var i = 0, node; (node = this[i]); i++){
446 this._place(content, node, position, i > 0);
447 }
448 return this; //dojo.NodeList
449 }
450 });
451
452 /*===== return dojo.NodeList; =====*/
453 return NodeList;
454 });