1 var accessID = 'simples'+ new Date().getTime(),
  2 	// The following elements throw uncatchable exceptions if you
  3 	// attempt to add data properties to them.
  4 	noData = {
  5 		"embed": true,
  6 		"object": true,
  7 		"applet": true
  8 	},
  9 	/** @private */
 10 	canDoData = function( elem ){
 11 		return elem && elem.nodeName && !( elem == WIN || noData[ elem.nodeName.toLowerCase() ] );
 12 	},
 13 	/** @private */
 14 	removeHTML5Data = function( elem, key ){
 15 		
 16 		var data = elem.dataset;
 17 		
 18 		if( data && data[ key ] ){
 19 			delete elem.dataset[ key ];
 20 		} else if( !data ){
 21 			Simples.attr( elem, "data-" + key, null );
 22 		}
 23 	},
 24 	/** @private */
 25 	readHTML5Data = function( elem, key, original ){
 26 		
 27 		var data = elem.dataset;
 28 		
 29 		if( key ){
 30 			var val = data ? data[ key ] : Simples.attr( elem, "data-" + key );
 31 			return ( val == null || val == "" ) ? UNDEF : val;
 32 		} else {
 33 			if (!data) {
 34 				data = {};
 35 				var attrs = elem.attributes, i = attrs ? attrs.length : 0;
 36 				while (i) {
 37 					var attr = attrs[ --i ];
 38 					if (attr.name.indexOf('data-') === 0) {
 39 						data[attr.name.substr(5)] = attr.value;
 40 					}
 41 				}
 42 			} else {
 43 				var newData = {};
 44 				for( var name in data ){
 45 					newData[ name ] = data[ name ];
 46 				}
 47 				data = newData;
 48 			}
 49 			return Simples.merge( data, original || {} );
 50 		}
 51 	};
 52 
 53 Simples.merge( /** @lends Simples */ {
 54 	/**
 55 	 * @description for the provided element you can save data to the elements dataset where a simple string or read data off of the element
 56 	 * @param {Element} elem the element to read and manipulate dataset
 57 	 * @param {String} key the name of the dataset to work with
 58 	 * @param {All} value the value to write to the dataset, where value is undefined will read, where value is null will remove the key and data
 59 	 * @returns {Object|Null|All} returns dataset object for read where no key, returns value where read and null for eveything else
 60 	 */
 61 	data : function( elem, key, value ){
 62 		if ( canDoData( elem ) && ( key === UNDEF || typeof key === "string" ) ) {
 63 			var data = !elem[ accessID ] ? elem[ accessID ] = {} : elem[ accessID ];
 64 
 65 			if( key && value !== UNDEF ){
 66 				// To remove the existing data-* attribute as well as the data value
 67 				removeHTML5Data( elem, key );
 68 				if( value !== null ){
 69 					data[ key ] = value;
 70 				} else {
 71 					delete data[ key ];
 72 				}      
 73 			} else if( value === UNDEF ){
 74 				if( !key ){
 75 					return Simples.merge( data, readHTML5Data( elem, null, data ) );
 76 				} else {
 77 					var val = data[ key ];
 78 					return typeof val === "undefined" ? readHTML5Data( elem, key ) : val;
 79 				}
 80 			}
 81 		}
 82 		return null;
 83 	},
 84 	/**
 85 	 * @description for the provided element you can save data to the elements dataset where a simple string or read data off of the element
 86 	 * @param {Element} elem the element to clean all data off of the children
 87 	 * @param {Boolean} andSelf whether to include the provided element in with its children in the cleaning process
 88 	 */
 89 	cleanData : function( elem, andSelf ){
 90 		// Remove element nodes and prevent memory leaks
 91 		var canClean = canDoData( elem ),
 92 			elems = canClean ? Simples.makeArray( elem.getElementsByTagName("*") ) : [];
 93 
 94 		if( canClean && andSelf !== false ){
 95 			elems.push( elem );
 96 		}
 97 		var i=elems.length;
 98 		while( i ){
 99 			// decrement to ensure correct array position
100 			i--;
101 			if ( elems[ i ].nodeType === 1 ) {
102 				// Clean up the element expando
103 				try {
104 					delete elems[ i ][ accessID ];
105 				} catch( e ) {
106 					// IE has trouble directly removing the expando
107 					// but it's ok with using removeAttribute
108 					if ( elems[ i ].removeAttribute ) {
109 						elems[ i ].removeAttribute( accessID );
110 					}
111 				}
112 			}
113 		}
114 	}
115 });
116 
117 Simples.extend( /** @lends Simples.fn */ {
118 	/**
119 	 * Simples( '*' ).data: for the elements on the Simples object you can save data to the elements dataset where a simple string or read data off of the element, Simples.data for more information
120 	 * @param {String} key the name of the dataset to work with
121 	 * @param {All} value the value to write to the dataset
122 	 * @returns {Simples|All} returns Simples object for write and delete and the value for read
123 	 */	
124 	data : function( key, value ){   
125 		if( typeof key === "string" ){
126 			if( value !== UNDEF ){
127 				var l=this.length;
128 				while( l ){
129 					Simples.data( this[--l], key, value );
130 				}
131 			} else {
132 				return this[0] ? Simples.data( this[0], key ) : null;
133 			}
134 		}
135 		return this;
136 	}
137 });