| /* |
| --- |
| MooTools: the javascript framework |
| |
| web build: |
| - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7 |
| |
| packager build: |
| - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff |
| |
| /* |
| --- |
| |
| name: Core |
| |
| description: The heart of MooTools. |
| |
| license: MIT-style license. |
| |
| copyright: Copyright (c) 2006-2010 [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] |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| this.MooTools = { |
| version: '1.3.2', |
| build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587' |
| }; |
| |
| // typeOf, instanceOf |
| |
| var typeOf = this.typeOf = function(item){ |
| if (item == null) return 'null'; |
| if (item.$family) 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 (item.callee) 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; |
| } |
| 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 (usePlural || typeof a != 'string') args = a; |
| else if (arguments.length > 1) args = arguments; |
| 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(); |
| //<1.2compat> |
| object.type = typeCheck; |
| //</1.2compat> |
| } |
| } |
| |
| 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){ |
| delete prototype[key]; |
| prototype[key] = proto.protect(); |
| } |
| } |
| |
| if (isType) object.implement(prototype); |
| |
| return force; |
| }; |
| |
| force('String', String, [ |
| 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', |
| 'slice', 'split', 'substr', 'substring', '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({ |
| |
| 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); |
| } |
| }, |
| |
| 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); |
| }); |
| |
| //<1.2compat> |
| |
| var Hash = this.Hash = new Type('Hash', function(object){ |
| if (typeOf(object) == 'hash') object = Object.clone(object.getClean()); |
| for (var key in object) this[key] = object[key]; |
| return this; |
| }); |
| |
| Hash.implement({ |
| |
| forEach: function(fn, bind){ |
| Object.forEach(this, fn, bind); |
| }, |
| |
| getClean: function(){ |
| var clean = {}; |
| for (var key in this){ |
| if (this.hasOwnProperty(key)) clean[key] = this[key]; |
| } |
| return clean; |
| }, |
| |
| getLength: function(){ |
| var length = 0; |
| for (var key in this){ |
| if (this.hasOwnProperty(key)) length++; |
| } |
| return length; |
| } |
| |
| }); |
| |
| Hash.alias('each', 'forEach'); |
| |
| Object.type = Type.isObject; |
| |
| var Native = this.Native = function(properties){ |
| return new Type(properties.name, properties.initialize); |
| }; |
| |
| Native.type = Type.type; |
| |
| Native.implement = function(objects, methods){ |
| for (var i = 0; i < objects.length; i++) objects[i].implement(methods); |
| return Native; |
| }; |
| |
| var arrayType = Array.type; |
| Array.type = function(item){ |
| return instanceOf(item, Array) || arrayType(item); |
| }; |
| |
| this.$A = function(item){ |
| return Array.from(item).slice(); |
| }; |
| |
| this.$arguments = function(i){ |
| return function(){ |
| return arguments[i]; |
| }; |
| }; |
| |
| this.$chk = function(obj){ |
| return !!(obj || obj === 0); |
| }; |
| |
| this.$clear = function(timer){ |
| clearTimeout(timer); |
| clearInterval(timer); |
| return null; |
| }; |
| |
| this.$defined = function(obj){ |
| return (obj != null); |
| }; |
| |
| this.$each = function(iterable, fn, bind){ |
| var type = typeOf(iterable); |
| ((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind); |
| }; |
| |
| this.$empty = function(){}; |
| |
| this.$extend = function(original, extended){ |
| return Object.append(original, extended); |
| }; |
| |
| this.$H = function(object){ |
| return new Hash(object); |
| }; |
| |
| this.$merge = function(){ |
| var args = Array.slice(arguments); |
| args.unshift({}); |
| return Object.merge.apply(null, args); |
| }; |
| |
| this.$lambda = Function.from; |
| this.$mixin = Object.merge; |
| this.$random = Number.random; |
| this.$splat = Array.from; |
| this.$time = Date.now; |
| |
| this.$type = function(object){ |
| var type = typeOf(object); |
| if (type == 'elements') return 'array'; |
| return (type == 'null') ? false : type; |
| }; |
| |
| this.$unlink = function(object){ |
| switch (typeOf(object)){ |
| case 'object': return Object.clone(object); |
| case 'array': return Array.clone(object); |
| case 'hash': return new Hash(object); |
| default: return object; |
| } |
| }; |
| |
| //</1.2compat> |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| 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; 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 i = 0, l = this.length; i < l; i++){ |
| if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); |
| } |
| return results; |
| }, |
| |
| indexOf: function(item, from){ |
| var len = this.length; |
| for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ |
| if (this[i] === item) return i; |
| } |
| return -1; |
| }, |
| |
| map: function(fn, bind){ |
| var results = []; |
| for (var i = 0, l = this.length; i < l; 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; 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 value.toInt(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(''); |
| } |
| |
| }); |
| |
| //<1.2compat> |
| |
| Array.alias('extend', 'append'); |
| |
| var $pick = function(){ |
| return Array.from(arguments).pick(); |
| }; |
| |
| //</1.2compat> |
| |
| |
| /* |
| --- |
| |
| name: String |
| |
| description: Contains String Prototypes like camelCase, capitalize, test, and toInt. |
| |
| license: MIT-style license. |
| |
| requires: Type |
| |
| provides: String |
| |
| ... |
| */ |
| |
| String.implement({ |
| |
| test: function(regex, params){ |
| return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); |
| }, |
| |
| contains: function(string, separator){ |
| return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; |
| }, |
| |
| trim: function(){ |
| return this.replace(/^\s+|\s+$/g, ''); |
| }, |
| |
| clean: function(){ |
| return this.replace(/\s+/g, ' ').trim(); |
| }, |
| |
| camelCase: function(){ |
| return this.replace(/-\D/g, function(match){ |
| return match.charAt(1).toUpperCase(); |
| }); |
| }, |
| |
| hyphenate: function(){ |
| return this.replace(/[A-Z]/g, function(match){ |
| return ('-' + match.charAt(0).toLowerCase()); |
| }); |
| }, |
| |
| capitalize: function(){ |
| return this.replace(/\b[a-z]/g, function(match){ |
| return match.toUpperCase(); |
| }); |
| }, |
| |
| escapeRegExp: function(){ |
| return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); |
| }, |
| |
| toInt: function(base){ |
| return parseInt(this, base || 10); |
| }, |
| |
| toFloat: function(){ |
| return parseFloat(this); |
| }, |
| |
| hexToRgb: function(array){ |
| var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); |
| return (hex) ? hex.slice(1).hexToRgb(array) : null; |
| }, |
| |
| rgbToHex: function(array){ |
| var rgb = this.match(/\d{1,3}/g); |
| return (rgb) ? rgb.rgbToHex(array) : null; |
| }, |
| |
| substitute: function(object, regexp){ |
| return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ |
| if (match.charAt(0) == '\\') return match.slice(1); |
| return (object[name] != null) ? object[name] : ''; |
| }); |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| 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: 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: function(bind){ |
| var self = this, |
| args = (arguments.length > 1) ? Array.slice(arguments, 1) : null; |
| |
| return function(){ |
| if (!args && !arguments.length) return self.call(bind); |
| if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments))); |
| return self.apply(bind, args || arguments); |
| }; |
| }, |
| /*</!ES5>*/ |
| |
| 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); |
| } |
| |
| }); |
| |
| //<1.2compat> |
| |
| delete Function.prototype.bind; |
| |
| Function.implement({ |
| |
| create: function(options){ |
| var self = this; |
| options = options || {}; |
| return function(event){ |
| var args = options.arguments; |
| args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0); |
| if (options.event) args = [event || window.event].extend(args); |
| var returns = function(){ |
| return self.apply(options.bind || null, args); |
| }; |
| if (options.delay) return setTimeout(returns, options.delay); |
| if (options.periodical) return setInterval(returns, options.periodical); |
| if (options.attempt) return Function.attempt(returns); |
| return returns(); |
| }; |
| }, |
| |
| bind: function(bind, args){ |
| var self = this; |
| if (args != null) args = Array.from(args); |
| return function(){ |
| return self.apply(bind, args || arguments); |
| }; |
| }, |
| |
| bindWithEvent: function(bind, args){ |
| var self = this; |
| if (args != null) args = Array.from(args); |
| return function(event){ |
| return self.apply(bind, (args == null) ? arguments : [event].concat(args)); |
| }; |
| }, |
| |
| run: function(args, bind){ |
| return this.apply(bind, Array.from(args)); |
| } |
| |
| }); |
| |
| var $try = Function.attempt; |
| |
| //</1.2compat> |
| |
| |
| /* |
| --- |
| |
| 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('&'); |
| } |
| |
| }); |
| |
| })(); |
| |
| //<1.2compat> |
| |
| Hash.implement({ |
| |
| has: Object.prototype.hasOwnProperty, |
| |
| keyOf: function(value){ |
| return Object.keyOf(this, value); |
| }, |
| |
| hasValue: function(value){ |
| return Object.contains(this, value); |
| }, |
| |
| extend: function(properties){ |
| Hash.each(properties || {}, function(value, key){ |
| Hash.set(this, key, value); |
| }, this); |
| return this; |
| }, |
| |
| combine: function(properties){ |
| Hash.each(properties || {}, function(value, key){ |
| Hash.include(this, key, value); |
| }, this); |
| return this; |
| }, |
| |
| erase: function(key){ |
| if (this.hasOwnProperty(key)) delete this[key]; |
| return this; |
| }, |
| |
| get: function(key){ |
| return (this.hasOwnProperty(key)) ? this[key] : null; |
| }, |
| |
| set: function(key, value){ |
| if (!this[key] || this.hasOwnProperty(key)) this[key] = value; |
| return this; |
| }, |
| |
| empty: function(){ |
| Hash.each(this, function(value, key){ |
| delete this[key]; |
| }, this); |
| return this; |
| }, |
| |
| include: function(key, value){ |
| if (this[key] == null) this[key] = value; |
| return this; |
| }, |
| |
| map: function(fn, bind){ |
| return new Hash(Object.map(this, fn, bind)); |
| }, |
| |
| filter: function(fn, bind){ |
| return new Hash(Object.filter(this, fn, bind)); |
| }, |
| |
| every: function(fn, bind){ |
| return Object.every(this, fn, bind); |
| }, |
| |
| some: function(fn, bind){ |
| return Object.some(this, fn, bind); |
| }, |
| |
| getKeys: function(){ |
| return Object.keys(this); |
| }, |
| |
| getValues: function(){ |
| return Object.values(this); |
| }, |
| |
| toQueryString: function(base){ |
| return Object.toQueryString(this, base); |
| } |
| |
| }); |
| |
| Hash.extend = Object.append; |
| |
| Hash.alias({indexOf: 'keyOf', contains: 'hasValue'}); |
| |
| //</1.2compat> |
| |
| |
| /* |
| --- |
| |
| name: Browser |
| |
| description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. |
| |
| license: MIT-style license. |
| |
| requires: [Array, Function, Number, String] |
| |
| provides: [Browser, Window, Document] |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var document = this.document; |
| var window = document.window = this; |
| |
| var UID = 1; |
| |
| this.$uid = (window.ActiveXObject) ? function(item){ |
| return (item.uid || (item.uid = [UID++]))[0]; |
| } : function(item){ |
| return item.uid || (item.uid = UID++); |
| }; |
| |
| $uid(window); |
| $uid(document); |
| |
| var ua = navigator.userAgent.toLowerCase(), |
| platform = navigator.platform.toLowerCase(), |
| UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], |
| mode = UA[1] == 'ie' && document.documentMode; |
| |
| var Browser = this.Browser = { |
| |
| extend: Function.prototype.extend, |
| |
| name: (UA[1] == 'version') ? UA[3] : UA[1], |
| |
| version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), |
| |
| Platform: { |
| name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] |
| }, |
| |
| Features: { |
| xpath: !!(document.evaluate), |
| air: !!(window.runtime), |
| query: !!(document.querySelector), |
| json: !!(window.JSON) |
| }, |
| |
| Plugins: {} |
| |
| }; |
| |
| Browser[Browser.name] = true; |
| Browser[Browser.name + parseInt(Browser.version, 10)] = true; |
| Browser.Platform[Browser.Platform.name] = true; |
| |
| // Request |
| |
| Browser.Request = (function(){ |
| |
| var XMLHTTP = function(){ |
| return new XMLHttpRequest(); |
| }; |
| |
| var MSXML2 = function(){ |
| return new ActiveXObject('MSXML2.XMLHTTP'); |
| }; |
| |
| var MSXML = function(){ |
| return new ActiveXObject('Microsoft.XMLHTTP'); |
| }; |
| |
| return Function.attempt(function(){ |
| XMLHTTP(); |
| return XMLHTTP; |
| }, function(){ |
| MSXML2(); |
| return MSXML2; |
| }, function(){ |
| MSXML(); |
| return MSXML; |
| }); |
| |
| })(); |
| |
| Browser.Features.xhr = !!(Browser.Request); |
| |
| // Flash detection |
| |
| var version = (Function.attempt(function(){ |
| return navigator.plugins['Shockwave Flash'].description; |
| }, function(){ |
| return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); |
| }) || '0 r0').match(/\d+/g); |
| |
| Browser.Plugins.Flash = { |
| version: Number(version[0] || '0.' + version[1]) || 0, |
| build: Number(version[2]) || 0 |
| }; |
| |
| // String scripts |
| |
| Browser.exec = function(text){ |
| if (!text) return text; |
| if (window.execScript){ |
| window.execScript(text); |
| } else { |
| var script = document.createElement('script'); |
| script.setAttribute('type', 'text/javascript'); |
| script.text = text; |
| document.head.appendChild(script); |
| document.head.removeChild(script); |
| } |
| return text; |
| }; |
| |
| String.implement('stripScripts', function(exec){ |
| var scripts = ''; |
| var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ |
| scripts += code + '\n'; |
| return ''; |
| }); |
| if (exec === true) Browser.exec(scripts); |
| else if (typeOf(exec) == 'function') exec(scripts, text); |
| return text; |
| }); |
| |
| // Window, Document |
| |
| Browser.extend({ |
| Document: this.Document, |
| Window: this.Window, |
| Element: this.Element, |
| Event: this.Event |
| }); |
| |
| this.Window = this.$constructor = new Type('Window', function(){}); |
| |
| this.$family = Function.from('window').hide(); |
| |
| Window.mirror(function(name, method){ |
| window[name] = method; |
| }); |
| |
| this.Document = document.$constructor = new Type('Document', function(){}); |
| |
| document.$family = Function.from('document').hide(); |
| |
| Document.mirror(function(name, method){ |
| document[name] = method; |
| }); |
| |
| document.html = document.documentElement; |
| if (!document.head) document.head = document.getElementsByTagName('head')[0]; |
| |
| if (document.execCommand) try { |
| document.execCommand("BackgroundImageCache", false, true); |
| } catch (e){} |
| |
| /*<ltIE9>*/ |
| if (this.attachEvent && !this.addEventListener){ |
| var unloadEvent = function(){ |
| this.detachEvent('onunload', unloadEvent); |
| document.head = document.html = document.window = null; |
| }; |
| this.attachEvent('onunload', unloadEvent); |
| } |
| |
| // IE fails on collections and <select>.options (refers to <select>) |
| var arrayFrom = Array.from; |
| try { |
| arrayFrom(document.html.childNodes); |
| } catch(e){ |
| Array.from = function(item){ |
| if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ |
| var i = item.length, array = new Array(i); |
| while (i--) array[i] = item[i]; |
| return array; |
| } |
| return arrayFrom(item); |
| }; |
| |
| var prototype = Array.prototype, |
| slice = prototype.slice; |
| ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ |
| var method = prototype[name]; |
| Array[name] = function(item){ |
| return method.apply(Array.from(item), slice.call(arguments, 1)); |
| }; |
| }); |
| } |
| /*</ltIE9>*/ |
| |
| //<1.2compat> |
| |
| if (Browser.Platform.ios) Browser.Platform.ipod = true; |
| |
| Browser.Engine = {}; |
| |
| var setEngine = function(name, version){ |
| Browser.Engine.name = name; |
| Browser.Engine[name + version] = true; |
| Browser.Engine.version = version; |
| }; |
| |
| if (Browser.ie){ |
| Browser.Engine.trident = true; |
| |
| switch (Browser.version){ |
| case 6: setEngine('trident', 4); break; |
| case 7: setEngine('trident', 5); break; |
| case 8: setEngine('trident', 6); |
| } |
| } |
| |
| if (Browser.firefox){ |
| Browser.Engine.gecko = true; |
| |
| if (Browser.version >= 3) setEngine('gecko', 19); |
| else setEngine('gecko', 18); |
| } |
| |
| if (Browser.safari || Browser.chrome){ |
| Browser.Engine.webkit = true; |
| |
| switch (Browser.version){ |
| case 2: setEngine('webkit', 419); break; |
| case 3: setEngine('webkit', 420); break; |
| case 4: setEngine('webkit', 525); |
| } |
| } |
| |
| if (Browser.opera){ |
| Browser.Engine.presto = true; |
| |
| if (Browser.version >= 9.6) setEngine('presto', 960); |
| else if (Browser.version >= 9.5) setEngine('presto', 950); |
| else setEngine('presto', 925); |
| } |
| |
| if (Browser.name == 'unknown'){ |
| switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){ |
| case 'webkit': |
| case 'khtml': |
| Browser.Engine.webkit = true; |
| break; |
| case 'gecko': |
| Browser.Engine.gecko = true; |
| } |
| } |
| |
| this.$exec = Browser.exec; |
| |
| //</1.2compat> |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| name: Event |
| |
| description: Contains the Event Class, to make the event object cross-browser. |
| |
| license: MIT-style license. |
| |
| requires: [Window, Document, Array, Function, String, Object] |
| |
| provides: Event |
| |
| ... |
| */ |
| |
| var Event = new Type('Event', function(event, win){ |
| if (!win) win = window; |
| var doc = win.document; |
| event = event || win.event; |
| if (event.$extended) return event; |
| this.$extended = true; |
| var type = event.type, |
| target = event.target || event.srcElement, |
| page = {}, |
| client = {}, |
| related = null, |
| rightClick, wheel, code, key; |
| while (target && target.nodeType == 3) target = target.parentNode; |
| |
| if (type.indexOf('key') != -1){ |
| code = event.which || event.keyCode; |
| key = Object.keyOf(Event.Keys, code); |
| if (type == 'keydown'){ |
| var fKey = code - 111; |
| if (fKey > 0 && fKey < 13) key = 'f' + fKey; |
| } |
| if (!key) key = String.fromCharCode(code).toLowerCase(); |
| } else if ((/click|mouse|menu/i).test(type)){ |
| doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; |
| page = { |
| x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, |
| y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop |
| }; |
| client = { |
| x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, |
| y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY |
| }; |
| if ((/DOMMouseScroll|mousewheel/).test(type)){ |
| wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; |
| } |
| rightClick = (event.which == 3) || (event.button == 2); |
| if ((/over|out/).test(type)){ |
| related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; |
| var testRelated = function(){ |
| while (related && related.nodeType == 3) related = related.parentNode; |
| return true; |
| }; |
| var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated(); |
| related = (hasRelated) ? related : null; |
| } |
| } else if ((/gesture|touch/i).test(type)){ |
| this.rotation = event.rotation; |
| this.scale = event.scale; |
| this.targetTouches = event.targetTouches; |
| this.changedTouches = event.changedTouches; |
| var touches = this.touches = event.touches; |
| if (touches && touches[0]){ |
| var touch = touches[0]; |
| page = {x: touch.pageX, y: touch.pageY}; |
| client = {x: touch.clientX, y: touch.clientY}; |
| } |
| } |
| |
| return Object.append(this, { |
| event: event, |
| type: type, |
| |
| page: page, |
| client: client, |
| rightClick: rightClick, |
| |
| wheel: wheel, |
| |
| relatedTarget: document.id(related), |
| target: document.id(target), |
| |
| code: code, |
| key: key, |
| |
| shift: event.shiftKey, |
| control: event.ctrlKey, |
| alt: event.altKey, |
| meta: event.metaKey |
| }); |
| }); |
| |
| Event.Keys = { |
| 'enter': 13, |
| 'up': 38, |
| 'down': 40, |
| 'left': 37, |
| 'right': 39, |
| 'esc': 27, |
| 'space': 32, |
| 'backspace': 8, |
| 'tab': 9, |
| 'delete': 46 |
| }; |
| |
| //<1.2compat> |
| |
| Event.Keys = new Hash(Event.Keys); |
| |
| //</1.2compat> |
| |
| Event.implement({ |
| |
| stop: function(){ |
| return this.stopPropagation().preventDefault(); |
| }, |
| |
| stopPropagation: function(){ |
| if (this.event.stopPropagation) this.event.stopPropagation(); |
| else this.event.cancelBubble = true; |
| return this; |
| }, |
| |
| preventDefault: function(){ |
| if (this.event.preventDefault) this.event.preventDefault(); |
| else this.event.returnValue = false; |
| return this; |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| 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); |
| |
| /*<1.2compat>*/ |
| if (fn == $empty) return this; |
| /*</1.2compat>*/ |
| |
| 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: 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: Slick.Finder |
| description: The new, superfast css selector engine. |
| provides: Slick.Finder |
| requires: Slick.Parser |
| ... |
| */ |
| |
| ;(function(){ |
| |
| var local = {}, |
| featuresCache = {}, |
| toString = Object.prototype.toString; |
| |
| // Feature / Bug detection |
| |
| local.isNativeCode = function(fn){ |
| return (/\{\s*\[native code\]\s*\}/).test('' + fn); |
| }; |
| |
| local.isXML = function(document){ |
| return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || |
| (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); |
| }; |
| |
| local.setDocument = function(document){ |
| |
| // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. |
| var nodeType = document.nodeType; |
| if (nodeType == 9); // document |
| else if (nodeType) document = document.ownerDocument; // node |
| else if (document.navigator) document = document.document; // window |
| else return; |
| |
| // check if it's the old document |
| |
| if (this.document === document) return; |
| this.document = document; |
| |
| // check if we have done feature detection on this document before |
| |
| var root = document.documentElement, |
| rootUid = this.getUIDXML(root), |
| features = featuresCache[rootUid], |
| feature; |
| |
| if (features){ |
| for (feature in features){ |
| this[feature] = features[feature]; |
| } |
| return; |
| } |
| |
| features = featuresCache[rootUid] = {}; |
| |
| features.root = root; |
| features.isXMLDocument = this.isXML(document); |
| |
| features.brokenStarGEBTN |
| = features.starSelectsClosedQSA |
| = features.idGetsName |
| = features.brokenMixedCaseQSA |
| = features.brokenGEBCN |
| = features.brokenCheckedQSA |
| = features.brokenEmptyAttributeQSA |
| = features.isHTMLDocument |
| = features.nativeMatchesSelector |
| = false; |
| |
| var starSelectsClosed, starSelectsComments, |
| brokenSecondClassNameGEBCN, cachedGetElementsByClassName, |
| brokenFormAttributeGetter; |
| |
| var selected, id = 'slick_uniqueid'; |
| var testNode = document.createElement('div'); |
| |
| var testRoot = document.body || document.getElementsByTagName('body')[0] || root; |
| testRoot.appendChild(testNode); |
| |
| // on non-HTML documents innerHTML and getElementsById doesnt work properly |
| try { |
| testNode.innerHTML = '<a id="'+id+'"></a>'; |
| features.isHTMLDocument = !!document.getElementById(id); |
| } catch(e){}; |
| |
| if (features.isHTMLDocument){ |
| |
| testNode.style.display = 'none'; |
| |
| // IE returns comment nodes for getElementsByTagName('*') for some documents |
| testNode.appendChild(document.createComment('')); |
| starSelectsComments = (testNode.getElementsByTagName('*').length > 1); |
| |
| // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents |
| try { |
| testNode.innerHTML = 'foo</foo>'; |
| selected = testNode.getElementsByTagName('*'); |
| starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); |
| } catch(e){}; |
| |
| features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; |
| |
| // IE returns elements with the name instead of just id for getElementsById for some documents |
| try { |
| testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>'; |
| features.idGetsName = document.getElementById(id) === testNode.firstChild; |
| } catch(e){}; |
| |
| if (testNode.getElementsByClassName){ |
| |
| // Safari 3.2 getElementsByClassName caches results |
| try { |
| testNode.innerHTML = '<a class="f"></a><a class="b"></a>'; |
| testNode.getElementsByClassName('b').length; |
| testNode.firstChild.className = 'b'; |
| cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); |
| } catch(e){}; |
| |
| // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one |
| try { |
| testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>'; |
| brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); |
| } catch(e){}; |
| |
| features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; |
| } |
| |
| if (testNode.querySelectorAll){ |
| // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents |
| try { |
| testNode.innerHTML = 'foo</foo>'; |
| selected = testNode.querySelectorAll('*'); |
| features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); |
| } catch(e){}; |
| |
| // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode |
| try { |
| testNode.innerHTML = '<a class="MiX"></a>'; |
| features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; |
| } catch(e){}; |
| |
| // Webkit and Opera dont return selected options on querySelectorAll |
| try { |
| testNode.innerHTML = '<select><option selected="selected">a</option></select>'; |
| features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); |
| } catch(e){}; |
| |
| // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll |
| try { |
| testNode.innerHTML = '<a class=""></a>'; |
| features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); |
| } catch(e){}; |
| |
| } |
| |
| // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input |
| try { |
| testNode.innerHTML = '<form action="s"><input id="action"/></form>'; |
| brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); |
| } catch(e){}; |
| |
| // native matchesSelector function |
| |
| features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; |
| if (features.nativeMatchesSelector) try { |
| // if matchesSelector trows errors on incorrect sintaxes we can use it |
| features.nativeMatchesSelector.call(root, ':slick'); |
| features.nativeMatchesSelector = null; |
| } catch(e){}; |
| |
| } |
| |
| try { |
| root.slick_expando = 1; |
| delete root.slick_expando; |
| features.getUID = this.getUIDHTML; |
| } catch(e) { |
| features.getUID = this.getUIDXML; |
| } |
| |
| testRoot.removeChild(testNode); |
| testNode = selected = testRoot = null; |
| |
| // getAttribute |
| |
| features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ |
| var method = this.attributeGetters[name]; |
| if (method) return method.call(node); |
| var attributeNode = node.getAttributeNode(name); |
| return (attributeNode) ? attributeNode.nodeValue : null; |
| } : function(node, name){ |
| var method = this.attributeGetters[name]; |
| return (method) ? method.call(node) : node.getAttribute(name); |
| }; |
| |
| // hasAttribute |
| |
| features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { |
| return node.hasAttribute(attribute); |
| } : function(node, attribute) { |
| node = node.getAttributeNode(attribute); |
| return !!(node && (node.specified || node.nodeValue)); |
| }; |
| |
| // contains |
| // FIXME: Add specs: local.contains should be different for xml and html documents? |
| features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){ |
| return context.contains(node); |
| } : (root && root.compareDocumentPosition) ? function(context, node){ |
| return context === node || !!(context.compareDocumentPosition(node) & 16); |
| } : function(context, node){ |
| if (node) do { |
| if (node === context) return true; |
| } while ((node = node.parentNode)); |
| return false; |
| }; |
| |
| // document order sorting |
| // credits to Sizzle (http://sizzlejs.com/) |
| |
| features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ |
| if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; |
| return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; |
| } : ('sourceIndex' in root) ? function(a, b){ |
| if (!a.sourceIndex || !b.sourceIndex) return 0; |
| return a.sourceIndex - b.sourceIndex; |
| } : (document.createRange) ? function(a, b){ |
| if (!a.ownerDocument || !b.ownerDocument) return 0; |
| var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); |
| aRange.setStart(a, 0); |
| aRange.setEnd(a, 0); |
| bRange.setStart(b, 0); |
| bRange.setEnd(b, 0); |
| return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); |
| } : null ; |
| |
| root = null; |
| |
| for (feature in features){ |
| this[feature] = features[feature]; |
| } |
| }; |
| |
| // Main Method |
| |
| var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, |
| reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, |
| qsaFailExpCache = {}; |
| |
| local.search = function(context, expression, append, first){ |
| |
| var found = this.found = (first) ? null : (append || []); |
| |
| if (!context) return found; |
| else if (context.navigator) context = context.document; // Convert the node from a window to a document |
| else if (!context.nodeType) return found; |
| |
| // setup |
| |
| var parsed, i, |
| uniques = this.uniques = {}, |
| hasOthers = !!(append && append.length), |
| contextIsDocument = (context.nodeType == 9); |
| |
| if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); |
| |
| // avoid duplicating items already in the append array |
| if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; |
| |
| // expression checks |
| |
| if (typeof expression == 'string'){ // expression is a string |
| |
| /*<simple-selectors-override>*/ |
| var simpleSelector = expression.match(reSimpleSelector); |
| simpleSelectors: if (simpleSelector) { |
| |
| var symbol = simpleSelector[1], |
| name = simpleSelector[2], |
| node, nodes; |
| |
| if (!symbol){ |
| |
| if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; |
| nodes = context.getElementsByTagName(name); |
| if (first) return nodes[0] || null; |
| for (i = 0; node = nodes[i++];){ |
| if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| } |
| |
| } else if (symbol == '#'){ |
| |
| if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; |
| node = context.getElementById(name); |
| if (!node) return found; |
| if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; |
| if (first) return node || null; |
| if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| |
| } else if (symbol == '.'){ |
| |
| if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; |
| if (context.getElementsByClassName && !this.brokenGEBCN){ |
| nodes = context.getElementsByClassName(name); |
| if (first) return nodes[0] || null; |
| for (i = 0; node = nodes[i++];){ |
| if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| } |
| } else { |
| var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); |
| nodes = context.getElementsByTagName('*'); |
| for (i = 0; node = nodes[i++];){ |
| className = node.className; |
| if (!(className && matchClass.test(className))) continue; |
| if (first) return node; |
| if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| } |
| } |
| |
| } |
| |
| if (hasOthers) this.sort(found); |
| return (first) ? null : found; |
| |
| } |
| /*</simple-selectors-override>*/ |
| |
| /*<query-selector-override>*/ |
| querySelector: if (context.querySelectorAll) { |
| |
| if (!this.isHTMLDocument |
| || qsaFailExpCache[expression] |
| //TODO: only skip when expression is actually mixed case |
| || this.brokenMixedCaseQSA |
| || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) |
| || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) |
| || (!contextIsDocument //Abort when !contextIsDocument and... |
| // there are multiple expressions in the selector |
| // since we currently only fix non-document rooted QSA for single expression selectors |
| && expression.indexOf(',') > -1 |
| ) |
| || Slick.disableQSA |
| ) break querySelector; |
| |
| var _expression = expression, _context = context; |
| if (!contextIsDocument){ |
| // non-document rooted QSA |
| // credits to Andrew Dupont |
| var currentId = _context.getAttribute('id'), slickid = 'slickid__'; |
| _context.setAttribute('id', slickid); |
| _expression = '#' + slickid + ' ' + _expression; |
| context = _context.parentNode; |
| } |
| |
| try { |
| if (first) return context.querySelector(_expression) || null; |
| else nodes = context.querySelectorAll(_expression); |
| } catch(e) { |
| qsaFailExpCache[expression] = 1; |
| break querySelector; |
| } finally { |
| if (!contextIsDocument){ |
| if (currentId) _context.setAttribute('id', currentId); |
| else _context.removeAttribute('id'); |
| context = _context; |
| } |
| } |
| |
| if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ |
| if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| } else for (i = 0; node = nodes[i++];){ |
| if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); |
| } |
| |
| if (hasOthers) this.sort(found); |
| return found; |
| |
| } |
| /*</query-selector-override>*/ |
| |
| parsed = this.Slick.parse(expression); |
| if (!parsed.length) return found; |
| } else if (expression == null){ // there is no expression |
| return found; |
| } else if (expression.Slick){ // expression is a parsed Slick object |
| parsed = expression; |
| } else if (this.contains(context.documentElement || context, expression)){ // expression is a node |
| (found) ? found.push(expression) : found = expression; |
| return found; |
| } else { // other junk |
| return found; |
| } |
| |
| /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ |
| |
| // cache elements for the nth selectors |
| |
| this.posNTH = {}; |
| this.posNTHLast = {}; |
| this.posNTHType = {}; |
| this.posNTHTypeLast = {}; |
| |
| /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ |
| |
| // if append is null and there is only a single selector with one expression use pushArray, else use pushUID |
| this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; |
| |
| if (found == null) found = []; |
| |
| // default engine |
| |
| var j, m, n; |
| var combinator, tag, id, classList, classes, attributes, pseudos; |
| var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; |
| |
| search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ |
| |
| combinator = 'combinator:' + currentBit.combinator; |
| if (!this[combinator]) continue search; |
| |
| tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); |
| id = currentBit.id; |
| classList = currentBit.classList; |
| classes = currentBit.classes; |
| attributes = currentBit.attributes; |
| pseudos = currentBit.pseudos; |
| lastBit = (j === (currentExpression.length - 1)); |
| |
| this.bitUniques = {}; |
| |
| if (lastBit){ |
| this.uniques = uniques; |
| this.found = found; |
| } else { |
| this.uniques = {}; |
| this.found = []; |
| } |
| |
| if (j === 0){ |
| this[combinator](context, tag, id, classes, attributes, pseudos, classList); |
| if (first && lastBit && found.length) break search; |
| } else { |
| if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ |
| this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); |
| if (found.length) break search; |
| } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); |
| } |
| |
| currentItems = this.found; |
| } |
| |
| // should sort if there are nodes in append and if you pass multiple expressions. |
| if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); |
| |
| return (first) ? (found[0] || null) : found; |
| }; |
| |
| // Utils |
| |
| local.uidx = 1; |
| local.uidk = 'slick-uniqueid'; |
| |
| local.getUIDXML = function(node){ |
| var uid = node.getAttribute(this.uidk); |
| if (!uid){ |
| uid = this.uidx++; |
| node.setAttribute(this.uidk, uid); |
| } |
| return uid; |
| }; |
| |
| local.getUIDHTML = function(node){ |
| return node.uniqueNumber || (node.uniqueNumber = this.uidx++); |
| }; |
| |
| // sort based on the setDocument documentSorter method. |
| |
| local.sort = function(results){ |
| if (!this.documentSorter) return results; |
| results.sort(this.documentSorter); |
| return results; |
| }; |
| |
| /*<pseudo-selectors>*//*<nth-pseudo-selectors>*/ |
| |
| local.cacheNTH = {}; |
| |
| local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; |
| |
| local.parseNTHArgument = function(argument){ |
| var parsed = argument.match(this.matchNTH); |
| if (!parsed) return false; |
| var special = parsed[2] || false; |
| var a = parsed[1] || 1; |
| if (a == '-') a = -1; |
| var b = +parsed[3] || 0; |
| parsed = |
| (special == 'n') ? {a: a, b: b} : |
| (special == 'odd') ? {a: 2, b: 1} : |
| (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; |
| |
| return (this.cacheNTH[argument] = parsed); |
| }; |
| |
| local.createNTHPseudo = function(child, sibling, positions, ofType){ |
| return function(node, argument){ |
| var uid = this.getUID(node); |
| if (!this[positions][uid]){ |
| var parent = node.parentNode; |
| if (!parent) return false; |
| var el = parent[child], count = 1; |
| if (ofType){ |
| var nodeName = node.nodeName; |
| do { |
| if (el.nodeName != nodeName) continue; |
| this[positions][this.getUID(el)] = count++; |
| } while ((el = el[sibling])); |
| } else { |
| do { |
| if (el.nodeType != 1) continue; |
| this[positions][this.getUID(el)] = count++; |
| } while ((el = el[sibling])); |
| } |
| } |
| argument = argument || 'n'; |
| var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); |
| if (!parsed) return false; |
| var a = parsed.a, b = parsed.b, pos = this[positions][uid]; |
| if (a == 0) return b == pos; |
| if (a > 0){ |
| if (pos < b) return false; |
| } else { |
| if (b < pos) return false; |
| } |
| return ((pos - b) % a) == 0; |
| }; |
| }; |
| |
| /*</nth-pseudo-selectors>*//*</pseudo-selectors>*/ |
| |
| local.pushArray = function(node, tag, id, classes, attributes, pseudos){ |
| if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); |
| }; |
| |
| local.pushUID = function(node, tag, id, classes, attributes, pseudos){ |
| var uid = this.getUID(node); |
| if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ |
| this.uniques[uid] = true; |
| this.found.push(node); |
| } |
| }; |
| |
| local.matchNode = function(node, selector){ |
| if (this.isHTMLDocument && this.nativeMatchesSelector){ |
| try { |
| return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); |
| } catch(matchError) {} |
| } |
| |
| var parsed = this.Slick.parse(selector); |
| if (!parsed) return true; |
| |
| // simple (single) selectors |
| var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i; |
| for (i = 0; (currentExpression = expressions[i]); i++){ |
| if (currentExpression.length == 1){ |
| var exp = currentExpression[0]; |
| if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; |
| simpleExpCounter++; |
| } |
| } |
| |
| if (simpleExpCounter == parsed.length) return false; |
| |
| var nodes = this.search(this.document, parsed), item; |
| for (i = 0; item = nodes[i++];){ |
| if (item === node) return true; |
| } |
| return false; |
| }; |
| |
| local.matchPseudo = function(node, name, argument){ |
| var pseudoName = 'pseudo:' + name; |
| if (this[pseudoName]) return this[pseudoName](node, argument); |
| var attribute = this.getAttribute(node, name); |
| return (argument) ? argument == attribute : !!attribute; |
| }; |
| |
| local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ |
| if (tag){ |
| var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); |
| if (tag == '*'){ |
| if (nodeName < '@') return false; // Fix for comment nodes and closed nodes |
| } else { |
| if (nodeName != tag) return false; |
| } |
| } |
| |
| if (id && node.getAttribute('id') != id) return false; |
| |
| var i, part, cls; |
| if (classes) for (i = classes.length; i--;){ |
| cls = node.getAttribute('class') || node.className; |
| if (!(cls && classes[i].regexp.test(cls))) return false; |
| } |
| if (attributes) for (i = attributes.length; i--;){ |
| part = attributes[i]; |
| if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; |
| } |
| if (pseudos) for (i = pseudos.length; i--;){ |
| part = pseudos[i]; |
| if (!this.matchPseudo(node, part.key, part.value)) return false; |
| } |
| return true; |
| }; |
| |
| var combinators = { |
| |
| ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level |
| |
| var i, item, children; |
| |
| if (this.isHTMLDocument){ |
| getById: if (id){ |
| item = this.document.getElementById(id); |
| if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ |
| // all[id] returns all the elements with that name or id inside node |
| // if theres just one it will return the element, else it will be a collection |
| children = node.all[id]; |
| if (!children) return; |
| if (!children[0]) children = [children]; |
| for (i = 0; item = children[i++];){ |
| var idNode = item.getAttributeNode('id'); |
| if (idNode && idNode.nodeValue == id){ |
| this.push(item, tag, null, classes, attributes, pseudos); |
| break; |
| } |
| } |
| return; |
| } |
| if (!item){ |
| // if the context is in the dom we return, else we will try GEBTN, breaking the getById label |
| if (this.contains(this.root, node)) return; |
| else break getById; |
| } else if (this.document !== node && !this.contains(node, item)) return; |
| this.push(item, tag, null, classes, attributes, pseudos); |
| return; |
| } |
| getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ |
| children = node.getElementsByClassName(classList.join(' ')); |
| if (!(children && children.length)) break getByClass; |
| for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); |
| return; |
| } |
| } |
| getByTag: { |
| children = node.getElementsByTagName(tag); |
| if (!(children && children.length)) break getByTag; |
| if (!this.brokenStarGEBTN) tag = null; |
| for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); |
| } |
| }, |
| |
| '>': function(node, tag, id, classes, attributes, pseudos){ // direct children |
| if ((node = node.firstChild)) do { |
| if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
| } while ((node = node.nextSibling)); |
| }, |
| |
| '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling |
| while ((node = node.nextSibling)) if (node.nodeType == 1){ |
| this.push(node, tag, id, classes, attributes, pseudos); |
| break; |
| } |
| }, |
| |
| '^': function(node, tag, id, classes, attributes, pseudos){ // first child |
| node = node.firstChild; |
| if (node){ |
| if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
| else this['combinator:+'](node, tag, id, classes, attributes, pseudos); |
| } |
| }, |
| |
| '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings |
| while ((node = node.nextSibling)){ |
| if (node.nodeType != 1) continue; |
| var uid = this.getUID(node); |
| if (this.bitUniques[uid]) break; |
| this.bitUniques[uid] = true; |
| this.push(node, tag, id, classes, attributes, pseudos); |
| } |
| }, |
| |
| '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling |
| this['combinator:+'](node, tag, id, classes, attributes, pseudos); |
| this['combinator:!+'](node, tag, id, classes, attributes, pseudos); |
| }, |
| |
| '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings |
| this['combinator:~'](node, tag, id, classes, attributes, pseudos); |
| this['combinator:!~'](node, tag, id, classes, attributes, pseudos); |
| }, |
| |
| '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document |
| while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); |
| }, |
| |
| '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) |
| node = node.parentNode; |
| if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); |
| }, |
| |
| '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling |
| while ((node = node.previousSibling)) if (node.nodeType == 1){ |
| this.push(node, tag, id, classes, attributes, pseudos); |
| break; |
| } |
| }, |
| |
| '!^': function(node, tag, id, classes, attributes, pseudos){ // last child |
| node = node.lastChild; |
| if (node){ |
| if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); |
| else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); |
| } |
| }, |
| |
| '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings |
| while ((node = node.previousSibling)){ |
| if (node.nodeType != 1) continue; |
| var uid = this.getUID(node); |
| if (this.bitUniques[uid]) break; |
| this.bitUniques[uid] = true; |
| this.push(node, tag, id, classes, attributes, pseudos); |
| } |
| } |
| |
| }; |
| |
| for (var c in combinators) local['combinator:' + c] = combinators[c]; |
| |
| var pseudos = { |
| |
| /*<pseudo-selectors>*/ |
| |
| 'empty': function(node){ |
| var child = node.firstChild; |
| return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; |
| }, |
| |
| 'not': function(node, expression){ |
| return !this.matchNode(node, expression); |
| }, |
| |
| 'contains': function(node, text){ |
| return (node.innerText || node.textContent || '').indexOf(text) > -1; |
| }, |
| |
| 'first-child': function(node){ |
| while ((node = node.previousSibling)) if (node.nodeType == 1) return false; |
| return true; |
| }, |
| |
| 'last-child': function(node){ |
| while ((node = node.nextSibling)) if (node.nodeType == 1) return false; |
| return true; |
| }, |
| |
| 'only-child': function(node){ |
| var prev = node; |
| while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; |
| var next = node; |
| while ((next = next.nextSibling)) if (next.nodeType == 1) return false; |
| return true; |
| }, |
| |
| /*<nth-pseudo-selectors>*/ |
| |
| 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), |
| |
| 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), |
| |
| 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), |
| |
| 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), |
| |
| 'index': function(node, index){ |
| return this['pseudo:nth-child'](node, '' + index + 1); |
| }, |
| |
| 'even': function(node){ |
| return this['pseudo:nth-child'](node, '2n'); |
| }, |
| |
| 'odd': function(node){ |
| return this['pseudo:nth-child'](node, '2n+1'); |
| }, |
| |
| /*</nth-pseudo-selectors>*/ |
| |
| /*<of-type-pseudo-selectors>*/ |
| |
| 'first-of-type': function(node){ |
| var nodeName = node.nodeName; |
| while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; |
| return true; |
| }, |
| |
| 'last-of-type': function(node){ |
| var nodeName = node.nodeName; |
| while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; |
| return true; |
| }, |
| |
| 'only-of-type': function(node){ |
| var prev = node, nodeName = node.nodeName; |
| while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; |
| var next = node; |
| while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; |
| return true; |
| }, |
| |
| /*</of-type-pseudo-selectors>*/ |
| |
| // custom pseudos |
| |
| 'enabled': function(node){ |
| return !node.disabled; |
| }, |
| |
| 'disabled': function(node){ |
| return node.disabled; |
| }, |
| |
| 'checked': function(node){ |
| return node.checked || node.selected; |
| }, |
| |
| 'focus': function(node){ |
| return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); |
| }, |
| |
| 'root': function(node){ |
| return (node === this.root); |
| }, |
| |
| 'selected': function(node){ |
| return node.selected; |
| } |
| |
| /*</pseudo-selectors>*/ |
| }; |
| |
| for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; |
| |
| // attributes methods |
| |
| local.attributeGetters = { |
| |
| 'class': function(){ |
| return this.getAttribute('class') || this.className; |
| }, |
| |
| 'for': function(){ |
| return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); |
| }, |
| |
| 'href': function(){ |
| return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); |
| }, |
| |
| 'style': function(){ |
| return (this.style) ? this.style.cssText : this.getAttribute('style'); |
| }, |
| |
| 'tabindex': function(){ |
| var attributeNode = this.getAttributeNode('tabindex'); |
| return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; |
| }, |
| |
| 'type': function(){ |
| return this.getAttribute('type'); |
| } |
| |
| }; |
| |
| // Slick |
| |
| var Slick = local.Slick = (this.Slick || {}); |
| |
| Slick.version = '1.1.5'; |
| |
| // Slick finder |
| |
| Slick.search = function(context, expression, append){ |
| return local.search(context, expression, append); |
| }; |
| |
| Slick.find = function(context, expression){ |
| return local.search(context, expression, null, true); |
| }; |
| |
| // Slick containment checker |
| |
| Slick.contains = function(container, node){ |
| local.setDocument(container); |
| return local.contains(container, node); |
| }; |
| |
| // Slick attribute getter |
| |
| Slick.getAttribute = function(node, name){ |
| return local.getAttribute(node, name); |
| }; |
| |
| // Slick matcher |
| |
| Slick.match = function(node, selector){ |
| if (!(node && selector)) return false; |
| if (!selector || selector === node) return true; |
| local.setDocument(node); |
| return local.matchNode(node, selector); |
| }; |
| |
| // Slick attribute accessor |
| |
| Slick.defineAttributeGetter = function(name, fn){ |
| local.attributeGetters[name] = fn; |
| return this; |
| }; |
| |
| Slick.lookupAttributeGetter = function(name){ |
| return local.attributeGetters[name]; |
| }; |
| |
| // Slick pseudo accessor |
| |
| Slick.definePseudo = function(name, fn){ |
| local['pseudo:' + name] = function(node, argument){ |
| return fn.call(node, argument); |
| }; |
| return this; |
| }; |
| |
| Slick.lookupPseudo = function(name){ |
| var pseudo = local['pseudo:' + name]; |
| if (pseudo) return function(argument){ |
| return pseudo.call(this, argument); |
| }; |
| return null; |
| }; |
| |
| // Slick overrides accessor |
| |
| Slick.override = function(regexp, fn){ |
| local.override(regexp, fn); |
| return this; |
| }; |
| |
| Slick.isXML = local.isXML; |
| |
| Slick.uidOf = function(node){ |
| return local.getUIDHTML(node); |
| }; |
| |
| if (!this.Slick) this.Slick = Slick; |
| |
| }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this); |
| |
| |
| /* |
| --- |
| |
| name: Element |
| |
| description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. |
| |
| license: MIT-style license. |
| |
| requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder] |
| |
| provides: [Element, Elements, $, $$, Iframe, Selectors] |
| |
| ... |
| */ |
| |
| var Element = function(tag, props){ |
| var konstructor = Element.Constructors[tag]; |
| if (konstructor) return konstructor(props); |
| if (typeof tag != 'string') return document.id(tag).set(props); |
| |
| if (!props) props = {}; |
| |
| if (!(/^[\w-]+$/).test(tag)){ |
| var parsed = Slick.parse(tag).expressions[0][0]; |
| tag = (parsed.tag == '*') ? 'div' : parsed.tag; |
| if (parsed.id && props.id == null) props.id = parsed.id; |
| |
| var attributes = parsed.attributes; |
| if (attributes) for (var i = 0, l = attributes.length; i < l; i++){ |
| var attr = attributes[i]; |
| if (props[attr.key] != null) continue; |
| |
| if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; |
| else if (!attr.value && !attr.operator) props[attr.key] = true; |
| } |
| |
| if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); |
| } |
| |
| return document.newElement(tag, props); |
| }; |
| |
| if (Browser.Element) Element.prototype = Browser.Element.prototype; |
| |
| new Type('Element', Element).mirror(function(name){ |
| if (Array.prototype[name]) return; |
| |
| var obj = {}; |
| obj[name] = function(){ |
| var results = [], args = arguments, elements = true; |
| for (var i = 0, l = this.length; i < l; i++){ |
| var element = this[i], result = results[i] = element[name].apply(element, args); |
| elements = (elements && typeOf(result) == 'element'); |
| } |
| return (elements) ? new Elements(results) : results; |
| }; |
| |
| Elements.implement(obj); |
| }); |
| |
| if (!Browser.Element){ |
| Element.parent = Object; |
| |
| Element.Prototype = {'$family': Function.from('element').hide()}; |
| |
| Element.mirror(function(name, method){ |
| Element.Prototype[name] = method; |
| }); |
| } |
| |
| Element.Constructors = {}; |
| |
| //<1.2compat> |
| |
| Element.Constructors = new Hash; |
| |
| //</1.2compat> |
| |
| var IFrame = new Type('IFrame', function(){ |
| var params = Array.link(arguments, { |
| properties: Type.isObject, |
| iframe: function(obj){ |
| return (obj != null); |
| } |
| }); |
| |
| var props = params.properties || {}, iframe; |
| if (params.iframe) iframe = document.id(params.iframe); |
| var onload = props.onload || function(){}; |
| delete props.onload; |
| props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); |
| iframe = new Element(iframe || 'iframe', props); |
| |
| var onLoad = function(){ |
| onload.call(iframe.contentWindow); |
| }; |
| |
| if (window.frames[props.id]) onLoad(); |
| else iframe.addListener('load', onLoad); |
| return iframe; |
| }); |
| |
| var Elements = this.Elements = function(nodes){ |
| if (nodes && nodes.length){ |
| var uniques = {}, node; |
| for (var i = 0; node = nodes[i++];){ |
| var uid = Slick.uidOf(node); |
| if (!uniques[uid]){ |
| uniques[uid] = true; |
| this.push(node); |
| } |
| } |
| } |
| }; |
| |
| Elements.prototype = {length: 0}; |
| Elements.parent = Array; |
| |
| new Type('Elements', Elements).implement({ |
| |
| filter: function(filter, bind){ |
| if (!filter) return this; |
| return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ |
| return item.match(filter); |
| } : filter, bind)); |
| }.protect(), |
| |
| push: function(){ |
| var length = this.length; |
| for (var i = 0, l = arguments.length; i < l; i++){ |
| var item = document.id(arguments[i]); |
| if (item) this[length++] = item; |
| } |
| return (this.length = length); |
| }.protect(), |
| |
| unshift: function(){ |
| var items = []; |
| for (var i = 0, l = arguments.length; i < l; i++){ |
| var item = document.id(arguments[i]); |
| if (item) items.push(item); |
| } |
| return Array.prototype.unshift.apply(this, items); |
| }.protect(), |
| |
| concat: function(){ |
| var newElements = new Elements(this); |
| for (var i = 0, l = arguments.length; i < l; i++){ |
| var item = arguments[i]; |
| if (Type.isEnumerable(item)) newElements.append(item); |
| else newElements.push(item); |
| } |
| return newElements; |
| }.protect(), |
| |
| append: function(collection){ |
| for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); |
| return this; |
| }.protect(), |
| |
| empty: function(){ |
| while (this.length) delete this[--this.length]; |
| return this; |
| }.protect() |
| |
| }); |
| |
| //<1.2compat> |
| |
| Elements.alias('extend', 'append'); |
| |
| //</1.2compat> |
| |
| (function(){ |
| |
| // FF, IE |
| var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; |
| |
| splice.call(object, 1, 1); |
| if (object[1] == 1) Elements.implement('splice', function(){ |
| var length = this.length; |
| splice.apply(this, arguments); |
| while (length >= this.length) delete this[length--]; |
| return this; |
| }.protect()); |
| |
| Elements.implement(Array.prototype); |
| |
| Array.mirror(Elements); |
| |
| /*<ltIE8>*/ |
| var createElementAcceptsHTML; |
| try { |
| var x = document.createElement('<input name=x>'); |
| createElementAcceptsHTML = (x.name == 'x'); |
| } catch(e){} |
| |
| var escapeQuotes = function(html){ |
| return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); |
| }; |
| /*</ltIE8>*/ |
| |
| Document.implement({ |
| |
| newElement: function(tag, props){ |
| if (props && props.checked != null) props.defaultChecked = props.checked; |
| /*<ltIE8>*/// Fix for readonly name and type properties in IE < 8 |
| if (createElementAcceptsHTML && props){ |
| tag = '<' + tag; |
| if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; |
| if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; |
| tag += '>'; |
| delete props.name; |
| delete props.type; |
| } |
| /*</ltIE8>*/ |
| return this.id(this.createElement(tag)).set(props); |
| } |
| |
| }); |
| |
| })(); |
| |
| Document.implement({ |
| |
| newTextNode: function(text){ |
| return this.createTextNode(text); |
| }, |
| |
| getDocument: function(){ |
| return this; |
| }, |
| |
| getWindow: function(){ |
| return this.window; |
| }, |
| |
| id: (function(){ |
| |
| var types = { |
| |
| string: function(id, nocash, doc){ |
| id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); |
| return (id) ? types.element(id, nocash) : null; |
| }, |
| |
| element: function(el, nocash){ |
| $uid(el); |
| if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ |
| Object.append(el, Element.Prototype); |
| } |
| return el; |
| }, |
| |
| object: function(obj, nocash, doc){ |
| if (obj.toElement) return types.element(obj.toElement(doc), nocash); |
| return null; |
| } |
| |
| }; |
| |
| types.textnode = types.whitespace = types.window = types.document = function(zero){ |
| return zero; |
| }; |
| |
| return function(el, nocash, doc){ |
| if (el && el.$family && el.uid) return el; |
| var type = typeOf(el); |
| return (types[type]) ? types[type](el, nocash, doc || document) : null; |
| }; |
| |
| })() |
| |
| }); |
| |
| if (window.$ == null) Window.implement('$', function(el, nc){ |
| return document.id(el, nc, this.document); |
| }); |
| |
| Window.implement({ |
| |
| getDocument: function(){ |
| return this.document; |
| }, |
| |
| getWindow: function(){ |
| return this; |
| } |
| |
| }); |
| |
| [Document, Element].invoke('implement', { |
| |
| getElements: function(expression){ |
| return Slick.search(this, expression, new Elements); |
| }, |
| |
| getElement: function(expression){ |
| return document.id(Slick.find(this, expression)); |
| } |
| |
| }); |
| |
| //<1.2compat> |
| |
| (function(search, find, match){ |
| |
| this.Selectors = {}; |
| var pseudos = this.Selectors.Pseudo = new Hash(); |
| |
| var addSlickPseudos = function(){ |
| for (var name in pseudos) if (pseudos.hasOwnProperty(name)){ |
| Slick.definePseudo(name, pseudos[name]); |
| delete pseudos[name]; |
| } |
| }; |
| |
| Slick.search = function(context, expression, append){ |
| addSlickPseudos(); |
| return search.call(this, context, expression, append); |
| }; |
| |
| Slick.find = function(context, expression){ |
| addSlickPseudos(); |
| return find.call(this, context, expression); |
| }; |
| |
| Slick.match = function(node, selector){ |
| addSlickPseudos(); |
| return match.call(this, node, selector); |
| }; |
| |
| })(Slick.search, Slick.find, Slick.match); |
| |
| if (window.$$ == null) Window.implement('$$', function(selector){ |
| var elements = new Elements; |
| if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements); |
| var args = Array.flatten(arguments); |
| for (var i = 0, l = args.length; i < l; i++){ |
| var item = args[i]; |
| switch (typeOf(item)){ |
| case 'element': elements.push(item); break; |
| case 'string': Slick.search(this.document, item, elements); |
| } |
| } |
| return elements; |
| }); |
| |
| //</1.2compat> |
| |
| if (window.$$ == null) Window.implement('$$', function(selector){ |
| if (arguments.length == 1){ |
| if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); |
| else if (Type.isEnumerable(selector)) return new Elements(selector); |
| } |
| return new Elements(arguments); |
| }); |
| |
| (function(){ |
| |
| var collected = {}, storage = {}; |
| var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; |
| |
| var get = function(uid){ |
| return (storage[uid] || (storage[uid] = {})); |
| }; |
| |
| var clean = function(item){ |
| var uid = item.uid; |
| if (item.removeEvents) item.removeEvents(); |
| if (item.clearAttributes) item.clearAttributes(); |
| if (uid != null){ |
| delete collected[uid]; |
| delete storage[uid]; |
| } |
| return item; |
| }; |
| |
| var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', |
| 'rowSpan', 'tabIndex', 'useMap' |
| ]; |
| var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', |
| 'noresize', 'defer', 'defaultChecked' |
| ]; |
| var attributes = { |
| 'html': 'innerHTML', |
| 'class': 'className', |
| 'for': 'htmlFor', |
| 'text': (function(){ |
| var temp = document.createElement('div'); |
| return (temp.textContent == null) ? 'innerText' : 'textContent'; |
| })() |
| }; |
| var readOnly = ['type']; |
| var expandos = ['value', 'defaultValue']; |
| var uriAttrs = /^(?:href|src|usemap)$/i; |
| |
| bools = bools.associate(bools); |
| camels = camels.associate(camels.map(String.toLowerCase)); |
| readOnly = readOnly.associate(readOnly); |
| |
| Object.append(attributes, expandos.associate(expandos)); |
| |
| var inserters = { |
| |
| before: function(context, element){ |
| var parent = element.parentNode; |
| if (parent) parent.insertBefore(context, element); |
| }, |
| |
| after: function(context, element){ |
| var parent = element.parentNode; |
| if (parent) parent.insertBefore(context, element.nextSibling); |
| }, |
| |
| bottom: function(context, element){ |
| element.appendChild(context); |
| }, |
| |
| top: function(context, element){ |
| element.insertBefore(context, element.firstChild); |
| } |
| |
| }; |
| |
| inserters.inside = inserters.bottom; |
| |
| //<1.2compat> |
| |
| Object.each(inserters, function(inserter, where){ |
| |
| where = where.capitalize(); |
| |
| var methods = {}; |
| |
| methods['inject' + where] = function(el){ |
| inserter(this, document.id(el, true)); |
| return this; |
| }; |
| |
| methods['grab' + where] = function(el){ |
| inserter(document.id(el, true), this); |
| return this; |
| }; |
| |
| Element.implement(methods); |
| |
| }); |
| |
| //</1.2compat> |
| |
| var injectCombinator = function(expression, combinator){ |
| if (!expression) return combinator; |
| |
| expression = Object.clone(Slick.parse(expression)); |
| |
| var expressions = expression.expressions; |
| for (var i = expressions.length; i--;) |
| expressions[i][0].combinator = combinator; |
| |
| return expression; |
| }; |
| |
| Element.implement({ |
| |
| set: function(prop, value){ |
| var property = Element.Properties[prop]; |
| (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); |
| }.overloadSetter(), |
| |
| get: function(prop){ |
| var property = Element.Properties[prop]; |
| return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); |
| }.overloadGetter(), |
| |
| erase: function(prop){ |
| var property = Element.Properties[prop]; |
| (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); |
| return this; |
| }, |
| |
| setProperty: function(attribute, value){ |
| attribute = camels[attribute] || attribute; |
| if (value == null) return this.removeProperty(attribute); |
| var key = attributes[attribute]; |
| (key) ? this[key] = value : |
| (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value); |
| return this; |
| }, |
| |
| setProperties: function(attributes){ |
| for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); |
| return this; |
| }, |
| |
| getProperty: function(attribute){ |
| attribute = camels[attribute] || attribute; |
| var key = attributes[attribute] || readOnly[attribute]; |
| return (key) ? this[key] : |
| (bools[attribute]) ? !!this[attribute] : |
| (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) : |
| (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null; |
| }, |
| |
| getProperties: function(){ |
| var args = Array.from(arguments); |
| return args.map(this.getProperty, this).associate(args); |
| }, |
| |
| removeProperty: function(attribute){ |
| attribute = camels[attribute] || attribute; |
| var key = attributes[attribute]; |
| (key) ? this[key] = '' : |
| (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute); |
| return this; |
| }, |
| |
| removeProperties: function(){ |
| Array.each(arguments, this.removeProperty, this); |
| return this; |
| }, |
| |
| hasClass: function(className){ |
| return this.className.clean().contains(className, ' '); |
| }, |
| |
| addClass: function(className){ |
| if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); |
| return this; |
| }, |
| |
| removeClass: function(className){ |
| this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); |
| return this; |
| }, |
| |
| toggleClass: function(className, force){ |
| if (force == null) force = !this.hasClass(className); |
| return (force) ? this.addClass(className) : this.removeClass(className); |
| }, |
| |
| adopt: function(){ |
| var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; |
| if (length > 1) parent = fragment = document.createDocumentFragment(); |
| |
| for (var i = 0; i < length; i++){ |
| var element = document.id(elements[i], true); |
| if (element) parent.appendChild(element); |
| } |
| |
| if (fragment) this.appendChild(fragment); |
| |
| return this; |
| }, |
| |
| appendText: function(text, where){ |
| return this.grab(this.getDocument().newTextNode(text), where); |
| }, |
| |
| grab: function(el, where){ |
| inserters[where || 'bottom'](document.id(el, true), this); |
| return this; |
| }, |
| |
| inject: function(el, where){ |
| inserters[where || 'bottom'](this, document.id(el, true)); |
| return this; |
| }, |
| |
| replaces: function(el){ |
| el = document.id(el, true); |
| el.parentNode.replaceChild(this, el); |
| return this; |
| }, |
| |
| wraps: function(el, where){ |
| el = document.id(el, true); |
| return this.replaces(el).grab(el, where); |
| }, |
| |
| getPrevious: function(expression){ |
| return document.id(Slick.find(this, injectCombinator(expression, '!~'))); |
| }, |
| |
| getAllPrevious: function(expression){ |
| return Slick.search(this, injectCombinator(expression, '!~'), new Elements); |
| }, |
| |
| getNext: function(expression){ |
| return document.id(Slick.find(this, injectCombinator(expression, '~'))); |
| }, |
| |
| getAllNext: function(expression){ |
| return Slick.search(this, injectCombinator(expression, '~'), new Elements); |
| }, |
| |
| getFirst: function(expression){ |
| return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); |
| }, |
| |
| getLast: function(expression){ |
| return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); |
| }, |
| |
| getParent: function(expression){ |
| return document.id(Slick.find(this, injectCombinator(expression, '!'))); |
| }, |
| |
| getParents: function(expression){ |
| return Slick.search(this, injectCombinator(expression, '!'), new Elements); |
| }, |
| |
| getSiblings: function(expression){ |
| return Slick.search(this, injectCombinator(expression, '~~'), new Elements); |
| }, |
| |
| getChildren: function(expression){ |
| return Slick.search(this, injectCombinator(expression, '>'), new Elements); |
| }, |
| |
| getWindow: function(){ |
| return this.ownerDocument.window; |
| }, |
| |
| getDocument: function(){ |
| return this.ownerDocument; |
| }, |
| |
| getElementById: function(id){ |
| return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); |
| }, |
| |
| getSelected: function(){ |
| this.selectedIndex; // Safari 3.2.1 |
| return new Elements(Array.from(this.options).filter(function(option){ |
| return option.selected; |
| })); |
| }, |
| |
| toQueryString: function(){ |
| var queryString = []; |
| this.getElements('input, select, textarea').each(function(el){ |
| var type = el.type; |
| if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; |
| |
| var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ |
| // IE |
| return document.id(opt).get('value'); |
| }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); |
| |
| Array.from(value).each(function(val){ |
| if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); |
| }); |
| }); |
| return queryString.join('&'); |
| }, |
| |
| destroy: function(){ |
| var children = clean(this).getElementsByTagName('*'); |
| Array.each(children, clean); |
| Element.dispose(this); |
| return null; |
| }, |
| |
| empty: function(){ |
| Array.from(this.childNodes).each(Element.dispose); |
| return this; |
| }, |
| |
| dispose: function(){ |
| return (this.parentNode) ? this.parentNode.removeChild(this) : this; |
| }, |
| |
| match: function(expression){ |
| return !expression || Slick.match(this, expression); |
| } |
| |
| }); |
| |
| var cleanClone = function(node, element, keepid){ |
| if (!keepid) node.setAttributeNode(document.createAttribute('id')); |
| if (node.clearAttributes){ |
| node.clearAttributes(); |
| node.mergeAttributes(element); |
| node.removeAttribute('uid'); |
| if (node.options){ |
| var no = node.options, eo = element.options; |
| for (var i = no.length; i--;) no[i].selected = eo[i].selected; |
| } |
| } |
| |
| var prop = formProps[element.tagName.toLowerCase()]; |
| if (prop && element[prop]) node[prop] = element[prop]; |
| }; |
| |
| Element.implement('clone', function(contents, keepid){ |
| contents = contents !== false; |
| var clone = this.cloneNode(contents), i; |
| |
| if (contents){ |
| var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); |
| for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid); |
| } |
| |
| cleanClone(clone, this, keepid); |
| |
| if (Browser.ie){ |
| var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); |
| for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; |
| } |
| return document.id(clone); |
| }); |
| |
| var contains = {contains: function(element){ |
| return Slick.contains(this, element); |
| }}; |
| |
| if (!document.contains) Document.implement(contains); |
| if (!document.createElement('div').contains) Element.implement(contains); |
| |
| //<1.2compat> |
| |
| Element.implement('hasChild', function(element){ |
| return this !== element && this.contains(element); |
| }); |
| |
| //</1.2compat> |
| |
| [Element, Window, Document].invoke('implement', { |
| |
| addListener: function(type, fn){ |
| if (type == 'unload'){ |
| var old = fn, self = this; |
| fn = function(){ |
| self.removeListener('unload', fn); |
| old(); |
| }; |
| } else { |
| collected[$uid(this)] = this; |
| } |
| if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); |
| else this.attachEvent('on' + type, fn); |
| return this; |
| }, |
| |
| removeListener: function(type, fn){ |
| if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); |
| else this.detachEvent('on' + type, fn); |
| return this; |
| }, |
| |
| retrieve: function(property, dflt){ |
| var storage = get($uid(this)), prop = storage[property]; |
| if (dflt != null && prop == null) prop = storage[property] = dflt; |
| return prop != null ? prop : null; |
| }, |
| |
| store: function(property, value){ |
| var storage = get($uid(this)); |
| storage[property] = value; |
| return this; |
| }, |
| |
| eliminate: function(property){ |
| var storage = get($uid(this)); |
| delete storage[property]; |
| return this; |
| } |
| |
| }); |
| |
| /*<ltIE9>*/ |
| if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){ |
| Object.each(collected, clean); |
| if (window.CollectGarbage) CollectGarbage(); |
| }); |
| /*</ltIE9>*/ |
| |
| })(); |
| |
| Element.Properties = {}; |
| |
| //<1.2compat> |
| |
| Element.Properties = new Hash; |
| |
| //</1.2compat> |
| |
| Element.Properties.style = { |
| |
| set: function(style){ |
| this.style.cssText = style; |
| }, |
| |
| get: function(){ |
| return this.style.cssText; |
| }, |
| |
| erase: function(){ |
| this.style.cssText = ''; |
| } |
| |
| }; |
| |
| Element.Properties.tag = { |
| |
| get: function(){ |
| return this.tagName.toLowerCase(); |
| } |
| |
| }; |
| |
| /*<ltIE9>*/ |
| (function(maxLength){ |
| if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = { |
| get: function(){ |
| var maxlength = this.getAttribute('maxLength'); |
| return maxlength == maxLength ? null : maxlength; |
| } |
| }; |
| })(document.createElement('input').getAttribute('maxLength')); |
| /*</ltIE9>*/ |
| |
| /*<!webkit>*/ |
| Element.Properties.html = (function(){ |
| |
| var tableTest = Function.attempt(function(){ |
| var table = document.createElement('table'); |
| table.innerHTML = '<tr><td></td></tr>'; |
| }); |
| |
| var wrapper = document.createElement('div'); |
| |
| var translations = { |
| table: [1, '<table>', '</table>'], |
| select: [1, '<select>', '</select>'], |
| tbody: [2, '<table><tbody>', '</tbody></table>'], |
| tr: [3, '<table><tbody><tr>', '</tr></tbody></table>'] |
| }; |
| translations.thead = translations.tfoot = translations.tbody; |
| |
| var html = { |
| set: function(){ |
| var html = Array.flatten(arguments).join(''); |
| var wrap = (!tableTest && translations[this.get('tag')]); |
| if (wrap){ |
| var first = wrapper; |
| first.innerHTML = wrap[1] + html + wrap[2]; |
| for (var i = wrap[0]; i--;) first = first.firstChild; |
| this.empty().adopt(first.childNodes); |
| } else { |
| this.innerHTML = html; |
| } |
| } |
| }; |
| |
| html.erase = html.set; |
| |
| return html; |
| })(); |
| /*</!webkit>*/ |
| |
| |
| /* |
| --- |
| |
| name: Element.Style |
| |
| description: Contains methods for interacting with the styles of Elements in a fashionable way. |
| |
| license: MIT-style license. |
| |
| requires: Element |
| |
| provides: Element.Style |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var html = document.html; |
| |
| Element.Properties.styles = {set: function(styles){ |
| this.setStyles(styles); |
| }}; |
| |
| var hasOpacity = (html.style.opacity != null); |
| var reAlpha = /alpha\(opacity=([\d.]+)\)/i; |
| |
| var setOpacity = function(element, opacity){ |
| if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; |
| if (hasOpacity){ |
| element.style.opacity = opacity; |
| } else { |
| opacity = (opacity * 100).limit(0, 100).round(); |
| opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; |
| var filter = element.style.filter || element.getComputedStyle('filter') || ''; |
| element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; |
| } |
| }; |
| |
| Element.Properties.opacity = { |
| |
| set: function(opacity){ |
| var visibility = this.style.visibility; |
| if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden'; |
| else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible'; |
| |
| setOpacity(this, opacity); |
| }, |
| |
| get: (hasOpacity) ? function(){ |
| var opacity = this.style.opacity || this.getComputedStyle('opacity'); |
| return (opacity == '') ? 1 : opacity; |
| } : function(){ |
| var opacity, filter = (this.style.filter || this.getComputedStyle('filter')); |
| if (filter) opacity = filter.match(reAlpha); |
| return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); |
| } |
| |
| }; |
| |
| var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat'; |
| |
| Element.implement({ |
| |
| getComputedStyle: function(property){ |
| if (this.currentStyle) return this.currentStyle[property.camelCase()]; |
| var defaultView = Element.getDocument(this).defaultView, |
| computed = defaultView ? defaultView.getComputedStyle(this, null) : null; |
| return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null; |
| }, |
| |
| setOpacity: function(value){ |
| setOpacity(this, value); |
| return this; |
| }, |
| |
| getOpacity: function(){ |
| return this.get('opacity'); |
| }, |
| |
| setStyle: function(property, value){ |
| switch (property){ |
| case 'opacity': return this.set('opacity', parseFloat(value)); |
| case 'float': property = floatName; |
| } |
| property = property.camelCase(); |
| if (typeOf(value) != 'string'){ |
| var map = (Element.Styles[property] || '@').split(' '); |
| value = Array.from(value).map(function(val, i){ |
| if (!map[i]) return ''; |
| return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; |
| }).join(' '); |
| } else if (value == String(Number(value))){ |
| value = Math.round(value); |
| } |
| this.style[property] = value; |
| return this; |
| }, |
| |
| getStyle: function(property){ |
| switch (property){ |
| case 'opacity': return this.get('opacity'); |
| case 'float': property = floatName; |
| } |
| property = property.camelCase(); |
| var result = this.style[property]; |
| if (!result || property == 'zIndex'){ |
| result = []; |
| for (var style in Element.ShortStyles){ |
| if (property != style) continue; |
| for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); |
| return result.join(' '); |
| } |
| result = this.getComputedStyle(property); |
| } |
| if (result){ |
| result = String(result); |
| var color = result.match(/rgba?\([\d\s,]+\)/); |
| if (color) result = result.replace(color[0], color[0].rgbToHex()); |
| } |
| if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){ |
| if ((/^(height|width)$/).test(property)){ |
| var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; |
| values.each(function(value){ |
| size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); |
| }, this); |
| return this['offset' + property.capitalize()] - size + 'px'; |
| } |
| if (Browser.opera && String(result).indexOf('px') != -1) return result; |
| if ((/^border(.+)Width|margin|padding/).test(property)) return '0px'; |
| } |
| return result; |
| }, |
| |
| setStyles: function(styles){ |
| for (var style in styles) this.setStyle(style, styles[style]); |
| return this; |
| }, |
| |
| getStyles: function(){ |
| var result = {}; |
| Array.flatten(arguments).each(function(key){ |
| result[key] = this.getStyle(key); |
| }, this); |
| return result; |
| } |
| |
| }); |
| |
| Element.Styles = { |
| left: '@px', top: '@px', bottom: '@px', right: '@px', |
| width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', |
| backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', |
| fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', |
| margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', |
| borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', |
| zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' |
| }; |
| |
| //<1.2compat> |
| |
| Element.Styles = new Hash(Element.Styles); |
| |
| //</1.2compat> |
| |
| Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; |
| |
| ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ |
| var Short = Element.ShortStyles; |
| var All = Element.Styles; |
| ['margin', 'padding'].each(function(style){ |
| var sd = style + direction; |
| Short[style][sd] = All[sd] = '@px'; |
| }); |
| var bd = 'border' + direction; |
| Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; |
| var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; |
| Short[bd] = {}; |
| Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; |
| Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; |
| Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; |
| }); |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| name: Element.Event |
| |
| description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events. |
| |
| license: MIT-style license. |
| |
| requires: [Element, Event] |
| |
| provides: Element.Event |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| Element.Properties.events = {set: function(events){ |
| this.addEvents(events); |
| }}; |
| |
| [Element, Window, Document].invoke('implement', { |
| |
| addEvent: function(type, fn){ |
| var events = this.retrieve('events', {}); |
| if (!events[type]) events[type] = {keys: [], values: []}; |
| if (events[type].keys.contains(fn)) return this; |
| events[type].keys.push(fn); |
| var realType = type, |
| custom = Element.Events[type], |
| condition = fn, |
| self = this; |
| if (custom){ |
| if (custom.onAdd) custom.onAdd.call(this, fn); |
| if (custom.condition){ |
| condition = function(event){ |
| if (custom.condition.call(this, event)) return fn.call(this, event); |
| return true; |
| }; |
| } |
| realType = custom.base || realType; |
| } |
| var defn = function(){ |
| return fn.call(self); |
| }; |
| var nativeEvent = Element.NativeEvents[realType]; |
| if (nativeEvent){ |
| if (nativeEvent == 2){ |
| defn = function(event){ |
| event = new Event(event, self.getWindow()); |
| if (condition.call(self, event) === false) event.stop(); |
| }; |
| } |
| this.addListener(realType, defn, arguments[2]); |
| } |
| events[type].values.push(defn); |
| return this; |
| }, |
| |
| removeEvent: function(type, fn){ |
| var events = this.retrieve('events'); |
| if (!events || !events[type]) return this; |
| var list = events[type]; |
| var index = list.keys.indexOf(fn); |
| if (index == -1) return this; |
| var value = list.values[index]; |
| delete list.keys[index]; |
| delete list.values[index]; |
| var custom = Element.Events[type]; |
| if (custom){ |
| if (custom.onRemove) custom.onRemove.call(this, fn); |
| type = custom.base || type; |
| } |
| return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; |
| }, |
| |
| addEvents: function(events){ |
| for (var event in events) this.addEvent(event, events[event]); |
| return this; |
| }, |
| |
| removeEvents: function(events){ |
| var type; |
| if (typeOf(events) == 'object'){ |
| for (type in events) this.removeEvent(type, events[type]); |
| return this; |
| } |
| var attached = this.retrieve('events'); |
| if (!attached) return this; |
| if (!events){ |
| for (type in attached) this.removeEvents(type); |
| this.eliminate('events'); |
| } else if (attached[events]){ |
| attached[events].keys.each(function(fn){ |
| this.removeEvent(events, fn); |
| }, this); |
| delete attached[events]; |
| } |
| return this; |
| }, |
| |
| fireEvent: function(type, args, delay){ |
| var events = this.retrieve('events'); |
| if (!events || !events[type]) return this; |
| args = Array.from(args); |
| |
| events[type].keys.each(function(fn){ |
| if (delay) fn.delay(delay, this, args); |
| else fn.apply(this, args); |
| }, this); |
| return this; |
| }, |
| |
| cloneEvents: function(from, type){ |
| from = document.id(from); |
| var events = from.retrieve('events'); |
| if (!events) return this; |
| if (!type){ |
| for (var eventType in events) this.cloneEvents(from, eventType); |
| } else if (events[type]){ |
| events[type].keys.each(function(fn){ |
| this.addEvent(type, fn); |
| }, this); |
| } |
| return this; |
| } |
| |
| }); |
| |
| Element.NativeEvents = { |
| click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons |
| mousewheel: 2, DOMMouseScroll: 2, //mouse wheel |
| mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement |
| keydown: 2, keypress: 2, keyup: 2, //keyboard |
| orientationchange: 2, // mobile |
| touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch |
| gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture |
| focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements |
| load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window |
| error: 1, abort: 1, scroll: 1 //misc |
| }; |
| |
| var check = function(event){ |
| var related = event.relatedTarget; |
| if (related == null) return true; |
| if (!related) return false; |
| return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); |
| }; |
| |
| Element.Events = { |
| |
| mouseenter: { |
| base: 'mouseover', |
| condition: check |
| }, |
| |
| mouseleave: { |
| base: 'mouseout', |
| condition: check |
| }, |
| |
| mousewheel: { |
| base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel' |
| } |
| |
| }; |
| |
| //<1.2compat> |
| |
| Element.Events = new Hash(Element.Events); |
| |
| //</1.2compat> |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| name: Element.Dimensions |
| |
| description: Contains methods to work with size, scroll, or positioning of Elements and the window object. |
| |
| license: MIT-style license. |
| |
| credits: |
| - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). |
| - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). |
| |
| requires: [Element, Element.Style] |
| |
| provides: [Element.Dimensions] |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var element = document.createElement('div'), |
| child = document.createElement('div'); |
| element.style.height = '0'; |
| element.appendChild(child); |
| var brokenOffsetParent = (child.offsetParent === element); |
| element = child = null; |
| |
| var isOffset = function(el){ |
| return styleString(el, 'position') != 'static' || isBody(el); |
| }; |
| |
| var isOffsetStatic = function(el){ |
| return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); |
| }; |
| |
| Element.implement({ |
| |
| scrollTo: function(x, y){ |
| if (isBody(this)){ |
| this.getWindow().scrollTo(x, y); |
| } else { |
| this.scrollLeft = x; |
| this.scrollTop = y; |
| } |
| return this; |
| }, |
| |
| getSize: function(){ |
| if (isBody(this)) return this.getWindow().getSize(); |
| return {x: this.offsetWidth, y: this.offsetHeight}; |
| }, |
| |
| getScrollSize: function(){ |
| if (isBody(this)) return this.getWindow().getScrollSize(); |
| return {x: this.scrollWidth, y: this.scrollHeight}; |
| }, |
| |
| getScroll: function(){ |
| if (isBody(this)) return this.getWindow().getScroll(); |
| return {x: this.scrollLeft, y: this.scrollTop}; |
| }, |
| |
| getScrolls: function(){ |
| var element = this.parentNode, position = {x: 0, y: 0}; |
| while (element && !isBody(element)){ |
| position.x += element.scrollLeft; |
| position.y += element.scrollTop; |
| element = element.parentNode; |
| } |
| return position; |
| }, |
| |
| getOffsetParent: brokenOffsetParent ? function(){ |
| var element = this; |
| if (isBody(element) || styleString(element, 'position') == 'fixed') return null; |
| |
| var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; |
| while ((element = element.parentNode)){ |
| if (isOffsetCheck(element)) return element; |
| } |
| return null; |
| } : function(){ |
| var element = this; |
| if (isBody(element) || styleString(element, 'position') == 'fixed') return null; |
| |
| try { |
| return element.offsetParent; |
| } catch(e) {} |
| return null; |
| }, |
| |
| getOffsets: function(){ |
| if (this.getBoundingClientRect && !Browser.Platform.ios){ |
| var bound = this.getBoundingClientRect(), |
| html = document.id(this.getDocument().documentElement), |
| htmlScroll = html.getScroll(), |
| elemScrolls = this.getScrolls(), |
| isFixed = (styleString(this, 'position') == 'fixed'); |
| |
| return { |
| x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, |
| y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop |
| }; |
| } |
| |
| var element = this, position = {x: 0, y: 0}; |
| if (isBody(this)) return position; |
| |
| while (element && !isBody(element)){ |
| position.x += element.offsetLeft; |
| position.y += element.offsetTop; |
| |
| if (Browser.firefox){ |
| if (!borderBox(element)){ |
| position.x += leftBorder(element); |
| position.y += topBorder(element); |
| } |
| var parent = element.parentNode; |
| if (parent && styleString(parent, 'overflow') != 'visible'){ |
| position.x += leftBorder(parent); |
| position.y += topBorder(parent); |
| } |
| } else if (element != this && Browser.safari){ |
| position.x += leftBorder(element); |
| position.y += topBorder(element); |
| } |
| |
| element = element.offsetParent; |
| } |
| if (Browser.firefox && !borderBox(this)){ |
| position.x -= leftBorder(this); |
| position.y -= topBorder(this); |
| } |
| return position; |
| }, |
| |
| getPosition: function(relative){ |
| if (isBody(this)) return {x: 0, y: 0}; |
| var offset = this.getOffsets(), |
| scroll = this.getScrolls(); |
| var position = { |
| x: offset.x - scroll.x, |
| y: offset.y - scroll.y |
| }; |
| |
| if (relative && (relative = document.id(relative))){ |
| var relativePosition = relative.getPosition(); |
| return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; |
| } |
| return position; |
| }, |
| |
| getCoordinates: function(element){ |
| if (isBody(this)) return this.getWindow().getCoordinates(); |
| var position = this.getPosition(element), |
| size = this.getSize(); |
| var obj = { |
| left: position.x, |
| top: position.y, |
| width: size.x, |
| height: size.y |
| }; |
| obj.right = obj.left + obj.width; |
| obj.bottom = obj.top + obj.height; |
| return obj; |
| }, |
| |
| computePosition: function(obj){ |
| return { |
| left: obj.x - styleNumber(this, 'margin-left'), |
| top: obj.y - styleNumber(this, 'margin-top') |
| }; |
| }, |
| |
| setPosition: function(obj){ |
| return this.setStyles(this.computePosition(obj)); |
| } |
| |
| }); |
| |
| |
| [Document, Window].invoke('implement', { |
| |
| getSize: function(){ |
| var doc = getCompatElement(this); |
| return {x: doc.clientWidth, y: doc.clientHeight}; |
| }, |
| |
| getScroll: function(){ |
| var win = this.getWindow(), doc = getCompatElement(this); |
| return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; |
| }, |
| |
| getScrollSize: function(){ |
| var doc = getCompatElement(this), |
| min = this.getSize(), |
| body = this.getDocument().body; |
| |
| return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; |
| }, |
| |
| getPosition: function(){ |
| return {x: 0, y: 0}; |
| }, |
| |
| getCoordinates: function(){ |
| var size = this.getSize(); |
| return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; |
| } |
| |
| }); |
| |
| // private methods |
| |
| var styleString = Element.getComputedStyle; |
| |
| function styleNumber(element, style){ |
| return styleString(element, style).toInt() || 0; |
| } |
| |
| function borderBox(element){ |
| return styleString(element, '-moz-box-sizing') == 'border-box'; |
| } |
| |
| function topBorder(element){ |
| return styleNumber(element, 'border-top-width'); |
| } |
| |
| function leftBorder(element){ |
| return styleNumber(element, 'border-left-width'); |
| } |
| |
| function isBody(element){ |
| return (/^(?:body|html)$/i).test(element.tagName); |
| } |
| |
| function getCompatElement(element){ |
| var doc = element.getDocument(); |
| return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; |
| } |
| |
| })(); |
| |
| //aliases |
| Element.alias({position: 'setPosition'}); //compatability |
| |
| [Window, Document, Element].invoke('implement', { |
| |
| getHeight: function(){ |
| return this.getSize().y; |
| }, |
| |
| getWidth: function(){ |
| return this.getSize().x; |
| }, |
| |
| getScrollTop: function(){ |
| return this.getScroll().y; |
| }, |
| |
| getScrollLeft: function(){ |
| return this.getScroll().x; |
| }, |
| |
| getScrollHeight: function(){ |
| return this.getScrollSize().y; |
| }, |
| |
| getScrollWidth: function(){ |
| return this.getScrollSize().x; |
| }, |
| |
| getTop: function(){ |
| return this.getPosition().y; |
| }, |
| |
| getLeft: function(){ |
| return this.getPosition().x; |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| name: Fx |
| |
| description: Contains the basic animation logic to be extended by all other Fx Classes. |
| |
| license: MIT-style license. |
| |
| requires: [Chain, Events, Options] |
| |
| provides: Fx |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var Fx = this.Fx = new Class({ |
| |
| Implements: [Chain, Events, Options], |
| |
| options: { |
| /* |
| onStart: nil, |
| onCancel: nil, |
| onComplete: nil, |
| */ |
| fps: 60, |
| unit: false, |
| duration: 500, |
| frames: null, |
| frameSkip: true, |
| link: 'ignore' |
| }, |
| |
| initialize: function(options){ |
| this.subject = this.subject || this; |
| this.setOptions(options); |
| }, |
| |
| getTransition: function(){ |
| return function(p){ |
| return -(Math.cos(Math.PI * p) - 1) / 2; |
| }; |
| }, |
| |
| step: function(now){ |
| if (this.options.frameSkip){ |
| var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; |
| this.time = now; |
| this.frame += frames; |
| } else { |
| this.frame++; |
| } |
| |
| if (this.frame < this.frames){ |
| var delta = this.transition(this.frame / this.frames); |
| this.set(this.compute(this.from, this.to, delta)); |
| } else { |
| this.frame = this.frames; |
| this.set(this.compute(this.from, this.to, 1)); |
| this.stop(); |
| } |
| }, |
| |
| set: function(now){ |
| return now; |
| }, |
| |
| compute: function(from, to, delta){ |
| return Fx.compute(from, to, delta); |
| }, |
| |
| check: function(){ |
| if (!this.isRunning()) return true; |
| switch (this.options.link){ |
| case 'cancel': this.cancel(); return true; |
| case 'chain': this.chain(this.caller.pass(arguments, this)); return false; |
| } |
| return false; |
| }, |
| |
| start: function(from, to){ |
| if (!this.check(from, to)) return this; |
| this.from = from; |
| this.to = to; |
| this.frame = (this.options.frameSkip) ? 0 : -1; |
| this.time = null; |
| this.transition = this.getTransition(); |
| var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; |
| this.duration = Fx.Durations[duration] || duration.toInt(); |
| this.frameInterval = 1000 / fps; |
| this.frames = frames || Math.round(this.duration / this.frameInterval); |
| this.fireEvent('start', this.subject); |
| pushInstance.call(this, fps); |
| return this; |
| }, |
| |
| stop: function(){ |
| if (this.isRunning()){ |
| this.time = null; |
| pullInstance.call(this, this.options.fps); |
| if (this.frames == this.frame){ |
| this.fireEvent('complete', this.subject); |
| if (!this.callChain()) this.fireEvent('chainComplete', this.subject); |
| } else { |
| this.fireEvent('stop', this.subject); |
| } |
| } |
| return this; |
| }, |
| |
| cancel: function(){ |
| if (this.isRunning()){ |
| this.time = null; |
| pullInstance.call(this, this.options.fps); |
| this.frame = this.frames; |
| this.fireEvent('cancel', this.subject).clearChain(); |
| } |
| return this; |
| }, |
| |
| pause: function(){ |
| if (this.isRunning()){ |
| this.time = null; |
| pullInstance.call(this, this.options.fps); |
| } |
| return this; |
| }, |
| |
| resume: function(){ |
| if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps); |
| return this; |
| }, |
| |
| isRunning: function(){ |
| var list = instances[this.options.fps]; |
| return list && list.contains(this); |
| } |
| |
| }); |
| |
| Fx.compute = function(from, to, delta){ |
| return (to - from) * delta + from; |
| }; |
| |
| Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; |
| |
| // global timers |
| |
| var instances = {}, timers = {}; |
| |
| var loop = function(){ |
| var now = Date.now(); |
| for (var i = this.length; i--;){ |
| var instance = this[i]; |
| if (instance) instance.step(now); |
| } |
| }; |
| |
| var pushInstance = function(fps){ |
| var list = instances[fps] || (instances[fps] = []); |
| list.push(this); |
| if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); |
| }; |
| |
| var pullInstance = function(fps){ |
| var list = instances[fps]; |
| if (list){ |
| list.erase(this); |
| if (!list.length && timers[fps]){ |
| delete instances[fps]; |
| timers[fps] = clearInterval(timers[fps]); |
| } |
| } |
| }; |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| name: Fx.CSS |
| |
| description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. |
| |
| license: MIT-style license. |
| |
| requires: [Fx, Element.Style] |
| |
| provides: Fx.CSS |
| |
| ... |
| */ |
| |
| Fx.CSS = new Class({ |
| |
| Extends: Fx, |
| |
| //prepares the base from/to object |
| |
| prepare: function(element, property, values){ |
| values = Array.from(values); |
| if (values[1] == null){ |
| values[1] = values[0]; |
| values[0] = element.getStyle(property); |
| } |
| var parsed = values.map(this.parse); |
| return {from: parsed[0], to: parsed[1]}; |
| }, |
| |
| //parses a value into an array |
| |
| parse: function(value){ |
| value = Function.from(value)(); |
| value = (typeof value == 'string') ? value.split(' ') : Array.from(value); |
| return value.map(function(val){ |
| val = String(val); |
| var found = false; |
| Object.each(Fx.CSS.Parsers, function(parser, key){ |
| if (found) return; |
| var parsed = parser.parse(val); |
| if (parsed || parsed === 0) found = {value: parsed, parser: parser}; |
| }); |
| found = found || {value: val, parser: Fx.CSS.Parsers.String}; |
| return found; |
| }); |
| }, |
| |
| //computes by a from and to prepared objects, using their parsers. |
| |
| compute: function(from, to, delta){ |
| var computed = []; |
| (Math.min(from.length, to.length)).times(function(i){ |
| computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); |
| }); |
| computed.$family = Function.from('fx:css:value'); |
| return computed; |
| }, |
| |
| //serves the value as settable |
| |
| serve: function(value, unit){ |
| if (typeOf(value) != 'fx:css:value') value = this.parse(value); |
| var returned = []; |
| value.each(function(bit){ |
| returned = returned.concat(bit.parser.serve(bit.value, unit)); |
| }); |
| return returned; |
| }, |
| |
| //renders the change to an element |
| |
| render: function(element, property, value, unit){ |
| element.setStyle(property, this.serve(value, unit)); |
| }, |
| |
| //searches inside the page css to find the values for a selector |
| |
| search: function(selector){ |
| if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; |
| var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); |
| Array.each(document.styleSheets, function(sheet, j){ |
| var href = sheet.href; |
| if (href && href.contains('://') && !href.contains(document.domain)) return; |
| var rules = sheet.rules || sheet.cssRules; |
| Array.each(rules, function(rule, i){ |
| if (!rule.style) return; |
| var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ |
| return m.toLowerCase(); |
| }) : null; |
| if (!selectorText || !selectorTest.test(selectorText)) return; |
| Object.each(Element.Styles, function(value, style){ |
| if (!rule.style[style] || Element.ShortStyles[style]) return; |
| value = String(rule.style[style]); |
| to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; |
| }); |
| }); |
| }); |
| return Fx.CSS.Cache[selector] = to; |
| } |
| |
| }); |
| |
| Fx.CSS.Cache = {}; |
| |
| Fx.CSS.Parsers = { |
| |
| Color: { |
| parse: function(value){ |
| if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); |
| return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; |
| }, |
| compute: function(from, to, delta){ |
| return from.map(function(value, i){ |
| return Math.round(Fx.compute(from[i], to[i], delta)); |
| }); |
| }, |
| serve: function(value){ |
| return value.map(Number); |
| } |
| }, |
| |
| Number: { |
| parse: parseFloat, |
| compute: Fx.compute, |
| serve: function(value, unit){ |
| return (unit) ? value + unit : value; |
| } |
| }, |
| |
| String: { |
| parse: Function.from(false), |
| compute: function(zero, one){ |
| return one; |
| }, |
| serve: function(zero){ |
| return zero; |
| } |
| } |
| |
| }; |
| |
| //<1.2compat> |
| |
| Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers); |
| |
| //</1.2compat> |
| |
| |
| /* |
| --- |
| |
| name: Fx.Tween |
| |
| description: Formerly Fx.Style, effect to transition any CSS property for an element. |
| |
| license: MIT-style license. |
| |
| requires: Fx.CSS |
| |
| provides: [Fx.Tween, Element.fade, Element.highlight] |
| |
| ... |
| */ |
| |
| Fx.Tween = new Class({ |
| |
| Extends: Fx.CSS, |
| |
| initialize: function(element, options){ |
| this.element = this.subject = document.id(element); |
| this.parent(options); |
| }, |
| |
| set: function(property, now){ |
| if (arguments.length == 1){ |
| now = property; |
| property = this.property || this.options.property; |
| } |
| this.render(this.element, property, now, this.options.unit); |
| return this; |
| }, |
| |
| start: function(property, from, to){ |
| if (!this.check(property, from, to)) return this; |
| var args = Array.flatten(arguments); |
| this.property = this.options.property || args.shift(); |
| var parsed = this.prepare(this.element, this.property, args); |
| return this.parent(parsed.from, parsed.to); |
| } |
| |
| }); |
| |
| Element.Properties.tween = { |
| |
| set: function(options){ |
| this.get('tween').cancel().setOptions(options); |
| return this; |
| }, |
| |
| get: function(){ |
| var tween = this.retrieve('tween'); |
| if (!tween){ |
| tween = new Fx.Tween(this, {link: 'cancel'}); |
| this.store('tween', tween); |
| } |
| return tween; |
| } |
| |
| }; |
| |
| Element.implement({ |
| |
| tween: function(property, from, to){ |
| this.get('tween').start(arguments); |
| return this; |
| }, |
| |
| fade: function(how){ |
| var fade = this.get('tween'), o = 'opacity', toggle; |
| how = [how, 'toggle'].pick(); |
| switch (how){ |
| case 'in': fade.start(o, 1); break; |
| case 'out': fade.start(o, 0); break; |
| case 'show': fade.set(o, 1); break; |
| case 'hide': fade.set(o, 0); break; |
| case 'toggle': |
| var flag = this.retrieve('fade:flag', this.get('opacity') == 1); |
| fade.start(o, (flag) ? 0 : 1); |
| this.store('fade:flag', !flag); |
| toggle = true; |
| break; |
| default: fade.start(o, arguments); |
| } |
| if (!toggle) this.eliminate('fade:flag'); |
| return this; |
| }, |
| |
| highlight: function(start, end){ |
| if (!end){ |
| end = this.retrieve('highlight:original', this.getStyle('background-color')); |
| end = (end == 'transparent') ? '#fff' : end; |
| } |
| var tween = this.get('tween'); |
| tween.start('background-color', start || '#ffff88', end).chain(function(){ |
| this.setStyle('background-color', this.retrieve('highlight:original')); |
| tween.callChain(); |
| }.bind(this)); |
| return this; |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| name: Fx.Morph |
| |
| description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. |
| |
| license: MIT-style license. |
| |
| requires: Fx.CSS |
| |
| provides: Fx.Morph |
| |
| ... |
| */ |
| |
| Fx.Morph = new Class({ |
| |
| Extends: Fx.CSS, |
| |
| initialize: function(element, options){ |
| this.element = this.subject = document.id(element); |
| this.parent(options); |
| }, |
| |
| set: function(now){ |
| if (typeof now == 'string') now = this.search(now); |
| for (var p in now) this.render(this.element, p, now[p], this.options.unit); |
| return this; |
| }, |
| |
| compute: function(from, to, delta){ |
| var now = {}; |
| for (var p in from) now[p] = this.parent(from[p], to[p], delta); |
| return now; |
| }, |
| |
| start: function(properties){ |
| if (!this.check(properties)) return this; |
| if (typeof properties == 'string') properties = this.search(properties); |
| var from = {}, to = {}; |
| for (var p in properties){ |
| var parsed = this.prepare(this.element, p, properties[p]); |
| from[p] = parsed.from; |
| to[p] = parsed.to; |
| } |
| return this.parent(from, to); |
| } |
| |
| }); |
| |
| Element.Properties.morph = { |
| |
| set: function(options){ |
| this.get('morph').cancel().setOptions(options); |
| return this; |
| }, |
| |
| get: function(){ |
| var morph = this.retrieve('morph'); |
| if (!morph){ |
| morph = new Fx.Morph(this, {link: 'cancel'}); |
| this.store('morph', morph); |
| } |
| return morph; |
| } |
| |
| }; |
| |
| Element.implement({ |
| |
| morph: function(props){ |
| this.get('morph').start(props); |
| return this; |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| name: Fx.Transitions |
| |
| description: Contains a set of advanced transitions to be used with any of the Fx Classes. |
| |
| license: MIT-style license. |
| |
| credits: |
| - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools. |
| |
| requires: Fx |
| |
| provides: Fx.Transitions |
| |
| ... |
| */ |
| |
| Fx.implement({ |
| |
| getTransition: function(){ |
| var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; |
| if (typeof trans == 'string'){ |
| var data = trans.split(':'); |
| trans = Fx.Transitions; |
| trans = trans[data[0]] || trans[data[0].capitalize()]; |
| if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; |
| } |
| return trans; |
| } |
| |
| }); |
| |
| Fx.Transition = function(transition, params){ |
| params = Array.from(params); |
| var easeIn = function(pos){ |
| return transition(pos, params); |
| }; |
| return Object.append(easeIn, { |
| easeIn: easeIn, |
| easeOut: function(pos){ |
| return 1 - transition(1 - pos, params); |
| }, |
| easeInOut: function(pos){ |
| return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; |
| } |
| }); |
| }; |
| |
| Fx.Transitions = { |
| |
| linear: function(zero){ |
| return zero; |
| } |
| |
| }; |
| |
| //<1.2compat> |
| |
| Fx.Transitions = new Hash(Fx.Transitions); |
| |
| //</1.2compat> |
| |
| Fx.Transitions.extend = function(transitions){ |
| for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); |
| }; |
| |
| Fx.Transitions.extend({ |
| |
| Pow: function(p, x){ |
| return Math.pow(p, x && x[0] || 6); |
| }, |
| |
| Expo: function(p){ |
| return Math.pow(2, 8 * (p - 1)); |
| }, |
| |
| Circ: function(p){ |
| return 1 - Math.sin(Math.acos(p)); |
| }, |
| |
| Sine: function(p){ |
| return 1 - Math.cos(p * Math.PI / 2); |
| }, |
| |
| Back: function(p, x){ |
| x = x && x[0] || 1.618; |
| return Math.pow(p, 2) * ((x + 1) * p - x); |
| }, |
| |
| Bounce: function(p){ |
| var value; |
| for (var a = 0, b = 1; 1; a += b, b /= 2){ |
| if (p >= (7 - 4 * a) / 11){ |
| value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); |
| break; |
| } |
| } |
| return value; |
| }, |
| |
| Elastic: function(p, x){ |
| return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); |
| } |
| |
| }); |
| |
| ['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ |
| Fx.Transitions[transition] = new Fx.Transition(function(p){ |
| return Math.pow(p, i + 2); |
| }); |
| }); |
| |
| |
| /* |
| --- |
| |
| name: Request |
| |
| description: Powerful all purpose Request Class. Uses XMLHTTPRequest. |
| |
| license: MIT-style license. |
| |
| requires: [Object, Element, Chain, Events, Options, Browser] |
| |
| provides: Request |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var empty = function(){}, |
| progressSupport = ('onprogress' in new Browser.Request); |
| |
| var Request = this.Request = new Class({ |
| |
| Implements: [Chain, Events, Options], |
| |
| options: {/* |
| onRequest: function(){}, |
| onLoadstart: function(event, xhr){}, |
| onProgress: function(event, xhr){}, |
| onComplete: function(){}, |
| onCancel: function(){}, |
| onSuccess: function(responseText, responseXML){}, |
| onFailure: function(xhr){}, |
| onException: function(headerName, value){}, |
| onTimeout: function(){}, |
| user: '', |
| password: '',*/ |
| url: '', |
| data: '', |
| headers: { |
| 'X-Requested-With': 'XMLHttpRequest', |
| 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' |
| }, |
| async: true, |
| format: false, |
| method: 'post', |
| link: 'ignore', |
| isSuccess: null, |
| emulation: true, |
| urlEncoded: true, |
| encoding: 'utf-8', |
| evalScripts: false, |
| evalResponse: false, |
| timeout: 0, |
| noCache: false |
| }, |
| |
| initialize: function(options){ |
| this.xhr = new Browser.Request(); |
| this.setOptions(options); |
| this.headers = this.options.headers; |
| }, |
| |
| onStateChange: function(){ |
| var xhr = this.xhr; |
| if (xhr.readyState != 4 || !this.running) return; |
| this.running = false; |
| this.status = 0; |
| Function.attempt(function(){ |
| var status = xhr.status; |
| this.status = (status == 1223) ? 204 : status; |
| }.bind(this)); |
| xhr.onreadystatechange = empty; |
| if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; |
| clearTimeout(this.timer); |
| |
| this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; |
| if (this.options.isSuccess.call(this, this.status)) |
| this.success(this.response.text, this.response.xml); |
| else |
| this.failure(); |
| }, |
| |
| isSuccess: function(){ |
| var status = this.status; |
| return (status >= 200 && status < 300); |
| }, |
| |
| isRunning: function(){ |
| return !!this.running; |
| }, |
| |
| processScripts: function(text){ |
| if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); |
| return text.stripScripts(this.options.evalScripts); |
| }, |
| |
| success: function(text, xml){ |
| this.onSuccess(this.processScripts(text), xml); |
| }, |
| |
| onSuccess: function(){ |
| this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); |
| }, |
| |
| failure: function(){ |
| this.onFailure(); |
| }, |
| |
| onFailure: function(){ |
| this.fireEvent('complete').fireEvent('failure', this.xhr); |
| }, |
| |
| loadstart: function(event){ |
| this.fireEvent('loadstart', [event, this.xhr]); |
| }, |
| |
| progress: function(event){ |
| this.fireEvent('progress', [event, this.xhr]); |
| }, |
| |
| timeout: function(){ |
| this.fireEvent('timeout', this.xhr); |
| }, |
| |
| setHeader: function(name, value){ |
| this.headers[name] = value; |
| return this; |
| }, |
| |
| getHeader: function(name){ |
| return Function.attempt(function(){ |
| return this.xhr.getResponseHeader(name); |
| }.bind(this)); |
| }, |
| |
| check: function(){ |
| if (!this.running) return true; |
| switch (this.options.link){ |
| case 'cancel': this.cancel(); return true; |
| case 'chain': this.chain(this.caller.pass(arguments, this)); return false; |
| } |
| return false; |
| }, |
| |
| send: function(options){ |
| if (!this.check(options)) return this; |
| |
| this.options.isSuccess = this.options.isSuccess || this.isSuccess; |
| this.running = true; |
| |
| var type = typeOf(options); |
| if (type == 'string' || type == 'element') options = {data: options}; |
| |
| var old = this.options; |
| options = Object.append({data: old.data, url: old.url, method: old.method}, options); |
| var data = options.data, url = String(options.url), method = options.method.toLowerCase(); |
| |
| switch (typeOf(data)){ |
| case 'element': data = document.id(data).toQueryString(); break; |
| case 'object': case 'hash': data = Object.toQueryString(data); |
| } |
| |
| if (this.options.format){ |
| var format = 'format=' + this.options.format; |
| data = (data) ? format + '&' + data : format; |
| } |
| |
| if (this.options.emulation && !['get', 'post'].contains(method)){ |
| var _method = '_method=' + method; |
| data = (data) ? _method + '&' + data : _method; |
| method = 'post'; |
| } |
| |
| if (this.options.urlEncoded && ['post', 'put'].contains(method)){ |
| var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; |
| this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; |
| } |
| |
| if (!url) url = document.location.pathname; |
| |
| var trimPosition = url.lastIndexOf('/'); |
| if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); |
| |
| if (this.options.noCache) |
| url += (url.contains('?') ? '&' : '?') + String.uniqueID(); |
| |
| if (data && method == 'get'){ |
| url += (url.contains('?') ? '&' : '?') + data; |
| data = null; |
| } |
| |
| var xhr = this.xhr; |
| if (progressSupport){ |
| xhr.onloadstart = this.loadstart.bind(this); |
| xhr.onprogress = this.progress.bind(this); |
| } |
| |
| xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); |
| if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; |
| |
| xhr.onreadystatechange = this.onStateChange.bind(this); |
| |
| Object.each(this.headers, function(value, key){ |
| try { |
| xhr.setRequestHeader(key, value); |
| } catch (e){ |
| this.fireEvent('exception', [key, value]); |
| } |
| }, this); |
| |
| this.fireEvent('request'); |
| xhr.send(data); |
| if (!this.options.async) this.onStateChange(); |
| if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); |
| return this; |
| }, |
| |
| cancel: function(){ |
| if (!this.running) return this; |
| this.running = false; |
| var xhr = this.xhr; |
| xhr.abort(); |
| clearTimeout(this.timer); |
| xhr.onreadystatechange = empty; |
| if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; |
| this.xhr = new Browser.Request(); |
| this.fireEvent('cancel'); |
| return this; |
| } |
| |
| }); |
| |
| var methods = {}; |
| ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ |
| methods[method] = function(data){ |
| var object = { |
| method: method |
| }; |
| if (data != null) object.data = data; |
| return this.send(object); |
| }; |
| }); |
| |
| Request.implement(methods); |
| |
| Element.Properties.send = { |
| |
| set: function(options){ |
| var send = this.get('send').cancel(); |
| send.setOptions(options); |
| return this; |
| }, |
| |
| get: function(){ |
| var send = this.retrieve('send'); |
| if (!send){ |
| send = new Request({ |
| data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') |
| }); |
| this.store('send', send); |
| } |
| return send; |
| } |
| |
| }; |
| |
| Element.implement({ |
| |
| send: function(url){ |
| var sender = this.get('send'); |
| sender.send({data: this, url: url || sender.options.url}); |
| return this; |
| } |
| |
| }); |
| |
| })(); |
| |
| /* |
| --- |
| |
| name: Request.HTML |
| |
| description: Extends the basic Request Class with additional methods for interacting with HTML responses. |
| |
| license: MIT-style license. |
| |
| requires: [Element, Request] |
| |
| provides: Request.HTML |
| |
| ... |
| */ |
| |
| Request.HTML = new Class({ |
| |
| Extends: Request, |
| |
| options: { |
| update: false, |
| append: false, |
| evalScripts: true, |
| filter: false, |
| headers: { |
| Accept: 'text/html, application/xml, text/xml, */*' |
| } |
| }, |
| |
| success: function(text){ |
| var options = this.options, response = this.response; |
| |
| response.html = text.stripScripts(function(script){ |
| response.javascript = script; |
| }); |
| |
| var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i); |
| if (match) response.html = match[1]; |
| var temp = new Element('div').set('html', response.html); |
| |
| response.tree = temp.childNodes; |
| response.elements = temp.getElements('*'); |
| |
| if (options.filter) response.tree = response.elements.filter(options.filter); |
| if (options.update) document.id(options.update).empty().set('html', response.html); |
| else if (options.append) document.id(options.append).adopt(temp.getChildren()); |
| if (options.evalScripts) Browser.exec(response.javascript); |
| |
| this.onSuccess(response.tree, response.elements, response.html, response.javascript); |
| } |
| |
| }); |
| |
| Element.Properties.load = { |
| |
| set: function(options){ |
| var load = this.get('load').cancel(); |
| load.setOptions(options); |
| return this; |
| }, |
| |
| get: function(){ |
| var load = this.retrieve('load'); |
| if (!load){ |
| load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); |
| this.store('load', load); |
| } |
| return load; |
| } |
| |
| }; |
| |
| Element.implement({ |
| |
| load: function(){ |
| this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); |
| return this; |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| name: JSON |
| |
| description: JSON encoder and decoder. |
| |
| license: MIT-style license. |
| |
| See Also: <http://www.json.org/> |
| |
| requires: [Array, String, Number, Function] |
| |
| provides: JSON |
| |
| ... |
| */ |
| |
| if (typeof JSON == 'undefined') this.JSON = {}; |
| |
| //<1.2compat> |
| |
| JSON = new Hash({ |
| stringify: JSON.stringify, |
| parse: JSON.parse |
| }); |
| |
| //</1.2compat> |
| |
| (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.decode = function(string, secure){ |
| if (!string || typeOf(string) != 'string') return null; |
| |
| if (secure || JSON.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 + ')'); |
| }; |
| |
| })(); |
| |
| |
| /* |
| --- |
| |
| name: Request.JSON |
| |
| description: Extends the basic Request Class with additional methods for sending and receiving JSON data. |
| |
| license: MIT-style license. |
| |
| requires: [Request, JSON] |
| |
| provides: Request.JSON |
| |
| ... |
| */ |
| |
| Request.JSON = new Class({ |
| |
| Extends: Request, |
| |
| options: { |
| /*onError: function(text, error){},*/ |
| secure: true |
| }, |
| |
| initialize: function(options){ |
| this.parent(options); |
| Object.append(this.headers, { |
| 'Accept': 'application/json', |
| 'X-Request': 'JSON' |
| }); |
| }, |
| |
| success: function(text){ |
| var json; |
| try { |
| json = this.response.json = JSON.decode(text, this.options.secure); |
| } catch (error){ |
| this.fireEvent('error', [text, error]); |
| return; |
| } |
| if (json == null) this.onFailure(); |
| else this.onSuccess(json, text); |
| } |
| |
| }); |
| |
| |
| /* |
| --- |
| |
| name: Cookie |
| |
| description: Class for creating, reading, and deleting browser Cookies. |
| |
| license: MIT-style license. |
| |
| credits: |
| - Based on the functions by Peter-Paul Koch (http://quirksmode.org). |
| |
| requires: [Options, Browser] |
| |
| provides: Cookie |
| |
| ... |
| */ |
| |
| var Cookie = new Class({ |
| |
| Implements: Options, |
| |
| options: { |
| path: '/', |
| domain: false, |
| duration: false, |
| secure: false, |
| document: document, |
| encode: true |
| }, |
| |
| initialize: function(key, options){ |
| this.key = key; |
| this.setOptions(options); |
| }, |
| |
| write: function(value){ |
| if (this.options.encode) value = encodeURIComponent(value); |
| if (this.options.domain) value += '; domain=' + this.options.domain; |
| if (this.options.path) value += '; path=' + this.options.path; |
| if (this.options.duration){ |
| var date = new Date(); |
| date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); |
| value += '; expires=' + date.toGMTString(); |
| } |
| if (this.options.secure) value += '; secure'; |
| this.options.document.cookie = this.key + '=' + value; |
| return this; |
| }, |
| |
| read: function(){ |
| var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); |
| return (value) ? decodeURIComponent(value[1]) : null; |
| }, |
| |
| dispose: function(){ |
| new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); |
| return this; |
| } |
| |
| }); |
| |
| Cookie.write = function(key, value, options){ |
| return new Cookie(key, options).write(value); |
| }; |
| |
| Cookie.read = function(key){ |
| return new Cookie(key).read(); |
| }; |
| |
| Cookie.dispose = function(key, options){ |
| return new Cookie(key, options).dispose(); |
| }; |
| |
| |
| /* |
| --- |
| |
| name: DOMReady |
| |
| description: Contains the custom event domready. |
| |
| license: MIT-style license. |
| |
| requires: [Browser, Element, Element.Event] |
| |
| provides: [DOMReady, DomReady] |
| |
| ... |
| */ |
| |
| (function(window, document){ |
| |
| var ready, |
| loaded, |
| checks = [], |
| shouldPoll, |
| timer, |
| testElement = document.createElement('div'); |
| |
| var domready = function(){ |
| clearTimeout(timer); |
| if (ready) return; |
| Browser.loaded = ready = true; |
| document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); |
| |
| document.fireEvent('domready'); |
| window.fireEvent('domready'); |
| }; |
| |
| var check = function(){ |
| for (var i = checks.length; i--;) if (checks[i]()){ |
| domready(); |
| return true; |
| } |
| return false; |
| }; |
| |
| var poll = function(){ |
| clearTimeout(timer); |
| if (!check()) timer = setTimeout(poll, 10); |
| }; |
| |
| document.addListener('DOMContentLoaded', domready); |
| |
| /*<ltIE8>*/ |
| // doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ |
| // testElement.doScroll() throws when the DOM is not ready, only in the top window |
| var doScrollWorks = function(){ |
| try { |
| testElement.doScroll(); |
| return true; |
| } catch (e){} |
| return false; |
| } |
| // If doScroll works already, it can't be used to determine domready |
| // e.g. in an iframe |
| if (testElement.doScroll && !doScrollWorks()){ |
| checks.push(doScrollWorks); |
| shouldPoll = true; |
| } |
| /*</ltIE8>*/ |
| |
| if (document.readyState) checks.push(function(){ |
| var state = document.readyState; |
| return (state == 'loaded' || state == 'complete'); |
| }); |
| |
| if ('onreadystatechange' in document) document.addListener('readystatechange', check); |
| else shouldPoll = true; |
| |
| if (shouldPoll) poll(); |
| |
| Element.Events.domready = { |
| onAdd: function(fn){ |
| if (ready) fn.call(this); |
| } |
| }; |
| |
| // Make sure that domready fires before load |
| Element.Events.load = { |
| base: 'load', |
| onAdd: function(fn){ |
| if (loaded && this == window) fn.call(this); |
| }, |
| condition: function(){ |
| if (this == window){ |
| domready(); |
| delete Element.Events.load; |
| } |
| return true; |
| } |
| }; |
| |
| // This is based on the custom load event |
| window.addEvent('load', function(){ |
| loaded = true; |
| }); |
| |
| })(window, document); |
| |
| |
| /* |
| --- |
| |
| name: Swiff |
| |
| description: Wrapper for embedding SWF movies. Supports External Interface Communication. |
| |
| license: MIT-style license. |
| |
| credits: |
| - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. |
| |
| requires: [Options, Object, Element] |
| |
| provides: Swiff |
| |
| ... |
| */ |
| |
| (function(){ |
| |
| var Swiff = this.Swiff = new Class({ |
| |
| Implements: Options, |
| |
| options: { |
| id: null, |
| height: 1, |
| width: 1, |
| container: null, |
| properties: {}, |
| params: { |
| quality: 'high', |
| allowScriptAccess: 'always', |
| wMode: 'window', |
| swLiveConnect: true |
| }, |
| callBacks: {}, |
| vars: {} |
| }, |
| |
| toElement: function(){ |
| return this.object; |
| }, |
| |
| initialize: function(path, options){ |
| this.instance = 'Swiff_' + String.uniqueID(); |
| |
| this.setOptions(options); |
| options = this.options; |
| var id = this.id = options.id || this.instance; |
| var container = document.id(options.container); |
| |
| Swiff.CallBacks[this.instance] = {}; |
| |
| var params = options.params, vars = options.vars, callBacks = options.callBacks; |
| var properties = Object.append({height: options.height, width: options.width}, options.properties); |
| |
| var self = this; |
| |
| for (var callBack in callBacks){ |
| Swiff.CallBacks[this.instance][callBack] = (function(option){ |
| return function(){ |
| return option.apply(self.object, arguments); |
| }; |
| })(callBacks[callBack]); |
| vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; |
| } |
| |
| params.flashVars = Object.toQueryString(vars); |
| if (Browser.ie){ |
| properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; |
| params.movie = path; |
| } else { |
| properties.type = 'application/x-shockwave-flash'; |
| } |
| properties.data = path; |
| |
| var build = '<object id="' + id + '"'; |
| for (var property in properties) build += ' ' + property + '="' + properties[property] + '"'; |
| build += '>'; |
| for (var param in params){ |
| if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />'; |
| } |
| build += '</object>'; |
| this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; |
| }, |
| |
| replaces: function(element){ |
| element = document.id(element, true); |
| element.parentNode.replaceChild(this.toElement(), element); |
| return this; |
| }, |
| |
| inject: function(element){ |
| document.id(element, true).appendChild(this.toElement()); |
| return this; |
| }, |
| |
| remote: function(){ |
| return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments)); |
| } |
| |
| }); |
| |
| Swiff.CallBacks = {}; |
| |
| Swiff.remote = function(obj, fn){ |
| var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>'); |
| return eval(rs); |
| }; |
| |
| })(); |
| |