]> git.wh0rd.org Git - 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 });