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