]>
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
){
2 /*===== var NodeList = dojo.NodeList; =====*/
3 var magicGuard = function(a
){
5 // the guard function for dojo.attr() and dojo.style()
6 return a
.length
== 1 && (typeof a
[0] == "string"); // inline'd type check
9 var orphan = function(node
){
11 // function to orphan nodes
12 var p
= node
.parentNode
;
17 // FIXME: should we move orphan() to dojo.html?
19 var NodeList
= query
.NodeList
,
20 awc
= NodeList
._adaptWithCondition
,
21 aafe
= NodeList
._adaptAsForEach
,
22 aam
= NodeList
._adaptAsMap
;
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
);
30 return module
.set(node
, name
, value
);
34 lang
.extend(NodeList
, {
35 _normalize: function(/*String||Element||Object||NodeList*/content
, /*DOMNode?*/refNode
){
37 // normalizes data to an array of items to insert.
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).
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.
54 var parse
= content
.parse
=== true;
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
;
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
);
71 }else if(!lang
.isArrayLike(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
);
79 //Pass around the parse info
81 content
._runParse
= true;
83 return content
; //Array
86 _cloneNode: function(/*DOMNode*/ node
){
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);
94 _place: function(/*Array*/ary
, /*DOMNode*/refNode
, /*String*/position
, /*Boolean*/useClone
){
96 // private utility to handle placing an array of nodes relative to another node.
98 // Allows for cloning the nodes in the array, and for
99 // optionally parsing widgets, if ary._runParse is true.
101 //Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
102 if(refNode
.nodeType
!= 1 && position
== "only"){
105 var rNode
= refNode
, tempNode
;
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
]);
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
){
118 tempNode
= rNode
.ownerDocument
.createElement("div");
120 tempNode
.appendChild(node
);
121 dojo
.parser
.parse(tempNode
);
122 node
= tempNode
.firstChild
;
123 while(tempNode
.firstChild
){
124 tempNode
.removeChild(tempNode
.firstChild
);
129 domCtr
.place(node
, rNode
, position
);
131 rNode
.parentNode
.insertBefore(node
, rNode
);
138 position: function(){
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.
144 return dojo.map(this, dojo.position); // Array
147 attr: function(property, value){
149 // gets or sets the DOM attribute for every element in the
150 // NodeList. See also `dojo.attr`
152 // the attribute to get/set
154 // optional. The value to set the property to
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
159 // Make all nodes with a particular class focusable:
160 // | dojo.query(".focusable").attr("tabIndex", -1);
162 // Disable a group of buttons:
163 // | dojo.query("button.group").attr("disabled", true);
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
172 style: function(property, value){
174 // gets or sets the CSS property for every element in the NodeList
176 // the CSS property to get/set, in JavaScript notation
177 // ("lineHieght" instead of "line-height")
179 // optional. The value to set the property to
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
187 addClass: function(className){
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
196 removeClass: function(className){
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
204 // dojo.NodeList, this list
205 return; // dojo.NodeList
208 toggleClass: function(className, condition){
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.
215 // the CSS class to add
216 return; // dojo.NodeList
221 // clears all content from each node in the list. Effectively
222 // equivalent to removing all child nodes from every item in
224 return this.forEach("item.innerHTML='';"); // dojo.NodeList
225 // FIXME: should we be checking for and/or disposing of widgets below these nodes?
229 // useful html methods
230 attr
: awc(getSet(domAttr
), magicGuard
),
231 style
: awc(getSet(domStyle
), magicGuard
),
233 addClass
: aafe(domCls
.add
),
234 removeClass
: aafe(domCls
.remove
),
235 replaceClass
: aafe(domCls
.replace
),
236 toggleClass
: aafe(domCls
.toggle
),
238 empty
: aafe(domCtr
.empty
),
239 removeAttr
: aafe(domAttr
.remove
),
241 position
: aam(domGeom
.position
),
242 marginBox
: aam(domGeom
.getMarginBox
),
244 // FIXME: connectPublisher()? connectRunOnce()?
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?
255 place: function(/*String||Node*/ queryOrNode
, /*String*/ position
){
257 // places elements of this node list relative to the first element matched
258 // by queryOrNode. Returns the original NodeList. See: `dojo.place`
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.
265 // | "last" (default)
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
276 orphan: function(/*String?*/ filter
){
278 // removes elements in this list that match the filter
279 // from their parents and returns them as a new NodeList.
281 // CSS selector like ".foo" or "div > span"
283 // `dojo.NodeList` containing the orphaned elements
284 return (filter
? query
._filterResult(this, filter
) : this).forEach(orphan
); // dojo.NodeList
287 adopt: function(/*String||Array||DomNode*/ queryOrListOrNode
, /*String?*/ position
){
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.
298 // | "last" (default)
304 // or an offset in the childNodes property
305 return query(queryOrListOrNode
).place(this[0], position
)._stash(this); // dojo.NodeList
308 // FIXME: do we need this?
309 query: function(/*String*/ queryStr
){
311 // Returns a new list whose members match the passed query,
312 // assuming elements of the current NodeList as the root for
315 // assume a DOM created by this markup:
318 // | bacon is tasty, <span>dontcha think?</span>
322 // | <p>great comedians may not be funny <span>in person</span></p>
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");
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){
341 return ret
._stash(this); // dojo.NodeList
344 filter: function(/*String|Function*/ filter
){
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
351 // If a string, a CSS rule like ".thinger" or "div > span".
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");
359 // the same filtering using a CSS selector
360 // | dojo.query("*").filter("p").styles("backgroundColor", "yellow");
362 var a
= arguments
, items
= this, start
= 0;
363 if(typeof filter
== "string"){ // inline'd type check
364 items
= query
._filterResult(this, a
[0]);
366 // if we only got a string query, pass back the filtered results
367 return items
._stash(this); // dojo.NodeList
369 // if we got a callback, run it over the filtered items
372 return this._wrap(array
.filter(items
, a
[start
], a
[start
+ 1]), this); // dojo.NodeList
376 // FIXME: should this be "copyTo" and include parenting info?
379 // creates node clones of each element of this list
380 // and returns a new list containing the clones
384 addContent: function(/*String||DomNode||Object||dojo.NodeList*/ content
, /*String||Integer?*/ position
){
386 // add a node, NodeList or some HTML as a string to every item in the
387 // list. Returns the original list.
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
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".
406 // | "last"||"end" (default)
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
414 // appends content to the end if the position is omitted
415 // | dojo.query("h3 > p").addContent("hey there!");
417 // add something to the front of each element that has a
418 // "thinger" property:
419 // | dojo.query("[thinger]").addContent("...", "first");
421 // adds a header before each element of the list
422 // | dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
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"));
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>',
433 // name: "Mr. Anderson"
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>',
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);
448 return this; //dojo.NodeList
452 /*===== return dojo.NodeList; =====*/