Last active
August 6, 2016 04:14
-
-
Save uolcano/a82ce104e67f1c73af6877342b720172 to your computer and use it in GitHub Desktop.
Some scripts
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
var uTools = {}; | |
/************************************ | |
Compatible solution for native methods | |
************************************/ | |
! function () { | |
'use strict'; | |
if (typeof Object.create != 'function') { | |
Object.create = function () { | |
var Temp = function () {}; | |
return function (proto) { | |
if (proto !== Object(proto) && proto !== null) { | |
throw new TypeError('Argument must be an object, or null'); | |
} | |
Temp.prototype = proto || {}; | |
var result = new Temp(); | |
Temp.prototype = null; | |
// simulate Object.create(null) | |
proto === null && (result.__proto__ = null); | |
return result; | |
} | |
}(); | |
} | |
}(); | |
! function () { | |
'use strict'; | |
if (typeof Function.prototype.bind != 'function') { | |
Function.prototype.bind = function (content) { | |
if (typeof this != 'function') { | |
throw new TypeError('what is trying to be bound is not callable.') | |
} | |
var args = Array.prototype.slice.call(arguments, 1), | |
toBind = this; | |
return function () { | |
toBind.apply(content, args.concat(Array.prototype.slice.call(arguments))); | |
} | |
}; | |
} | |
}(); | |
// source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice#Streamlining_cross-browser_behavior | |
// deal with that slice can not be call with DOM elements in IE < 9 | |
! function () { | |
'use strict'; | |
var slice = Array.prototype.slice; | |
try { | |
// slice can not be used with DOM elements in IE < 9 | |
slice.call(document.documentElement); | |
} catch (e) { | |
Array.prototype.slice = function (begin, end) { | |
end = typeof end != 'undefined' ? end : this.length; | |
// if the caller is an native Array | |
if (Object.prototype.toString.call(this).slice(8, -1) == 'Array') { | |
return slice.call(this, begin, end); | |
} | |
var i, size, start, last, | |
obj = Object(this), | |
copy = [], | |
len = obj.length; | |
// format arguments | |
start = typeof begin != 'number' ? 0 : | |
begin >= 0 ? begin : | |
Math.max(0, len + begin); | |
last = typeof end != 'number' ? len : | |
end >= 0 ? Math.min(end, len) : | |
len + end; | |
size = last - start; | |
if (size > 0) { | |
copy = new Array(size); | |
// process when slice bound to a string | |
if (obj.charAt) { | |
for (i = 0; i < size; i++) { | |
copy[i] = obj.charAt(start + i); | |
} | |
} else { | |
for (i = 0; i < size; i++) { | |
copy[i] = obj[start + i]; | |
} | |
} | |
} | |
return copy; | |
}; | |
} | |
}(); | |
! function () { | |
'use strict'; | |
if (typeof Array.prototype.forEach != 'function') { | |
Array.prototype.forEach = function (fn) { | |
var arr = Object(this), | |
i = 0, | |
len = 0; | |
if (Object.prototype.toString.call(arr).slice(8, -1) != 'Array') { | |
throw new TypeError('Argument must be an array!'); | |
} | |
if (!(len = arr.length)) return; | |
do { | |
fn(arr[i], i, arr); | |
} while (++i < len); | |
fn = null; | |
arr = null; | |
} | |
} | |
}(); | |
! function () { | |
'use strict'; | |
if (typeof Array.prototype.reduce != 'function') { | |
Array.prototype.reduce = function (fn, orig) { | |
var arr = Object(this), | |
i = 0, | |
len = 0, | |
pre = 0; | |
if (Object.prototype.toString.call(arr).slice(8, -1) != 'Array') { | |
throw new TypeError('Argument must be an array!'); | |
} | |
if (!(len = arr.length)) return; | |
if (typeof orig != 'undefined') { | |
pre = orig; | |
} else { | |
pre = arr[0]; | |
if (len === 1) { | |
return pre; | |
} | |
i++; | |
} | |
do { | |
pre = fn(pre, arr[i], i, arr); | |
} while (++i < len); | |
fn = null; | |
org = null; | |
arr = null; | |
return pre; | |
} | |
} | |
}(); | |
! function () { | |
'use strict'; | |
if (typeof Array.prototype.join != 'function') { | |
Array.prototype.join = function (rep) { | |
rep = String(rep); | |
this.reduce(function (pre, crt, idx, arr) { | |
return '' + pre + rep + crt; | |
}); | |
} | |
} | |
}(); | |
! function () { | |
'use strict'; | |
if (typeof Object.defineProperty != 'function') { | |
Object.defineProperty = function (o, p, d) { | |
o.__defineGetter__(p, d.get); | |
o.__defineSetter__(p, d.set); | |
} | |
} | |
}(); | |
/****************************** | |
Common tool set | |
******************************/ | |
! function ($, global) { | |
var hasOwn = Object.prototype.hasOwnProperty, | |
getOwns = Object.getOwnPropertyNames, | |
slice = Array.prototype.slice; | |
function getTypeOf(obj) { | |
var type = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); | |
if (type != 'object') return type; | |
if (obj.constructor && | |
!hasOwn.call(obj, 'constructor') && | |
!hasOwn.call(obj, 'isPrototypeOf')) { | |
return obj.constructor.toString().match(/function\s*([^\(\s]*)/)[1].toLowerCase(); | |
} | |
} | |
// return true if it is a array | |
function isArray(obj) { | |
return getTypeOf(obj) == 'array'; | |
} | |
// return true if it is a DOM node | |
function isNode(obj) { | |
return typeof Node == 'object' ? obj instanceof Node : | |
obj && typeof obj == 'object' && typeof obj.nodeType == 'number' && typeof obj.nodeName == 'string' | |
} | |
// return true if it is a DOM element | |
function isElement(obj) { | |
return typeof HTMLElement == 'object' ? obj instanceof HTMLElement : | |
obj && typeof obj == 'object' && obj != null && obj.nodeType === 1 && typeof obj.nodeName == 'string'; | |
} | |
// detect IE or IE version | |
function isIE(ver) { | |
var b = document.createElement('b'); | |
b.innerHTML = '<!--[if IE ' + ver + ']><i></i><![endif]-->'; | |
return b.getElementsByTagName('i').length === 1; | |
}; | |
// function lazy load | |
function lazyLoad(expr, fn1, fn2) { | |
if (typeof fn1 != 'function') { | |
throw new ReferenceError('The second parameter must be a function to be returned.'); | |
} | |
if (typeof fn2 != 'function') { | |
throw new ReferenceError('The third parameter must be a function to be returned.'); | |
} | |
if (typeof expr == 'boolean') { | |
return expr ? fn1 : fn2; | |
} else if (typeof expr == 'function') { | |
return expr() ? fn1 : fn2; | |
} else { | |
throw new new TypeError('The first parameter should be a boolean or function to be called.'); | |
} | |
} | |
var getWinWidth = function () { | |
return lazyLoad(typeof global.innerWidth == 'number', function () { | |
return global.innerWidth; | |
}, | |
function () { | |
return document.body.clientWidth || document.documentElement.clientWidth | |
}); | |
}(); | |
var getElms = function (parent, selector) { | |
return slice.call(parent.querySelectorAll(selector)); | |
}; | |
var hasPrototypeProperty = function (obj, name) { | |
return !hasOwn.call(obj) && (name in obj); | |
}; | |
function each(obj, fn) { | |
var p, v; | |
// convert NodeList into array if the first element is node | |
if (isNode(obj[0])) { | |
obj = slice.call(obj, 0); | |
} | |
if (isArray(obj)) { | |
obj.forEach(fn); | |
} else if (typeof obj == 'object') { | |
for (p in obj) { | |
if (hasOwn.call(obj, p)) { | |
v = obj[p]; | |
fn(v, p, obj); | |
} | |
} | |
} else { | |
throw new TypeError('This method only accept array or object.'); | |
} | |
return obj; | |
} | |
var clone = function f(obj) { | |
var newObj, | |
i = 0, | |
len, | |
prop, | |
props, | |
constructor, | |
fnArr; | |
if (obj == undefined) { | |
throw new TypeError('undefined can not be cloned.'); | |
} | |
if (obj.nodeType) { | |
throw new TypeError('not support DOM clone.'); | |
} | |
if (!(constructor = obj.constructor)) console.log('Can not get prototype.'); | |
switch (typeof obj) { | |
case 'boolean': | |
case 'number': | |
case 'string': | |
return obj; | |
} | |
if (typeof constructor == 'function') { | |
switch (getTypeOf(obj)) { | |
case 'math': | |
return obj; | |
case 'object': | |
newObj = {}; | |
break; | |
case 'array': | |
newObj = []; | |
break; | |
case 'function': | |
fnArr = obj.match(/^function[^\(]*\(([^\(\)]*)\)\s*\{([\s\S]*)\}$/); | |
fnArr.shift(); | |
newObj = Function.apply(null, arr); | |
break; | |
case 'regexp': | |
newObj = new RegExp(obj.source, obj.flags); | |
break; | |
case 'date': | |
newObj = new Date(obj.toString()); | |
break; | |
default: | |
newObj = new constructor(obj); | |
} | |
} | |
props = getOwns(obj); | |
if ((len = props.length) === 0) return newObj; | |
do { | |
prop = props[i]; | |
newObj[prop] = f(obj[prop]); | |
} while (++i < len); | |
return newObj; | |
} | |
// get computed style in a DOM element | |
var getStyle = function () { | |
return lazyLoad(function () { | |
return typeof global.getComputedStyle == 'function'; | |
}, function (domElm) { | |
return global.getComputedStyle(domElm); | |
}, function (domElm) { | |
return domElm.currentStyle; | |
}); | |
}(); | |
var getRules = function (sheet) { | |
return sheet.cssRules || sheet.rules; | |
} | |
$.fn = Object.create({ | |
name: 'generic tools', | |
getTypeOf: getTypeOf, | |
isArray: isArray, | |
isNode: isNode, | |
isElement: isElement, | |
isIE: isIE, | |
hasPrototypeProperty: hasPrototypeProperty, | |
lazyLoad: lazyLoad, | |
each: each, | |
getWinWidth: getWinWidth, | |
getStyle: getStyle, | |
getRules: getRules, | |
getElms: getElms | |
}); | |
global._uTools = global.$ = global._$ = $; | |
}(uTools, window || self); | |
/********************** | |
The event wrapper for compatibility | |
*********************/ | |
! function ($) { | |
function EventWrapper(obj) { | |
this.handlers = {}; | |
this.source = obj; | |
} | |
function preventDefault() { | |
this.preventDefault ? | |
this.preventDefault() : | |
this.returnValue = false; | |
}; | |
EventWrapper.prototype = { | |
constructor: EventWrapper, | |
fire: function () {}, | |
on: function (type, handler) { | |
if (!(this instanceof EventWrapper)) { | |
throw TypeError('This object is not EventWrapper instance.'); | |
} | |
if (typeof this.handlers[type] == 'undefined') { | |
this.handlers[type] = []; | |
this.fire = this.trigger.bind(this); | |
this.source.addEventListener ? | |
this.source.addEventListener(type, this.fire) : | |
this.source.attachEvent('on' + type, this.fire); | |
} | |
this.handlers[type].push(handler); | |
return this; | |
}, | |
off: function (type, handler) { | |
var idx = -1; | |
if (!(this instanceof EventWrapper)) { | |
throw TypeError('This object is not EventWrapper instance.'); | |
} | |
if (typeof this.handlers[type] == 'undefined') { | |
console.log('This handler had not been added.'); | |
} else { | |
idx = this.handlers[type].indexOf(handler); | |
this.handlers[type].splice(idx, 1); | |
} | |
if (!this.handlers[type].length) { | |
this.removeAll(type); | |
} | |
return this; | |
}, | |
removeAll: function (type) { | |
this.source.removeEventListener ? | |
this.source.removeEventListener(type, this.fire) : | |
this.source.detachEvent('on' + type, this.fire); | |
return this; | |
}, | |
// can be extended to accept second argument, | |
// can only trigger handlers, while not trigger event | |
trigger: function (event) { | |
event = event || window.event; | |
event.target || (event.target = event.srcElement); | |
event.preventDefault = preventDefault; | |
this.handlers[event.type] | |
.forEach(function (item) { | |
item(event); | |
}); | |
return this; | |
} | |
}; | |
$.EventWrapper = EventWrapper; | |
}(uTools); | |
/************************* | |
The DOM wrapper for compatibility | |
************************/ | |
! function ($, global) { | |
var hasOwn = Object.prototype.hasOwnProperty; | |
function DOMWrapper(domElm) { | |
this.source = domElm; | |
} | |
var proto = new $.EventWrapper(); | |
// add class on the DOM element | |
proto.addClass = function (val) { | |
if (typeof val == 'undefined') return; | |
var domElm = this.source, | |
classList = domElm.className.split(' '); | |
classList.indexOf(val) > -1 || | |
(domElm.className += ' ' + String(val)); | |
return this; | |
}; | |
// remove class on the DOM element | |
proto.removeClass = function (val) { | |
if (typeof val == 'undefined') return; | |
var domElm = this.source, | |
classList = domElm.className.split(' '), | |
idx = classList.indexOf(val), | |
removed; | |
idx > -1 && | |
(removed = classList.splice(idx, 1), | |
domElm.className = classList.join('')); | |
return this; | |
}; | |
// argument [val] will not contain leading or heading white space, | |
// and <script> or <style> element do not use this method! | |
proto.text = function () { | |
return $.fn.lazyLoad(function () { | |
var b = document.createElement('b'), | |
t = typeof b.textContent == 'undefined'; | |
b = null; | |
return t; | |
}, function (val) { | |
var domElm = this.source, | |
value = val == null ? | |
domElm.innerText : | |
(domElm.innerText = String(val)); | |
return value; | |
}, | |
function (val) { | |
var domElm = this.source, | |
value = val == null ? | |
domElm.textContent : | |
(domElm.textContent = String(val)); | |
return value; | |
}); | |
}(); | |
// get or set data in a DOM element's data attribute, | |
// can choose get string or parsed object | |
proto.data = function () { | |
return $.fn.lazyLoad(function () { | |
var b = document.createElement('b'), | |
t = typeof b.dataset == 'undefined'; | |
b = null; | |
return t; | |
}, function (name, val, dontParse) { | |
var domElm = this.source, | |
value; | |
// detect null and undefined | |
if (name == null) return; | |
name = String(name); | |
// eliminate the '-*' or '*-' data name | |
if (/^-.+|.+-$/g.test(name)) { | |
throw SyntaxError('The leading or trailing dash not allowed!'); | |
} | |
// process the data name except for 'data-*' | |
/^data-.+/.test(name) || | |
/[^-]-[^-]/.test() ? | |
(name = 'data-' + name) : // prepend 'data-' into the '*-*' data name | |
(name = 'data-' + name.replace(/[A-Z]/g, function (m) { | |
return '-' + m.toLowerCase(); | |
})); | |
// detect null and undefined | |
if (val == null) { | |
value = domElm.getAttribute(name); | |
dontParse || (value = JSON.parse(value)); | |
} else { | |
value = dontParse ? val : JSON.stringify(val); | |
domElm.setAttribute(name, value); | |
} | |
return value; | |
}, function (name, val, dontParse) { | |
var domElm = this.source, | |
value; | |
// detect null and undefined | |
if (name == null) return; | |
name = String(name); | |
if (/^-.+|.+-$/g.test(name)) { | |
throw SyntaxError('The leading or trailing dash not allowed!'); | |
} | |
// process the wrong format of name, like data-at-of-by into atOfBy | |
/^data-.+/.test(name) && | |
(name = name.replace(/^data-/, '')); | |
name = name.replace(/-([^-])/g, function (m, p) { | |
return p.toUpperCase(); | |
}); | |
// detect null and undefined | |
if (val == null) { | |
value = domElm.dataset[name]; | |
dontParse || (value = JSON.parse(value)); | |
} else { | |
value = dontParse ? val : JSON.stringify(val); | |
domElm.dataset[name] = value; | |
} | |
return value; | |
}); | |
}(); | |
// get or set the attribute of a DOM element | |
proto.attr = function (name, val) { | |
var value, | |
domElm = this.source; | |
if (typeof name == 'undefined') return; | |
name = String(name); | |
// detect null and undefined | |
val == null ? | |
(value = domElm.getAttribute(String(name))) : | |
(value = String(val), | |
domElm.setAttribute(name, value)); | |
return value; | |
}; | |
// get or set the property of a DOM element | |
proto.prop = function (name, val) { | |
var value, | |
domElm = this.source; | |
if (typeof name == 'undefined') return; | |
name = String(name); | |
// detect null and undefined | |
val == null ? | |
(value = domElm[name]) : | |
(value = String(val), | |
domElm[name] = value); | |
return value; | |
}; | |
// get or set the style sheets in a DOM element | |
// support simple arithmetic about size(px/em/%) | |
proto.css = function (obj) { | |
var p, v, s, f, mv, ms, | |
domElm = this.source, | |
reg1 = /([\+\-\*\/])([\d\.]*)(px|em|%)?/, | |
reg2 = /([\d\.]*)px/; | |
// detect null and undefined | |
if (obj == null) | |
return $.fn.getStyle(domElm); | |
if (typeof obj == 'object') { | |
for (p in obj) { | |
if (hasOwn.call(obj, p)) { | |
v = obj[p]; | |
if (typeof v != 'string') continue; | |
mv = v.match(reg1); | |
// need for arithmetic computation | |
if (mv && mv[0].length == v.length && mv[1]) { | |
s = $.fn.getStyle(domElm); | |
// base value used to evaluate the relative value setting | |
// em can not work in IE 8, | |
// because of IE8's computed font-size is measured in em. | |
f = parseFloat(s.fontSize); | |
// the computed styles contain the prop | |
if (ms = s[p].match(reg2)) { | |
switch (mv[3]) { | |
case 'em': | |
v = eval((+mv[2] * f) + mv[1] + ms[1]); | |
break; | |
case '%': | |
v = eval((+mv[2] / 100 * ms[1]) + mv[1] + ms[1]); | |
break; | |
default: // deal with px and pure numbr in the indentical | |
v = eval(mv[2] + mv[1] + ms[1]); | |
break; | |
} | |
} else { | |
continue; | |
} | |
v += 'px'; | |
} | |
domElm.style[p] = v; | |
} | |
} | |
} | |
return this; | |
}; | |
proto.append = function (wrpObj) { | |
var parent = this.source, | |
newChild = wrpObj.source; | |
parent.appendChild(newChild); | |
return this; | |
}; | |
proto.prepend = function (wrpObj) { | |
var parent = this.source, | |
newChild = wrpObj.source, | |
firstChild = parent.firstChild; | |
parent.insertBefore(newChild, firstChild); | |
return this; | |
}; | |
proto.before = function (wrpObj) { | |
var newChild = wrpObj.source, | |
refChild = this.source, | |
parent = refChild.parentNode; | |
parent.insertBefore(newChild, refChild); | |
return this; | |
} | |
proto.after = function (wrpObj) { | |
var newChild = wrpObj.source, | |
refChild = this.source, | |
parent = refChild.parentNode, | |
nextChild; | |
if (refChild == parent.lastChild) { | |
parent.appendChild(newChild); | |
} else { | |
nextChild = refChild.nextSibling; | |
parent.insertBefore(newChild, nextChild); | |
} | |
return this; | |
} | |
proto.appendTo = function (wrpObj) { | |
wrpObj.append(this); | |
return this; | |
}; | |
proto.prependTo = function (wrpObj) { | |
wrpObj.prepend(this); | |
return this; | |
}; | |
proto.insertBefore = function (wrpObj) { | |
wrpObj.before(this); | |
return this; | |
}; | |
proto.insertAfter = function (wrpObj) { | |
wrpObj.after(this); | |
return this; | |
}; | |
DOMWrapper.prototype = proto; | |
proto = null; | |
$.DOMWrapper = DOMWrapper; | |
}(uTools, window || self); | |
! function ($) { | |
$.wrp = function (obj) { | |
// detect whether create a DOM element | |
var reg1 = /^\s*\<([\d\w]+)[\s\S]*\>[\s\S]*\<\/\1\>\s*$/, // complete tag | |
reg2 = /^\s*\<([\d\w]+)[^\<\>]*\/\>\s*$/, // self-closed tag | |
m, | |
docFrag, | |
tmpDiv; | |
if ($.fn.isNode(obj)) { | |
return new $.DOMWrapper(obj); | |
} else if (typeof obj == 'object') { | |
return new $.EventWrapper(obj); | |
} else if (typeof obj == 'string') { | |
m = obj.match(reg1) || obj.match(reg2) || obj.match(reg3); | |
console.log('To creat a ' + m[1] + ' element'); | |
docFrag = document.createDocumentFragment(); | |
tmpDiv = document.createElement('div'); | |
tmpDiv.innerHTML = obj; | |
$.fn.each(tmpDiv.childNodes, function (child) { | |
if (child.nodeType === 1) { | |
docFrag.appendChild(child); | |
} | |
}); | |
tmpDiv = null; | |
return $.wrp(docFrag); | |
} | |
throw new TypeError('The parameter should be an object or DOM element.'); | |
} | |
}(uTools); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment