source: Dev/branches/rest-dojo-ui/client/dojo/NodeList-data.js @ 274

Last change on this file since 274 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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