Created
March 20, 2012 18:29
-
-
Save rwaldron/2139330 to your computer and use it in GitHub Desktop.
This file contains 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
(function( window ) { | |
// "DoQuery" is a fake, future descendant of "jQuery" | |
// Create a WeakMap instance for Node data storage. This is perfect | |
// because using the Node as the key ensures that any data associated | |
// with the Node will be GC'ed if the Node is removed from the DOM | |
var nodeData = new WeakMap(); | |
class DoQuery { | |
// Definition of new instances | |
new( selector, context ) { | |
var matches; | |
this.context = context || document; | |
// Handle DoQuery(DOMElement) | |
if ( selector.nodeType ) { | |
this.context = this[ 0 ] = selector; | |
this.length = 1; | |
return this; | |
} | |
// query DOM for elements | |
matches = (context || document).querySelectorAll( selector ); | |
if ( matches.length ) { | |
// spread matches NodeList into an array | |
[ ...matches ].forEach((match, index) => { | |
// do-expression retains outer |this| | |
this[ index ] = match; | |
}); | |
this.length = matches.length; | |
} | |
} | |
each( callback ) { | |
// Spread the "array like" instance object into an array | |
[ ...this ].forEach(( node, index ) => { | |
// Inside the callback: | |
// Preserve jQuery's "node is |this|" style semantics | |
// Also, index comes first in jQuery callback params | |
callback.call( node, index, node ); | |
}); | |
return this; | |
} | |
data( opts ) { | |
// If no argument, return stored data of first item in set | |
if ( !opts ) { | |
return nodeData.get( this[0] ); | |
} | |
// |this| is the DoQuery/jQuery instance/query match set | |
return this.each((index) => { | |
// Inside the callback: | |
// |this| refers to the node, as set by | |
// callback.call( node, ... ) in | |
// DoQuery.prototype.each | |
let merged = {}, | |
data = nodeData.get( this ); | |
// I need a way to merge two objects. | |
// A serious pain-point. This is totally made up | |
// and has no proposal to back it up | |
Object.merge( merged, data, opts ); | |
nodeData.set( this, merged ); | |
}); | |
} | |
css( ...args ) { | |
let [ prop, value ] = args; | |
// If no value, return current style of | |
// first node in collection | |
if ( !value ) { | |
return DoQuery.syle( this[0], prop ); | |
} | |
// Otherwise, apply new style to | |
// all nodes in collection | |
return DoQuery.execute( this, prop, value, (node, k, v) => DoQuery.style(node, k, v) ); | |
} | |
} | |
// Multipurpose static function for getting and setting | |
// values to a node collection | |
// The value(s) can optionally be executed if it's a function | |
DoQuery.execute = function( ...args ) { | |
let [ nodes, key, val, fn ] = args, | |
length = nodes.length, | |
p; | |
// Call self to set many { key: val } | |
// on a collection | |
if ( key && typeof key === "object" ) { | |
for ( p in key ) { | |
DoQuery.execute( nodes, p, key[ p ], fn ); | |
} | |
// Sets a single "key" to "val" for | |
// all nodes in a collection | |
} else { | |
nodes.each( (node) => fn(node, key, val) ); | |
} | |
return nodes; | |
}; | |
// Static style get/set function | |
DoQuery.style = function( node, prop, value ) { | |
let defaultView = node.ownerDocument.defaultView; | |
if ( value ) { | |
node.style[ prop ] = value; | |
} else { | |
return defaultView.getComputedStyle( node ).getPropertyValue( prop ); | |
} | |
}; | |
window.DoQuery = function( selector, context ) { | |
return new DoQuery( selector, context || null ); | |
}; | |
})( this ); | |
// Notable: https://gist.github.com/1350563 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment