Created
August 27, 2010 12:23
-
-
Save phiggins42/553257 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dojo.provide("dojo.NodeList-data"); | |
(function(d){ | |
/*===== | |
dojo.NodeList.prototype.data = function(key, value){ | |
// summary: stash or get some arbitrary data on/from these nodes. | |
// | |
// description: | |
// Stash or get some arbirtrary data on/from these nodes. This private _data function is | |
// exposed publicly on `dojo.NodeList`, eg: as the result of a `dojo.query` call. | |
// DIFFERS from jQuery.data in that when used as a getter, the entire list is ALWAYS | |
// returned. EVEN WHEN THE LIST IS length == 1 | |
// | |
// node: String|DomNode | |
// The node to associate data with | |
// | |
// key: Object?|String? | |
// If an object, act as a setter and iterate over said object setting data items as defined. | |
// If a string, and `value` present, set the data for defined `key` to `value` | |
// If a string, and `value` absent, act as a getter, returning the data associated with said `key` | |
// | |
// value: Anything? | |
// The value to set for said `key`, provided `key` is a string (and not an object) | |
// | |
// example: | |
// Set a key `bar` to some data, then retrieve it. | |
// | dojo.query(".foo").data("bar", "touched"); | |
// | var touched = dojo.query(".foo").data("bar"); | |
// | if(touched[0] == "touched"){ alert('win'); } | |
// | |
// example: | |
// Get all the data items for a given node. | |
// | var list = dojo.query(".foo").data(); | |
// | var first = list[0]; | |
// | |
// example: | |
// Set the data to a complex hash. Overwrites existing keys with new value | |
// | dojo.query(".foo").data({ bar:"baz", foo:"bar" }); | |
// Then get some random key: | |
// | dojo.query(".foo").data("foo"); // returns `bar` | |
// | |
// returns: Object|Anything|Nothing | |
// When used as a setter via `dojo.NodeList`, a NodeList instance is returned | |
// for further chaning. When used as a getter via `dojo.NodeList` an ARRAY | |
// of items is returned. The items in the array correspond to the elements | |
// in the original list. This is true even when the list length is 1, eg: | |
// when looking up a node by ID (#foo) | |
} | |
=====*/ | |
var dataCache = {}, x = 0, dataattr = "data-dojo-dataid", nl = d.NodeList, | |
dopid = function(node){ | |
// summary: Return a uniqueish ID for the passed node reference | |
var pid = d.attr(node, dataattr); | |
if(!pid){ | |
pid = "pid" + (x++); | |
d.attr(node, dataattr, pid); | |
} | |
return pid; | |
} | |
; | |
// FIXME: how to expose in dojo.*? | |
var dodata = d._nodeData = function(node, key, value){ | |
var pid = dopid(node), r; | |
if(!dataCache[pid]){ dataCache[pid] = {}; } | |
// API discrepency: calling with only a node returns the whole object. $.data throws | |
if(arguments.length == 1){ r = dataCache[pid]; } | |
if(typeof key == "string"){ | |
// either getter or setter, based on `value` presence | |
if(arguments.length > 2){ | |
dataCache[pid][key] = value; | |
}else{ | |
r = dataCache[pid][key]; | |
} | |
}else{ | |
// must be a setter, mix `value` into data hash | |
// API discrepency: using object as setter works here | |
r = d._mixin(dataCache[pid], key); | |
} | |
return r; // Object|Anything|Nothing | |
}; | |
// FIXME: how to expose in dojo.*? | |
var removeData = function(node, key){ | |
// summary: Remove some data from this node | |
// node: String|DomNode | |
// The node reference to remove data from | |
// key: String? | |
// If omitted, remove all data in this dataset. | |
// If passed, remove only the passed `key` in the associated dataset | |
var pid = dopid(node); | |
if(dataCache[pid]){ | |
if(key){ | |
delete dataCache[pid][key]; | |
}else{ | |
delete dataCache[pid]; | |
} | |
} | |
}; | |
d._cleanData = function(){ | |
// summary: super expensive: GC all data in the data for nodes that no longer exist in the dom. | |
// MUCH safer to do this yourself, manually. | |
var livePids = dojo.query("[" + dataattr + "]").map(dopid); | |
for(var i in dataCache){ | |
if(!~dojo.indexOf(livePids, i)){ delete dataCache[i]; } | |
} | |
}; | |
// TODO: this is the basic implemetation of adaptWithCondtionAndWhenMappedConsiderLength, for lack of a better API name | |
// it conflicts with the the `dojo.NodeList` way: always always return an arrayLike thinger. | |
// | |
// nl.prototype.data = function(key, value){ | |
// var a = arguments, r; | |
// if(a.length === 0 || a.length == 1 && (typeof a[0] == "string")){ | |
// r = this.map(function(node){ | |
// return d._data(node, key); | |
// }); | |
// if(r.length == 1){ r = r[0]; } // the offending line, and the diff on adaptWithCondition | |
// }else{ | |
// r = this.forEach(function(node){ | |
// d._data(node, key, value); | |
// }); | |
// } | |
// return r; // dojo.NodeList|Array|SingleItem | |
// }; | |
d.extend(nl, { | |
data: nl._adaptWithCondition(dodata, function(a){ | |
return a.length === 0 || a.length == 1 && (typeof a[0] == "string"); | |
}), | |
removeData: nl._adaptAsForEach(removeData) | |
}); | |
})(dojo); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment