UNPKG

instance-js

Version:
437 lines (341 loc) 9.41 kB
(function(root) { function Inst(obj, opt) { return new Instance(obj, opt); } function Instance(obj, opt) { if( isString(obj) ) { if( isFunction(Inst.classStringHandler) ) { return Inst.classStringHandler.call(this, obj, opt) } } else if(obj != null ) { if( isArrayLike(obj) && !isElement(obj) && !isWindow(obj) ) { for( var i=0; i < obj.length; i++ ) { this[i] = obj[ i ]; } this.length = obj.length; } else { this[0] = obj; this.length = 1; } } } Inst.classStringHandler = function(obj, opt) { var nodes; if( /</.test(obj) ) { nodes = nodeFromString(obj, opt); } else { nodes = (opt || document).querySelectorAll(obj); } for(var i=0; i<nodes.length; i++) { this[i] = nodes[i]; } this.length = nodes.length; } // #Extensions // jQuery.extend + overwrite Inst.extend = (Inst.proto = Instance.prototype).extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ], i = 1, length = arguments.length, deep = false, overwrite = true; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i++ ]; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !isFunction( target ) ) { target = {}; } // Extend this if only one argument is passed if ( i === length ) { target = this; i--; } if( typeof arguments[ length - 1] === "boolean" ) { overwrite = arguments[ --length ]; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent overwrite if( !overwrite && name in target ) { continue; } // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( isPlainObject( copy ) || ( copyIsArray = isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && isArray( src ) ? src : []; } else { clone = src && isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = Inst.extend( deep, clone, copy, overwrite ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; } // #Wire Event Emitter var wire = { events: {}, add: function(name, fn) { if( !Array.isArray(this.events[name]) ) { this.events[name] = []; } if( !~this.events[name].indexOf(fn) && typeof fn === "function" ) { this.events[name] = this.events[name].concat(fn); } }, remove: function(name, fn) { var fns = this.events[name]; if( !fns ) { return; } if( fn ) { var index = fns.indexOf(fn); if( ~index ) { this.events[name] = fns.slice(0, index).concat( fns.slice(index + 1) ); } } else { this.events[name] = []; } }, send: function(name, data, scope) { var fns = this.events[name]; data = 1 in arguments ? [data] : []; if( !fns ) { throw new ReferenceError(name + " event was not found."); } for(var i=0; i<fns.length; i++) { fns[i].apply(scope, data); } }, check: function(name) { return !!this.events[name]; } }; Inst.extend({ on: wire.add.bind(wire), off: wire.remove.bind(wire), emit: wire.send.bind(wire), emitterCheck: wire.check.bind(wire) }); var hangFire = (function() { var hang = {}; var defaultWait = 300; return function hangFire(callback, wait, callbackId) { // identifies functions by string callbackId = callbackId ? callbackId : callback.toString(); if( hang[ callbackId ] !== undefined ) { clearTimeout( hang[callbackId] ); } return hang[callbackId] = setTimeout(callback, typeof wait === "number" ? wait : defaultWait); } })(); Inst.hangFire = hangFire; // #Math Inst.random = function random(min, max, ignr) { ignr = 2 in arguments ? Array.isArray(ignr) ? ignr : [ignr] : [] if( max == null ) { max = min == null ? 1 : min; min = 0; } if( max < min ) { var tempMax = max; max = min; min = tempMax; } var rand; while( (rand = Math.round(Math.random() * max)) < min || ~ignr.indexOf(rand) ); return rand; } // #Ajax Inst.ajax = (function() { var requests = {}; return function ajax( a ) { var req = new XMLHttpRequest; a.method = a.method ? a.method.toUpperCase() : "POST"; a.url = a.url ? a.url : ""; req.open(a.method, a.url, !a.sync); req.onreadystatechange = function() { if( this.readyState === 4 ) { if( this.status === 200 ) { a.success&&a.success.call(this, JSON.parse(this.responseText)); } else { a.failure&&a.failure.call(this, {code: this.status, text: this.statusText}) } } } req.onerror = a.error||null if( a.progress ) { if( a.method === "POST" ) { a.upload.addEventListener('progress', a.progress); } else { req.onprogress = a.progress; } } req.onloadstart = a.start || null; req.onloadend = a.end || null; req.onabort = a.abort || null; if( a.header ) { for( var header in a.header ) { req.setRequestHeader(header, a.header[ header ]); } } var contentType = a.contentType != null ? a.contentType : "application/x-www-form-urlencoded"; if( contentType ) { req.setRequestHeader("Content-Type", contentType); } if( a.restart && ( a.name || a.url ) && requests[ a.name || a.url ] ) { requests[ a.name || a.url ].abort(); } requests[ a.name || a.url ] = req; req.send( a.data ); return req; } })(); // #Promise Inst.promise = (function() { function sendReq(type, url, data) { return new Promise(function(rs, rj) { Inst.ajax({ url: url, data: data||null, method: type||null, success: function(response) { rs(response) }, failure: function(status) { rj(Error("statusCode: " + status.code + ", statusText: '" + status.text + "'")) }, error: function(e) { rj(e) } }) }) } var P = { toPost: function(url, data) { return sendReq("post", url, data) }, toGet: function(url) { return sendReq("get", url) }, toPut: function(url, data) { return sendReq("put", url, data) }, toDelete: function(url) { return sendReq("delete", url) }, } P.toUpdate = P.toPut; // #alias Inst.post = P.toPost; Inst.get = P.toGet; Inst.update = P.toUpdate; Inst.delete = P.delete; return P; })(); // #Native Inst.proto.extend({ splice: Array.prototype.splice, push: Array.prototype.push, }); // #Abstract var nodeFromString = (function() { var wrapper = document.createElement('div'), placeholders = /(.?)(?:\@)([\w-]+)((?:\.[\w-]+|\[\s*\d+\s*])*)/g, bracketNotations = /\[\s*(\d+)\s*]/g; function placeData(str, vo) { var obj, chainList; return str.replace(placeholders, function(m, charbefore, ph, chain) { if( charbefore === "\\" ) { return "@" + ph + chain; } if( !vo ) { return m; } obj = vo[ ph ]; chainList = str.replace(bracketNotations, ".$1").split(".").slice(1); for( var i=0; i<chainList.length; i++ ) { obj = obj[ chainList[i] ]; if( obj == null ) { obj = ""; break; } } return charbefore + (obj || ""); }); } return function(HTMLString, valuesObject) { var nodes = []; wrapper.innerHTML = placeData(HTMLString, valuesObject); while( wrapper.firstChild ) { nodes.push( wrapper.removeChild( wrapper.firstChild ) ); } return nodes; } })(); // #Predicates function isString(obj) { return obj != null && (typeof obj === "string" || obj.constructor === String); } function isFunction(obj) { return obj != null && (typeof obj === "function" || obj.constructor === Function); } function isArrayLike( obj ) { if( isString(obj) ) return true; return ( obj != null && typeof obj === "object" && "length" in obj && +obj.length + 1 > 0 && ( obj.length - 1 in obj || obj.length === 0 ) ); } function isWindow( obj ) { return obj === window; } function isElement( obj ) { return !!( typeof HTMLElement === "object" ? obj instanceof HTMLElement : // for the heck of it obj && obj.nodeType === 1 && obj.removeChild && obj.nodeName ) } if(typeof module !== 'undefined' && module.exports) { module.exports.Instance = module.exports.Inst = module.exports.I = Inst; } else { root.Instance = root.Inst = root.I = Inst; } })(this);