]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/NodeList-data.js
upgrade Dojo to 1.6.1
[tt-rss.git] / lib / dojo / NodeList-data.js
1 /*
2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
5 */
6
7
8 if(!dojo._hasResource["dojo.NodeList-data"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9 dojo._hasResource["dojo.NodeList-data"] = true;
10 dojo.provide("dojo.NodeList-data");
11
12 (function(d){
13
14 /*=====
15 dojo.NodeList.prototype.data = function(key, value){
16 // summary: stash or get some arbitrary data on/from these nodes.
17 //
18 // description:
19 // Stash or get some arbirtrary data on/from these nodes. This private _data function is
20 // exposed publicly on `dojo.NodeList`, eg: as the result of a `dojo.query` call.
21 // DIFFERS from jQuery.data in that when used as a getter, the entire list is ALWAYS
22 // returned. EVEN WHEN THE LIST IS length == 1.
23 //
24 // A single-node version of this function is provided as `dojo._nodeData`, which follows
25 // the same signature, though expects a String ID or DomNode reference in the first
26 // position, before key/value arguments.
27 //
28 // node: String|DomNode
29 // The node to associate data with
30 //
31 // key: Object?|String?
32 // If an object, act as a setter and iterate over said object setting data items as defined.
33 // If a string, and `value` present, set the data for defined `key` to `value`
34 // If a string, and `value` absent, act as a getter, returning the data associated with said `key`
35 //
36 // value: Anything?
37 // The value to set for said `key`, provided `key` is a string (and not an object)
38 //
39 // example:
40 // Set a key `bar` to some data, then retrieve it.
41 // | dojo.query(".foo").data("bar", "touched");
42 // | var touched = dojo.query(".foo").data("bar");
43 // | if(touched[0] == "touched"){ alert('win'); }
44 //
45 // example:
46 // Get all the data items for a given node.
47 // | var list = dojo.query(".foo").data();
48 // | var first = list[0];
49 //
50 // example:
51 // Set the data to a complex hash. Overwrites existing keys with new value
52 // | dojo.query(".foo").data({ bar:"baz", foo:"bar" });
53 // Then get some random key:
54 // | dojo.query(".foo").data("foo"); // returns [`bar`]
55 //
56 // returns: Object|Anything|Nothing
57 // When used as a setter via `dojo.NodeList`, a NodeList instance is returned
58 // for further chaning. When used as a getter via `dojo.NodeList` an ARRAY
59 // of items is returned. The items in the array correspond to the elements
60 // in the original list. This is true even when the list length is 1, eg:
61 // when looking up a node by ID (#foo)
62 };
63
64 dojo.NodeList.prototype.removeData = function(key){
65 // summary: Remove the data associated with these nodes.
66 // key: String?
67 // If ommitted, clean all data for this node.
68 // If passed, remove the data item found at `key`
69 };
70
71 dojo._nodeDataCache = {
72 // summary: An alias to the private dataCache for NodeList-data. NEVER USE THIS!
73 // This private is only exposed for the benefit of unit testing, and is
74 // removed during the build process.
75 };
76
77 =====*/
78
79 var dataCache = {}, x = 0, dataattr = "data-dojo-dataid", nl = d.NodeList,
80 dopid = function(node){
81 // summary: Return a uniqueish ID for the passed node reference
82 var pid = d.attr(node, dataattr);
83 if(!pid){
84 pid = "pid" + (x++);
85 d.attr(node, dataattr, pid);
86 }
87 return pid;
88 }
89 ;
90
91
92 var dodata = d._nodeData = function(node, key, value){
93
94 var pid = dopid(node), r;
95 if(!dataCache[pid]){ dataCache[pid] = {}; }
96
97 // API discrepency: calling with only a node returns the whole object. $.data throws
98 if(arguments.length == 1){ r = dataCache[pid]; }
99 if(typeof key == "string"){
100 // either getter or setter, based on `value` presence
101 if(arguments.length > 2){
102 dataCache[pid][key] = value;
103 }else{
104 r = dataCache[pid][key];
105 }
106 }else{
107 // must be a setter, mix `value` into data hash
108 // API discrepency: using object as setter works here
109 r = d._mixin(dataCache[pid], key);
110 }
111
112 return r; // Object|Anything|Nothing
113 };
114
115 var removeData = d._removeNodeData = function(node, key){
116 // summary: Remove some data from this node
117 // node: String|DomNode
118 // The node reference to remove data from
119 // key: String?
120 // If omitted, remove all data in this dataset.
121 // If passed, remove only the passed `key` in the associated dataset
122 var pid = dopid(node);
123 if(dataCache[pid]){
124 if(key){
125 delete dataCache[pid][key];
126 }else{
127 delete dataCache[pid];
128 }
129 }
130 };
131
132 d._gcNodeData = function(){
133 // summary: super expensive: GC all data in the data for nodes that no longer exist in the dom.
134 // description:
135 // super expensive: GC all data in the data for nodes that no longer exist in the dom.
136 // MUCH safer to do this yourself, manually, on a per-node basis (via `NodeList.removeData()`)
137 // provided as a stop-gap for exceptionally large/complex applications with constantly changing
138 // content regions (eg: a dijit.layout.ContentPane with replacing data)
139 // There is NO automatic GC going on. If you dojo.destroy() a node, you should _removeNodeData
140 // prior to destruction.
141 var livePids = dojo.query("[" + dataattr + "]").map(dopid);
142 for(var i in dataCache){
143 if(dojo.indexOf(livePids, i) < 0){ delete dataCache[i]; }
144 }
145 };
146
147 // make nodeData and removeNodeData public on dojo.NodeList:
148 d.extend(nl, {
149 data: nl._adaptWithCondition(dodata, function(a){
150 return a.length === 0 || a.length == 1 && (typeof a[0] == "string");
151 }),
152 removeData: nl._adaptAsForEach(removeData)
153 });
154
155 // TODO: this is the basic implemetation of adaptWithCondtionAndWhenMappedConsiderLength, for lack of a better API name
156 // it conflicts with the the `dojo.NodeList` way: always always return an arrayLike thinger. Consider for 2.0:
157 //
158 // nl.prototype.data = function(key, value){
159 // var a = arguments, r;
160 // if(a.length === 0 || a.length == 1 && (typeof a[0] == "string")){
161 // r = this.map(function(node){
162 // return d._data(node, key);
163 // });
164 // if(r.length == 1){ r = r[0]; } // the offending line, and the diff on adaptWithCondition
165 // }else{
166 // r = this.forEach(function(node){
167 // d._data(node, key, value);
168 // });
169 // }
170 // return r; // dojo.NodeList|Array|SingleItem
171 // };
172
173 })(dojo);
174
175 }