Created
May 20, 2015 10:57
-
-
Save xurenlu/3ecdb0cfb336fc1d12ee to your computer and use it in GitHub Desktop.
simplemootools.js
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
/** | |
* Created by r on 14/12/17. | |
*/ | |
/* MooTools: the javascript framework. license: MIT-style license. copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/).*/ | |
/* | |
Web Build: http://mootools.net/core/builder/e426a9ae7167c5807b173d5deff673fc | |
*/ | |
/* | |
--- | |
name: Core | |
description: The heart of MooTools. | |
license: MIT-style license. | |
copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/). | |
authors: The MooTools production team (http://mootools.net/developers/) | |
inspiration: | |
- Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) | |
- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) | |
provides: [Core, MooTools, Type, typeOf, instanceOf, Native] | |
... | |
*/ | |
/*! MooTools: the javascript framework. license: MIT-style license. copyright: Copyright (c) 2006-2014 [Valerio Proietti](http://mad4milk.net/).*/ | |
(function(){ | |
this.MooTools = { | |
version: '1.5.1', | |
build: '0542c135fdeb7feed7d9917e01447a408f22c876' | |
}; | |
// typeOf, instanceOf | |
var typeOf = this.typeOf = function(item){ | |
if (item == null) return 'null'; | |
if (item.$family != null) return item.$family(); | |
if (item.nodeName){ | |
if (item.nodeType == 1) return 'element'; | |
if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; | |
} else if (typeof item.length == 'number'){ | |
if ('callee' in item) return 'arguments'; | |
if ('item' in item) return 'collection'; | |
} | |
return typeof item; | |
}; | |
var instanceOf = this.instanceOf = function(item, object){ | |
if (item == null) return false; | |
var constructor = item.$constructor || item.constructor; | |
while (constructor){ | |
if (constructor === object) return true; | |
constructor = constructor.parent; | |
} | |
/*<ltIE8>*/ | |
if (!item.hasOwnProperty) return false; | |
/*</ltIE8>*/ | |
return item instanceof object; | |
}; | |
// Function overloading | |
var Function = this.Function; | |
var enumerables = true; | |
for (var i in {toString: 1}) enumerables = null; | |
if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; | |
Function.prototype.overloadSetter = function(usePlural){ | |
var self = this; | |
return function(a, b){ | |
if (a == null) return this; | |
if (usePlural || typeof a != 'string'){ | |
for (var k in a) self.call(this, k, a[k]); | |
if (enumerables) for (var i = enumerables.length; i--;){ | |
k = enumerables[i]; | |
if (a.hasOwnProperty(k)) self.call(this, k, a[k]); | |
} | |
} else { | |
self.call(this, a, b); | |
} | |
return this; | |
}; | |
}; | |
Function.prototype.overloadGetter = function(usePlural){ | |
var self = this; | |
return function(a){ | |
var args, result; | |
if (typeof a != 'string') args = a; | |
else if (arguments.length > 1) args = arguments; | |
else if (usePlural) args = [a]; | |
if (args){ | |
result = {}; | |
for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); | |
} else { | |
result = self.call(this, a); | |
} | |
return result; | |
}; | |
}; | |
Function.prototype.extend = function(key, value){ | |
this[key] = value; | |
}.overloadSetter(); | |
Function.prototype.implement = function(key, value){ | |
this.prototype[key] = value; | |
}.overloadSetter(); | |
// From | |
var slice = Array.prototype.slice; | |
Function.from = function(item){ | |
return (typeOf(item) == 'function') ? item : function(){ | |
return item; | |
}; | |
}; | |
Array.from = function(item){ | |
if (item == null) return []; | |
return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; | |
}; | |
Number.from = function(item){ | |
var number = parseFloat(item); | |
return isFinite(number) ? number : null; | |
}; | |
String.from = function(item){ | |
return item + ''; | |
}; | |
// hide, protect | |
Function.implement({ | |
hide: function(){ | |
this.$hidden = true; | |
return this; | |
}, | |
protect: function(){ | |
this.$protected = true; | |
return this; | |
} | |
}); | |
// Type | |
var Type = this.Type = function(name, object){ | |
if (name){ | |
var lower = name.toLowerCase(); | |
var typeCheck = function(item){ | |
return (typeOf(item) == lower); | |
}; | |
Type['is' + name] = typeCheck; | |
if (object != null){ | |
object.prototype.$family = (function(){ | |
return lower; | |
}).hide(); | |
} | |
} | |
if (object == null) return null; | |
object.extend(this); | |
object.$constructor = Type; | |
object.prototype.$constructor = object; | |
return object; | |
}; | |
var toString = Object.prototype.toString; | |
Type.isEnumerable = function(item){ | |
return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); | |
}; | |
var hooks = {}; | |
var hooksOf = function(object){ | |
var type = typeOf(object.prototype); | |
return hooks[type] || (hooks[type] = []); | |
}; | |
var implement = function(name, method){ | |
if (method && method.$hidden) return; | |
var hooks = hooksOf(this); | |
for (var i = 0; i < hooks.length; i++){ | |
var hook = hooks[i]; | |
if (typeOf(hook) == 'type') implement.call(hook, name, method); | |
else hook.call(this, name, method); | |
} | |
var previous = this.prototype[name]; | |
if (previous == null || !previous.$protected) this.prototype[name] = method; | |
if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ | |
return method.apply(item, slice.call(arguments, 1)); | |
}); | |
}; | |
var extend = function(name, method){ | |
if (method && method.$hidden) return; | |
var previous = this[name]; | |
if (previous == null || !previous.$protected) this[name] = method; | |
}; | |
Type.implement({ | |
implement: implement.overloadSetter(), | |
extend: extend.overloadSetter(), | |
alias: function(name, existing){ | |
implement.call(this, name, this.prototype[existing]); | |
}.overloadSetter(), | |
mirror: function(hook){ | |
hooksOf(this).push(hook); | |
return this; | |
} | |
}); | |
new Type('Type', Type); | |
// Default Types | |
var force = function(name, object, methods){ | |
var isType = (object != Object), | |
prototype = object.prototype; | |
if (isType) object = new Type(name, object); | |
for (var i = 0, l = methods.length; i < l; i++){ | |
var key = methods[i], | |
generic = object[key], | |
proto = prototype[key]; | |
if (generic) generic.protect(); | |
if (isType && proto) object.implement(key, proto.protect()); | |
} | |
if (isType){ | |
var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); | |
object.forEachMethod = function(fn){ | |
if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ | |
fn.call(prototype, prototype[methods[i]], methods[i]); | |
} | |
for (var key in prototype) fn.call(prototype, prototype[key], key); | |
}; | |
} | |
return force; | |
}; | |
force('String', String, [ | |
'charAt', 'charCodeAt', 'concat', 'contains', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', | |
'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' | |
])('Array', Array, [ | |
'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', | |
'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' | |
])('Number', Number, [ | |
'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' | |
])('Function', Function, [ | |
'apply', 'call', 'bind' | |
])('RegExp', RegExp, [ | |
'exec', 'test' | |
])('Object', Object, [ | |
'create', 'defineProperty', 'defineProperties', 'keys', | |
'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', | |
'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' | |
])('Date', Date, ['now']); | |
Object.extend = extend.overloadSetter(); | |
Date.extend('now', function(){ | |
return +(new Date); | |
}); | |
new Type('Boolean', Boolean); | |
// fixes NaN returning as Number | |
Number.prototype.$family = function(){ | |
return isFinite(this) ? 'number' : 'null'; | |
}.hide(); | |
// Number.random | |
Number.extend('random', function(min, max){ | |
return Math.floor(Math.random() * (max - min + 1) + min); | |
}); | |
// forEach, each | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
Object.extend('forEach', function(object, fn, bind){ | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); | |
} | |
}); | |
Object.each = Object.forEach; | |
Array.implement({ | |
/*<!ES5>*/ | |
forEach: function(fn, bind){ | |
for (var i = 0, l = this.length; i < l; i++){ | |
if (i in this) fn.call(bind, this[i], i, this); | |
} | |
}, | |
/*</!ES5>*/ | |
each: function(fn, bind){ | |
Array.forEach(this, fn, bind); | |
return this; | |
} | |
}); | |
// Array & Object cloning, Object merging and appending | |
var cloneOf = function(item){ | |
switch (typeOf(item)){ | |
case 'array': return item.clone(); | |
case 'object': return Object.clone(item); | |
default: return item; | |
} | |
}; | |
Array.implement('clone', function(){ | |
var i = this.length, clone = new Array(i); | |
while (i--) clone[i] = cloneOf(this[i]); | |
return clone; | |
}); | |
var mergeOne = function(source, key, current){ | |
switch (typeOf(current)){ | |
case 'object': | |
if (typeOf(source[key]) == 'object') Object.merge(source[key], current); | |
else source[key] = Object.clone(current); | |
break; | |
case 'array': source[key] = current.clone(); break; | |
default: source[key] = current; | |
} | |
return source; | |
}; | |
Object.extend({ | |
merge: function(source, k, v){ | |
if (typeOf(k) == 'string') return mergeOne(source, k, v); | |
for (var i = 1, l = arguments.length; i < l; i++){ | |
var object = arguments[i]; | |
for (var key in object) mergeOne(source, key, object[key]); | |
} | |
return source; | |
}, | |
clone: function(object){ | |
var clone = {}; | |
for (var key in object) clone[key] = cloneOf(object[key]); | |
return clone; | |
}, | |
append: function(original){ | |
for (var i = 1, l = arguments.length; i < l; i++){ | |
var extended = arguments[i] || {}; | |
for (var key in extended) original[key] = extended[key]; | |
} | |
return original; | |
} | |
}); | |
// Object-less types | |
['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ | |
new Type(name); | |
}); | |
// Unique ID | |
var UID = Date.now(); | |
String.extend('uniqueID', function(){ | |
return (UID++).toString(36); | |
}); | |
})(); | |
/* | |
--- | |
name: Array | |
description: Contains Array Prototypes like each, contains, and erase. | |
license: MIT-style license. | |
requires: [Type] | |
provides: Array | |
... | |
*/ | |
Array.implement({ | |
/*<!ES5>*/ | |
every: function(fn, bind){ | |
for (var i = 0, l = this.length >>> 0; i < l; i++){ | |
if ((i in this) && !fn.call(bind, this[i], i, this)) return false; | |
} | |
return true; | |
}, | |
filter: function(fn, bind){ | |
var results = []; | |
for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ | |
value = this[i]; | |
if (fn.call(bind, value, i, this)) results.push(value); | |
} | |
return results; | |
}, | |
indexOf: function(item, from){ | |
var length = this.length >>> 0; | |
for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ | |
if (this[i] === item) return i; | |
} | |
return -1; | |
}, | |
map: function(fn, bind){ | |
var length = this.length >>> 0, results = Array(length); | |
for (var i = 0; i < length; i++){ | |
if (i in this) results[i] = fn.call(bind, this[i], i, this); | |
} | |
return results; | |
}, | |
some: function(fn, bind){ | |
for (var i = 0, l = this.length >>> 0; i < l; i++){ | |
if ((i in this) && fn.call(bind, this[i], i, this)) return true; | |
} | |
return false; | |
}, | |
/*</!ES5>*/ | |
clean: function(){ | |
return this.filter(function(item){ | |
return item != null; | |
}); | |
}, | |
invoke: function(methodName){ | |
var args = Array.slice(arguments, 1); | |
return this.map(function(item){ | |
return item[methodName].apply(item, args); | |
}); | |
}, | |
associate: function(keys){ | |
var obj = {}, length = Math.min(this.length, keys.length); | |
for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; | |
return obj; | |
}, | |
link: function(object){ | |
var result = {}; | |
for (var i = 0, l = this.length; i < l; i++){ | |
for (var key in object){ | |
if (object[key](this[i])){ | |
result[key] = this[i]; | |
delete object[key]; | |
break; | |
} | |
} | |
} | |
return result; | |
}, | |
contains: function(item, from){ | |
return this.indexOf(item, from) != -1; | |
}, | |
append: function(array){ | |
this.push.apply(this, array); | |
return this; | |
}, | |
getLast: function(){ | |
return (this.length) ? this[this.length - 1] : null; | |
}, | |
getRandom: function(){ | |
return (this.length) ? this[Number.random(0, this.length - 1)] : null; | |
}, | |
include: function(item){ | |
if (!this.contains(item)) this.push(item); | |
return this; | |
}, | |
combine: function(array){ | |
for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); | |
return this; | |
}, | |
erase: function(item){ | |
for (var i = this.length; i--;){ | |
if (this[i] === item) this.splice(i, 1); | |
} | |
return this; | |
}, | |
empty: function(){ | |
this.length = 0; | |
return this; | |
}, | |
flatten: function(){ | |
var array = []; | |
for (var i = 0, l = this.length; i < l; i++){ | |
var type = typeOf(this[i]); | |
if (type == 'null') continue; | |
array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); | |
} | |
return array; | |
}, | |
pick: function(){ | |
for (var i = 0, l = this.length; i < l; i++){ | |
if (this[i] != null) return this[i]; | |
} | |
return null; | |
}, | |
hexToRgb: function(array){ | |
if (this.length != 3) return null; | |
var rgb = this.map(function(value){ | |
if (value.length == 1) value += value; | |
return parseInt(value, 16); | |
}); | |
return (array) ? rgb : 'rgb(' + rgb + ')'; | |
}, | |
rgbToHex: function(array){ | |
if (this.length < 3) return null; | |
if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; | |
var hex = []; | |
for (var i = 0; i < 3; i++){ | |
var bit = (this[i] - 0).toString(16); | |
hex.push((bit.length == 1) ? '0' + bit : bit); | |
} | |
return (array) ? hex : '#' + hex.join(''); | |
} | |
}); | |
/* | |
--- | |
name: Function | |
description: Contains Function Prototypes like create, bind, pass, and delay. | |
license: MIT-style license. | |
requires: Type | |
provides: Function | |
... | |
*/ | |
Function.extend({ | |
attempt: function(){ | |
for (var i = 0, l = arguments.length; i < l; i++){ | |
try { | |
return arguments[i](); | |
} catch (e){} | |
} | |
return null; | |
} | |
}); | |
Function.implement({ | |
attempt: function(args, bind){ | |
try { | |
return this.apply(bind, Array.from(args)); | |
} catch (e){} | |
return null; | |
}, | |
/*<!ES5-bind>*/ | |
bind: function(that){ | |
var self = this, | |
args = arguments.length > 1 ? Array.slice(arguments, 1) : null, | |
F = function(){}; | |
var bound = function(){ | |
var context = that, length = arguments.length; | |
if (this instanceof bound){ | |
F.prototype = self.prototype; | |
context = new F; | |
} | |
var result = (!args && !length) | |
? self.call(context) | |
: self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); | |
return context == that ? result : context; | |
}; | |
return bound; | |
}, | |
/*</!ES5-bind>*/ | |
pass: function(args, bind){ | |
var self = this; | |
if (args != null) args = Array.from(args); | |
return function(){ | |
return self.apply(bind, args || arguments); | |
}; | |
}, | |
delay: function(delay, bind, args){ | |
return setTimeout(this.pass((args == null ? [] : args), bind), delay); | |
}, | |
periodical: function(periodical, bind, args){ | |
return setInterval(this.pass((args == null ? [] : args), bind), periodical); | |
} | |
}); | |
/* | |
--- | |
name: Number | |
description: Contains Number Prototypes like limit, round, times, and ceil. | |
license: MIT-style license. | |
requires: Type | |
provides: Number | |
... | |
*/ | |
Number.implement({ | |
limit: function(min, max){ | |
return Math.min(max, Math.max(min, this)); | |
}, | |
round: function(precision){ | |
precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); | |
return Math.round(this * precision) / precision; | |
}, | |
times: function(fn, bind){ | |
for (var i = 0; i < this; i++) fn.call(bind, i, this); | |
}, | |
toFloat: function(){ | |
return parseFloat(this); | |
}, | |
toInt: function(base){ | |
return parseInt(this, base || 10); | |
} | |
}); | |
Number.alias('each', 'times'); | |
(function(math){ | |
var methods = {}; | |
math.each(function(name){ | |
if (!Number[name]) methods[name] = function(){ | |
return Math[name].apply(null, [this].concat(Array.from(arguments))); | |
}; | |
}); | |
Number.implement(methods); | |
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); | |
/* | |
--- | |
name: String | |
description: Contains String Prototypes like camelCase, capitalize, test, and toInt. | |
license: MIT-style license. | |
requires: [Type, Array] | |
provides: String | |
... | |
*/ | |
String.implement({ | |
//<!ES6> | |
contains: function(string, index){ | |
return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1; | |
}, | |
//</!ES6> | |
test: function(regex, params){ | |
return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); | |
}, | |
trim: function(){ | |
return String(this).replace(/^\s+|\s+$/g, ''); | |
}, | |
clean: function(){ | |
return String(this).replace(/\s+/g, ' ').trim(); | |
}, | |
camelCase: function(){ | |
return String(this).replace(/-\D/g, function(match){ | |
return match.charAt(1).toUpperCase(); | |
}); | |
}, | |
hyphenate: function(){ | |
return String(this).replace(/[A-Z]/g, function(match){ | |
return ('-' + match.charAt(0).toLowerCase()); | |
}); | |
}, | |
capitalize: function(){ | |
return String(this).replace(/\b[a-z]/g, function(match){ | |
return match.toUpperCase(); | |
}); | |
}, | |
escapeRegExp: function(){ | |
return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); | |
}, | |
toInt: function(base){ | |
return parseInt(this, base || 10); | |
}, | |
toFloat: function(){ | |
return parseFloat(this); | |
}, | |
hexToRgb: function(array){ | |
var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); | |
return (hex) ? hex.slice(1).hexToRgb(array) : null; | |
}, | |
rgbToHex: function(array){ | |
var rgb = String(this).match(/\d{1,3}/g); | |
return (rgb) ? rgb.rgbToHex(array) : null; | |
}, | |
substitute: function(object, regexp){ | |
return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ | |
if (match.charAt(0) == '\\') return match.slice(1); | |
return (object[name] != null) ? object[name] : ''; | |
}); | |
} | |
}); | |
/* | |
--- | |
name: Class | |
description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. | |
license: MIT-style license. | |
requires: [Array, String, Function, Number] | |
provides: Class | |
... | |
*/ | |
(function(){ | |
var Class = this.Class = new Type('Class', function(params){ | |
if (instanceOf(params, Function)) params = {initialize: params}; | |
var newClass = function(){ | |
reset(this); | |
if (newClass.$prototyping) return this; | |
this.$caller = null; | |
var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; | |
this.$caller = this.caller = null; | |
return value; | |
}.extend(this).implement(params); | |
newClass.$constructor = Class; | |
newClass.prototype.$constructor = newClass; | |
newClass.prototype.parent = parent; | |
return newClass; | |
}); | |
var parent = function(){ | |
if (!this.$caller) throw new Error('The method "parent" cannot be called.'); | |
var name = this.$caller.$name, | |
parent = this.$caller.$owner.parent, | |
previous = (parent) ? parent.prototype[name] : null; | |
if (!previous) throw new Error('The method "' + name + '" has no parent.'); | |
return previous.apply(this, arguments); | |
}; | |
var reset = function(object){ | |
for (var key in object){ | |
var value = object[key]; | |
switch (typeOf(value)){ | |
case 'object': | |
var F = function(){}; | |
F.prototype = value; | |
object[key] = reset(new F); | |
break; | |
case 'array': object[key] = value.clone(); break; | |
} | |
} | |
return object; | |
}; | |
var wrap = function(self, key, method){ | |
if (method.$origin) method = method.$origin; | |
var wrapper = function(){ | |
if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); | |
var caller = this.caller, current = this.$caller; | |
this.caller = current; this.$caller = wrapper; | |
var result = method.apply(this, arguments); | |
this.$caller = current; this.caller = caller; | |
return result; | |
}.extend({$owner: self, $origin: method, $name: key}); | |
return wrapper; | |
}; | |
var implement = function(key, value, retain){ | |
if (Class.Mutators.hasOwnProperty(key)){ | |
value = Class.Mutators[key].call(this, value); | |
if (value == null) return this; | |
} | |
if (typeOf(value) == 'function'){ | |
if (value.$hidden) return this; | |
this.prototype[key] = (retain) ? value : wrap(this, key, value); | |
} else { | |
Object.merge(this.prototype, key, value); | |
} | |
return this; | |
}; | |
var getInstance = function(klass){ | |
klass.$prototyping = true; | |
var proto = new klass; | |
delete klass.$prototyping; | |
return proto; | |
}; | |
Class.implement('implement', implement.overloadSetter()); | |
Class.Mutators = { | |
Extends: function(parent){ | |
this.parent = parent; | |
this.prototype = getInstance(parent); | |
}, | |
Implements: function(items){ | |
Array.from(items).each(function(item){ | |
var instance = new item; | |
for (var key in instance) implement.call(this, key, instance[key], true); | |
}, this); | |
} | |
}; | |
})(); | |
/* | |
--- | |
name: Class.Extras | |
description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. | |
license: MIT-style license. | |
requires: Class | |
provides: [Class.Extras, Chain, Events, Options] | |
... | |
*/ | |
(function(){ | |
this.Chain = new Class({ | |
$chain: [], | |
chain: function(){ | |
this.$chain.append(Array.flatten(arguments)); | |
return this; | |
}, | |
callChain: function(){ | |
return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; | |
}, | |
clearChain: function(){ | |
this.$chain.empty(); | |
return this; | |
} | |
}); | |
var removeOn = function(string){ | |
return string.replace(/^on([A-Z])/, function(full, first){ | |
return first.toLowerCase(); | |
}); | |
}; | |
this.Events = new Class({ | |
$events: {}, | |
addEvent: function(type, fn, internal){ | |
type = removeOn(type); | |
this.$events[type] = (this.$events[type] || []).include(fn); | |
if (internal) fn.internal = true; | |
return this; | |
}, | |
addEvents: function(events){ | |
for (var type in events) this.addEvent(type, events[type]); | |
return this; | |
}, | |
fireEvent: function(type, args, delay){ | |
type = removeOn(type); | |
var events = this.$events[type]; | |
if (!events) return this; | |
args = Array.from(args); | |
events.each(function(fn){ | |
if (delay) fn.delay(delay, this, args); | |
else fn.apply(this, args); | |
}, this); | |
return this; | |
}, | |
removeEvent: function(type, fn){ | |
type = removeOn(type); | |
var events = this.$events[type]; | |
if (events && !fn.internal){ | |
var index = events.indexOf(fn); | |
if (index != -1) delete events[index]; | |
} | |
return this; | |
}, | |
removeEvents: function(events){ | |
var type; | |
if (typeOf(events) == 'object'){ | |
for (type in events) this.removeEvent(type, events[type]); | |
return this; | |
} | |
if (events) events = removeOn(events); | |
for (type in this.$events){ | |
if (events && events != type) continue; | |
var fns = this.$events[type]; | |
for (var i = fns.length; i--;) if (i in fns){ | |
this.removeEvent(type, fns[i]); | |
} | |
} | |
return this; | |
} | |
}); | |
this.Options = new Class({ | |
setOptions: function(){ | |
var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); | |
if (this.addEvent) for (var option in options){ | |
if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; | |
this.addEvent(option, options[option]); | |
delete options[option]; | |
} | |
return this; | |
} | |
}); | |
})(); | |
/* | |
--- | |
name: Object | |
description: Object generic methods | |
license: MIT-style license. | |
requires: Type | |
provides: [Object, Hash] | |
... | |
*/ | |
(function(){ | |
var hasOwnProperty = Object.prototype.hasOwnProperty; | |
Object.extend({ | |
subset: function(object, keys){ | |
var results = {}; | |
for (var i = 0, l = keys.length; i < l; i++){ | |
var k = keys[i]; | |
if (k in object) results[k] = object[k]; | |
} | |
return results; | |
}, | |
map: function(object, fn, bind){ | |
var results = {}; | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); | |
} | |
return results; | |
}, | |
filter: function(object, fn, bind){ | |
var results = {}; | |
for (var key in object){ | |
var value = object[key]; | |
if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; | |
} | |
return results; | |
}, | |
every: function(object, fn, bind){ | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; | |
} | |
return true; | |
}, | |
some: function(object, fn, bind){ | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; | |
} | |
return false; | |
}, | |
keys: function(object){ | |
var keys = []; | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key)) keys.push(key); | |
} | |
return keys; | |
}, | |
values: function(object){ | |
var values = []; | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key)) values.push(object[key]); | |
} | |
return values; | |
}, | |
getLength: function(object){ | |
return Object.keys(object).length; | |
}, | |
keyOf: function(object, value){ | |
for (var key in object){ | |
if (hasOwnProperty.call(object, key) && object[key] === value) return key; | |
} | |
return null; | |
}, | |
contains: function(object, value){ | |
return Object.keyOf(object, value) != null; | |
}, | |
toQueryString: function(object, base){ | |
var queryString = []; | |
Object.each(object, function(value, key){ | |
if (base) key = base + '[' + key + ']'; | |
var result; | |
switch (typeOf(value)){ | |
case 'object': result = Object.toQueryString(value, key); break; | |
case 'array': | |
var qs = {}; | |
value.each(function(val, i){ | |
qs[i] = val; | |
}); | |
result = Object.toQueryString(qs, key); | |
break; | |
default: result = key + '=' + encodeURIComponent(value); | |
} | |
if (value != null) queryString.push(result); | |
}); | |
return queryString.join('&'); | |
} | |
}); | |
})(); | |
/* | |
--- | |
name: Slick.Parser | |
description: Standalone CSS3 Selector parser | |
provides: Slick.Parser | |
... | |
*/ | |
;(function(){ | |
var parsed, | |
separatorIndex, | |
combinatorIndex, | |
reversed, | |
cache = {}, | |
reverseCache = {}, | |
reUnescape = /\\/g; | |
var parse = function(expression, isReversed){ | |
if (expression == null) return null; | |
if (expression.Slick === true) return expression; | |
expression = ('' + expression).replace(/^\s+|\s+$/g, ''); | |
reversed = !!isReversed; | |
var currentCache = (reversed) ? reverseCache : cache; | |
if (currentCache[expression]) return currentCache[expression]; | |
parsed = { | |
Slick: true, | |
expressions: [], | |
raw: expression, | |
reverse: function(){ | |
return parse(this.raw, true); | |
} | |
}; | |
separatorIndex = -1; | |
while (expression != (expression = expression.replace(regexp, parser))); | |
parsed.length = parsed.expressions.length; | |
return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; | |
}; | |
var reverseCombinator = function(combinator){ | |
if (combinator === '!') return ' '; | |
else if (combinator === ' ') return '!'; | |
else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); | |
else return '!' + combinator; | |
}; | |
var reverse = function(expression){ | |
var expressions = expression.expressions; | |
for (var i = 0; i < expressions.length; i++){ | |
var exp = expressions[i]; | |
var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; | |
for (var j = 0; j < exp.length; j++){ | |
var cexp = exp[j]; | |
if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; | |
cexp.combinator = cexp.reverseCombinator; | |
delete cexp.reverseCombinator; | |
} | |
exp.reverse().push(last); | |
} | |
return expression; | |
}; | |
var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License | |
return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ | |
return '\\' + match; | |
}); | |
}; | |
var regexp = new RegExp( | |
/* | |
#!/usr/bin/env ruby | |
puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') | |
__END__ | |
"(?x)^(?:\ | |
\\s* ( , ) \\s* # Separator \n\ | |
| \\s* ( <combinator>+ ) \\s* # Combinator \n\ | |
| ( \\s+ ) # CombinatorChildren \n\ | |
| ( <unicode>+ | \\* ) # Tag \n\ | |
| \\# ( <unicode>+ ) # ID \n\ | |
| \\. ( <unicode>+ ) # ClassName \n\ | |
| # Attribute \n\ | |
\\[ \ | |
\\s* (<unicode1>+) (?: \ | |
\\s* ([*^$!~|]?=) (?: \ | |
\\s* (?:\ | |
([\"']?)(.*?)\\9 \ | |
)\ | |
) \ | |
)? \\s* \ | |
\\](?!\\]) \n\ | |
| :+ ( <unicode>+ )(?:\ | |
\\( (?:\ | |
(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ | |
) \\)\ | |
)?\ | |
)" | |
*/ | |
"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" | |
.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']') | |
.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') | |
.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') | |
); | |
function parser( | |
rawMatch, | |
separator, | |
combinator, | |
combinatorChildren, | |
tagName, | |
id, | |
className, | |
attributeKey, | |
attributeOperator, | |
attributeQuote, | |
attributeValue, | |
pseudoMarker, | |
pseudoClass, | |
pseudoQuote, | |
pseudoClassQuotedValue, | |
pseudoClassValue | |
){ | |
if (separator || separatorIndex === -1){ | |
parsed.expressions[++separatorIndex] = []; | |
combinatorIndex = -1; | |
if (separator) return ''; | |
} | |
if (combinator || combinatorChildren || combinatorIndex === -1){ | |
combinator = combinator || ' '; | |
var currentSeparator = parsed.expressions[separatorIndex]; | |
if (reversed && currentSeparator[combinatorIndex]) | |
currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); | |
currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; | |
} | |
var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; | |
if (tagName){ | |
currentParsed.tag = tagName.replace(reUnescape, ''); | |
} else if (id){ | |
currentParsed.id = id.replace(reUnescape, ''); | |
} else if (className){ | |
className = className.replace(reUnescape, ''); | |
if (!currentParsed.classList) currentParsed.classList = []; | |
if (!currentParsed.classes) currentParsed.classes = []; | |
currentParsed.classList.push(className); | |
currentParsed.classes.push({ | |
value: className, | |
regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') | |
}); | |
} else if (pseudoClass){ | |
pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; | |
pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; | |
if (!currentParsed.pseudos) currentParsed.pseudos = []; | |
currentParsed.pseudos.push({ | |
key: pseudoClass.replace(reUnescape, ''), | |
value: pseudoClassValue, | |
type: pseudoMarker.length == 1 ? 'class' : 'element' | |
}); | |
} else if (attributeKey){ | |
attributeKey = attributeKey.replace(reUnescape, ''); | |
attributeValue = (attributeValue || '').replace(reUnescape, ''); | |
var test, regexp; | |
switch (attributeOperator){ | |
case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; | |
case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; | |
case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; | |
case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; | |
case '=' : test = function(value){ | |
return attributeValue == value; | |
}; break; | |
case '*=' : test = function(value){ | |
return value && value.indexOf(attributeValue) > -1; | |
}; break; | |
case '!=' : test = function(value){ | |
return attributeValue != value; | |
}; break; | |
default : test = function(value){ | |
return !!value; | |
}; | |
} | |
if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ | |
return false; | |
}; | |
if (!test) test = function(value){ | |
return value && regexp.test(value); | |
}; | |
if (!currentParsed.attributes) currentParsed.attributes = []; | |
currentParsed.attributes.push({ | |
key: attributeKey, | |
operator: attributeOperator, | |
value: attributeValue, | |
test: test | |
}); | |
} | |
return ''; | |
}; | |
// Slick NS | |
var Slick = (this.Slick || {}); | |
Slick.parse = function(expression){ | |
return parse(expression); | |
}; | |
Slick.escapeRegExp = escapeRegExp; | |
if (!this.Slick) this.Slick = Slick; | |
}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); | |
/* | |
--- | |
name: JSON | |
description: JSON encoder and decoder. | |
license: MIT-style license. | |
SeeAlso: <http://www.json.org/> | |
requires: [Array, String, Number, Function] | |
provides: JSON | |
... | |
*/ | |
if (typeof JSON == 'undefined') this.JSON = {}; | |
(function(){ | |
var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; | |
var escape = function(chr){ | |
return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); | |
}; | |
JSON.validate = function(string){ | |
string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). | |
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). | |
replace(/(?:^|:|,)(?:\s*\[)+/g, ''); | |
return (/^[\],:{}\s]*$/).test(string); | |
}; | |
JSON.encode = JSON.stringify ? function(obj){ | |
return JSON.stringify(obj); | |
} : function(obj){ | |
if (obj && obj.toJSON) obj = obj.toJSON(); | |
switch (typeOf(obj)){ | |
case 'string': | |
return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; | |
case 'array': | |
return '[' + obj.map(JSON.encode).clean() + ']'; | |
case 'object': case 'hash': | |
var string = []; | |
Object.each(obj, function(value, key){ | |
var json = JSON.encode(value); | |
if (json) string.push(JSON.encode(key) + ':' + json); | |
}); | |
return '{' + string + '}'; | |
case 'number': case 'boolean': return '' + obj; | |
case 'null': return 'null'; | |
} | |
return null; | |
}; | |
JSON.secure = true; | |
JSON.decode = function(string, secure){ | |
if (!string || typeOf(string) != 'string') return null; | |
if (secure == null) secure = JSON.secure; | |
if (secure){ | |
if (JSON.parse) return JSON.parse(string); | |
if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); | |
} | |
return eval('(' + string + ')'); | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment