Last active
November 7, 2021 09:25
-
-
Save MayankFawkes/014868ea6420b5ea1656dbd358c07366 to your computer and use it in GitHub Desktop.
A Simple clone of jQuery.
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
| (function() { | |
| var document = window.document; | |
| var version = "0.1.0"; | |
| var arr = []; | |
| var isFunction = function isFunction( obj ) { | |
| return typeof obj === "function" && typeof obj.nodeType !== "number" && | |
| typeof obj.item !== "function"; | |
| }; | |
| var isWindow = function isWindow( obj ) { | |
| return obj != null && obj === obj.window; | |
| }; | |
| function isArrayLike(obj) { | |
| let type = typeof obj; | |
| if (obj instanceof Mscript) { | |
| return true | |
| } | |
| if ( isFunction( obj ) || isWindow( obj ) ) { | |
| return false; | |
| } | |
| if (Array.isArray) { | |
| return Array.isArray(obj) | |
| } | |
| return obj.constructor.name === "Array" || obj.constructor.name.toLocaleLowerCase() === "array" | |
| } | |
| function Mscript(selector) { | |
| return new Mscript.fn.init(selector) | |
| } | |
| Mscript.fn = Mscript.prototype = { | |
| version: version, | |
| constructor: Mscript, | |
| length: 0, | |
| ready: function(cb) { | |
| const isReady = this.some(e => { | |
| return e.readyState != null && e.readyState != "loading" | |
| }); | |
| if (isReady) { | |
| cb() | |
| } else { | |
| this.on("DOMContentLoaded", cb) | |
| } | |
| return this; | |
| }, | |
| on: function(event, cbOrSelector, cb) { | |
| if (typeof cbOrSelector === "function") { | |
| this.forEach(e => e.addEventListener(event, cbOrSelector)) | |
| } else { | |
| this.forEach(elem => { | |
| elem.addEventListener(event, e => { | |
| if (e.target.matches(cbOrSelector)) cb(e); | |
| }) | |
| }) | |
| } | |
| return this; | |
| }, | |
| next: function() { | |
| return this.map(e => e.nextElementSibling).filter(e => e != null); | |
| }, | |
| prev: function() { | |
| return this.map(e => e.previousElementSibling).filter(e => e != null); | |
| }, | |
| push: arr.push, | |
| sort: arr.sort, | |
| splice: arr.splice, | |
| some: arr.some, | |
| indexOf: arr.indexOf, | |
| forEach: arr.forEach, | |
| }; | |
| if ( typeof Symbol === "function" ) { | |
| Mscript.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; | |
| } | |
| init = Mscript.fn.init = function(selector) { | |
| if ( selector == undefined ) { | |
| return this; | |
| } | |
| if (isArrayLike(selector)){ | |
| return Mscript.makeArray(selector, this); | |
| }else if (selector instanceof HTMLElement) { | |
| this[0] = selector; | |
| this.length = 1; | |
| return this; | |
| }else if (typeof selector === "string"){ | |
| if ( selector[ 0 ] === "<" && | |
| selector[ selector.length - 1 ] === ">" && | |
| selector.length >= 3 ) { | |
| // make $(html) -> $(array) | |
| }else{ | |
| node = document.querySelectorAll(selector); | |
| if (node.length > 0) { | |
| Mscript.makeArray(node, this); | |
| } | |
| } | |
| }else if (typeof selector == "object"){ | |
| this[0] = selector; | |
| this.length = 1; | |
| } | |
| return this; | |
| } | |
| init.prototype = Mscript.fn; | |
| Mscript.extend = Mscript.fn.extend = function() { | |
| var options, name, copy, | |
| tmp = arguments[ 0 ], | |
| i = 0, | |
| length = arguments.length, | |
| force = true, | |
| target = this; | |
| // Handle a deep copy situation | |
| if ( typeof tmp === "boolean" ) { | |
| force = tmp; | |
| i++; | |
| } | |
| for ( ; i < length; i++ ) { | |
| // Only deal with non-null/undefined values | |
| if ( ( options = arguments[ i ] ) != null ) { | |
| if (typeof options != "object"){ | |
| continue; | |
| } | |
| // Extend the base object | |
| for ( name in options ) { | |
| copy = options[ name ]; | |
| if (!isFunction(copy)){ | |
| continue; | |
| } | |
| // Prevent Object.prototype pollution | |
| // Prevent never-ending loop | |
| if ( name === "__proto__" || target === copy ) { | |
| continue; | |
| } | |
| if (!force && this.hasOwnProperty(name)){ | |
| continue; | |
| } | |
| if ( copy !== undefined ) { | |
| target[ name ] = copy; | |
| } | |
| } | |
| } | |
| } | |
| // Return the modified object | |
| return target; | |
| }; | |
| // handle some external functions | |
| Mscript.extend({ | |
| makeArray: function(arr, results) { | |
| results = results || []; | |
| if (typeof arr === "object") { | |
| length = results.length || 0; | |
| for (const [key, value] of Object.entries(arr)) { | |
| results[parseInt(key)+length] = value; | |
| } | |
| results.length = arr.length + length; | |
| } | |
| } | |
| }) | |
| // Slicing the object | |
| Mscript.fn.extend({ | |
| eq: function(i) { | |
| var len = this.length, | |
| j = +i + ( i < 0 ? len : 0 ); | |
| return this.pushStack(( j >= 0 && j < len ? [ this[ j ] ] : [] )); | |
| }, | |
| get: function( num ) { | |
| if ( num == null ) { | |
| return Array.slice.call( this ); | |
| } | |
| return num < 0 ? this[ num + this.length ] : this[ num ]; | |
| }, | |
| first: function() { | |
| return this.eq(0) | |
| }, | |
| last: function() { | |
| return this.eq(-1) | |
| }, | |
| pushStack: function(arr) { | |
| return Mscript(arr) | |
| }, | |
| slice: function() { | |
| return this.pushStack( slice.apply( this, arguments ) ); | |
| } | |
| }) | |
| // HTML elemants manuplation | |
| Mscript.fn.extend({ | |
| children: function() { | |
| if (!this.length) return | |
| elem = this[0]; | |
| return this.pushStack(Array(...(elem.children))); | |
| }, | |
| removeClass: function(className) { | |
| this.forEach(e => e.classList.remove(className)); | |
| return this; | |
| }, | |
| addClass: function(className) { | |
| this.forEach(e => e.classList.add(className)); | |
| return this; | |
| }, | |
| toggle: function(className, state) { | |
| if (state == undefined) { | |
| this.forEach(e => e.classList.toggle(className)); | |
| } else if (typeof (state) == "boolean") { | |
| this.forEach(e => e.classList.toggle(className, state)); | |
| } else { | |
| this.forEach(e => e.classList.toggle(className)); | |
| } | |
| return this; | |
| }, | |
| getStyles: function(elem) { | |
| elem = elem? elem: this[0]; | |
| var view = elem.ownerDocument.defaultView; | |
| if ( !view || !view.opener ) { | |
| view = window; | |
| } | |
| return view.getComputedStyle(elem); | |
| }, | |
| css: function(property, value) { | |
| if (value == undefined) { | |
| return this.getStyles(this[0])[property]; | |
| } else { | |
| const camelProp = property.replace(/(-[a-z])/, g => { | |
| return g.replace("-", "").toUpperCase(); | |
| }) | |
| this.forEach(e => (e.style[camelProp] = value)); | |
| } | |
| return this; | |
| }, | |
| rcss: function(property) { | |
| this.forEach(e => (e.style.removeProperty(property))); | |
| return this; | |
| }, | |
| show: function() { | |
| return this.rcss("display"); | |
| }, | |
| hide: function(timeout=0) { | |
| return this.css("display", "none"); | |
| }, | |
| val: function(value) { | |
| if (!this.length) return ''; | |
| let elem = this[0]; | |
| if (value === undefined){ | |
| let mselect = []; | |
| if (!elem.name || elem.disabled || ['file', 'reset', 'submit', 'button'].indexOf(elem.type) > -1) return; | |
| if (elem.type === 'select-multiple') { | |
| Array.prototype.slice.call(elem.options).forEach(function (option) { | |
| if (!option.selected) return; | |
| mselect.push(option.value); | |
| }); | |
| return mselect; | |
| } | |
| if (mselect.length) { | |
| return mselect; | |
| } | |
| if (['checkbox', 'radio'].indexOf(elem.type) > -1 && !elem.checked) { | |
| return "off"; | |
| }else { | |
| return "on"; | |
| } | |
| return elem.value; | |
| } else { | |
| if (!elem.name || elem.disabled || ['file', 'reset', 'submit', 'button'].indexOf(elem.type) > -1) return; | |
| if (elem.type === 'select-multiple') { | |
| return Array.prototype.slice.call(elem.options).forEach(function (option) { | |
| if (value.includes(option.value)) { | |
| option.selected = true; | |
| } | |
| }); | |
| } | |
| if (['checkbox'].indexOf(elem.type) > -1) { | |
| if (value === "off") return elem.checked = false; | |
| if (value === "on") return elem.checked = true; | |
| } | |
| if (['radio'].indexOf(elem.type) > -1) { | |
| return this.each(this, function() { | |
| if (this.value == value) this.checked = true; | |
| }) | |
| } | |
| return elem.value = value; | |
| } | |
| }, | |
| text: function(txt) { | |
| if (txt === undefined) { | |
| if (this.length) { | |
| return this[0].innerText; | |
| } | |
| return null; | |
| } | |
| this.each(function() {this.innerText = txt}); | |
| }, | |
| html: function(txt) { | |
| if (txt === undefined) { | |
| if (this.length) { | |
| return this[0].innerHTML; | |
| } | |
| return null; | |
| } | |
| this.each(function() {this.innerHTML = txt}); | |
| }, | |
| }) | |
| // Filtering | |
| Mscript.fn.extend({ | |
| find: function(selector) { | |
| let arr = []; | |
| if (typeof selector !== "string") { | |
| return false; | |
| } | |
| this.forEach(e => { | |
| arr.push(...(e.querySelectorAll(selector))); | |
| }) | |
| return this.pushStack(arr); | |
| }, | |
| each: function(obj,cb) { | |
| if (isFunction(obj)){cb=obj;obj=this;} | |
| var length, i = 0; | |
| if (isArrayLike( obj )) { | |
| length = obj.length; | |
| for ( ; i < length; i++ ) { | |
| if ( cb.call( obj[ i ], i, obj[ i ] ) === false ) { | |
| break; | |
| } | |
| } | |
| } else { | |
| for ( i in obj ) { | |
| if ( cb.call( obj[ i ], i, obj[ i ] ) === false ) { | |
| break; | |
| } | |
| } | |
| } | |
| return obj; | |
| }, | |
| }) | |
| // Make all possible events | |
| Mscript.fn.each( | |
| ( "blur focus focusin focusout resize scroll click dblclick " + | |
| "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + | |
| "change select submit keydown keypress keyup contextmenu" ).split( " " ), | |
| function( _i, name ) { | |
| // Handle event binding | |
| Mscript.fn[ name ] = function(fn) { | |
| this.on( name, fn ) | |
| }; | |
| } | |
| ); | |
| // Manage forms | |
| Mscript.fn.extend({ | |
| serializeArray: function () { | |
| var arr = []; | |
| this.forEach(e => { | |
| Array.prototype.slice.call(e.elements).forEach(function (field) { | |
| if (!field.name || field.disabled || ['file', 'reset', 'submit', 'button'].indexOf(field.type) > -1) return false; | |
| if (field.type === 'select-multiple') { | |
| Array.prototype.slice.call(field.options).forEach(function (option) { | |
| if (!option.selected) return; | |
| arr.push({ | |
| name: field.name, | |
| value: option.value | |
| }); | |
| }); | |
| return; | |
| } | |
| if (["radio", "checkbox"].indexOf(field.type) > -1 && !field.checked) return false; | |
| arr.push({ | |
| name: field.name, | |
| value: field.value | |
| }); | |
| }); | |
| }) | |
| return arr; | |
| }, | |
| formData: function () { | |
| var o = {}; | |
| var a = this.serializeArray(); | |
| this.each(a, function () { | |
| if (o[this.name]) { | |
| if (!o[this.name].push) { | |
| o[this.name] = [o[this.name]]; | |
| } | |
| o[this.name].push(this.value || ''); | |
| } else { | |
| o[this.name] = this.value || ''; | |
| } | |
| }); | |
| return o; | |
| }, | |
| autoFill: function(map, fillby) { | |
| fillby = fillby || "name" | |
| for (const [key, value] of Object.entries(map)) { | |
| this.find(`[${fillby}="${key}"]`).val(value) | |
| } | |
| } | |
| }) | |
| window.$ = window.Mscript = Mscript; | |
| })() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment