]>
git.wh0rd.org - tt-rss.git/blob - 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
){
4 // dojo/NodeList-dom.js
9 // Adds DOM related methods to NodeList, and returns NodeList constructor.
13 var magicGuard = function(a
){
15 // the guard function for dojo.attr() and dojo.style()
16 return a
.length
== 1 && (typeof a
[0] == "string"); // inline'd type check
19 var orphan = function(node
){
21 // function to orphan nodes
22 var p
= node
.parentNode
;
27 // FIXME: should we move orphan() to dojo.html?
29 var NodeList
= query
.NodeList
,
30 awc
= NodeList
._adaptWithCondition
,
31 aafe
= NodeList
._adaptAsForEach
,
32 aam
= NodeList
._adaptAsMap
;
34 function getSet(module
){
35 return function(node
, name
, value
){
36 if(arguments
.length
== 2){
37 return module
[typeof name
== "string" ? "get" : "set"](node
, name
);
40 return module
.set(node
, name
, value
);
44 lang
.extend(NodeList
, {
45 _normalize: function(/*String||Element||Object||NodeList*/content
, /*DOMNode?*/refNode
){
47 // normalizes data to an array of items to insert.
49 // If content is an object, it can have special properties "template" and
50 // "parse". If "template" is defined, then the template value is run through
51 // dojo.string.substitute (if dojo/string.substitute() has been dojo.required elsewhere),
52 // or if templateFunc is a function on the content, that function will be used to
53 // transform the template into a final string to be used for for passing to dojo/dom-construct.toDom().
54 // If content.parse is true, then it is remembered for later, for when the content
55 // nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
56 // (if dojo.parser has been dojo.required elsewhere).
58 //Wanted to just use a DocumentFragment, but for the array/NodeList
59 //case that meant using cloneNode, but we may not want that.
60 //Cloning should only happen if the node operations span
61 //multiple refNodes. Also, need a real array, not a NodeList from the
62 //DOM since the node movements could change those NodeLists.
64 var parse
= content
.parse
=== true;
66 //Do we have an object that needs to be run through a template?
67 if(typeof content
.template
== "string"){
68 var templateFunc
= content
.templateFunc
|| (dojo
.string
&& dojo
.string
.substitute
);
69 content
= templateFunc
? templateFunc(content
.template
, content
) : content
;
72 var type
= (typeof content
);
73 if(type
== "string" || type
== "number"){
74 content
= domCtr
.toDom(content
, (refNode
&& refNode
.ownerDocument
));
75 if(content
.nodeType
== 11){
76 //DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
77 content
= lang
._toArray(content
.childNodes
);
81 }else if(!lang
.isArrayLike(content
)){
83 }else if(!lang
.isArray(content
)){
84 //To get to this point, content is array-like, but
85 //not an array, which likely means a DOM NodeList. Convert it now.
86 content
= lang
._toArray(content
);
89 //Pass around the parse info
91 content
._runParse
= true;
93 return content
; //Array
96 _cloneNode: function(/*DOMNode*/ node
){
98 // private utility to clone a node. Not very interesting in the vanilla
99 // dojo/NodeList case, but delegates could do interesting things like
100 // clone event handlers if that is derivable from the node.
101 return node
.cloneNode(true);
104 _place: function(/*Array*/ary
, /*DOMNode*/refNode
, /*String*/position
, /*Boolean*/useClone
){
106 // private utility to handle placing an array of nodes relative to another node.
108 // Allows for cloning the nodes in the array, and for
109 // optionally parsing widgets, if ary._runParse is true.
111 //Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
112 if(refNode
.nodeType
!= 1 && position
== "only"){
115 var rNode
= refNode
, tempNode
;
117 //Always cycle backwards in case the array is really a
118 //DOM NodeList and the DOM operations take it out of the live collection.
119 var length
= ary
.length
;
120 for(var i
= length
- 1; i
>= 0; i
--){
121 var node
= (useClone
? this._cloneNode(ary
[i
]) : ary
[i
]);
123 //If need widget parsing, use a temp node, instead of waiting after inserting into
124 //real DOM because we need to start widget parsing at one node up from current node,
125 //which could cause some already parsed widgets to be parsed again.
126 if(ary
._runParse
&& dojo
.parser
&& dojo
.parser
.parse
){
128 tempNode
= rNode
.ownerDocument
.createElement("div");
130 tempNode
.appendChild(node
);
131 dojo
.parser
.parse(tempNode
);
132 node
= tempNode
.firstChild
;
133 while(tempNode
.firstChild
){
134 tempNode
.removeChild(tempNode
.firstChild
);
139 domCtr
.place(node
, rNode
, position
);
141 rNode
.parentNode
.insertBefore(node
, rNode
);
148 position
: aam(domGeom
.position
),
150 position: function(){
152 // Returns border-box objects (x/y/w/h) of all elements in a node list
153 // as an Array (*not* a NodeList). Acts like `dojo.position`, though
154 // assumes the node passed is each node in this list.
156 return dojo.map(this, dojo.position); // Array
160 attr
: awc(getSet(domAttr
), magicGuard
),
162 attr: function(property, value){
164 // gets or sets the DOM attribute for every element in the
165 // NodeList. See also `dojo.attr`
167 // the attribute to get/set
169 // optional. The value to set the property to
171 // if no value is passed, the result is an array of attribute values
172 // If a value is passed, the return is this NodeList
174 // Make all nodes with a particular class focusable:
175 // | dojo.query(".focusable").attr("tabIndex", -1);
177 // Disable a group of buttons:
178 // | dojo.query("button.group").attr("disabled", true);
180 // innerHTML can be assigned or retrieved as well:
181 // | // get the innerHTML (as an array) for each list item
182 // | var ih = dojo.query("li.replaceable").attr("innerHTML");
183 return; // dojo/NodeList|Array
187 style
: awc(getSet(domStyle
), magicGuard
),
189 style: function(property, value){
191 // gets or sets the CSS property for every element in the NodeList
193 // the CSS property to get/set, in JavaScript notation
194 // ("lineHieght" instead of "line-height")
196 // optional. The value to set the property to
198 // if no value is passed, the result is an array of strings.
199 // If a value is passed, the return is this NodeList
200 return; // dojo/NodeList
205 addClass
: aafe(domCls
.add
),
207 addClass: function(className){
209 // adds the specified class to every node in the list
210 // className: String|Array
211 // A String class name to add, or several space-separated class names,
212 // or an array of class names.
213 return; // dojo/NodeList
217 removeClass
: aafe(domCls
.remove
),
219 removeClass: function(className){
221 // removes the specified class from every node in the list
222 // className: String|Array?
223 // An optional String class name to remove, or several space-separated
224 // class names, or an array of class names. If omitted, all class names
228 return; // dojo/NodeList
232 toggleClass
: aafe(domCls
.toggle
),
234 toggleClass: function(className, condition){
236 // Adds a class to node if not present, or removes if present.
237 // Pass a boolean condition if you want to explicitly add or remove.
238 // condition: Boolean?
239 // If passed, true means to add the class, false means to remove.
241 // the CSS class to add
242 return; // dojo/NodeList
246 replaceClass
: aafe(domCls
.replace
),
248 replaceClass: function(addClassStr, removeClassStr){
250 // Replaces one or more classes on a node if not present.
251 // Operates more quickly than calling `removeClass()` and `addClass()`
252 // addClassStr: String|Array
253 // A String class name to add, or several space-separated class names,
254 // or an array of class names.
255 // removeClassStr: String|Array?
256 // A String class name to remove, or several space-separated class names,
257 // or an array of class names.
258 return; // dojo/NodeList
262 empty
: aafe(domCtr
.empty
),
266 // clears all content from each node in the list. Effectively
267 // equivalent to removing all child nodes from every item in
269 return this.forEach("item.innerHTML='';"); // dojo/NodeList
270 // FIXME: should we be checking for and/or disposing of widgets below these nodes?
274 removeAttr
: aafe(domAttr
.remove
),
276 removeAttr: function(name){
278 // Removes an attribute from each node in the list.
280 // the name of the attribute to remove
281 return; // dojo/NodeList
285 marginBox
: aam(domGeom
.getMarginBox
),
287 marginBox: function(){
289 // Returns margin-box size of nodes
290 return; // dojo/NodeList
294 // FIXME: connectPublisher()? connectRunOnce()?
299 // destroys every item in the list.
300 this.forEach(d.destroy);
301 // FIXME: should we be checking for and/or disposing of widgets below these nodes?
305 place: function(/*String||Node*/ queryOrNode
, /*String*/ position
){
307 // places elements of this node list relative to the first element matched
308 // by queryOrNode. Returns the original NodeList. See: `dojo.place`
310 // may be a string representing any valid CSS3 selector or a DOM node.
311 // In the selector case, only the first matching element will be used
312 // for relative positioning.
316 // - "last" (default)
323 // or an offset in the childNodes property
324 var item
= query(queryOrNode
)[0];
325 return this.forEach(function(node
){ domCtr
.place(node
, item
, position
); }); // dojo/NodeList
328 orphan: function(/*String?*/ filter
){
330 // removes elements in this list that match the filter
331 // from their parents and returns them as a new NodeList.
333 // CSS selector like ".foo" or "div > span"
335 // NodeList containing the orphaned elements
336 return (filter
? query
._filterResult(this, filter
) : this).forEach(orphan
); // dojo/NodeList
339 adopt: function(/*String||Array||DomNode*/ queryOrListOrNode
, /*String?*/ position
){
341 // places any/all elements in queryOrListOrNode at a
342 // position relative to the first element in this list.
343 // Returns a dojo/NodeList of the adopted elements.
344 // queryOrListOrNode:
345 // a DOM node or a query string or a query result.
346 // Represents the nodes to be adopted relative to the
347 // first element of this NodeList.
351 // - "last" (default)
358 // or an offset in the childNodes property
359 return query(queryOrListOrNode
).place(this[0], position
)._stash(this); // dojo/NodeList
362 // FIXME: do we need this?
363 query: function(/*String*/ queryStr
){
365 // Returns a new list whose members match the passed query,
366 // assuming elements of the current NodeList as the root for
369 // assume a DOM created by this markup:
372 // | bacon is tasty, <span>dontcha think?</span>
376 // | <p>great comedians may not be funny <span>in person</span></p>
378 // If we are presented with the following definition for a NodeList:
379 // | var l = new NodeList(dojo.byId("foo"), dojo.byId("bar"));
380 // it's possible to find all span elements under paragraphs
381 // contained by these elements with this sub-query:
382 // | var spans = l.query("p span");
384 // FIXME: probably slow
385 if(!queryStr
){ return this; }
386 var ret
= new NodeList
;
387 this.map(function(node
){
388 // FIXME: why would we ever get undefined here?
389 query(queryStr
, node
).forEach(function(subNode
){
390 if(subNode
!== undefined){
395 return ret
._stash(this); // dojo/NodeList
398 filter: function(/*String|Function*/ filter
){
400 // "masks" the built-in javascript filter() method (supported
401 // in Dojo via `dojo.filter`) to support passing a simple
402 // string filter in addition to supporting filtering function
405 // If a string, a CSS rule like ".thinger" or "div > span".
407 // "regular" JS filter syntax as exposed in dojo.filter:
408 // | dojo.query("*").filter(function(item){
409 // | // highlight every paragraph
410 // | return (item.nodeName == "p");
411 // | }).style("backgroundColor", "yellow");
413 // the same filtering using a CSS selector
414 // | dojo.query("*").filter("p").styles("backgroundColor", "yellow");
416 var a
= arguments
, items
= this, start
= 0;
417 if(typeof filter
== "string"){ // inline'd type check
418 items
= query
._filterResult(this, a
[0]);
420 // if we only got a string query, pass back the filtered results
421 return items
._stash(this); // dojo/NodeList
423 // if we got a callback, run it over the filtered items
426 return this._wrap(array
.filter(items
, a
[start
], a
[start
+ 1]), this); // dojo/NodeList
430 // FIXME: should this be "copyTo" and include parenting info?
433 // creates node clones of each element of this list
434 // and returns a new list containing the clones
438 addContent: function(/*String||DomNode||Object||dojo/NodeList*/ content, /*String||Integer?*/ position
){
440 // add a node, NodeList or some HTML as a string to every item in the
441 // list. Returns the original list.
443 // a copy of the HTML content is added to each item in the
444 // list, with an optional position argument. If no position
445 // argument is provided, the content is appended to the end of
448 // DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
449 // NodeList, the content will be cloned if the current NodeList has more than one
450 // element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
451 // it should be an object with at "template" String property that has the HTML string
452 // to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
453 // will be used on the "template" to generate the final HTML string. Other allowed
454 // properties on the object are: "parse" if the HTML
455 // string should be parsed for widgets (dojo.require("dojo.parser") to get that
456 // option to work), and "templateFunc" if a template function besides dojo.string.substitute
457 // should be used to transform the "template".
461 // - "last"||"end" (default)
465 // - "replace" (replaces nodes in this NodeList with new content)
466 // - "only" (removes other children of the nodes so new content is the only child)
468 // or an offset in the childNodes property
470 // appends content to the end if the position is omitted
471 // | dojo.query("h3 > p").addContent("hey there!");
473 // add something to the front of each element that has a
474 // "thinger" property:
475 // | dojo.query("[thinger]").addContent("...", "first");
477 // adds a header before each element of the list
478 // | dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
480 // add a clone of a DOM node to the end of every element in
481 // the list, removing it from its existing parent.
482 // | dojo.query(".note").addContent(dojo.byId("foo"));
484 // Append nodes from a templatized string.
485 // | dojo.require("dojo.string");
486 // | dojo.query(".note").addContent({
487 // | template: '<b>${id}: </b><span>${name}</span>',
489 // | name: "Mr. Anderson"
492 // Append nodes from a templatized string that also has widgets parsed.
493 // | dojo.require("dojo.string");
494 // | dojo.require("dojo.parser");
495 // | var notes = dojo.query(".note").addContent({
496 // | template: '<button dojoType="dijit/form/Button">${text}</button>',
500 content
= this._normalize(content
, this[0]);
501 for(var i
= 0, node
; (node
= this[i
]); i
++){
502 this._place(content
, node
, position
, i
> 0);
504 return this; // dojo/NodeList