Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Created March 20, 2012 18:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rwaldron/2139330 to your computer and use it in GitHub Desktop.
Save rwaldron/2139330 to your computer and use it in GitHub Desktop.
(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