Last active
January 27, 2019 13:26
-
-
Save liron-navon/29cfdc7018917a01f5f72104ba17c56f to your computer and use it in GitHub Desktop.
A rebuild of JQuery with es6
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
| // a simple utility function for normalizing return values | |
| const returnValue = values => values.length === 1 ? values[0] : values;; | |
| // a simple function to check existence | |
| const exists = value => value !== undefined && value !== null; | |
| const isString = value => typeof value === 'string'; | |
| const isArray = value => Array.isArray(value); | |
| // This is the actual class to hold all of our classes | |
| class ElementAbstraction { | |
| constructor(htmlElements) { | |
| // we can use __elementAbstraction to identify our abstraction instances | |
| this.__elementAbstraction = true; | |
| if (!htmlElements && htmlElements.length === 0) { | |
| // if no elements were past, we can default to body | |
| this.elements = [document.body]; | |
| } else if (htmlElements.__elementAbstraction && htmlElements.elements) { | |
| // we just copy the elements from the passed abstraction | |
| this.elements = htmlElements.elements; | |
| } else { | |
| // turn the NodeList elements from a selector into an array | |
| this.elements = [...htmlElements]; | |
| } | |
| } | |
| // set or get html | |
| html(newHTML) { | |
| const values = this.elements.map(el => { | |
| if (exists(newHTML)) { | |
| el.innerHTML = newHTML; | |
| } | |
| return el.innerHTML; | |
| }); | |
| return returnValue(values); | |
| } | |
| // find the children of the elements | |
| find(selector) { | |
| if(!exists(selector)) { | |
| return this; | |
| } | |
| const elements = this.elements.reduce((acc, el) => { | |
| return [...acc, ...el.querySelectorAll(selector)]; | |
| }, []); | |
| return new ElementAbstraction(elements); | |
| } | |
| // hide the elements | |
| hide() { | |
| this.element.forEach(el => { | |
| el.style.visibility = "hidden"; | |
| }); | |
| } | |
| // show the elements | |
| show() { | |
| this.element.forEach(el => { | |
| el.style.visibility = "visible"; | |
| }); | |
| } | |
| // append to the elements | |
| append(...elementsOrAbstractions) { | |
| this.elements.forEach(el => { | |
| elementsOrAbstractions.forEach(elementOrAbstraction => { | |
| const newElement = elementOrAbstraction.__elementAbstraction | |
| ? elementOrAbstraction.element | |
| : elementOrAbstraction; | |
| el.append(newElement); | |
| }); | |
| }); | |
| } | |
| // prepend elements | |
| prepend(...elementsOrAbstractions) { | |
| this.elements.forEach(el => { | |
| elementsOrAbstractions.forEach(elementOrAbstraction => { | |
| const newElement = elementOrAbstraction.__elementAbstraction | |
| ? elementOrAbstraction.element | |
| : elementOrAbstraction; | |
| el.prepend(newElement); | |
| }); | |
| }); | |
| } | |
| // attach event to elements | |
| on(eventName, callbackOrSelector, callback) { | |
| if (isString(callbackOrSelector)) { | |
| this.elements.forEach(el => { | |
| el = el.find(callbackOrSelector); | |
| if (el) { | |
| el.addEventListener(eventName, callback); | |
| } | |
| }); | |
| } else { | |
| this.elements.forEach(el => | |
| el.addEventListener(eventName, callbackOrSelector) | |
| ); | |
| } | |
| } | |
| // remove event from elements | |
| off(eventName, callbackOrSelector, callback = null) { | |
| if (isString(callbackOrSelector)) { | |
| this.elements.forEach(el => { | |
| el = el.find(callbackOrSelector); | |
| if (el) { | |
| el.removeEventListener(eventName, callback); | |
| } | |
| }); | |
| } else { | |
| this.elements.forEach(el => | |
| el.removeEventListener(eventName, callbackOrSelector) | |
| ); | |
| } | |
| } | |
| // sets or get the css of the elements, can also accept an array of propNames | |
| css(propNames, value = null) { | |
| if (value) { | |
| this.elements.forEach(el => (el.css[propNames] = value)); | |
| } else if (isArray(propNames)) { | |
| const els = this.elements.reduce( | |
| (acc, el) => [...acc, propNames.map(name => el.css[name])], | |
| [] | |
| ); | |
| return returnValue(els); | |
| } else { | |
| const els = this.element.reduce( | |
| (acc, el) => [...acc, el.css[propNames]], | |
| acc | |
| ); | |
| return returnValue(els); | |
| } | |
| } | |
| // sets or get the attribute of the elements, can also accept an array of attributeNames | |
| attr(attributeNames, value = null) { | |
| if (value) { | |
| this.elements.forEach(el => (el.attributes[attributeNames] = value)); | |
| } else if (isArray(attributeNames)) { | |
| const els = this.elements.reduce( | |
| (acc, el) => [...acc, attributeNames.map(name => el.attributes[name])], | |
| [] | |
| ); | |
| return returnValue(els); | |
| } else { | |
| const els = this.element.reduce( | |
| (acc, el) => [...acc, el.attributes[attributeNames]], | |
| acc | |
| ); | |
| return returnValue(els); | |
| } | |
| } | |
| // get the value of elements, optionally pass a callback | |
| val(callback = null) { | |
| if (callback) { | |
| this.elements.forEach(callback); | |
| } else { | |
| const values = this.elements.reduce((acc, el) => [...acc, el.value], []); | |
| return returnValue(values); | |
| } | |
| } | |
| // get the combined text of the element and it's children | |
| text() { | |
| const values = this.elements.map(el => el.innerText); | |
| return returnValue(values); | |
| } | |
| // loop the elements, and call a callback with the context of the element | |
| each(callback) { | |
| this.element.forEach((el, index) => callback.call(el, index)); | |
| } | |
| } | |
| // here is the main function to generate the abstractions for us | |
| const jquery = selector => { | |
| if (!selector) { | |
| // when calling "$()"" | |
| return new ElementAbstraction(); | |
| } | |
| if (typeof selector === "string") { | |
| // when calling "$('li')" | |
| return new ElementAbstraction(document.querySelectorAll(selector)); | |
| } else if (selector.__elementAbstraction) { | |
| // when calling "$($(li))", people do it for some reason | |
| return new ElementAbstraction([selector.element]); | |
| } else { | |
| // when calling "$()" | |
| return new ElementAbstraction(); | |
| } | |
| }; | |
| window.$ = jquery; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment