source: Dev/trunk/src/client/dojo/NodeList-data.js @ 525

Last change on this file since 525 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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