Created
August 29, 2017 22:56
-
-
Save justinbmeyer/8b4c12d1ca9f6acfedfc68a271493328 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() { | |
$ = function(selector) { | |
// tesla instanceof Tesla | |
if(!(this instanceof $)) { | |
return new $(selector); | |
} | |
var elements; | |
if(typeof selector === "string") { | |
elements = document.querySelectorAll(selector); | |
} else { | |
elements = selector; | |
} | |
for(var i = 0; i< elements.length; i++) { | |
this[i] = elements[i]; | |
} | |
this.length = elements.length; | |
}; | |
// target = {} | |
// o1 = {foo:"bar", zed: "ted"} | |
// o2 = {} | |
// extend(target, [o1, o2]) | |
// target //-> {0: o1, 1: o2, length: 2} | |
$.extend = function(target, source) { | |
for( var prop in source ) { | |
target[prop] = source[prop]; | |
} | |
return target; | |
}; | |
// Static methods | |
var isArrayLike = function(obj) { | |
if(obj && typeof obj.length === "number") { | |
if(obj.length > 0) { | |
return (obj.length - 1) in obj; | |
} else { | |
return obj.length === 0; | |
} | |
} else { | |
return false; | |
} | |
}; | |
// $.each([1,2,3], function(index, value, collection){ this //-> collection }) | |
$.extend($, { | |
isArray: function(obj) { | |
return Object.prototype.toString.call(obj) === "[object Array]"; | |
}, | |
each: function(collection, cb) { | |
if(isArrayLike(collection)) { | |
for(var i = 0 ; i < collection.length; i++) { | |
if( cb.call(collection, i, collection[i], collection) === false ) { | |
break; | |
} | |
} | |
} else { | |
for(var prop in collection) { | |
if( cb.call(collection, prop, collection[prop], collection) === false ) { | |
break; | |
} | |
} | |
} | |
return collection; | |
}, | |
makeArray: function(arr) { | |
var array = []; | |
$.each(arr, function(index, value){ | |
array.push(value); | |
}) | |
return array; | |
}, | |
proxy: function(fn, context) { | |
return function(){ | |
return fn.apply(context, arguments); | |
}; | |
} | |
}); | |
function getText(el) { | |
var text = ""; | |
$.each(el.childNodes, function(i, node){ | |
if(node.nodeType === Node.ELEMENT_NODE) { | |
text += getText(node); | |
}else if(node.nodeType === Node.TEXT_NODE) { | |
text += node.nodeValue; // add to accumulator | |
} | |
}); | |
return text; | |
} | |
function makeMutator(property) { | |
return function(newHtml) { | |
if(arguments.length) { | |
return $.each(this, function(i, element){ | |
element[property] = newHtml; | |
}); | |
} else { | |
return this[0][property]; | |
} | |
} | |
} | |
function makeTraverser(traverse) { | |
return function(){ | |
var newElements = []; | |
var args = arguments; | |
$.each(this, function(i, element){ | |
var elements = traverse.apply(element, args); | |
if(elements) { | |
if(isArrayLike(elements)) { | |
Array.prototype.push.apply(newElements, elements); | |
} else { | |
newElements.push(elements); | |
} | |
} | |
}); | |
return $(newElements) //-> instanceof jQuery | |
}; | |
} | |
function makeGetSibling(property){ | |
return function(){ | |
var next = this[property]; | |
while(next && next.nodeType !== Node.ELEMENT_NODE) { | |
next = next[property]; | |
} | |
return next; | |
} | |
} | |
$.extend($.prototype, { | |
html: makeMutator("innerHTML"), | |
val: makeMutator("value"), | |
text: function(newText) { | |
if(arguments.length) { | |
this.html(""); | |
return $.each(this, function(i, element){ | |
element.appendChild( document.createTextNode(newText) ) | |
}); | |
} else { | |
return getText(this[0]); | |
} | |
}, | |
// $('div').find('img') //-> $images | |
find: makeTraverser(function(selector){ | |
return this.querySelectorAll(selector); | |
}), | |
next: makeTraverser(makeGetSibling("nextSibling")), | |
prev: makeTraverser(makeGetSibling("previousSibling")), | |
parent: makeTraverser(function(){ | |
return this.parentNode; | |
}), | |
children: makeTraverser(function(){ | |
return this.children; | |
}), | |
attr: function(attrName, value) {}, | |
css: function(cssPropName, value) {}, | |
width: function() {}, | |
offset: function() { | |
var offset = this[0].getBoundingClientRect(); | |
return { | |
top: offset.top + window.pageYOffset, | |
left: offset.left + window.pageXOffset | |
}; | |
}, | |
hide: function() {}, | |
show: function() {}, | |
// Events | |
bind: function(eventName, handler) {}, | |
unbind: function(eventName, handler) {}, | |
has: function(selector) { | |
var elements = []; | |
$.each(this, function(i, el) { | |
if(el.matches(selector)) { | |
elements.push(el); | |
} | |
}); | |
return $( elements ); | |
}, | |
on: function(eventType, selector, handler) { | |
return this.bind(eventType, function(ev){ | |
var cur = ev.target; | |
do { | |
if ($([ cur ]).has(selector).length) { | |
handler.call(cur, ev); | |
} | |
cur = cur.parentNode; | |
} while (cur && cur !== ev.currentTarget); | |
}); | |
}, | |
off: function(eventType, selector, handler) {}, | |
data: function(propName, data) {}, | |
// Extra | |
addClass: function(className) {}, | |
removeClass: function(className) {}, | |
append: function(element) {} | |
}); | |
$.buildFragment = function(html) {}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment