You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9070 lines
344 KiB
9070 lines
344 KiB
(function() {
|
|
this.MooTools = {
|
|
version: "1.5.1",
|
|
build: "0542c135fdeb7feed7d9917e01447a408f22c876"
|
|
};
|
|
var typeOf = this.typeOf = function(item) {
|
|
if (item == null) return "null";
|
|
if (item.$family != null) return item.$family();
|
|
if (item.nodeName) {
|
|
if (item.nodeType == 1) return "element";
|
|
if (item.nodeType == 3) return /\S/.test(item.nodeValue) ? "textnode" : "whitespace";
|
|
} else if (typeof item.length == "number") {
|
|
if ("callee" in item) return "arguments";
|
|
if ("item" in item) return "collection";
|
|
}
|
|
return typeof item;
|
|
};
|
|
var instanceOf = this.instanceOf = function(item, object) {
|
|
if (item == null) return false;
|
|
var constructor = item.$constructor || item.constructor;
|
|
while (constructor) {
|
|
if (constructor === object) return true;
|
|
constructor = constructor.parent;
|
|
}
|
|
if (!item.hasOwnProperty) return false;
|
|
return item instanceof object;
|
|
};
|
|
var Function = this.Function;
|
|
var enumerables = true;
|
|
for (var i in {
|
|
toString: 1
|
|
}) enumerables = null;
|
|
if (enumerables) enumerables = [ "hasOwnProperty", "valueOf", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "constructor" ];
|
|
Function.prototype.overloadSetter = function(usePlural) {
|
|
var self = this;
|
|
return function(a, b) {
|
|
if (a == null) return this;
|
|
if (usePlural || typeof a != "string") {
|
|
for (var k in a) self.call(this, k, a[k]);
|
|
if (enumerables) for (var i = enumerables.length; i--; ) {
|
|
k = enumerables[i];
|
|
if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
|
|
}
|
|
} else {
|
|
self.call(this, a, b);
|
|
}
|
|
return this;
|
|
};
|
|
};
|
|
Function.prototype.overloadGetter = function(usePlural) {
|
|
var self = this;
|
|
return function(a) {
|
|
var args, result;
|
|
if (typeof a != "string") args = a; else if (arguments.length > 1) args = arguments; else if (usePlural) args = [ a ];
|
|
if (args) {
|
|
result = {};
|
|
for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
|
|
} else {
|
|
result = self.call(this, a);
|
|
}
|
|
return result;
|
|
};
|
|
};
|
|
Function.prototype.extend = function(key, value) {
|
|
this[key] = value;
|
|
}.overloadSetter();
|
|
Function.prototype.implement = function(key, value) {
|
|
this.prototype[key] = value;
|
|
}.overloadSetter();
|
|
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 + "";
|
|
};
|
|
Function.implement({
|
|
hide: function() {
|
|
this.$hidden = true;
|
|
return this;
|
|
},
|
|
protect: function() {
|
|
this.$protected = true;
|
|
return this;
|
|
}
|
|
});
|
|
var Type = this.Type = function(name, object) {
|
|
if (name) {
|
|
var lower = name.toLowerCase();
|
|
var typeCheck = function(item) {
|
|
return typeOf(item) == lower;
|
|
};
|
|
Type["is" + name] = typeCheck;
|
|
if (object != null) {
|
|
object.prototype.$family = function() {
|
|
return lower;
|
|
}.hide();
|
|
}
|
|
}
|
|
if (object == null) return null;
|
|
object.extend(this);
|
|
object.$constructor = Type;
|
|
object.prototype.$constructor = object;
|
|
return object;
|
|
};
|
|
var toString = Object.prototype.toString;
|
|
Type.isEnumerable = function(item) {
|
|
return item != null && typeof item.length == "number" && toString.call(item) != "[object Function]";
|
|
};
|
|
var hooks = {};
|
|
var hooksOf = function(object) {
|
|
var type = typeOf(object.prototype);
|
|
return hooks[type] || (hooks[type] = []);
|
|
};
|
|
var implement = function(name, method) {
|
|
if (method && method.$hidden) return;
|
|
var hooks = hooksOf(this);
|
|
for (var i = 0; i < hooks.length; i++) {
|
|
var hook = hooks[i];
|
|
if (typeOf(hook) == "type") implement.call(hook, name, method); else hook.call(this, name, method);
|
|
}
|
|
var previous = this.prototype[name];
|
|
if (previous == null || !previous.$protected) this.prototype[name] = method;
|
|
if (this[name] == null && typeOf(method) == "function") extend.call(this, name, function(item) {
|
|
return method.apply(item, slice.call(arguments, 1));
|
|
});
|
|
};
|
|
var extend = function(name, method) {
|
|
if (method && method.$hidden) return;
|
|
var previous = this[name];
|
|
if (previous == null || !previous.$protected) this[name] = method;
|
|
};
|
|
Type.implement({
|
|
implement: implement.overloadSetter(),
|
|
extend: extend.overloadSetter(),
|
|
alias: function(name, existing) {
|
|
implement.call(this, name, this.prototype[existing]);
|
|
}.overloadSetter(),
|
|
mirror: function(hook) {
|
|
hooksOf(this).push(hook);
|
|
return this;
|
|
}
|
|
});
|
|
new Type("Type", Type);
|
|
var force = function(name, object, methods) {
|
|
var isType = object != Object, prototype = object.prototype;
|
|
if (isType) object = new Type(name, object);
|
|
for (var i = 0, l = methods.length; i < l; i++) {
|
|
var key = methods[i], generic = object[key], proto = prototype[key];
|
|
if (generic) generic.protect();
|
|
if (isType && proto) object.implement(key, proto.protect());
|
|
}
|
|
if (isType) {
|
|
var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]);
|
|
object.forEachMethod = function(fn) {
|
|
if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++) {
|
|
fn.call(prototype, prototype[methods[i]], methods[i]);
|
|
}
|
|
for (var key in prototype) fn.call(prototype, prototype[key], key);
|
|
};
|
|
}
|
|
return force;
|
|
};
|
|
force("String", String, [ "charAt", "charCodeAt", "concat", "contains", "indexOf", "lastIndexOf", "match", "quote", "replace", "search", "slice", "split", "substr", "substring", "trim", "toLowerCase", "toUpperCase" ])("Array", Array, [ "pop", "push", "reverse", "shift", "sort", "splice", "unshift", "concat", "join", "slice", "indexOf", "lastIndexOf", "filter", "forEach", "every", "map", "some", "reduce", "reduceRight" ])("Number", Number, [ "toExponential", "toFixed", "toLocaleString", "toPrecision" ])("Function", Function, [ "apply", "call", "bind" ])("RegExp", RegExp, [ "exec", "test" ])("Object", Object, [ "create", "defineProperty", "defineProperties", "keys", "getPrototypeOf", "getOwnPropertyDescriptor", "getOwnPropertyNames", "preventExtensions", "isExtensible", "seal", "isSealed", "freeze", "isFrozen" ])("Date", Date, [ "now" ]);
|
|
Object.extend = extend.overloadSetter();
|
|
Date.extend("now", function() {
|
|
return +new Date();
|
|
});
|
|
new Type("Boolean", Boolean);
|
|
Number.prototype.$family = function() {
|
|
return isFinite(this) ? "number" : "null";
|
|
}.hide();
|
|
Number.extend("random", function(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1) + min);
|
|
});
|
|
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;
|
|
}
|
|
});
|
|
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", "WhiteSpace", "TextNode", "Collection", "Arguments" ].each(function(name) {
|
|
new Type(name);
|
|
});
|
|
var UID = Date.now();
|
|
String.extend("uniqueID", function() {
|
|
return (UID++).toString(36);
|
|
});
|
|
})();
|
|
|
|
Array.implement({
|
|
every: function(fn, bind) {
|
|
for (var i = 0, l = this.length >>> 0; i < l; i++) {
|
|
if (i in this && !fn.call(bind, this[i], i, this)) return false;
|
|
}
|
|
return true;
|
|
},
|
|
filter: function(fn, bind) {
|
|
var results = [];
|
|
for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this) {
|
|
value = this[i];
|
|
if (fn.call(bind, value, i, this)) results.push(value);
|
|
}
|
|
return results;
|
|
},
|
|
indexOf: function(item, from) {
|
|
var length = this.length >>> 0;
|
|
for (var i = from < 0 ? Math.max(0, length + from) : from || 0; i < length; i++) {
|
|
if (this[i] === item) return i;
|
|
}
|
|
return -1;
|
|
},
|
|
map: function(fn, bind) {
|
|
var length = this.length >>> 0, results = Array(length);
|
|
for (var i = 0; i < length; i++) {
|
|
if (i in this) results[i] = fn.call(bind, this[i], i, this);
|
|
}
|
|
return results;
|
|
},
|
|
some: function(fn, bind) {
|
|
for (var i = 0, l = this.length >>> 0; i < l; i++) {
|
|
if (i in this && fn.call(bind, this[i], i, this)) return true;
|
|
}
|
|
return false;
|
|
},
|
|
clean: function() {
|
|
return this.filter(function(item) {
|
|
return item != null;
|
|
});
|
|
},
|
|
invoke: function(methodName) {
|
|
var args = Array.slice(arguments, 1);
|
|
return this.map(function(item) {
|
|
return item[methodName].apply(item, args);
|
|
});
|
|
},
|
|
associate: function(keys) {
|
|
var obj = {}, length = Math.min(this.length, keys.length);
|
|
for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
|
|
return obj;
|
|
},
|
|
link: function(object) {
|
|
var result = {};
|
|
for (var i = 0, l = this.length; i < l; i++) {
|
|
for (var key in object) {
|
|
if (object[key](this[i])) {
|
|
result[key] = this[i];
|
|
delete object[key];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
contains: function(item, from) {
|
|
return this.indexOf(item, from) != -1;
|
|
},
|
|
append: function(array) {
|
|
this.push.apply(this, array);
|
|
return this;
|
|
},
|
|
getLast: function() {
|
|
return this.length ? this[this.length - 1] : null;
|
|
},
|
|
getRandom: function() {
|
|
return this.length ? this[Number.random(0, this.length - 1)] : null;
|
|
},
|
|
include: function(item) {
|
|
if (!this.contains(item)) this.push(item);
|
|
return this;
|
|
},
|
|
combine: function(array) {
|
|
for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
|
|
return this;
|
|
},
|
|
erase: function(item) {
|
|
for (var i = this.length; i--; ) {
|
|
if (this[i] === item) this.splice(i, 1);
|
|
}
|
|
return this;
|
|
},
|
|
empty: function() {
|
|
this.length = 0;
|
|
return this;
|
|
},
|
|
flatten: function() {
|
|
var array = [];
|
|
for (var i = 0, l = this.length; i < l; i++) {
|
|
var type = typeOf(this[i]);
|
|
if (type == "null") continue;
|
|
array = array.concat(type == "array" || type == "collection" || type == "arguments" || instanceOf(this[i], Array) ? Array.flatten(this[i]) : this[i]);
|
|
}
|
|
return array;
|
|
},
|
|
pick: function() {
|
|
for (var i = 0, l = this.length; i < l; i++) {
|
|
if (this[i] != null) return this[i];
|
|
}
|
|
return null;
|
|
},
|
|
hexToRgb: function(array) {
|
|
if (this.length != 3) return null;
|
|
var rgb = this.map(function(value) {
|
|
if (value.length == 1) value += value;
|
|
return parseInt(value, 16);
|
|
});
|
|
return array ? rgb : "rgb(" + rgb + ")";
|
|
},
|
|
rgbToHex: function(array) {
|
|
if (this.length < 3) return null;
|
|
if (this.length == 4 && this[3] == 0 && !array) return "transparent";
|
|
var hex = [];
|
|
for (var i = 0; i < 3; i++) {
|
|
var bit = (this[i] - 0).toString(16);
|
|
hex.push(bit.length == 1 ? "0" + bit : bit);
|
|
}
|
|
return array ? hex : "#" + hex.join("");
|
|
}
|
|
});
|
|
|
|
String.implement({
|
|
contains: function(string, index) {
|
|
return (index ? String(this).slice(index) : String(this)).indexOf(string) > -1;
|
|
},
|
|
test: function(regex, params) {
|
|
return (typeOf(regex) == "regexp" ? regex : new RegExp("" + regex, params)).test(this);
|
|
},
|
|
trim: function() {
|
|
return String(this).replace(/^\s+|\s+$/g, "");
|
|
},
|
|
clean: function() {
|
|
return String(this).replace(/\s+/g, " ").trim();
|
|
},
|
|
camelCase: function() {
|
|
return String(this).replace(/-\D/g, function(match) {
|
|
return match.charAt(1).toUpperCase();
|
|
});
|
|
},
|
|
hyphenate: function() {
|
|
return String(this).replace(/[A-Z]/g, function(match) {
|
|
return "-" + match.charAt(0).toLowerCase();
|
|
});
|
|
},
|
|
capitalize: function() {
|
|
return String(this).replace(/\b[a-z]/g, function(match) {
|
|
return match.toUpperCase();
|
|
});
|
|
},
|
|
escapeRegExp: function() {
|
|
return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
|
|
},
|
|
toInt: function(base) {
|
|
return parseInt(this, base || 10);
|
|
},
|
|
toFloat: function() {
|
|
return parseFloat(this);
|
|
},
|
|
hexToRgb: function(array) {
|
|
var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
|
|
return hex ? hex.slice(1).hexToRgb(array) : null;
|
|
},
|
|
rgbToHex: function(array) {
|
|
var rgb = String(this).match(/\d{1,3}/g);
|
|
return rgb ? rgb.rgbToHex(array) : null;
|
|
},
|
|
substitute: function(object, regexp) {
|
|
return String(this).replace(regexp || /\\?\{([^{}]+)\}/g, function(match, name) {
|
|
if (match.charAt(0) == "\\") return match.slice(1);
|
|
return object[name] != null ? object[name] : "";
|
|
});
|
|
}
|
|
});
|
|
|
|
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;
|
|
},
|
|
bind: function(that) {
|
|
var self = this, args = arguments.length > 1 ? Array.slice(arguments, 1) : null, F = function() {};
|
|
var bound = function() {
|
|
var context = that, length = arguments.length;
|
|
if (this instanceof bound) {
|
|
F.prototype = self.prototype;
|
|
context = new F();
|
|
}
|
|
var result = !args && !length ? self.call(context) : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
|
|
return context == that ? result : context;
|
|
};
|
|
return bound;
|
|
},
|
|
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);
|
|
}
|
|
});
|
|
|
|
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" ]);
|
|
|
|
(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);
|
|
}
|
|
};
|
|
})();
|
|
|
|
(function() {
|
|
this.Chain = new Class({
|
|
$chain: [],
|
|
chain: function() {
|
|
this.$chain.append(Array.flatten(arguments));
|
|
return this;
|
|
},
|
|
callChain: function() {
|
|
return this.$chain.length ? this.$chain.shift().apply(this, arguments) : false;
|
|
},
|
|
clearChain: function() {
|
|
this.$chain.empty();
|
|
return this;
|
|
}
|
|
});
|
|
var removeOn = function(string) {
|
|
return string.replace(/^on([A-Z])/, function(full, first) {
|
|
return first.toLowerCase();
|
|
});
|
|
};
|
|
this.Events = new Class({
|
|
$events: {},
|
|
addEvent: function(type, fn, internal) {
|
|
type = removeOn(type);
|
|
this.$events[type] = (this.$events[type] || []).include(fn);
|
|
if (internal) fn.internal = true;
|
|
return this;
|
|
},
|
|
addEvents: function(events) {
|
|
for (var type in events) this.addEvent(type, events[type]);
|
|
return this;
|
|
},
|
|
fireEvent: function(type, args, delay) {
|
|
type = removeOn(type);
|
|
var events = this.$events[type];
|
|
if (!events) return this;
|
|
args = Array.from(args);
|
|
events.each(function(fn) {
|
|
if (delay) fn.delay(delay, this, args); else fn.apply(this, args);
|
|
}, this);
|
|
return this;
|
|
},
|
|
removeEvent: function(type, fn) {
|
|
type = removeOn(type);
|
|
var events = this.$events[type];
|
|
if (events && !fn.internal) {
|
|
var index = events.indexOf(fn);
|
|
if (index != -1) delete events[index];
|
|
}
|
|
return this;
|
|
},
|
|
removeEvents: function(events) {
|
|
var type;
|
|
if (typeOf(events) == "object") {
|
|
for (type in events) this.removeEvent(type, events[type]);
|
|
return this;
|
|
}
|
|
if (events) events = removeOn(events);
|
|
for (type in this.$events) {
|
|
if (events && events != type) continue;
|
|
var fns = this.$events[type];
|
|
for (var i = fns.length; i--; ) if (i in fns) {
|
|
this.removeEvent(type, fns[i]);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
this.Options = new Class({
|
|
setOptions: function() {
|
|
var options = this.options = Object.merge.apply(null, [ {}, this.options ].append(arguments));
|
|
if (this.addEvent) for (var option in options) {
|
|
if (typeOf(options[option]) != "function" || !/^on[A-Z]/.test(option)) continue;
|
|
this.addEvent(option, options[option]);
|
|
delete options[option];
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
})();
|
|
|
|
(function() {
|
|
var document = this.document;
|
|
var window = document.window = this;
|
|
var parse = function(ua, platform) {
|
|
ua = ua.toLowerCase();
|
|
platform = platform ? platform.toLowerCase() : "";
|
|
var UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [ null, "unknown", 0 ];
|
|
if (UA[1] == "trident") {
|
|
UA[1] = "ie";
|
|
if (UA[4]) UA[2] = UA[4];
|
|
} else if (UA[1] == "crios") {
|
|
UA[1] = "chrome";
|
|
}
|
|
platform = ua.match(/ip(?:ad|od|hone)/) ? "ios" : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || [ "other" ])[0];
|
|
if (platform == "win") platform = "windows";
|
|
return {
|
|
extend: Function.prototype.extend,
|
|
name: UA[1] == "version" ? UA[3] : UA[1],
|
|
version: parseFloat(UA[1] == "opera" && UA[4] ? UA[4] : UA[2]),
|
|
platform: platform
|
|
};
|
|
};
|
|
var Browser = this.Browser = parse(navigator.userAgent, navigator.platform);
|
|
if (Browser.name == "ie") {
|
|
Browser.version = document.documentMode;
|
|
}
|
|
Browser.extend({
|
|
Features: {
|
|
xpath: !!document.evaluate,
|
|
air: !!window.runtime,
|
|
query: !!document.querySelector,
|
|
json: !!window.JSON
|
|
},
|
|
parseUA: parse
|
|
});
|
|
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;
|
|
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;
|
|
});
|
|
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) {}
|
|
if (this.attachEvent && !this.addEventListener) {
|
|
var unloadEvent = function() {
|
|
this.detachEvent("onunload", unloadEvent);
|
|
document.head = document.html = document.window = null;
|
|
window = this.Window = document = null;
|
|
};
|
|
this.attachEvent("onunload", unloadEvent);
|
|
}
|
|
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));
|
|
};
|
|
});
|
|
}
|
|
})();
|
|
|
|
(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("&");
|
|
}
|
|
});
|
|
})();
|
|
|
|
(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) {
|
|
return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match) {
|
|
return "\\" + match;
|
|
});
|
|
};
|
|
var regexp = new RegExp("^(?:\\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 "";
|
|
}
|
|
var Slick = this.Slick || {};
|
|
Slick.parse = function(expression) {
|
|
return parse(expression);
|
|
};
|
|
Slick.escapeRegExp = escapeRegExp;
|
|
if (!this.Slick) this.Slick = Slick;
|
|
}).apply(typeof exports != "undefined" ? exports : this);
|
|
|
|
(function() {
|
|
var local = {}, featuresCache = {}, toString = Object.prototype.toString;
|
|
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) {
|
|
var nodeType = document.nodeType;
|
|
if (nodeType == 9) ; else if (nodeType) document = document.ownerDocument; else if (document.navigator) document = document.document; else return;
|
|
if (this.document === document) return;
|
|
this.document = document;
|
|
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);
|
|
try {
|
|
testNode.innerHTML = '<a id="' + id + '"></a>';
|
|
features.isHTMLDocument = !!document.getElementById(id);
|
|
} catch (e) {}
|
|
if (features.isHTMLDocument) {
|
|
testNode.style.display = "none";
|
|
testNode.appendChild(document.createComment(""));
|
|
starSelectsComments = testNode.getElementsByTagName("*").length > 1;
|
|
try {
|
|
testNode.innerHTML = "foo</foo>";
|
|
selected = testNode.getElementsByTagName("*");
|
|
starSelectsClosed = selected && !!selected.length && selected[0].nodeName.charAt(0) == "/";
|
|
} catch (e) {}
|
|
features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
|
|
try {
|
|
testNode.innerHTML = '<a name="' + id + '"></a><b id="' + id + '"></b>';
|
|
features.idGetsName = document.getElementById(id) === testNode.firstChild;
|
|
} catch (e) {}
|
|
if (testNode.getElementsByClassName) {
|
|
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) {}
|
|
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) {
|
|
try {
|
|
testNode.innerHTML = "foo</foo>";
|
|
selected = testNode.querySelectorAll("*");
|
|
features.starSelectsClosedQSA = selected && !!selected.length && selected[0].nodeName.charAt(0) == "/";
|
|
} catch (e) {}
|
|
try {
|
|
testNode.innerHTML = '<a class="MiX"></a>';
|
|
features.brokenMixedCaseQSA = !testNode.querySelectorAll(".MiX").length;
|
|
} catch (e) {}
|
|
try {
|
|
testNode.innerHTML = '<select><option selected="selected">a</option></select>';
|
|
features.brokenCheckedQSA = testNode.querySelectorAll(":checked").length == 0;
|
|
} catch (e) {}
|
|
try {
|
|
testNode.innerHTML = '<a class=""></a>';
|
|
features.brokenEmptyAttributeQSA = testNode.querySelectorAll('[class*=""]').length != 0;
|
|
} catch (e) {}
|
|
}
|
|
try {
|
|
testNode.innerHTML = '<form action="s"><input id="action"/></form>';
|
|
brokenFormAttributeGetter = testNode.firstChild.getAttribute("action") != "s";
|
|
} catch (e) {}
|
|
features.nativeMatchesSelector = root.matches || root.mozMatchesSelector || root.webkitMatchesSelector;
|
|
if (features.nativeMatchesSelector) try {
|
|
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;
|
|
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);
|
|
};
|
|
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));
|
|
};
|
|
var nativeRootContains = root && this.isNativeCode(root.contains), nativeDocumentContains = document && this.isNativeCode(document.contains);
|
|
features.contains = nativeRootContains && nativeDocumentContains ? function(context, node) {
|
|
return context.contains(node);
|
|
} : nativeRootContains && !nativeDocumentContains ? function(context, node) {
|
|
return context === node || (context === document ? document.documentElement : 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;
|
|
};
|
|
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];
|
|
}
|
|
};
|
|
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; else if (!context.nodeType) return found;
|
|
var parsed, i, uniques = this.uniques = {}, hasOthers = !!(append && append.length), contextIsDocument = context.nodeType == 9;
|
|
if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
|
|
if (hasOthers) for (i = found.length; i--; ) uniques[this.getUID(found[i])] = true;
|
|
if (typeof expression == "string") {
|
|
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;
|
|
}
|
|
querySelector: if (context.querySelectorAll) {
|
|
if (!this.isHTMLDocument || qsaFailExpCache[expression] || this.brokenMixedCaseQSA || this.brokenCheckedQSA && expression.indexOf(":checked") > -1 || this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression) || !contextIsDocument && expression.indexOf(",") > -1 || Slick.disableQSA) break querySelector;
|
|
var _expression = expression, _context = context;
|
|
if (!contextIsDocument) {
|
|
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;
|
|
}
|
|
parsed = this.Slick.parse(expression);
|
|
if (!parsed.length) return found;
|
|
} else if (expression == null) {
|
|
return found;
|
|
} else if (expression.Slick) {
|
|
parsed = expression;
|
|
} else if (this.contains(context.documentElement || context, expression)) {
|
|
found ? found.push(expression) : found = expression;
|
|
return found;
|
|
} else {
|
|
return found;
|
|
}
|
|
this.posNTH = {};
|
|
this.posNTHLast = {};
|
|
this.posNTHType = {};
|
|
this.posNTHTypeLast = {};
|
|
this.push = !hasOthers && (first || parsed.length == 1 && parsed.expressions[0].length == 1) ? this.pushArray : this.pushUID;
|
|
if (found == null) found = [];
|
|
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;
|
|
}
|
|
if (hasOthers || parsed.expressions.length > 1) this.sort(found);
|
|
return first ? found[0] || null : found;
|
|
};
|
|
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++);
|
|
};
|
|
local.sort = function(results) {
|
|
if (!this.documentSorter) return results;
|
|
results.sort(this.documentSorter);
|
|
return results;
|
|
};
|
|
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;
|
|
};
|
|
};
|
|
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;
|
|
var expressions = parsed.expressions, simpleExpCounter = 0, i, currentExpression;
|
|
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;
|
|
} 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 = this.getAttribute(node, "class");
|
|
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) {
|
|
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) {
|
|
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 (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) {
|
|
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) {
|
|
while (node = node.nextSibling) if (node.nodeType == 1) {
|
|
this.push(node, tag, id, classes, attributes, pseudos);
|
|
break;
|
|
}
|
|
},
|
|
"^": function(node, tag, id, classes, attributes, pseudos) {
|
|
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) {
|
|
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) {
|
|
this["combinator:+"](node, tag, id, classes, attributes, pseudos);
|
|
this["combinator:!+"](node, tag, id, classes, attributes, pseudos);
|
|
},
|
|
"~~": function(node, tag, id, classes, attributes, pseudos) {
|
|
this["combinator:~"](node, tag, id, classes, attributes, pseudos);
|
|
this["combinator:!~"](node, tag, id, classes, attributes, pseudos);
|
|
},
|
|
"!": function(node, tag, id, classes, attributes, pseudos) {
|
|
while (node = node.parentNode) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
|
|
},
|
|
"!>": function(node, tag, id, classes, attributes, pseudos) {
|
|
node = node.parentNode;
|
|
if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
|
|
},
|
|
"!+": function(node, tag, id, classes, attributes, pseudos) {
|
|
while (node = node.previousSibling) if (node.nodeType == 1) {
|
|
this.push(node, tag, id, classes, attributes, pseudos);
|
|
break;
|
|
}
|
|
},
|
|
"!^": function(node, tag, id, classes, attributes, pseudos) {
|
|
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) {
|
|
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 = {
|
|
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-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");
|
|
},
|
|
"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;
|
|
},
|
|
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;
|
|
}
|
|
};
|
|
for (var p in pseudos) local["pseudo:" + p] = pseudos[p];
|
|
var attributeGetters = local.attributeGetters = {
|
|
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");
|
|
},
|
|
maxlength: function() {
|
|
var attributeNode = this.getAttributeNode("maxLength");
|
|
return attributeNode && attributeNode.specified ? attributeNode.nodeValue : null;
|
|
}
|
|
};
|
|
attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength;
|
|
var Slick = local.Slick = this.Slick || {};
|
|
Slick.version = "1.1.7";
|
|
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.contains = function(container, node) {
|
|
local.setDocument(container);
|
|
return local.contains(container, node);
|
|
};
|
|
Slick.getAttribute = function(node, name) {
|
|
local.setDocument(node);
|
|
return local.getAttribute(node, name);
|
|
};
|
|
Slick.hasAttribute = function(node, name) {
|
|
local.setDocument(node);
|
|
return local.hasAttribute(node, name);
|
|
};
|
|
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.defineAttributeGetter = function(name, fn) {
|
|
local.attributeGetters[name] = fn;
|
|
return this;
|
|
};
|
|
Slick.lookupAttributeGetter = function(name) {
|
|
return local.attributeGetters[name];
|
|
};
|
|
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.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(typeof exports != "undefined" ? exports : this);
|
|
|
|
var Element = this.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 attr, i = 0, l = attributes.length; i < l; i++) {
|
|
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;
|
|
Element.prototype._fireEvent = function(fireEvent) {
|
|
return function(type, event) {
|
|
return fireEvent.call(this, type, event);
|
|
};
|
|
}(Element.prototype.fireEvent);
|
|
}
|
|
|
|
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 = {
|
|
$constructor: Element,
|
|
$family: Function.from("element").hide()
|
|
};
|
|
Element.mirror(function(name, method) {
|
|
Element.Prototype[name] = method;
|
|
});
|
|
}
|
|
|
|
Element.Constructors = {};
|
|
|
|
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()
|
|
});
|
|
|
|
(function() {
|
|
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;
|
|
var result = splice.apply(this, arguments);
|
|
while (length >= this.length) delete this[length--];
|
|
return result;
|
|
}.protect());
|
|
Array.forEachMethod(function(method, name) {
|
|
Elements.implement(name, method);
|
|
});
|
|
Array.mirror(Elements);
|
|
var createElementAcceptsHTML;
|
|
try {
|
|
createElementAcceptsHTML = document.createElement("<input name=x>").name == "x";
|
|
} catch (e) {}
|
|
var escapeQuotes = function(html) {
|
|
return ("" + html).replace(/&/g, "&").replace(/"/g, """);
|
|
};
|
|
var canChangeStyleHTML = function() {
|
|
var div = document.createElement("style"), flag = false;
|
|
try {
|
|
div.innerHTML = "#justTesing{margin: 0px;}";
|
|
flag = !!div.innerHTML;
|
|
} catch (e) {}
|
|
return flag;
|
|
}();
|
|
Document.implement({
|
|
newElement: function(tag, props) {
|
|
if (props) {
|
|
if (props.checked != null) props.defaultChecked = props.checked;
|
|
if ((props.type == "checkbox" || props.type == "radio") && props.value == null) props.value = "on";
|
|
if (!canChangeStyleHTML && tag == "style") {
|
|
var styleElement = document.createElement("style");
|
|
styleElement.setAttribute("type", "text/css");
|
|
if (props.type) delete props.type;
|
|
return this.id(styleElement).set(props);
|
|
}
|
|
if (createElementAcceptsHTML) {
|
|
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;
|
|
}
|
|
}
|
|
return this.id(this.createElement(tag)).set(props);
|
|
}
|
|
});
|
|
})();
|
|
|
|
(function() {
|
|
Slick.uidOf(window);
|
|
Slick.uidOf(document);
|
|
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) {
|
|
Slick.uidOf(el);
|
|
if (!nocash && !el.$family && !/^(?:object|embed)$/i.test(el.tagName)) {
|
|
var fireEvent = el.fireEvent;
|
|
el._fireEvent = function(type, event) {
|
|
return fireEvent(type, event);
|
|
};
|
|
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.uniqueNumber) 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));
|
|
}
|
|
});
|
|
var contains = {
|
|
contains: function(element) {
|
|
return Slick.contains(this, element);
|
|
}
|
|
};
|
|
if (!document.contains) Document.implement(contains);
|
|
if (!document.createElement("div").contains) Element.implement(contains);
|
|
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;
|
|
};
|
|
Object.forEach({
|
|
getNext: "~",
|
|
getPrevious: "!~",
|
|
getParent: "!"
|
|
}, function(combinator, method) {
|
|
Element.implement(method, function(expression) {
|
|
return this.getElement(injectCombinator(expression, combinator));
|
|
});
|
|
});
|
|
Object.forEach({
|
|
getAllNext: "~",
|
|
getAllPrevious: "!~",
|
|
getSiblings: "~~",
|
|
getChildren: ">",
|
|
getParents: "!"
|
|
}, function(combinator, method) {
|
|
Element.implement(method, function(expression) {
|
|
return this.getElements(injectCombinator(expression, combinator));
|
|
});
|
|
});
|
|
Element.implement({
|
|
getFirst: function(expression) {
|
|
return document.id(Slick.search(this, injectCombinator(expression, ">"))[0]);
|
|
},
|
|
getLast: function(expression) {
|
|
return document.id(Slick.search(this, injectCombinator(expression, ">")).getLast());
|
|
},
|
|
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")));
|
|
},
|
|
match: function(expression) {
|
|
return !expression || Slick.match(this, expression);
|
|
}
|
|
});
|
|
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);
|
|
});
|
|
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;
|
|
var propertyGetters = {}, propertySetters = {};
|
|
var properties = {};
|
|
Array.forEach([ "type", "value", "defaultValue", "accessKey", "cellPadding", "cellSpacing", "colSpan", "frameBorder", "rowSpan", "tabIndex", "useMap" ], function(property) {
|
|
properties[property.toLowerCase()] = property;
|
|
});
|
|
properties.html = "innerHTML";
|
|
properties.text = document.createElement("div").textContent == null ? "innerText" : "textContent";
|
|
Object.forEach(properties, function(real, key) {
|
|
propertySetters[key] = function(node, value) {
|
|
node[real] = value;
|
|
};
|
|
propertyGetters[key] = function(node) {
|
|
return node[real];
|
|
};
|
|
});
|
|
propertySetters.text = function(setter) {
|
|
return function(node, value) {
|
|
if (node.get("tag") == "style") node.set("html", value); else node[properties.text] = value;
|
|
};
|
|
}(propertySetters.text);
|
|
propertyGetters.text = function(getter) {
|
|
return function(node) {
|
|
return node.get("tag") == "style" ? node.innerHTML : getter(node);
|
|
};
|
|
}(propertyGetters.text);
|
|
var bools = [ "compact", "nowrap", "ismap", "declare", "noshade", "checked", "disabled", "readOnly", "multiple", "selected", "noresize", "defer", "defaultChecked", "autofocus", "controls", "autoplay", "loop" ];
|
|
var booleans = {};
|
|
Array.forEach(bools, function(bool) {
|
|
var lower = bool.toLowerCase();
|
|
booleans[lower] = bool;
|
|
propertySetters[lower] = function(node, value) {
|
|
node[bool] = !!value;
|
|
};
|
|
propertyGetters[lower] = function(node) {
|
|
return !!node[bool];
|
|
};
|
|
});
|
|
Object.append(propertySetters, {
|
|
class: function(node, value) {
|
|
"className" in node ? node.className = value || "" : node.setAttribute("class", value);
|
|
},
|
|
for: function(node, value) {
|
|
"htmlFor" in node ? node.htmlFor = value : node.setAttribute("for", value);
|
|
},
|
|
style: function(node, value) {
|
|
node.style ? node.style.cssText = value : node.setAttribute("style", value);
|
|
},
|
|
value: function(node, value) {
|
|
node.value = value != null ? value : "";
|
|
}
|
|
});
|
|
propertyGetters["class"] = function(node) {
|
|
return "className" in node ? node.className || null : node.getAttribute("class");
|
|
};
|
|
var el = document.createElement("button");
|
|
try {
|
|
el.type = "button";
|
|
} catch (e) {}
|
|
if (el.type != "button") propertySetters.type = function(node, value) {
|
|
node.setAttribute("type", value);
|
|
};
|
|
el = null;
|
|
var canChangeStyleHTML = function() {
|
|
var div = document.createElement("style"), flag = false;
|
|
try {
|
|
div.innerHTML = "#justTesing{margin: 0px;}";
|
|
flag = !!div.innerHTML;
|
|
} catch (e) {}
|
|
return flag;
|
|
}();
|
|
var input = document.createElement("input"), volatileInputValue, html5InputSupport;
|
|
input.value = "t";
|
|
input.type = "submit";
|
|
volatileInputValue = input.value != "t";
|
|
try {
|
|
input.type = "email";
|
|
html5InputSupport = input.type == "email";
|
|
} catch (e) {}
|
|
input = null;
|
|
if (volatileInputValue || !html5InputSupport) propertySetters.type = function(node, type) {
|
|
try {
|
|
var value = node.value;
|
|
node.type = type;
|
|
node.value = value;
|
|
} catch (e) {}
|
|
};
|
|
var pollutesGetAttribute = function(div) {
|
|
div.random = "attribute";
|
|
return div.getAttribute("random") == "attribute";
|
|
}(document.createElement("div"));
|
|
var hasCloneBug = function(test) {
|
|
test.innerHTML = '<object><param name="should_fix" value="the unknown" /></object>';
|
|
return test.cloneNode(true).firstChild.childNodes.length != 1;
|
|
}(document.createElement("div"));
|
|
var hasClassList = !!document.createElement("div").classList;
|
|
var classes = function(className) {
|
|
var classNames = (className || "").clean().split(" "), uniques = {};
|
|
return classNames.filter(function(className) {
|
|
if (className !== "" && !uniques[className]) return uniques[className] = className;
|
|
});
|
|
};
|
|
var addToClassList = function(name) {
|
|
this.classList.add(name);
|
|
};
|
|
var removeFromClassList = function(name) {
|
|
this.classList.remove(name);
|
|
};
|
|
Element.implement({
|
|
setProperty: function(name, value) {
|
|
var setter = propertySetters[name.toLowerCase()];
|
|
if (setter) {
|
|
setter(this, value);
|
|
} else {
|
|
var attributeWhiteList;
|
|
if (pollutesGetAttribute) attributeWhiteList = this.retrieve("$attributeWhiteList", {});
|
|
if (value == null) {
|
|
this.removeAttribute(name);
|
|
if (pollutesGetAttribute) delete attributeWhiteList[name];
|
|
} else {
|
|
this.setAttribute(name, "" + value);
|
|
if (pollutesGetAttribute) attributeWhiteList[name] = true;
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
setProperties: function(attributes) {
|
|
for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
|
|
return this;
|
|
},
|
|
getProperty: function(name) {
|
|
var getter = propertyGetters[name.toLowerCase()];
|
|
if (getter) return getter(this);
|
|
if (pollutesGetAttribute) {
|
|
var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve("$attributeWhiteList", {});
|
|
if (!attr) return null;
|
|
if (attr.expando && !attributeWhiteList[name]) {
|
|
var outer = this.outerHTML;
|
|
if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null;
|
|
attributeWhiteList[name] = true;
|
|
}
|
|
}
|
|
var result = Slick.getAttribute(this, name);
|
|
return !result && !Slick.hasAttribute(this, name) ? null : result;
|
|
},
|
|
getProperties: function() {
|
|
var args = Array.from(arguments);
|
|
return args.map(this.getProperty, this).associate(args);
|
|
},
|
|
removeProperty: function(name) {
|
|
return this.setProperty(name, null);
|
|
},
|
|
removeProperties: function() {
|
|
Array.each(arguments, this.removeProperty, this);
|
|
return this;
|
|
},
|
|
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;
|
|
},
|
|
hasClass: hasClassList ? function(className) {
|
|
return this.classList.contains(className);
|
|
} : function(className) {
|
|
return classes(this.className).contains(className);
|
|
},
|
|
addClass: hasClassList ? function(className) {
|
|
classes(className).forEach(addToClassList, this);
|
|
return this;
|
|
} : function(className) {
|
|
this.className = classes(className + " " + this.className).join(" ");
|
|
return this;
|
|
},
|
|
removeClass: hasClassList ? function(className) {
|
|
classes(className).forEach(removeFromClassList, this);
|
|
return this;
|
|
} : function(className) {
|
|
var classNames = classes(this.className);
|
|
classes(className).forEach(classNames.erase, classNames);
|
|
this.className = classNames.join(" ");
|
|
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);
|
|
},
|
|
getSelected: function() {
|
|
this.selectedIndex;
|
|
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) {
|
|
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("&");
|
|
}
|
|
});
|
|
var appendInserters = {
|
|
before: "beforeBegin",
|
|
after: "afterEnd",
|
|
bottom: "beforeEnd",
|
|
top: "afterBegin",
|
|
inside: "beforeEnd"
|
|
};
|
|
Element.implement("appendHTML", "insertAdjacentHTML" in document.createElement("div") ? function(html, where) {
|
|
this.insertAdjacentHTML(appendInserters[where || "bottom"], html);
|
|
return this;
|
|
} : function(html, where) {
|
|
var temp = new Element("div", {
|
|
html: html
|
|
}), children = temp.childNodes, fragment = temp.firstChild;
|
|
if (!fragment) return this;
|
|
if (children.length > 1) {
|
|
fragment = document.createDocumentFragment();
|
|
for (var i = 0, l = children.length; i < l; i++) {
|
|
fragment.appendChild(children[i]);
|
|
}
|
|
}
|
|
inserters[where || "bottom"](fragment, this);
|
|
return this;
|
|
});
|
|
var collected = {}, storage = {};
|
|
var get = function(uid) {
|
|
return storage[uid] || (storage[uid] = {});
|
|
};
|
|
var clean = function(item) {
|
|
var uid = item.uniqueNumber;
|
|
if (item.removeEvents) item.removeEvents();
|
|
if (item.clearAttributes) item.clearAttributes();
|
|
if (uid != null) {
|
|
delete collected[uid];
|
|
delete storage[uid];
|
|
}
|
|
return item;
|
|
};
|
|
var formProps = {
|
|
input: "checked",
|
|
option: "selected",
|
|
textarea: "value"
|
|
};
|
|
Element.implement({
|
|
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;
|
|
},
|
|
clone: function(contents, keepid) {
|
|
contents = contents !== false;
|
|
var clone = this.cloneNode(contents), ce = [ clone ], te = [ this ], i;
|
|
if (contents) {
|
|
ce.append(Array.from(clone.getElementsByTagName("*")));
|
|
te.append(Array.from(this.getElementsByTagName("*")));
|
|
}
|
|
for (i = ce.length; i--; ) {
|
|
var node = ce[i], element = te[i];
|
|
if (!keepid) node.removeAttribute("id");
|
|
if (node.clearAttributes) {
|
|
node.clearAttributes();
|
|
node.mergeAttributes(element);
|
|
node.removeAttribute("uniqueNumber");
|
|
if (node.options) {
|
|
var no = node.options, eo = element.options;
|
|
for (var j = no.length; j--; ) no[j].selected = eo[j].selected;
|
|
}
|
|
}
|
|
var prop = formProps[element.tagName.toLowerCase()];
|
|
if (prop && element[prop]) node[prop] = element[prop];
|
|
}
|
|
if (hasCloneBug) {
|
|
var co = clone.getElementsByTagName("object"), to = this.getElementsByTagName("object");
|
|
for (i = co.length; i--; ) co[i].outerHTML = to[i].outerHTML;
|
|
}
|
|
return document.id(clone);
|
|
}
|
|
});
|
|
[ Element, Window, Document ].invoke("implement", {
|
|
addListener: function(type, fn) {
|
|
if (window.attachEvent && !window.addEventListener) {
|
|
collected[Slick.uidOf(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(Slick.uidOf(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(Slick.uidOf(this));
|
|
storage[property] = value;
|
|
return this;
|
|
},
|
|
eliminate: function(property) {
|
|
var storage = get(Slick.uidOf(this));
|
|
delete storage[property];
|
|
return this;
|
|
}
|
|
});
|
|
if (window.attachEvent && !window.addEventListener) {
|
|
var gc = function() {
|
|
Object.each(collected, clean);
|
|
if (window.CollectGarbage) CollectGarbage();
|
|
window.removeListener("unload", gc);
|
|
};
|
|
window.addListener("unload", gc);
|
|
}
|
|
Element.Properties = {};
|
|
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();
|
|
}
|
|
};
|
|
Element.Properties.html = {
|
|
set: function(html) {
|
|
if (html == null) html = ""; else if (typeOf(html) == "array") html = html.join("");
|
|
if (this.styleSheet && !canChangeStyleHTML) this.styleSheet.cssText = html; else this.innerHTML = html;
|
|
},
|
|
erase: function() {
|
|
this.set("html", "");
|
|
}
|
|
};
|
|
var supportsHTML5Elements = true, supportsTableInnerHTML = true, supportsTRInnerHTML = true;
|
|
var div = document.createElement("div");
|
|
div.innerHTML = "<nav></nav>";
|
|
supportsHTML5Elements = div.childNodes.length == 1;
|
|
if (!supportsHTML5Elements) {
|
|
var tags = "abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "), fragment = document.createDocumentFragment(), l = tags.length;
|
|
while (l--) fragment.createElement(tags[l]);
|
|
}
|
|
div = null;
|
|
supportsTableInnerHTML = Function.attempt(function() {
|
|
var table = document.createElement("table");
|
|
table.innerHTML = "<tr><td></td></tr>";
|
|
return true;
|
|
});
|
|
var tr = document.createElement("tr"), html = "<td></td>";
|
|
tr.innerHTML = html;
|
|
supportsTRInnerHTML = tr.innerHTML == html;
|
|
tr = null;
|
|
if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements) {
|
|
Element.Properties.html.set = function(set) {
|
|
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;
|
|
return function(html) {
|
|
if (this.styleSheet) return set.call(this, html);
|
|
var wrap = translations[this.get("tag")];
|
|
if (!wrap && !supportsHTML5Elements) wrap = [ 0, "", "" ];
|
|
if (!wrap) return set.call(this, html);
|
|
var level = wrap[0], wrapper = document.createElement("div"), target = wrapper;
|
|
if (!supportsHTML5Elements) fragment.appendChild(wrapper);
|
|
wrapper.innerHTML = [ wrap[1], html, wrap[2] ].flatten().join("");
|
|
while (level--) target = target.firstChild;
|
|
this.empty().adopt(target.childNodes);
|
|
if (!supportsHTML5Elements) fragment.removeChild(wrapper);
|
|
wrapper = null;
|
|
};
|
|
}(Element.Properties.html.set);
|
|
}
|
|
var testForm = document.createElement("form");
|
|
testForm.innerHTML = "<select><option>s</option></select>";
|
|
if (testForm.firstChild.value != "s") Element.Properties.value = {
|
|
set: function(value) {
|
|
var tag = this.get("tag");
|
|
if (tag != "select") return this.setProperty("value", value);
|
|
var options = this.getElements("option");
|
|
value = String(value);
|
|
for (var i = 0; i < options.length; i++) {
|
|
var option = options[i], attr = option.getAttributeNode("value"), optionValue = attr && attr.specified ? option.value : option.get("text");
|
|
if (optionValue === value) return option.selected = true;
|
|
}
|
|
},
|
|
get: function() {
|
|
var option = this, tag = option.get("tag");
|
|
if (tag != "select" && tag != "option") return this.getProperty("value");
|
|
if (tag == "select" && !(option = option.getSelected()[0])) return "";
|
|
var attr = option.getAttributeNode("value");
|
|
return attr && attr.specified ? option.value : option.get("text");
|
|
}
|
|
};
|
|
testForm = null;
|
|
if (document.createElement("div").getAttributeNode("id")) Element.Properties.id = {
|
|
set: function(id) {
|
|
this.id = this.getAttributeNode("id").value = id;
|
|
},
|
|
get: function() {
|
|
return this.id || null;
|
|
},
|
|
erase: function() {
|
|
this.id = this.getAttributeNode("id").value = "";
|
|
}
|
|
};
|
|
})();
|
|
|
|
(function() {
|
|
var _keys = {};
|
|
var normalizeWheelSpeed = function(event) {
|
|
var normalized;
|
|
if (event.wheelDelta) {
|
|
normalized = event.wheelDelta % 120 == 0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
|
|
} else {
|
|
var rawAmount = event.deltaY || event.detail || 0;
|
|
normalized = -(rawAmount % 3 == 0 ? rawAmount / 3 : rawAmount * 10);
|
|
}
|
|
return normalized;
|
|
};
|
|
var DOMEvent = this.DOMEvent = new Type("DOMEvent", function(event, win) {
|
|
if (!win) win = window;
|
|
event = event || win.event;
|
|
if (event.$extended) return event;
|
|
this.event = event;
|
|
this.$extended = true;
|
|
this.shift = event.shiftKey;
|
|
this.control = event.ctrlKey;
|
|
this.alt = event.altKey;
|
|
this.meta = event.metaKey;
|
|
var type = this.type = event.type;
|
|
var target = event.target || event.srcElement;
|
|
while (target && target.nodeType == 3) target = target.parentNode;
|
|
this.target = document.id(target);
|
|
if (type.indexOf("key") == 0) {
|
|
var code = this.code = event.which || event.keyCode;
|
|
this.key = _keys[code];
|
|
if (type == "keydown" || type == "keyup") {
|
|
if (code > 111 && code < 124) this.key = "f" + (code - 111); else if (code > 95 && code < 106) this.key = code - 96;
|
|
}
|
|
if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
|
|
} else if (type == "click" || type == "dblclick" || type == "contextmenu" || type == "wheel" || type == "DOMMouseScroll" || type.indexOf("mouse") == 0) {
|
|
var doc = win.document;
|
|
doc = !doc.compatMode || doc.compatMode == "CSS1Compat" ? doc.html : doc.body;
|
|
this.page = {
|
|
x: event.pageX != null ? event.pageX : event.clientX + doc.scrollLeft,
|
|
y: event.pageY != null ? event.pageY : event.clientY + doc.scrollTop
|
|
};
|
|
this.client = {
|
|
x: event.pageX != null ? event.pageX - win.pageXOffset : event.clientX,
|
|
y: event.pageY != null ? event.pageY - win.pageYOffset : event.clientY
|
|
};
|
|
if (type == "DOMMouseScroll" || type == "wheel" || type == "mousewheel") this.wheel = normalizeWheelSpeed(event);
|
|
this.rightClick = event.which == 3 || event.button == 2;
|
|
if (type == "mouseover" || type == "mouseout") {
|
|
var related = event.relatedTarget || event[(type == "mouseover" ? "from" : "to") + "Element"];
|
|
while (related && related.nodeType == 3) related = related.parentNode;
|
|
this.relatedTarget = document.id(related);
|
|
}
|
|
} else if (type.indexOf("touch") == 0 || type.indexOf("gesture") == 0) {
|
|
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];
|
|
this.page = {
|
|
x: touch.pageX,
|
|
y: touch.pageY
|
|
};
|
|
this.client = {
|
|
x: touch.clientX,
|
|
y: touch.clientY
|
|
};
|
|
}
|
|
}
|
|
if (!this.client) this.client = {};
|
|
if (!this.page) this.page = {};
|
|
});
|
|
DOMEvent.implement({
|
|
stop: function() {
|
|
return this.preventDefault().stopPropagation();
|
|
},
|
|
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;
|
|
}
|
|
});
|
|
DOMEvent.defineKey = function(code, key) {
|
|
_keys[code] = key;
|
|
return this;
|
|
};
|
|
DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
|
|
DOMEvent.defineKeys({
|
|
"38": "up",
|
|
"40": "down",
|
|
"37": "left",
|
|
"39": "right",
|
|
"27": "esc",
|
|
"32": "space",
|
|
"8": "backspace",
|
|
"9": "tab",
|
|
"46": "delete",
|
|
"13": "enter"
|
|
});
|
|
})();
|
|
|
|
(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, type);
|
|
if (custom.condition) {
|
|
condition = function(event) {
|
|
if (custom.condition.call(this, event, type)) return fn.call(this, event);
|
|
return true;
|
|
};
|
|
}
|
|
if (custom.base) realType = Function.from(custom.base).call(this, type);
|
|
}
|
|
var defn = function() {
|
|
return fn.call(self);
|
|
};
|
|
var nativeEvent = Element.NativeEvents[realType];
|
|
if (nativeEvent) {
|
|
if (nativeEvent == 2) {
|
|
defn = function(event) {
|
|
event = new DOMEvent(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);
|
|
if (custom.base) type = Function.from(custom.base).call(this, 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,
|
|
wheel: 2,
|
|
mousewheel: 2,
|
|
DOMMouseScroll: 2,
|
|
mouseover: 2,
|
|
mouseout: 2,
|
|
mousemove: 2,
|
|
selectstart: 2,
|
|
selectend: 2,
|
|
keydown: 2,
|
|
keypress: 2,
|
|
keyup: 2,
|
|
orientationchange: 2,
|
|
touchstart: 2,
|
|
touchmove: 2,
|
|
touchend: 2,
|
|
touchcancel: 2,
|
|
gesturestart: 2,
|
|
gesturechange: 2,
|
|
gestureend: 2,
|
|
focus: 2,
|
|
blur: 2,
|
|
change: 2,
|
|
reset: 2,
|
|
select: 2,
|
|
submit: 2,
|
|
paste: 2,
|
|
input: 2,
|
|
load: 2,
|
|
unload: 1,
|
|
beforeunload: 2,
|
|
resize: 1,
|
|
move: 1,
|
|
DOMContentLoaded: 1,
|
|
readystatechange: 1,
|
|
hashchange: 1,
|
|
popstate: 2,
|
|
error: 1,
|
|
abort: 1,
|
|
scroll: 1,
|
|
message: 2
|
|
};
|
|
Element.Events = {
|
|
mousewheel: {
|
|
base: "onwheel" in document ? "wheel" : "onmousewheel" in document ? "mousewheel" : "DOMMouseScroll"
|
|
}
|
|
};
|
|
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);
|
|
};
|
|
if ("onmouseenter" in document.documentElement) {
|
|
Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2;
|
|
Element.MouseenterCheck = check;
|
|
} else {
|
|
Element.Events.mouseenter = {
|
|
base: "mouseover",
|
|
condition: check
|
|
};
|
|
Element.Events.mouseleave = {
|
|
base: "mouseout",
|
|
condition: check
|
|
};
|
|
}
|
|
if (!window.addEventListener) {
|
|
Element.NativeEvents.propertychange = 2;
|
|
Element.Events.change = {
|
|
base: function() {
|
|
var type = this.type;
|
|
return this.get("tag") == "input" && (type == "radio" || type == "checkbox") ? "propertychange" : "change";
|
|
},
|
|
condition: function(event) {
|
|
return event.type != "propertychange" || event.event.propertyName == "checked";
|
|
}
|
|
};
|
|
}
|
|
})();
|
|
|
|
(function() {
|
|
var eventListenerSupport = !!window.addEventListener;
|
|
Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2;
|
|
var bubbleUp = function(self, match, fn, event, target) {
|
|
while (target && target != self) {
|
|
if (match(target, event)) return fn.call(target, event, target);
|
|
target = document.id(target.parentNode);
|
|
}
|
|
};
|
|
var map = {
|
|
mouseenter: {
|
|
base: "mouseover",
|
|
condition: Element.MouseenterCheck
|
|
},
|
|
mouseleave: {
|
|
base: "mouseout",
|
|
condition: Element.MouseenterCheck
|
|
},
|
|
focus: {
|
|
base: "focus" + (eventListenerSupport ? "" : "in"),
|
|
capture: true
|
|
},
|
|
blur: {
|
|
base: eventListenerSupport ? "blur" : "focusout",
|
|
capture: true
|
|
}
|
|
};
|
|
var _key = "$delegation:";
|
|
var formObserver = function(type) {
|
|
return {
|
|
base: "focusin",
|
|
remove: function(self, uid) {
|
|
var list = self.retrieve(_key + type + "listeners", {})[uid];
|
|
if (list && list.forms) for (var i = list.forms.length; i--; ) {
|
|
if (list.forms[i].removeEvent) list.forms[i].removeEvent(type, list.fns[i]);
|
|
}
|
|
},
|
|
listen: function(self, match, fn, event, target, uid) {
|
|
var form = target.get("tag") == "form" ? target : event.target.getParent("form");
|
|
if (!form) return;
|
|
var listeners = self.retrieve(_key + type + "listeners", {}), listener = listeners[uid] || {
|
|
forms: [],
|
|
fns: []
|
|
}, forms = listener.forms, fns = listener.fns;
|
|
if (forms.indexOf(form) != -1) return;
|
|
forms.push(form);
|
|
var _fn = function(event) {
|
|
bubbleUp(self, match, fn, event, target);
|
|
};
|
|
form.addEvent(type, _fn);
|
|
fns.push(_fn);
|
|
listeners[uid] = listener;
|
|
self.store(_key + type + "listeners", listeners);
|
|
}
|
|
};
|
|
};
|
|
var inputObserver = function(type) {
|
|
return {
|
|
base: "focusin",
|
|
listen: function(self, match, fn, event, target) {
|
|
var events = {
|
|
blur: function() {
|
|
this.removeEvents(events);
|
|
}
|
|
};
|
|
events[type] = function(event) {
|
|
bubbleUp(self, match, fn, event, target);
|
|
};
|
|
event.target.addEvents(events);
|
|
}
|
|
};
|
|
};
|
|
if (!eventListenerSupport) Object.append(map, {
|
|
submit: formObserver("submit"),
|
|
reset: formObserver("reset"),
|
|
change: inputObserver("change"),
|
|
select: inputObserver("select")
|
|
});
|
|
var proto = Element.prototype, addEvent = proto.addEvent, removeEvent = proto.removeEvent;
|
|
var relay = function(old, method) {
|
|
return function(type, fn, useCapture) {
|
|
if (type.indexOf(":relay") == -1) return old.call(this, type, fn, useCapture);
|
|
var parsed = Slick.parse(type).expressions[0][0];
|
|
if (parsed.pseudos[0].key != "relay") return old.call(this, type, fn, useCapture);
|
|
var newType = parsed.tag;
|
|
parsed.pseudos.slice(1).each(function(pseudo) {
|
|
newType += ":" + pseudo.key + (pseudo.value ? "(" + pseudo.value + ")" : "");
|
|
});
|
|
old.call(this, type, fn);
|
|
return method.call(this, newType, parsed.pseudos[0].value, fn);
|
|
};
|
|
};
|
|
var delegation = {
|
|
addEvent: function(type, match, fn) {
|
|
var storage = this.retrieve("$delegates", {}), stored = storage[type];
|
|
if (stored) for (var _uid in stored) {
|
|
if (stored[_uid].fn == fn && stored[_uid].match == match) return this;
|
|
}
|
|
var _type = type, _match = match, _fn = fn, _map = map[type] || {};
|
|
type = _map.base || _type;
|
|
match = function(target) {
|
|
return Slick.match(target, _match);
|
|
};
|
|
var elementEvent = Element.Events[_type];
|
|
if (_map.condition || elementEvent && elementEvent.condition) {
|
|
var __match = match, condition = _map.condition || elementEvent.condition;
|
|
match = function(target, event) {
|
|
return __match(target, event) && condition.call(target, event, type);
|
|
};
|
|
}
|
|
var self = this, uid = String.uniqueID();
|
|
var delegator = _map.listen ? function(event, target) {
|
|
if (!target && event && event.target) target = event.target;
|
|
if (target) _map.listen(self, match, fn, event, target, uid);
|
|
} : function(event, target) {
|
|
if (!target && event && event.target) target = event.target;
|
|
if (target) bubbleUp(self, match, fn, event, target);
|
|
};
|
|
if (!stored) stored = {};
|
|
stored[uid] = {
|
|
match: _match,
|
|
fn: _fn,
|
|
delegator: delegator
|
|
};
|
|
storage[_type] = stored;
|
|
return addEvent.call(this, type, delegator, _map.capture);
|
|
},
|
|
removeEvent: function(type, match, fn, _uid) {
|
|
var storage = this.retrieve("$delegates", {}), stored = storage[type];
|
|
if (!stored) return this;
|
|
if (_uid) {
|
|
var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {};
|
|
type = _map.base || _type;
|
|
if (_map.remove) _map.remove(this, _uid);
|
|
delete stored[_uid];
|
|
storage[_type] = stored;
|
|
return removeEvent.call(this, type, delegator, _map.capture);
|
|
}
|
|
var __uid, s;
|
|
if (fn) for (__uid in stored) {
|
|
s = stored[__uid];
|
|
if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid);
|
|
} else for (__uid in stored) {
|
|
s = stored[__uid];
|
|
if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid);
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
[ Element, Window, Document ].invoke("implement", {
|
|
addEvent: relay(addEvent, delegation.addEvent),
|
|
removeEvent: relay(removeEvent, delegation.removeEvent)
|
|
});
|
|
})();
|
|
|
|
(function() {
|
|
var html = document.html, el;
|
|
el = document.createElement("div");
|
|
el.style.color = "red";
|
|
el.style.color = null;
|
|
var doesNotRemoveStyles = el.style.color == "red";
|
|
var border = "1px solid #123abc";
|
|
el.style.border = border;
|
|
var returnsBordersInWrongOrder = el.style.border != border;
|
|
el = null;
|
|
var hasGetComputedStyle = !!window.getComputedStyle, supportBorderRadius = document.createElement("div").style.borderRadius != null;
|
|
Element.Properties.styles = {
|
|
set: function(styles) {
|
|
this.setStyles(styles);
|
|
}
|
|
};
|
|
var hasOpacity = html.style.opacity != null, hasFilter = html.style.filter != null, reAlpha = /alpha\(opacity=([\d.]+)\)/i;
|
|
var setVisibility = function(element, opacity) {
|
|
element.store("$opacity", opacity);
|
|
element.style.visibility = opacity > 0 || opacity == null ? "visible" : "hidden";
|
|
};
|
|
var setFilter = function(element, regexp, value) {
|
|
var style = element.style, filter = style.filter || element.getComputedStyle("filter") || "";
|
|
style.filter = (regexp.test(filter) ? filter.replace(regexp, value) : filter + " " + value).trim();
|
|
if (!style.filter) style.removeAttribute("filter");
|
|
};
|
|
var setOpacity = hasOpacity ? function(element, opacity) {
|
|
element.style.opacity = opacity;
|
|
} : hasFilter ? function(element, opacity) {
|
|
if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1;
|
|
if (opacity == null || opacity == 1) {
|
|
setFilter(element, reAlpha, "");
|
|
if (opacity == 1 && getOpacity(element) != 1) setFilter(element, reAlpha, "alpha(opacity=100)");
|
|
} else {
|
|
setFilter(element, reAlpha, "alpha(opacity=" + (opacity * 100).limit(0, 100).round() + ")");
|
|
}
|
|
} : setVisibility;
|
|
var getOpacity = hasOpacity ? function(element) {
|
|
var opacity = element.style.opacity || element.getComputedStyle("opacity");
|
|
return opacity == "" ? 1 : opacity.toFloat();
|
|
} : hasFilter ? function(element) {
|
|
var filter = element.style.filter || element.getComputedStyle("filter"), opacity;
|
|
if (filter) opacity = filter.match(reAlpha);
|
|
return opacity == null || filter == null ? 1 : opacity[1] / 100;
|
|
} : function(element) {
|
|
var opacity = element.retrieve("$opacity");
|
|
if (opacity == null) opacity = element.style.visibility == "hidden" ? 0 : 1;
|
|
return opacity;
|
|
};
|
|
var floatName = html.style.cssFloat == null ? "styleFloat" : "cssFloat", namedPositions = {
|
|
left: "0%",
|
|
top: "0%",
|
|
center: "50%",
|
|
right: "100%",
|
|
bottom: "100%"
|
|
}, hasBackgroundPositionXY = html.style.backgroundPositionX != null;
|
|
var removeStyle = function(style, property) {
|
|
if (property == "backgroundPosition") {
|
|
style.removeAttribute(property + "X");
|
|
property += "Y";
|
|
}
|
|
style.removeAttribute(property);
|
|
};
|
|
Element.implement({
|
|
getComputedStyle: function(property) {
|
|
if (!hasGetComputedStyle && 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()) : "";
|
|
},
|
|
setStyle: function(property, value) {
|
|
if (property == "opacity") {
|
|
if (value != null) value = parseFloat(value);
|
|
setOpacity(this, value);
|
|
return this;
|
|
}
|
|
property = (property == "float" ? floatName : 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;
|
|
if ((value == "" || value == null) && doesNotRemoveStyles && this.style.removeAttribute) {
|
|
removeStyle(this.style, property);
|
|
}
|
|
return this;
|
|
},
|
|
getStyle: function(property) {
|
|
if (property == "opacity") return getOpacity(this);
|
|
property = (property == "float" ? floatName : property).camelCase();
|
|
if (supportBorderRadius && property.indexOf("borderRadius") != -1) {
|
|
return [ "borderTopLeftRadius", "borderTopRightRadius", "borderBottomRightRadius", "borderBottomLeftRadius" ].map(function(corner) {
|
|
return this.style[corner] || "0px";
|
|
}, this).join(" ");
|
|
}
|
|
var result = this.style[property];
|
|
if (!result || property == "zIndex") {
|
|
if (Element.ShortStyles.hasOwnProperty(property)) {
|
|
result = [];
|
|
for (var s in Element.ShortStyles[property]) result.push(this.getStyle(s));
|
|
return result.join(" ");
|
|
}
|
|
result = this.getComputedStyle(property);
|
|
}
|
|
if (hasBackgroundPositionXY && /^backgroundPosition[XY]?$/.test(property)) {
|
|
return result.replace(/(top|right|bottom|left)/g, function(position) {
|
|
return namedPositions[position];
|
|
}) || "0px";
|
|
}
|
|
if (!result && property == "backgroundPosition") return "0px 0px";
|
|
if (result) {
|
|
result = String(result);
|
|
var color = result.match(/rgba?\([\d\s,]+\)/);
|
|
if (color) result = result.replace(color[0], color[0].rgbToHex());
|
|
}
|
|
if (!hasGetComputedStyle && !this.style[property]) {
|
|
if (/^(height|width)$/.test(property) && !/px$/.test(result)) {
|
|
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 (/^border(.+)Width|margin|padding/.test(property) && isNaN(parseFloat(result))) {
|
|
return "0px";
|
|
}
|
|
}
|
|
if (returnsBordersInWrongOrder && /^border(Top|Right|Bottom|Left)?$/.test(property) && /^#/.test(result)) {
|
|
return result.replace(/^(.+)\s(.+)\s(.+)$/, "$2 $3 $1");
|
|
}
|
|
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(@, @, @)",
|
|
backgroundSize: "@px",
|
|
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: "@",
|
|
borderRadius: "@px @px @px @px"
|
|
};
|
|
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(@, @, @)";
|
|
});
|
|
if (hasBackgroundPositionXY) Element.ShortStyles.backgroundPosition = {
|
|
backgroundPositionX: "@",
|
|
backgroundPositionY: "@"
|
|
};
|
|
})();
|
|
|
|
(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 heightComponents = [ "height", "paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth" ], widthComponents = [ "width", "paddingLeft", "paddingRight", "borderLeftWidth", "borderRightWidth" ];
|
|
var svgCalculateSize = function(el) {
|
|
var gCS = window.getComputedStyle(el), bounds = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
heightComponents.each(function(css) {
|
|
bounds.y += parseFloat(gCS[css]);
|
|
});
|
|
widthComponents.each(function(css) {
|
|
bounds.x += parseFloat(gCS[css]);
|
|
});
|
|
return bounds;
|
|
};
|
|
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();
|
|
if (!window.getComputedStyle) return {
|
|
x: this.offsetWidth,
|
|
y: this.offsetHeight
|
|
};
|
|
if (this.get("tag") == "svg") return svgCalculateSize(this);
|
|
var bounds = this.getBoundingClientRect();
|
|
return {
|
|
x: bounds.width,
|
|
y: bounds.height
|
|
};
|
|
},
|
|
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() {
|
|
var hasGetBoundingClientRect = this.getBoundingClientRect;
|
|
if (hasGetBoundingClientRect) {
|
|
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;
|
|
element = element.offsetParent;
|
|
}
|
|
return position;
|
|
},
|
|
getPosition: function(relative) {
|
|
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
|
|
};
|
|
}
|
|
});
|
|
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;
|
|
}
|
|
})();
|
|
|
|
Element.alias({
|
|
position: "setPosition"
|
|
});
|
|
|
|
[ 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;
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var Fx = this.Fx = new Class({
|
|
Implements: [ Chain, Events, Options ],
|
|
options: {
|
|
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 = 1e3 / 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.isPaused()) pushInstance.call(this, this.options.fps);
|
|
return this;
|
|
},
|
|
isRunning: function() {
|
|
var list = instances[this.options.fps];
|
|
return list && list.contains(this);
|
|
},
|
|
isPaused: function() {
|
|
return this.frame < this.frames && !this.isRunning();
|
|
}
|
|
});
|
|
Fx.compute = function(from, to, delta) {
|
|
return (to - from) * delta + from;
|
|
};
|
|
Fx.Durations = {
|
|
short: 250,
|
|
normal: 500,
|
|
long: 1e3
|
|
};
|
|
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(1e3 / 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]);
|
|
}
|
|
}
|
|
};
|
|
})();
|
|
|
|
Fx.CSS = new Class({
|
|
Extends: Fx,
|
|
prepare: function(element, property, values) {
|
|
values = Array.from(values);
|
|
var from = values[0], to = values[1];
|
|
if (to == null) {
|
|
to = from;
|
|
from = element.getStyle(property);
|
|
var unit = this.options.unit;
|
|
if (unit && from && typeof from == "string" && from.slice(-unit.length) != unit && parseFloat(from) != 0) {
|
|
element.setStyle(property, to + unit);
|
|
var value = element.getComputedStyle(property);
|
|
if (!/px$/.test(value)) {
|
|
value = element.style[("pixel-" + property).camelCase()];
|
|
if (value == null) {
|
|
var left = element.style.left;
|
|
element.style.left = to + unit;
|
|
value = element.style.pixelLeft;
|
|
element.style.left = left;
|
|
}
|
|
}
|
|
from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0);
|
|
element.setStyle(property, from + unit);
|
|
}
|
|
}
|
|
return {
|
|
from: this.parse(from),
|
|
to: this.parse(to)
|
|
};
|
|
},
|
|
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;
|
|
});
|
|
},
|
|
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;
|
|
},
|
|
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;
|
|
},
|
|
render: function(element, property, value, unit) {
|
|
element.setStyle(property, this.serve(value, unit));
|
|
},
|
|
search: function(selector) {
|
|
if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
|
|
var to = {}, selectorTest = new RegExp("^" + selector.escapeRegExp() + "$");
|
|
var searchStyles = function(rules) {
|
|
Array.each(rules, function(rule, i) {
|
|
if (rule.media) {
|
|
searchStyles(rule.rules || rule.cssRules);
|
|
return;
|
|
}
|
|
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;
|
|
});
|
|
});
|
|
};
|
|
Array.each(document.styleSheets, function(sheet, j) {
|
|
var href = sheet.href;
|
|
if (href && href.indexOf("://") > -1 && href.indexOf(document.domain) == -1) return;
|
|
var rules = sheet.rules || sheet.cssRules;
|
|
searchStyles(rules);
|
|
});
|
|
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;
|
|
}
|
|
}
|
|
};
|
|
|
|
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;
|
|
}
|
|
});
|
|
|
|
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 <= .5 ? transition(2 * pos, params) : 2 - transition(2 * (1 - pos), params)) / 2;
|
|
}
|
|
});
|
|
};
|
|
|
|
Fx.Transitions = {
|
|
linear: function(zero) {
|
|
return zero;
|
|
}
|
|
};
|
|
|
|
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);
|
|
});
|
|
});
|
|
|
|
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(property, from, to);
|
|
return this;
|
|
},
|
|
fade: function(how) {
|
|
var fade = this.get("tween"), method, args = [ "opacity" ].append(arguments), toggle;
|
|
if (args[1] == null) args[1] = "toggle";
|
|
switch (args[1]) {
|
|
case "in":
|
|
method = "start";
|
|
args[1] = 1;
|
|
break;
|
|
|
|
case "out":
|
|
method = "start";
|
|
args[1] = 0;
|
|
break;
|
|
|
|
case "show":
|
|
method = "set";
|
|
args[1] = 1;
|
|
break;
|
|
|
|
case "hide":
|
|
method = "set";
|
|
args[1] = 0;
|
|
break;
|
|
|
|
case "toggle":
|
|
var flag = this.retrieve("fade:flag", this.getStyle("opacity") == 1);
|
|
method = "start";
|
|
args[1] = flag ? 0 : 1;
|
|
this.store("fade:flag", !flag);
|
|
toggle = true;
|
|
break;
|
|
|
|
default:
|
|
method = "start";
|
|
}
|
|
if (!toggle) this.eliminate("fade:flag");
|
|
fade[method].apply(fade, args);
|
|
var to = args[args.length - 1];
|
|
if (method == "set" || to != 0) this.setStyle("visibility", to == 0 ? "hidden" : "visible"); else fade.chain(function() {
|
|
this.element.setStyle("visibility", "hidden");
|
|
this.callChain();
|
|
});
|
|
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;
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var empty = function() {}, progressSupport = "onprogress" in new Browser.Request();
|
|
var Request = this.Request = new Class({
|
|
Implements: [ Chain, Events, Options ],
|
|
options: {
|
|
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;
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
delete 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.indexOf("?") > -1 ? "&" : "?") + String.uniqueID();
|
|
if (data && (method == "get" || method == "delete")) {
|
|
url += (url.indexOf("?") > -1 ? "&" : "?") + 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.withCredentials && "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(); else 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();
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
delete 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", "patch", "head", "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD" ].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;
|
|
}
|
|
});
|
|
})();
|
|
|
|
if (typeof JSON == "undefined") this.JSON = {};
|
|
|
|
(function() {
|
|
var special = {
|
|
"\b": "\\b",
|
|
" ": "\\t",
|
|
"\n": "\\n",
|
|
"\f": "\\f",
|
|
"\r": "\\r",
|
|
'"': '\\"',
|
|
"\\": "\\\\"
|
|
};
|
|
var escape = function(chr) {
|
|
return special[chr] || "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).slice(-4);
|
|
};
|
|
JSON.validate = function(string) {
|
|
string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]").replace(/(?:^|:|,)(?:\s*\[)+/g, "");
|
|
return /^[\],:{}\s]*$/.test(string);
|
|
};
|
|
JSON.encode = JSON.stringify ? function(obj) {
|
|
return JSON.stringify(obj);
|
|
} : function(obj) {
|
|
if (obj && obj.toJSON) obj = obj.toJSON();
|
|
switch (typeOf(obj)) {
|
|
case "string":
|
|
return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
|
|
|
|
case "array":
|
|
return "[" + obj.map(JSON.encode).clean() + "]";
|
|
|
|
case "object":
|
|
case "hash":
|
|
var string = [];
|
|
Object.each(obj, function(value, key) {
|
|
var json = JSON.encode(value);
|
|
if (json) string.push(JSON.encode(key) + ":" + json);
|
|
});
|
|
return "{" + string + "}";
|
|
|
|
case "number":
|
|
case "boolean":
|
|
return "" + obj;
|
|
|
|
case "null":
|
|
return "null";
|
|
}
|
|
return null;
|
|
};
|
|
JSON.secure = true;
|
|
JSON.decode = function(string, secure) {
|
|
if (!string || typeOf(string) != "string") return null;
|
|
if (secure == null) secure = JSON.secure;
|
|
if (secure) {
|
|
if (JSON.parse) return JSON.parse(string);
|
|
if (!JSON.validate(string)) throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");
|
|
}
|
|
return eval("(" + string + ")");
|
|
};
|
|
})();
|
|
|
|
Request.JSON = new Class({
|
|
Extends: Request,
|
|
options: {
|
|
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);
|
|
}
|
|
});
|
|
|
|
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 * 1e3);
|
|
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();
|
|
};
|
|
|
|
(function(window, document) {
|
|
var ready, loaded, checks = [], shouldPoll, timer, testElement = document.createElement("div");
|
|
var domready = function() {
|
|
clearTimeout(timer);
|
|
if (!ready) {
|
|
Browser.loaded = ready = true;
|
|
document.removeListener("DOMContentLoaded", domready).removeListener("readystatechange", check);
|
|
document.fireEvent("domready");
|
|
window.fireEvent("domready");
|
|
}
|
|
document = window = testElement = null;
|
|
};
|
|
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);
|
|
var doScrollWorks = function() {
|
|
try {
|
|
testElement.doScroll();
|
|
return true;
|
|
} catch (e) {}
|
|
return false;
|
|
};
|
|
if (testElement.doScroll && !doScrollWorks()) {
|
|
checks.push(doScrollWorks);
|
|
shouldPoll = true;
|
|
}
|
|
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);
|
|
}
|
|
};
|
|
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;
|
|
}
|
|
};
|
|
window.addEvent("load", function() {
|
|
loaded = true;
|
|
});
|
|
})(window, document);
|
|
|
|
MooTools.More = {
|
|
version: "1.5.1",
|
|
build: "2dd695ba957196ae4b0275a690765d6636a61ccd"
|
|
};
|
|
|
|
(function() {
|
|
Events.Pseudos = function(pseudos, addEvent, removeEvent) {
|
|
var storeKey = "_monitorEvents:";
|
|
var storageOf = function(object) {
|
|
return {
|
|
store: object.store ? function(key, value) {
|
|
object.store(storeKey + key, value);
|
|
} : function(key, value) {
|
|
(object._monitorEvents || (object._monitorEvents = {}))[key] = value;
|
|
},
|
|
retrieve: object.retrieve ? function(key, dflt) {
|
|
return object.retrieve(storeKey + key, dflt);
|
|
} : function(key, dflt) {
|
|
if (!object._monitorEvents) return dflt;
|
|
return object._monitorEvents[key] || dflt;
|
|
}
|
|
};
|
|
};
|
|
var splitType = function(type) {
|
|
if (type.indexOf(":") == -1 || !pseudos) return null;
|
|
var parsed = Slick.parse(type).expressions[0][0], parsedPseudos = parsed.pseudos, l = parsedPseudos.length, splits = [];
|
|
while (l--) {
|
|
var pseudo = parsedPseudos[l].key, listener = pseudos[pseudo];
|
|
if (listener != null) splits.push({
|
|
event: parsed.tag,
|
|
value: parsedPseudos[l].value,
|
|
pseudo: pseudo,
|
|
original: type,
|
|
listener: listener
|
|
});
|
|
}
|
|
return splits.length ? splits : null;
|
|
};
|
|
return {
|
|
addEvent: function(type, fn, internal) {
|
|
var split = splitType(type);
|
|
if (!split) return addEvent.call(this, type, fn, internal);
|
|
var storage = storageOf(this), events = storage.retrieve(type, []), eventType = split[0].event, args = Array.slice(arguments, 2), stack = fn, self = this;
|
|
split.each(function(item) {
|
|
var listener = item.listener, stackFn = stack;
|
|
if (listener == false) eventType += ":" + item.pseudo + "(" + item.value + ")"; else stack = function() {
|
|
listener.call(self, item, stackFn, arguments, stack);
|
|
};
|
|
});
|
|
events.include({
|
|
type: eventType,
|
|
event: fn,
|
|
monitor: stack
|
|
});
|
|
storage.store(type, events);
|
|
if (type != eventType) addEvent.apply(this, [ type, fn ].concat(args));
|
|
return addEvent.apply(this, [ eventType, stack ].concat(args));
|
|
},
|
|
removeEvent: function(type, fn) {
|
|
var split = splitType(type);
|
|
if (!split) return removeEvent.call(this, type, fn);
|
|
var storage = storageOf(this), events = storage.retrieve(type);
|
|
if (!events) return this;
|
|
var args = Array.slice(arguments, 2);
|
|
removeEvent.apply(this, [ type, fn ].concat(args));
|
|
events.each(function(monitor, i) {
|
|
if (!fn || monitor.event == fn) removeEvent.apply(this, [ monitor.type, monitor.monitor ].concat(args));
|
|
delete events[i];
|
|
}, this);
|
|
storage.store(type, events);
|
|
return this;
|
|
}
|
|
};
|
|
};
|
|
var pseudos = {
|
|
once: function(split, fn, args, monitor) {
|
|
fn.apply(this, args);
|
|
this.removeEvent(split.event, monitor).removeEvent(split.original, fn);
|
|
},
|
|
throttle: function(split, fn, args) {
|
|
if (!fn._throttled) {
|
|
fn.apply(this, args);
|
|
fn._throttled = setTimeout(function() {
|
|
fn._throttled = false;
|
|
}, split.value || 250);
|
|
}
|
|
},
|
|
pause: function(split, fn, args) {
|
|
clearTimeout(fn._pause);
|
|
fn._pause = fn.delay(split.value || 250, this, args);
|
|
}
|
|
};
|
|
Events.definePseudo = function(key, listener) {
|
|
pseudos[key] = listener;
|
|
return this;
|
|
};
|
|
Events.lookupPseudo = function(key) {
|
|
return pseudos[key];
|
|
};
|
|
var proto = Events.prototype;
|
|
Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent));
|
|
[ "Request", "Fx" ].each(function(klass) {
|
|
if (this[klass]) this[klass].implement(Events.prototype);
|
|
});
|
|
})();
|
|
|
|
var Drag = new Class({
|
|
Implements: [ Events, Options ],
|
|
options: {
|
|
snap: 6,
|
|
unit: "px",
|
|
grid: false,
|
|
style: true,
|
|
limit: false,
|
|
handle: false,
|
|
invert: false,
|
|
preventDefault: false,
|
|
stopPropagation: false,
|
|
compensateScroll: false,
|
|
modifiers: {
|
|
x: "left",
|
|
y: "top"
|
|
}
|
|
},
|
|
initialize: function() {
|
|
var params = Array.link(arguments, {
|
|
options: Type.isObject,
|
|
element: function(obj) {
|
|
return obj != null;
|
|
}
|
|
});
|
|
this.element = document.id(params.element);
|
|
this.document = this.element.getDocument();
|
|
this.setOptions(params.options || {});
|
|
var htype = typeOf(this.options.handle);
|
|
this.handles = (htype == "array" || htype == "collection" ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
|
|
this.mouse = {
|
|
now: {},
|
|
pos: {}
|
|
};
|
|
this.value = {
|
|
start: {},
|
|
now: {}
|
|
};
|
|
this.offsetParent = function(el) {
|
|
var offsetParent = el.getOffsetParent();
|
|
var isBody = !offsetParent || /^(?:body|html)$/i.test(offsetParent.tagName);
|
|
return isBody ? window : document.id(offsetParent);
|
|
}(this.element);
|
|
this.selection = "selectstart" in document ? "selectstart" : "mousedown";
|
|
this.compensateScroll = {
|
|
start: {},
|
|
diff: {},
|
|
last: {}
|
|
};
|
|
if ("ondragstart" in document && !("FileReader" in window) && !Drag.ondragstartFixed) {
|
|
document.ondragstart = Function.from(false);
|
|
Drag.ondragstartFixed = true;
|
|
}
|
|
this.bound = {
|
|
start: this.start.bind(this),
|
|
check: this.check.bind(this),
|
|
drag: this.drag.bind(this),
|
|
stop: this.stop.bind(this),
|
|
cancel: this.cancel.bind(this),
|
|
eventStop: Function.from(false),
|
|
scrollListener: this.scrollListener.bind(this)
|
|
};
|
|
this.attach();
|
|
},
|
|
attach: function() {
|
|
this.handles.addEvent("mousedown", this.bound.start);
|
|
if (this.options.compensateScroll) this.offsetParent.addEvent("scroll", this.bound.scrollListener);
|
|
return this;
|
|
},
|
|
detach: function() {
|
|
this.handles.removeEvent("mousedown", this.bound.start);
|
|
if (this.options.compensateScroll) this.offsetParent.removeEvent("scroll", this.bound.scrollListener);
|
|
return this;
|
|
},
|
|
scrollListener: function() {
|
|
if (!this.mouse.start) return;
|
|
var newScrollValue = this.offsetParent.getScroll();
|
|
if (this.element.getStyle("position") == "absolute") {
|
|
var scrollDiff = this.sumValues(newScrollValue, this.compensateScroll.last, -1);
|
|
this.mouse.now = this.sumValues(this.mouse.now, scrollDiff, 1);
|
|
} else {
|
|
this.compensateScroll.diff = this.sumValues(newScrollValue, this.compensateScroll.start, -1);
|
|
}
|
|
if (this.offsetParent != window) this.compensateScroll.diff = this.sumValues(this.compensateScroll.start, newScrollValue, -1);
|
|
this.compensateScroll.last = newScrollValue;
|
|
this.render(this.options);
|
|
},
|
|
sumValues: function(alpha, beta, op) {
|
|
var sum = {}, options = this.options;
|
|
for (z in options.modifiers) {
|
|
if (!options.modifiers[z]) continue;
|
|
sum[z] = alpha[z] + beta[z] * op;
|
|
}
|
|
return sum;
|
|
},
|
|
start: function(event) {
|
|
var options = this.options;
|
|
if (event.rightClick) return;
|
|
if (options.preventDefault) event.preventDefault();
|
|
if (options.stopPropagation) event.stopPropagation();
|
|
this.compensateScroll.start = this.compensateScroll.last = this.offsetParent.getScroll();
|
|
this.compensateScroll.diff = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
this.mouse.start = event.page;
|
|
this.fireEvent("beforeStart", this.element);
|
|
var limit = options.limit;
|
|
this.limit = {
|
|
x: [],
|
|
y: []
|
|
};
|
|
var z, coordinates, offsetParent = this.offsetParent == window ? null : this.offsetParent;
|
|
for (z in options.modifiers) {
|
|
if (!options.modifiers[z]) continue;
|
|
var style = this.element.getStyle(options.modifiers[z]);
|
|
if (style && !style.match(/px$/)) {
|
|
if (!coordinates) coordinates = this.element.getCoordinates(offsetParent);
|
|
style = coordinates[options.modifiers[z]];
|
|
}
|
|
if (options.style) this.value.now[z] = (style || 0).toInt(); else this.value.now[z] = this.element[options.modifiers[z]];
|
|
if (options.invert) this.value.now[z] *= -1;
|
|
this.mouse.pos[z] = event.page[z] - this.value.now[z];
|
|
if (limit && limit[z]) {
|
|
var i = 2;
|
|
while (i--) {
|
|
var limitZI = limit[z][i];
|
|
if (limitZI || limitZI === 0) this.limit[z][i] = typeof limitZI == "function" ? limitZI() : limitZI;
|
|
}
|
|
}
|
|
}
|
|
if (typeOf(this.options.grid) == "number") this.options.grid = {
|
|
x: this.options.grid,
|
|
y: this.options.grid
|
|
};
|
|
var events = {
|
|
mousemove: this.bound.check,
|
|
mouseup: this.bound.cancel
|
|
};
|
|
events[this.selection] = this.bound.eventStop;
|
|
this.document.addEvents(events);
|
|
},
|
|
check: function(event) {
|
|
if (this.options.preventDefault) event.preventDefault();
|
|
var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
|
|
if (distance > this.options.snap) {
|
|
this.cancel();
|
|
this.document.addEvents({
|
|
mousemove: this.bound.drag,
|
|
mouseup: this.bound.stop
|
|
});
|
|
this.fireEvent("start", [ this.element, event ]).fireEvent("snap", this.element);
|
|
}
|
|
},
|
|
drag: function(event) {
|
|
var options = this.options;
|
|
if (options.preventDefault) event.preventDefault();
|
|
this.mouse.now = this.sumValues(event.page, this.compensateScroll.diff, -1);
|
|
this.render(options);
|
|
this.fireEvent("drag", [ this.element, event ]);
|
|
},
|
|
render: function(options) {
|
|
for (var z in options.modifiers) {
|
|
if (!options.modifiers[z]) continue;
|
|
this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
|
|
if (options.invert) this.value.now[z] *= -1;
|
|
if (options.limit && this.limit[z]) {
|
|
if ((this.limit[z][1] || this.limit[z][1] === 0) && this.value.now[z] > this.limit[z][1]) {
|
|
this.value.now[z] = this.limit[z][1];
|
|
} else if ((this.limit[z][0] || this.limit[z][0] === 0) && this.value.now[z] < this.limit[z][0]) {
|
|
this.value.now[z] = this.limit[z][0];
|
|
}
|
|
}
|
|
if (options.grid[z]) this.value.now[z] -= (this.value.now[z] - (this.limit[z][0] || 0)) % options.grid[z];
|
|
if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); else this.element[options.modifiers[z]] = this.value.now[z];
|
|
}
|
|
},
|
|
cancel: function(event) {
|
|
this.document.removeEvents({
|
|
mousemove: this.bound.check,
|
|
mouseup: this.bound.cancel
|
|
});
|
|
if (event) {
|
|
this.document.removeEvent(this.selection, this.bound.eventStop);
|
|
this.fireEvent("cancel", this.element);
|
|
}
|
|
},
|
|
stop: function(event) {
|
|
var events = {
|
|
mousemove: this.bound.drag,
|
|
mouseup: this.bound.stop
|
|
};
|
|
events[this.selection] = this.bound.eventStop;
|
|
this.document.removeEvents(events);
|
|
this.mouse.start = null;
|
|
if (event) this.fireEvent("complete", [ this.element, event ]);
|
|
}
|
|
});
|
|
|
|
Element.implement({
|
|
makeResizable: function(options) {
|
|
var drag = new Drag(this, Object.merge({
|
|
modifiers: {
|
|
x: "width",
|
|
y: "height"
|
|
}
|
|
}, options));
|
|
this.store("resizer", drag);
|
|
return drag.addEvent("drag", function() {
|
|
this.fireEvent("resize", drag);
|
|
}.bind(this));
|
|
}
|
|
});
|
|
|
|
Drag.Move = new Class({
|
|
Extends: Drag,
|
|
options: {
|
|
droppables: [],
|
|
container: false,
|
|
precalculate: false,
|
|
includeMargins: true,
|
|
checkDroppables: true
|
|
},
|
|
initialize: function(element, options) {
|
|
this.parent(element, options);
|
|
element = this.element;
|
|
this.droppables = $$(this.options.droppables);
|
|
this.setContainer(this.options.container);
|
|
if (this.options.style) {
|
|
if (this.options.modifiers.x == "left" && this.options.modifiers.y == "top") {
|
|
var parent = element.getOffsetParent(), styles = element.getStyles("left", "top");
|
|
if (parent && (styles.left == "auto" || styles.top == "auto")) {
|
|
element.setPosition(element.getPosition(parent));
|
|
}
|
|
}
|
|
if (element.getStyle("position") == "static") element.setStyle("position", "absolute");
|
|
}
|
|
this.addEvent("start", this.checkDroppables, true);
|
|
this.overed = null;
|
|
},
|
|
setContainer: function(container) {
|
|
this.container = document.id(container);
|
|
if (this.container && typeOf(this.container) != "element") {
|
|
this.container = document.id(this.container.getDocument().body);
|
|
}
|
|
},
|
|
start: function(event) {
|
|
if (this.container) this.options.limit = this.calculateLimit();
|
|
if (this.options.precalculate) {
|
|
this.positions = this.droppables.map(function(el) {
|
|
return el.getCoordinates();
|
|
});
|
|
}
|
|
this.parent(event);
|
|
},
|
|
calculateLimit: function() {
|
|
var element = this.element, container = this.container, offsetParent = document.id(element.getOffsetParent()) || document.body, containerCoordinates = container.getCoordinates(offsetParent), elementMargin = {}, elementBorder = {}, containerMargin = {}, containerBorder = {}, offsetParentPadding = {}, offsetScroll = offsetParent.getScroll();
|
|
[ "top", "right", "bottom", "left" ].each(function(pad) {
|
|
elementMargin[pad] = element.getStyle("margin-" + pad).toInt();
|
|
elementBorder[pad] = element.getStyle("border-" + pad).toInt();
|
|
containerMargin[pad] = container.getStyle("margin-" + pad).toInt();
|
|
containerBorder[pad] = container.getStyle("border-" + pad).toInt();
|
|
offsetParentPadding[pad] = offsetParent.getStyle("padding-" + pad).toInt();
|
|
}, this);
|
|
var width = element.offsetWidth + elementMargin.left + elementMargin.right, height = element.offsetHeight + elementMargin.top + elementMargin.bottom, left = 0 + offsetScroll.x, top = 0 + offsetScroll.y, right = containerCoordinates.right - containerBorder.right - width + offsetScroll.x, bottom = containerCoordinates.bottom - containerBorder.bottom - height + offsetScroll.y;
|
|
if (this.options.includeMargins) {
|
|
left += elementMargin.left;
|
|
top += elementMargin.top;
|
|
} else {
|
|
right += elementMargin.right;
|
|
bottom += elementMargin.bottom;
|
|
}
|
|
if (element.getStyle("position") == "relative") {
|
|
var coords = element.getCoordinates(offsetParent);
|
|
coords.left -= element.getStyle("left").toInt();
|
|
coords.top -= element.getStyle("top").toInt();
|
|
left -= coords.left;
|
|
top -= coords.top;
|
|
if (container.getStyle("position") != "relative") {
|
|
left += containerBorder.left;
|
|
top += containerBorder.top;
|
|
}
|
|
right += elementMargin.left - coords.left;
|
|
bottom += elementMargin.top - coords.top;
|
|
if (container != offsetParent) {
|
|
left += containerMargin.left + offsetParentPadding.left;
|
|
if (!offsetParentPadding.left && left < 0) left = 0;
|
|
top += offsetParent == document.body ? 0 : containerMargin.top + offsetParentPadding.top;
|
|
if (!offsetParentPadding.top && top < 0) top = 0;
|
|
}
|
|
} else {
|
|
left -= elementMargin.left;
|
|
top -= elementMargin.top;
|
|
if (container != offsetParent) {
|
|
left += containerCoordinates.left + containerBorder.left;
|
|
top += containerCoordinates.top + containerBorder.top;
|
|
}
|
|
}
|
|
return {
|
|
x: [ left, right ],
|
|
y: [ top, bottom ]
|
|
};
|
|
},
|
|
getDroppableCoordinates: function(element) {
|
|
var position = element.getCoordinates();
|
|
if (element.getStyle("position") == "fixed") {
|
|
var scroll = window.getScroll();
|
|
position.left += scroll.x;
|
|
position.right += scroll.x;
|
|
position.top += scroll.y;
|
|
position.bottom += scroll.y;
|
|
}
|
|
return position;
|
|
},
|
|
checkDroppables: function() {
|
|
var overed = this.droppables.filter(function(el, i) {
|
|
el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el);
|
|
var now = this.mouse.now;
|
|
return now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top;
|
|
}, this).getLast();
|
|
if (this.overed != overed) {
|
|
if (this.overed) this.fireEvent("leave", [ this.element, this.overed ]);
|
|
if (overed) this.fireEvent("enter", [ this.element, overed ]);
|
|
this.overed = overed;
|
|
}
|
|
},
|
|
drag: function(event) {
|
|
this.parent(event);
|
|
if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
|
|
},
|
|
stop: function(event) {
|
|
this.checkDroppables();
|
|
this.fireEvent("drop", [ this.element, this.overed, event ]);
|
|
this.overed = null;
|
|
return this.parent(event);
|
|
}
|
|
});
|
|
|
|
Element.implement({
|
|
makeDraggable: function(options) {
|
|
var drag = new Drag.Move(this, options);
|
|
this.store("dragger", drag);
|
|
return drag;
|
|
}
|
|
});
|
|
|
|
var Sortables = new Class({
|
|
Implements: [ Events, Options ],
|
|
options: {
|
|
opacity: 1,
|
|
clone: false,
|
|
revert: false,
|
|
handle: false,
|
|
dragOptions: {},
|
|
unDraggableTags: [ "button", "input", "a", "textarea", "select", "option" ]
|
|
},
|
|
initialize: function(lists, options) {
|
|
this.setOptions(options);
|
|
this.elements = [];
|
|
this.lists = [];
|
|
this.idle = true;
|
|
this.addLists($$(document.id(lists) || lists));
|
|
if (!this.options.clone) this.options.revert = false;
|
|
if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({
|
|
duration: 250,
|
|
link: "cancel"
|
|
}, this.options.revert));
|
|
},
|
|
attach: function() {
|
|
this.addLists(this.lists);
|
|
return this;
|
|
},
|
|
detach: function() {
|
|
this.lists = this.removeLists(this.lists);
|
|
return this;
|
|
},
|
|
addItems: function() {
|
|
Array.flatten(arguments).each(function(element) {
|
|
this.elements.push(element);
|
|
var start = element.retrieve("sortables:start", function(event) {
|
|
this.start.call(this, event, element);
|
|
}.bind(this));
|
|
(this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent("mousedown", start);
|
|
}, this);
|
|
return this;
|
|
},
|
|
addLists: function() {
|
|
Array.flatten(arguments).each(function(list) {
|
|
this.lists.include(list);
|
|
this.addItems(list.getChildren());
|
|
}, this);
|
|
return this;
|
|
},
|
|
removeItems: function() {
|
|
return $$(Array.flatten(arguments).map(function(element) {
|
|
this.elements.erase(element);
|
|
var start = element.retrieve("sortables:start");
|
|
(this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent("mousedown", start);
|
|
return element;
|
|
}, this));
|
|
},
|
|
removeLists: function() {
|
|
return $$(Array.flatten(arguments).map(function(list) {
|
|
this.lists.erase(list);
|
|
this.removeItems(list.getChildren());
|
|
return list;
|
|
}, this));
|
|
},
|
|
getDroppableCoordinates: function(element) {
|
|
var offsetParent = element.getOffsetParent();
|
|
var position = element.getPosition(offsetParent);
|
|
var scroll = {
|
|
w: window.getScroll(),
|
|
offsetParent: offsetParent.getScroll()
|
|
};
|
|
position.x += scroll.offsetParent.x;
|
|
position.y += scroll.offsetParent.y;
|
|
if (offsetParent.getStyle("position") == "fixed") {
|
|
position.x -= scroll.w.x;
|
|
position.y -= scroll.w.y;
|
|
}
|
|
return position;
|
|
},
|
|
getClone: function(event, element) {
|
|
if (!this.options.clone) return new Element(element.tagName).inject(document.body);
|
|
if (typeOf(this.options.clone) == "function") return this.options.clone.call(this, event, element, this.list);
|
|
var clone = element.clone(true).setStyles({
|
|
margin: 0,
|
|
position: "absolute",
|
|
visibility: "hidden",
|
|
width: element.getStyle("width")
|
|
}).addEvent("mousedown", function(event) {
|
|
element.fireEvent("mousedown", event);
|
|
});
|
|
if (clone.get("html").test("radio")) {
|
|
clone.getElements("input[type=radio]").each(function(input, i) {
|
|
input.set("name", "clone_" + i);
|
|
if (input.get("checked")) element.getElements("input[type=radio]")[i].set("checked", true);
|
|
});
|
|
}
|
|
return clone.inject(this.list).setPosition(this.getDroppableCoordinates(this.element));
|
|
},
|
|
getDroppables: function() {
|
|
var droppables = this.list.getChildren().erase(this.clone).erase(this.element);
|
|
if (!this.options.constrain) droppables.append(this.lists).erase(this.list);
|
|
return droppables;
|
|
},
|
|
insert: function(dragging, element) {
|
|
var where = "inside";
|
|
if (this.lists.contains(element)) {
|
|
this.list = element;
|
|
this.drag.droppables = this.getDroppables();
|
|
} else {
|
|
where = this.element.getAllPrevious().contains(element) ? "before" : "after";
|
|
}
|
|
this.element.inject(element, where);
|
|
this.fireEvent("sort", [ this.element, this.clone ]);
|
|
},
|
|
start: function(event, element) {
|
|
if (!this.idle || event.rightClick || !this.options.handle && this.options.unDraggableTags.contains(event.target.get("tag"))) return;
|
|
this.idle = false;
|
|
this.element = element;
|
|
this.opacity = element.getStyle("opacity");
|
|
this.list = element.getParent();
|
|
this.clone = this.getClone(event, element);
|
|
this.drag = new Drag.Move(this.clone, Object.merge({
|
|
droppables: this.getDroppables()
|
|
}, this.options.dragOptions)).addEvents({
|
|
onSnap: function() {
|
|
event.stop();
|
|
this.clone.setStyle("visibility", "visible");
|
|
this.element.setStyle("opacity", this.options.opacity || 0);
|
|
this.fireEvent("start", [ this.element, this.clone ]);
|
|
}.bind(this),
|
|
onEnter: this.insert.bind(this),
|
|
onCancel: this.end.bind(this),
|
|
onComplete: this.end.bind(this)
|
|
});
|
|
this.clone.inject(this.element, "before");
|
|
this.drag.start(event);
|
|
},
|
|
end: function() {
|
|
this.drag.detach();
|
|
this.element.setStyle("opacity", this.opacity);
|
|
var self = this;
|
|
if (this.effect) {
|
|
var dim = this.element.getStyles("width", "height"), clone = this.clone, pos = clone.computePosition(this.getDroppableCoordinates(clone));
|
|
var destroy = function() {
|
|
this.removeEvent("cancel", destroy);
|
|
clone.destroy();
|
|
self.reset();
|
|
};
|
|
this.effect.element = clone;
|
|
this.effect.start({
|
|
top: pos.top,
|
|
left: pos.left,
|
|
width: dim.width,
|
|
height: dim.height,
|
|
opacity: .25
|
|
}).addEvent("cancel", destroy).chain(destroy);
|
|
} else {
|
|
this.clone.destroy();
|
|
self.reset();
|
|
}
|
|
},
|
|
reset: function() {
|
|
this.idle = true;
|
|
this.fireEvent("complete", this.element);
|
|
},
|
|
serialize: function() {
|
|
var params = Array.link(arguments, {
|
|
modifier: Type.isFunction,
|
|
index: function(obj) {
|
|
return obj != null;
|
|
}
|
|
});
|
|
var serial = this.lists.map(function(list) {
|
|
return list.getChildren().map(params.modifier || function(element) {
|
|
return element.get("id");
|
|
}, this);
|
|
}, this);
|
|
var index = params.index;
|
|
if (this.lists.length == 1) index = 0;
|
|
return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial;
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var special = {
|
|
a: /[àáâãäåăą]/g,
|
|
A: /[ÀÁÂÃÄÅĂĄ]/g,
|
|
c: /[ćčç]/g,
|
|
C: /[ĆČÇ]/g,
|
|
d: /[ďđ]/g,
|
|
D: /[ĎÐ]/g,
|
|
e: /[èéêëěę]/g,
|
|
E: /[ÈÉÊËĚĘ]/g,
|
|
g: /[ğ]/g,
|
|
G: /[Ğ]/g,
|
|
i: /[ìíîï]/g,
|
|
I: /[ÌÍÎÏ]/g,
|
|
l: /[ĺľł]/g,
|
|
L: /[ĹĽŁ]/g,
|
|
n: /[ñňń]/g,
|
|
N: /[ÑŇŃ]/g,
|
|
o: /[òóôõöøő]/g,
|
|
O: /[ÒÓÔÕÖØ]/g,
|
|
r: /[řŕ]/g,
|
|
R: /[ŘŔ]/g,
|
|
s: /[ššş]/g,
|
|
S: /[ŠŞŚ]/g,
|
|
t: /[ťţ]/g,
|
|
T: /[ŤŢ]/g,
|
|
u: /[ùúûůüµ]/g,
|
|
U: /[ÙÚÛŮÜ]/g,
|
|
y: /[ÿý]/g,
|
|
Y: /[ŸÝ]/g,
|
|
z: /[žźż]/g,
|
|
Z: /[ŽŹŻ]/g,
|
|
th: /[þ]/g,
|
|
TH: /[Þ]/g,
|
|
dh: /[ð]/g,
|
|
DH: /[Ð]/g,
|
|
ss: /[ß]/g,
|
|
oe: /[œ]/g,
|
|
OE: /[Œ]/g,
|
|
ae: /[æ]/g,
|
|
AE: /[Æ]/g
|
|
}, tidy = {
|
|
" ": /[\xa0\u2002\u2003\u2009]/g,
|
|
"*": /[\xb7]/g,
|
|
"'": /[\u2018\u2019]/g,
|
|
'"': /[\u201c\u201d]/g,
|
|
"...": /[\u2026]/g,
|
|
"-": /[\u2013]/g,
|
|
"»": /[\uFFFD]/g
|
|
}, conversions = {
|
|
ms: 1,
|
|
s: 1e3,
|
|
m: 6e4,
|
|
h: 36e5
|
|
}, findUnits = /(\d*.?\d+)([msh]+)/;
|
|
var walk = function(string, replacements) {
|
|
var result = string, key;
|
|
for (key in replacements) result = result.replace(replacements[key], key);
|
|
return result;
|
|
};
|
|
var getRegexForTag = function(tag, contents) {
|
|
tag = tag || "";
|
|
var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)</" + tag + "(?!\\w)>" : "</?" + tag + "([^>]+)?>", reg = new RegExp(regstr, "gi");
|
|
return reg;
|
|
};
|
|
String.implement({
|
|
standardize: function() {
|
|
return walk(this, special);
|
|
},
|
|
repeat: function(times) {
|
|
return new Array(times + 1).join(this);
|
|
},
|
|
pad: function(length, str, direction) {
|
|
if (this.length >= length) return this;
|
|
var pad = (str == null ? " " : "" + str).repeat(length - this.length).substr(0, length - this.length);
|
|
if (!direction || direction == "right") return this + pad;
|
|
if (direction == "left") return pad + this;
|
|
return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil());
|
|
},
|
|
getTags: function(tag, contents) {
|
|
return this.match(getRegexForTag(tag, contents)) || [];
|
|
},
|
|
stripTags: function(tag, contents) {
|
|
return this.replace(getRegexForTag(tag, contents), "");
|
|
},
|
|
tidy: function() {
|
|
return walk(this, tidy);
|
|
},
|
|
truncate: function(max, trail, atChar) {
|
|
var string = this;
|
|
if (trail == null && arguments.length == 1) trail = "…";
|
|
if (string.length > max) {
|
|
string = string.substring(0, max);
|
|
if (atChar) {
|
|
var index = string.lastIndexOf(atChar);
|
|
if (index != -1) string = string.substr(0, index);
|
|
}
|
|
if (trail) string += trail;
|
|
}
|
|
return string;
|
|
},
|
|
ms: function() {
|
|
var units = findUnits.exec(this);
|
|
if (units == null) return Number(this);
|
|
return Number(units[1]) * conversions[units[2]];
|
|
}
|
|
});
|
|
})();
|
|
|
|
Element.implement({
|
|
tidy: function() {
|
|
this.set("value", this.get("value").tidy());
|
|
},
|
|
getTextInRange: function(start, end) {
|
|
return this.get("value").substring(start, end);
|
|
},
|
|
getSelectedText: function() {
|
|
if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd());
|
|
return document.selection.createRange().text;
|
|
},
|
|
getSelectedRange: function() {
|
|
if (this.selectionStart != null) {
|
|
return {
|
|
start: this.selectionStart,
|
|
end: this.selectionEnd
|
|
};
|
|
}
|
|
var pos = {
|
|
start: 0,
|
|
end: 0
|
|
};
|
|
var range = this.getDocument().selection.createRange();
|
|
if (!range || range.parentElement() != this) return pos;
|
|
var duplicate = range.duplicate();
|
|
if (this.type == "text") {
|
|
pos.start = 0 - duplicate.moveStart("character", -1e5);
|
|
pos.end = pos.start + range.text.length;
|
|
} else {
|
|
var value = this.get("value");
|
|
var offset = value.length;
|
|
duplicate.moveToElementText(this);
|
|
duplicate.setEndPoint("StartToEnd", range);
|
|
if (duplicate.text.length) offset -= value.match(/[\n\r]*$/)[0].length;
|
|
pos.end = offset - duplicate.text.length;
|
|
duplicate.setEndPoint("StartToStart", range);
|
|
pos.start = offset - duplicate.text.length;
|
|
}
|
|
return pos;
|
|
},
|
|
getSelectionStart: function() {
|
|
return this.getSelectedRange().start;
|
|
},
|
|
getSelectionEnd: function() {
|
|
return this.getSelectedRange().end;
|
|
},
|
|
setCaretPosition: function(pos) {
|
|
if (pos == "end") pos = this.get("value").length;
|
|
this.selectRange(pos, pos);
|
|
return this;
|
|
},
|
|
getCaretPosition: function() {
|
|
return this.getSelectedRange().start;
|
|
},
|
|
selectRange: function(start, end) {
|
|
if (this.setSelectionRange) {
|
|
this.focus();
|
|
this.setSelectionRange(start, end);
|
|
} else {
|
|
var value = this.get("value");
|
|
var diff = value.substr(start, end - start).replace(/\r/g, "").length;
|
|
start = value.substr(0, start).replace(/\r/g, "").length;
|
|
var range = this.createTextRange();
|
|
range.collapse(true);
|
|
range.moveEnd("character", start + diff);
|
|
range.moveStart("character", start);
|
|
range.select();
|
|
}
|
|
return this;
|
|
},
|
|
insertAtCursor: function(value, select) {
|
|
var pos = this.getSelectedRange();
|
|
var text = this.get("value");
|
|
this.set("value", text.substring(0, pos.start) + value + text.substring(pos.end, text.length));
|
|
if (select !== false) this.selectRange(pos.start, pos.start + value.length); else this.setCaretPosition(pos.start + value.length);
|
|
return this;
|
|
},
|
|
insertAroundCursor: function(options, select) {
|
|
options = Object.append({
|
|
before: "",
|
|
defaultMiddle: "",
|
|
after: ""
|
|
}, options);
|
|
var value = this.getSelectedText() || options.defaultMiddle;
|
|
var pos = this.getSelectedRange();
|
|
var text = this.get("value");
|
|
if (pos.start == pos.end) {
|
|
this.set("value", text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length));
|
|
this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length);
|
|
} else {
|
|
var current = text.substring(pos.start, pos.end);
|
|
this.set("value", text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length));
|
|
var selStart = pos.start + options.before.length;
|
|
if (select !== false) this.selectRange(selStart, selStart + current.length); else this.setCaretPosition(selStart + text.length);
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var getStylesList = function(styles, planes) {
|
|
var list = [];
|
|
Object.each(planes, function(directions) {
|
|
Object.each(directions, function(edge) {
|
|
styles.each(function(style) {
|
|
list.push(style + "-" + edge + (style == "border" ? "-width" : ""));
|
|
});
|
|
});
|
|
});
|
|
return list;
|
|
};
|
|
var calculateEdgeSize = function(edge, styles) {
|
|
var total = 0;
|
|
Object.each(styles, function(value, style) {
|
|
if (style.test(edge)) total = total + value.toInt();
|
|
});
|
|
return total;
|
|
};
|
|
var isVisible = function(el) {
|
|
return !!(!el || el.offsetHeight || el.offsetWidth);
|
|
};
|
|
Element.implement({
|
|
measure: function(fn) {
|
|
if (isVisible(this)) return fn.call(this);
|
|
var parent = this.getParent(), toMeasure = [];
|
|
while (!isVisible(parent) && parent != document.body) {
|
|
toMeasure.push(parent.expose());
|
|
parent = parent.getParent();
|
|
}
|
|
var restore = this.expose(), result = fn.call(this);
|
|
restore();
|
|
toMeasure.each(function(restore) {
|
|
restore();
|
|
});
|
|
return result;
|
|
},
|
|
expose: function() {
|
|
if (this.getStyle("display") != "none") return function() {};
|
|
var before = this.style.cssText;
|
|
this.setStyles({
|
|
display: "block",
|
|
position: "absolute",
|
|
visibility: "hidden"
|
|
});
|
|
return function() {
|
|
this.style.cssText = before;
|
|
}.bind(this);
|
|
},
|
|
getDimensions: function(options) {
|
|
options = Object.merge({
|
|
computeSize: false
|
|
}, options);
|
|
var dim = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
var getSize = function(el, options) {
|
|
return options.computeSize ? el.getComputedSize(options) : el.getSize();
|
|
};
|
|
var parent = this.getParent("body");
|
|
if (parent && this.getStyle("display") == "none") {
|
|
dim = this.measure(function() {
|
|
return getSize(this, options);
|
|
});
|
|
} else if (parent) {
|
|
try {
|
|
dim = getSize(this, options);
|
|
} catch (e) {}
|
|
}
|
|
return Object.append(dim, dim.x || dim.x === 0 ? {
|
|
width: dim.x,
|
|
height: dim.y
|
|
} : {
|
|
x: dim.width,
|
|
y: dim.height
|
|
});
|
|
},
|
|
getComputedSize: function(options) {
|
|
options = Object.merge({
|
|
styles: [ "padding", "border" ],
|
|
planes: {
|
|
height: [ "top", "bottom" ],
|
|
width: [ "left", "right" ]
|
|
},
|
|
mode: "both"
|
|
}, options);
|
|
var styles = {}, size = {
|
|
width: 0,
|
|
height: 0
|
|
}, dimensions;
|
|
if (options.mode == "vertical") {
|
|
delete size.width;
|
|
delete options.planes.width;
|
|
} else if (options.mode == "horizontal") {
|
|
delete size.height;
|
|
delete options.planes.height;
|
|
}
|
|
getStylesList(options.styles, options.planes).each(function(style) {
|
|
styles[style] = this.getStyle(style).toInt();
|
|
}, this);
|
|
Object.each(options.planes, function(edges, plane) {
|
|
var capitalized = plane.capitalize(), style = this.getStyle(plane);
|
|
if (style == "auto" && !dimensions) dimensions = this.getDimensions();
|
|
style = styles[plane] = style == "auto" ? dimensions[plane] : style.toInt();
|
|
size["total" + capitalized] = style;
|
|
edges.each(function(edge) {
|
|
var edgesize = calculateEdgeSize(edge, styles);
|
|
size["computed" + edge.capitalize()] = edgesize;
|
|
size["total" + capitalized] += edgesize;
|
|
});
|
|
}, this);
|
|
return Object.append(size, styles);
|
|
}
|
|
});
|
|
})();
|
|
|
|
(function(original) {
|
|
var local = Element.Position = {
|
|
options: {
|
|
relativeTo: document.body,
|
|
position: {
|
|
x: "center",
|
|
y: "center"
|
|
},
|
|
offset: {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
},
|
|
getOptions: function(element, options) {
|
|
options = Object.merge({}, local.options, options);
|
|
local.setPositionOption(options);
|
|
local.setEdgeOption(options);
|
|
local.setOffsetOption(element, options);
|
|
local.setDimensionsOption(element, options);
|
|
return options;
|
|
},
|
|
setPositionOption: function(options) {
|
|
options.position = local.getCoordinateFromValue(options.position);
|
|
},
|
|
setEdgeOption: function(options) {
|
|
var edgeOption = local.getCoordinateFromValue(options.edge);
|
|
options.edge = edgeOption ? edgeOption : options.position.x == "center" && options.position.y == "center" ? {
|
|
x: "center",
|
|
y: "center"
|
|
} : {
|
|
x: "left",
|
|
y: "top"
|
|
};
|
|
},
|
|
setOffsetOption: function(element, options) {
|
|
var parentOffset = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
var parentScroll = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
var offsetParent = element.measure(function() {
|
|
return document.id(this.getOffsetParent());
|
|
});
|
|
if (!offsetParent || offsetParent == element.getDocument().body) return;
|
|
parentScroll = offsetParent.getScroll();
|
|
parentOffset = offsetParent.measure(function() {
|
|
var position = this.getPosition();
|
|
if (this.getStyle("position") == "fixed") {
|
|
var scroll = window.getScroll();
|
|
position.x += scroll.x;
|
|
position.y += scroll.y;
|
|
}
|
|
return position;
|
|
});
|
|
options.offset = {
|
|
parentPositioned: offsetParent != document.id(options.relativeTo),
|
|
x: options.offset.x - parentOffset.x + parentScroll.x,
|
|
y: options.offset.y - parentOffset.y + parentScroll.y
|
|
};
|
|
},
|
|
setDimensionsOption: function(element, options) {
|
|
options.dimensions = element.getDimensions({
|
|
computeSize: true,
|
|
styles: [ "padding", "border", "margin" ]
|
|
});
|
|
},
|
|
getPosition: function(element, options) {
|
|
var position = {};
|
|
options = local.getOptions(element, options);
|
|
var relativeTo = document.id(options.relativeTo) || document.body;
|
|
local.setPositionCoordinates(options, position, relativeTo);
|
|
if (options.edge) local.toEdge(position, options);
|
|
var offset = options.offset;
|
|
position.left = (position.x >= 0 || offset.parentPositioned || options.allowNegative ? position.x : 0).toInt();
|
|
position.top = (position.y >= 0 || offset.parentPositioned || options.allowNegative ? position.y : 0).toInt();
|
|
local.toMinMax(position, options);
|
|
if (options.relFixedPosition || relativeTo.getStyle("position") == "fixed") local.toRelFixedPosition(relativeTo, position);
|
|
if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position);
|
|
if (options.ignoreMargins) local.toIgnoreMargins(position, options);
|
|
position.left = Math.ceil(position.left);
|
|
position.top = Math.ceil(position.top);
|
|
delete position.x;
|
|
delete position.y;
|
|
return position;
|
|
},
|
|
setPositionCoordinates: function(options, position, relativeTo) {
|
|
var offsetY = options.offset.y, offsetX = options.offset.x, calc = relativeTo == document.body ? window.getScroll() : relativeTo.getPosition(), top = calc.y, left = calc.x, winSize = window.getSize();
|
|
switch (options.position.x) {
|
|
case "left":
|
|
position.x = left + offsetX;
|
|
break;
|
|
|
|
case "right":
|
|
position.x = left + offsetX + relativeTo.offsetWidth;
|
|
break;
|
|
|
|
default:
|
|
position.x = left + (relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2 + offsetX;
|
|
break;
|
|
}
|
|
switch (options.position.y) {
|
|
case "top":
|
|
position.y = top + offsetY;
|
|
break;
|
|
|
|
case "bottom":
|
|
position.y = top + offsetY + relativeTo.offsetHeight;
|
|
break;
|
|
|
|
default:
|
|
position.y = top + (relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2 + offsetY;
|
|
break;
|
|
}
|
|
},
|
|
toMinMax: function(position, options) {
|
|
var xy = {
|
|
left: "x",
|
|
top: "y"
|
|
}, value;
|
|
[ "minimum", "maximum" ].each(function(minmax) {
|
|
[ "left", "top" ].each(function(lr) {
|
|
value = options[minmax] ? options[minmax][xy[lr]] : null;
|
|
if (value != null && (minmax == "minimum" ? position[lr] < value : position[lr] > value)) position[lr] = value;
|
|
});
|
|
});
|
|
},
|
|
toRelFixedPosition: function(relativeTo, position) {
|
|
var winScroll = window.getScroll();
|
|
position.top += winScroll.y;
|
|
position.left += winScroll.x;
|
|
},
|
|
toIgnoreScroll: function(relativeTo, position) {
|
|
var relScroll = relativeTo.getScroll();
|
|
position.top -= relScroll.y;
|
|
position.left -= relScroll.x;
|
|
},
|
|
toIgnoreMargins: function(position, options) {
|
|
position.left += options.edge.x == "right" ? options.dimensions["margin-right"] : options.edge.x != "center" ? -options.dimensions["margin-left"] : -options.dimensions["margin-left"] + (options.dimensions["margin-right"] + options.dimensions["margin-left"]) / 2;
|
|
position.top += options.edge.y == "bottom" ? options.dimensions["margin-bottom"] : options.edge.y != "center" ? -options.dimensions["margin-top"] : -options.dimensions["margin-top"] + (options.dimensions["margin-bottom"] + options.dimensions["margin-top"]) / 2;
|
|
},
|
|
toEdge: function(position, options) {
|
|
var edgeOffset = {}, dimensions = options.dimensions, edge = options.edge;
|
|
switch (edge.x) {
|
|
case "left":
|
|
edgeOffset.x = 0;
|
|
break;
|
|
|
|
case "right":
|
|
edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft;
|
|
break;
|
|
|
|
default:
|
|
edgeOffset.x = -Math.round(dimensions.totalWidth / 2);
|
|
break;
|
|
}
|
|
switch (edge.y) {
|
|
case "top":
|
|
edgeOffset.y = 0;
|
|
break;
|
|
|
|
case "bottom":
|
|
edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom;
|
|
break;
|
|
|
|
default:
|
|
edgeOffset.y = -Math.round(dimensions.totalHeight / 2);
|
|
break;
|
|
}
|
|
position.x += edgeOffset.x;
|
|
position.y += edgeOffset.y;
|
|
},
|
|
getCoordinateFromValue: function(option) {
|
|
if (typeOf(option) != "string") return option;
|
|
option = option.toLowerCase();
|
|
return {
|
|
x: option.test("left") ? "left" : option.test("right") ? "right" : "center",
|
|
y: option.test(/upper|top/) ? "top" : option.test("bottom") ? "bottom" : "center"
|
|
};
|
|
}
|
|
};
|
|
Element.implement({
|
|
position: function(options) {
|
|
if (options && (options.x != null || options.y != null)) {
|
|
return original ? original.apply(this, arguments) : this;
|
|
}
|
|
var position = this.setStyle("position", "absolute").calculatePosition(options);
|
|
return options && options.returnPos ? position : this.setStyles(position);
|
|
},
|
|
calculatePosition: function(options) {
|
|
return local.getPosition(this, options);
|
|
}
|
|
});
|
|
})(Element.prototype.position);
|
|
|
|
Element.implement({
|
|
isDisplayed: function() {
|
|
return this.getStyle("display") != "none";
|
|
},
|
|
isVisible: function() {
|
|
var w = this.offsetWidth, h = this.offsetHeight;
|
|
return w == 0 && h == 0 ? false : w > 0 && h > 0 ? true : this.style.display != "none";
|
|
},
|
|
toggle: function() {
|
|
return this[this.isDisplayed() ? "hide" : "show"]();
|
|
},
|
|
hide: function() {
|
|
var d;
|
|
try {
|
|
d = this.getStyle("display");
|
|
} catch (e) {}
|
|
if (d == "none") return this;
|
|
return this.store("element:_originalDisplay", d || "").setStyle("display", "none");
|
|
},
|
|
show: function(display) {
|
|
if (!display && this.isDisplayed()) return this;
|
|
display = display || this.retrieve("element:_originalDisplay") || "block";
|
|
return this.setStyle("display", display == "none" ? "block" : display);
|
|
},
|
|
swapClass: function(remove, add) {
|
|
return this.removeClass(remove).addClass(add);
|
|
}
|
|
});
|
|
|
|
Document.implement({
|
|
clearSelection: function() {
|
|
if (window.getSelection) {
|
|
var selection = window.getSelection();
|
|
if (selection && selection.removeAllRanges) selection.removeAllRanges();
|
|
} else if (document.selection && document.selection.empty) {
|
|
try {
|
|
document.selection.empty();
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var defined = function(value) {
|
|
return value != null;
|
|
};
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
Object.extend({
|
|
getFromPath: function(source, parts) {
|
|
if (typeof parts == "string") parts = parts.split(".");
|
|
for (var i = 0, l = parts.length; i < l; i++) {
|
|
if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]]; else return null;
|
|
}
|
|
return source;
|
|
},
|
|
cleanValues: function(object, method) {
|
|
method = method || defined;
|
|
for (var key in object) if (!method(object[key])) {
|
|
delete object[key];
|
|
}
|
|
return object;
|
|
},
|
|
erase: function(object, key) {
|
|
if (hasOwnProperty.call(object, key)) delete object[key];
|
|
return object;
|
|
},
|
|
run: function(object) {
|
|
var args = Array.slice(arguments, 1);
|
|
for (var key in object) if (object[key].apply) {
|
|
object[key].apply(object, args);
|
|
}
|
|
return object;
|
|
}
|
|
});
|
|
})();
|
|
|
|
(function() {
|
|
var current = null, locales = {}, inherits = {};
|
|
var getSet = function(set) {
|
|
if (instanceOf(set, Locale.Set)) return set; else return locales[set];
|
|
};
|
|
var Locale = this.Locale = {
|
|
define: function(locale, set, key, value) {
|
|
var name;
|
|
if (instanceOf(locale, Locale.Set)) {
|
|
name = locale.name;
|
|
if (name) locales[name] = locale;
|
|
} else {
|
|
name = locale;
|
|
if (!locales[name]) locales[name] = new Locale.Set(name);
|
|
locale = locales[name];
|
|
}
|
|
if (set) locale.define(set, key, value);
|
|
if (!current) current = locale;
|
|
return locale;
|
|
},
|
|
use: function(locale) {
|
|
locale = getSet(locale);
|
|
if (locale) {
|
|
current = locale;
|
|
this.fireEvent("change", locale);
|
|
}
|
|
return this;
|
|
},
|
|
getCurrent: function() {
|
|
return current;
|
|
},
|
|
get: function(key, args) {
|
|
return current ? current.get(key, args) : "";
|
|
},
|
|
inherit: function(locale, inherits, set) {
|
|
locale = getSet(locale);
|
|
if (locale) locale.inherit(inherits, set);
|
|
return this;
|
|
},
|
|
list: function() {
|
|
return Object.keys(locales);
|
|
}
|
|
};
|
|
Object.append(Locale, new Events());
|
|
Locale.Set = new Class({
|
|
sets: {},
|
|
inherits: {
|
|
locales: [],
|
|
sets: {}
|
|
},
|
|
initialize: function(name) {
|
|
this.name = name || "";
|
|
},
|
|
define: function(set, key, value) {
|
|
var defineData = this.sets[set];
|
|
if (!defineData) defineData = {};
|
|
if (key) {
|
|
if (typeOf(key) == "object") defineData = Object.merge(defineData, key); else defineData[key] = value;
|
|
}
|
|
this.sets[set] = defineData;
|
|
return this;
|
|
},
|
|
get: function(key, args, _base) {
|
|
var value = Object.getFromPath(this.sets, key);
|
|
if (value != null) {
|
|
var type = typeOf(value);
|
|
if (type == "function") value = value.apply(null, Array.from(args)); else if (type == "object") value = Object.clone(value);
|
|
return value;
|
|
}
|
|
var index = key.indexOf("."), set = index < 0 ? key : key.substr(0, index), names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include("en-US");
|
|
if (!_base) _base = [];
|
|
for (var i = 0, l = names.length; i < l; i++) {
|
|
if (_base.contains(names[i])) continue;
|
|
_base.include(names[i]);
|
|
var locale = locales[names[i]];
|
|
if (!locale) continue;
|
|
value = locale.get(key, args, _base);
|
|
if (value != null) return value;
|
|
}
|
|
return "";
|
|
},
|
|
inherit: function(names, set) {
|
|
names = Array.from(names);
|
|
if (set && !this.inherits.sets[set]) this.inherits.sets[set] = [];
|
|
var l = names.length;
|
|
while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]);
|
|
return this;
|
|
}
|
|
});
|
|
})();
|
|
|
|
Locale.define("en-US", "Date", {
|
|
months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
|
|
months_abbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
|
|
days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
|
|
days_abbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
|
|
dateOrder: [ "month", "date", "year" ],
|
|
shortDate: "%m/%d/%Y",
|
|
shortTime: "%I:%M%p",
|
|
AM: "AM",
|
|
PM: "PM",
|
|
firstDayOfWeek: 0,
|
|
ordinal: function(dayOfMonth) {
|
|
return dayOfMonth > 3 && dayOfMonth < 21 ? "th" : [ "th", "st", "nd", "rd", "th" ][Math.min(dayOfMonth % 10, 4)];
|
|
},
|
|
lessThanMinuteAgo: "less than a minute ago",
|
|
minuteAgo: "about a minute ago",
|
|
minutesAgo: "{delta} minutes ago",
|
|
hourAgo: "about an hour ago",
|
|
hoursAgo: "about {delta} hours ago",
|
|
dayAgo: "1 day ago",
|
|
daysAgo: "{delta} days ago",
|
|
weekAgo: "1 week ago",
|
|
weeksAgo: "{delta} weeks ago",
|
|
monthAgo: "1 month ago",
|
|
monthsAgo: "{delta} months ago",
|
|
yearAgo: "1 year ago",
|
|
yearsAgo: "{delta} years ago",
|
|
lessThanMinuteUntil: "less than a minute from now",
|
|
minuteUntil: "about a minute from now",
|
|
minutesUntil: "{delta} minutes from now",
|
|
hourUntil: "about an hour from now",
|
|
hoursUntil: "about {delta} hours from now",
|
|
dayUntil: "1 day from now",
|
|
daysUntil: "{delta} days from now",
|
|
weekUntil: "1 week from now",
|
|
weeksUntil: "{delta} weeks from now",
|
|
monthUntil: "1 month from now",
|
|
monthsUntil: "{delta} months from now",
|
|
yearUntil: "1 year from now",
|
|
yearsUntil: "{delta} years from now"
|
|
});
|
|
|
|
(function() {
|
|
var Date = this.Date;
|
|
var DateMethods = Date.Methods = {
|
|
ms: "Milliseconds",
|
|
year: "FullYear",
|
|
min: "Minutes",
|
|
mo: "Month",
|
|
sec: "Seconds",
|
|
hr: "Hours"
|
|
};
|
|
[ "Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds", "Time", "TimezoneOffset", "Week", "Timezone", "GMTOffset", "DayOfYear", "LastMonth", "LastDayOfMonth", "UTCDate", "UTCDay", "UTCFullYear", "AMPM", "Ordinal", "UTCHours", "UTCMilliseconds", "UTCMinutes", "UTCMonth", "UTCSeconds", "UTCMilliseconds" ].each(function(method) {
|
|
Date.Methods[method.toLowerCase()] = method;
|
|
});
|
|
var pad = function(n, digits, string) {
|
|
if (digits == 1) return n;
|
|
return n < Math.pow(10, digits - 1) ? (string || "0") + pad(n, digits - 1, string) : n;
|
|
};
|
|
Date.implement({
|
|
set: function(prop, value) {
|
|
prop = prop.toLowerCase();
|
|
var method = DateMethods[prop] && "set" + DateMethods[prop];
|
|
if (method && this[method]) this[method](value);
|
|
return this;
|
|
}.overloadSetter(),
|
|
get: function(prop) {
|
|
prop = prop.toLowerCase();
|
|
var method = DateMethods[prop] && "get" + DateMethods[prop];
|
|
if (method && this[method]) return this[method]();
|
|
return null;
|
|
}.overloadGetter(),
|
|
clone: function() {
|
|
return new Date(this.get("time"));
|
|
},
|
|
increment: function(interval, times) {
|
|
interval = interval || "day";
|
|
times = times != null ? times : 1;
|
|
switch (interval) {
|
|
case "year":
|
|
return this.increment("month", times * 12);
|
|
|
|
case "month":
|
|
var d = this.get("date");
|
|
this.set("date", 1).set("mo", this.get("mo") + times);
|
|
return this.set("date", d.min(this.get("lastdayofmonth")));
|
|
|
|
case "week":
|
|
return this.increment("day", times * 7);
|
|
|
|
case "day":
|
|
return this.set("date", this.get("date") + times);
|
|
}
|
|
if (!Date.units[interval]) throw new Error(interval + " is not a supported interval");
|
|
return this.set("time", this.get("time") + times * Date.units[interval]());
|
|
},
|
|
decrement: function(interval, times) {
|
|
return this.increment(interval, -1 * (times != null ? times : 1));
|
|
},
|
|
isLeapYear: function() {
|
|
return Date.isLeapYear(this.get("year"));
|
|
},
|
|
clearTime: function() {
|
|
return this.set({
|
|
hr: 0,
|
|
min: 0,
|
|
sec: 0,
|
|
ms: 0
|
|
});
|
|
},
|
|
diff: function(date, resolution) {
|
|
if (typeOf(date) == "string") date = Date.parse(date);
|
|
return ((date - this) / Date.units[resolution || "day"](3, 3)).round();
|
|
},
|
|
getLastDayOfMonth: function() {
|
|
return Date.daysInMonth(this.get("mo"), this.get("year"));
|
|
},
|
|
getDayOfYear: function() {
|
|
return (Date.UTC(this.get("year"), this.get("mo"), this.get("date") + 1) - Date.UTC(this.get("year"), 0, 1)) / Date.units.day();
|
|
},
|
|
setDay: function(day, firstDayOfWeek) {
|
|
if (firstDayOfWeek == null) {
|
|
firstDayOfWeek = Date.getMsg("firstDayOfWeek");
|
|
if (firstDayOfWeek === "") firstDayOfWeek = 1;
|
|
}
|
|
day = (7 + Date.parseDay(day, true) - firstDayOfWeek) % 7;
|
|
var currentDay = (7 + this.get("day") - firstDayOfWeek) % 7;
|
|
return this.increment("day", day - currentDay);
|
|
},
|
|
getWeek: function(firstDayOfWeek) {
|
|
if (firstDayOfWeek == null) {
|
|
firstDayOfWeek = Date.getMsg("firstDayOfWeek");
|
|
if (firstDayOfWeek === "") firstDayOfWeek = 1;
|
|
}
|
|
var date = this, dayOfWeek = (7 + date.get("day") - firstDayOfWeek) % 7, dividend = 0, firstDayOfYear;
|
|
if (firstDayOfWeek == 1) {
|
|
var month = date.get("month"), startOfWeek = date.get("date") - dayOfWeek;
|
|
if (month == 11 && startOfWeek > 28) return 1;
|
|
if (month == 0 && startOfWeek < -2) {
|
|
date = new Date(date).decrement("day", dayOfWeek);
|
|
dayOfWeek = 0;
|
|
}
|
|
firstDayOfYear = new Date(date.get("year"), 0, 1).get("day") || 7;
|
|
if (firstDayOfYear > 4) dividend = -7;
|
|
} else {
|
|
firstDayOfYear = new Date(date.get("year"), 0, 1).get("day");
|
|
}
|
|
dividend += date.get("dayofyear");
|
|
dividend += 6 - dayOfWeek;
|
|
dividend += (7 + firstDayOfYear - firstDayOfWeek) % 7;
|
|
return dividend / 7;
|
|
},
|
|
getOrdinal: function(day) {
|
|
return Date.getMsg("ordinal", day || this.get("date"));
|
|
},
|
|
getTimezone: function() {
|
|
return this.toString().replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, "$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
|
|
},
|
|
getGMTOffset: function() {
|
|
var off = this.get("timezoneOffset");
|
|
return (off > 0 ? "-" : "+") + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2);
|
|
},
|
|
setAMPM: function(ampm) {
|
|
ampm = ampm.toUpperCase();
|
|
var hr = this.get("hr");
|
|
if (hr > 11 && ampm == "AM") return this.decrement("hour", 12); else if (hr < 12 && ampm == "PM") return this.increment("hour", 12);
|
|
return this;
|
|
},
|
|
getAMPM: function() {
|
|
return this.get("hr") < 12 ? "AM" : "PM";
|
|
},
|
|
parse: function(str) {
|
|
this.set("time", Date.parse(str));
|
|
return this;
|
|
},
|
|
isValid: function(date) {
|
|
if (!date) date = this;
|
|
return typeOf(date) == "date" && !isNaN(date.valueOf());
|
|
},
|
|
format: function(format) {
|
|
if (!this.isValid()) return "invalid date";
|
|
if (!format) format = "%x %X";
|
|
if (typeof format == "string") format = formats[format.toLowerCase()] || format;
|
|
if (typeof format == "function") return format(this);
|
|
var d = this;
|
|
return format.replace(/%([a-z%])/gi, function($0, $1) {
|
|
switch ($1) {
|
|
case "a":
|
|
return Date.getMsg("days_abbr")[d.get("day")];
|
|
|
|
case "A":
|
|
return Date.getMsg("days")[d.get("day")];
|
|
|
|
case "b":
|
|
return Date.getMsg("months_abbr")[d.get("month")];
|
|
|
|
case "B":
|
|
return Date.getMsg("months")[d.get("month")];
|
|
|
|
case "c":
|
|
return d.format("%a %b %d %H:%M:%S %Y");
|
|
|
|
case "d":
|
|
return pad(d.get("date"), 2);
|
|
|
|
case "e":
|
|
return pad(d.get("date"), 2, " ");
|
|
|
|
case "H":
|
|
return pad(d.get("hr"), 2);
|
|
|
|
case "I":
|
|
return pad(d.get("hr") % 12 || 12, 2);
|
|
|
|
case "j":
|
|
return pad(d.get("dayofyear"), 3);
|
|
|
|
case "k":
|
|
return pad(d.get("hr"), 2, " ");
|
|
|
|
case "l":
|
|
return pad(d.get("hr") % 12 || 12, 2, " ");
|
|
|
|
case "L":
|
|
return pad(d.get("ms"), 3);
|
|
|
|
case "m":
|
|
return pad(d.get("mo") + 1, 2);
|
|
|
|
case "M":
|
|
return pad(d.get("min"), 2);
|
|
|
|
case "o":
|
|
return d.get("ordinal");
|
|
|
|
case "p":
|
|
return Date.getMsg(d.get("ampm"));
|
|
|
|
case "s":
|
|
return Math.round(d / 1e3);
|
|
|
|
case "S":
|
|
return pad(d.get("seconds"), 2);
|
|
|
|
case "T":
|
|
return d.format("%H:%M:%S");
|
|
|
|
case "U":
|
|
return pad(d.get("week"), 2);
|
|
|
|
case "w":
|
|
return d.get("day");
|
|
|
|
case "x":
|
|
return d.format(Date.getMsg("shortDate"));
|
|
|
|
case "X":
|
|
return d.format(Date.getMsg("shortTime"));
|
|
|
|
case "y":
|
|
return d.get("year").toString().substr(2);
|
|
|
|
case "Y":
|
|
return d.get("year");
|
|
|
|
case "z":
|
|
return d.get("GMTOffset");
|
|
|
|
case "Z":
|
|
return d.get("Timezone");
|
|
}
|
|
return $1;
|
|
});
|
|
},
|
|
toISOString: function() {
|
|
return this.format("iso8601");
|
|
}
|
|
}).alias({
|
|
toJSON: "toISOString",
|
|
compare: "diff",
|
|
strftime: "format"
|
|
});
|
|
var rfcDayAbbr = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], rfcMonthAbbr = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
|
|
var formats = {
|
|
db: "%Y-%m-%d %H:%M:%S",
|
|
compact: "%Y%m%dT%H%M%S",
|
|
short: "%d %b %H:%M",
|
|
long: "%B %d, %Y %H:%M",
|
|
rfc822: function(date) {
|
|
return rfcDayAbbr[date.get("day")] + date.format(", %d ") + rfcMonthAbbr[date.get("month")] + date.format(" %Y %H:%M:%S %Z");
|
|
},
|
|
rfc2822: function(date) {
|
|
return rfcDayAbbr[date.get("day")] + date.format(", %d ") + rfcMonthAbbr[date.get("month")] + date.format(" %Y %H:%M:%S %z");
|
|
},
|
|
iso8601: function(date) {
|
|
return date.getUTCFullYear() + "-" + pad(date.getUTCMonth() + 1, 2) + "-" + pad(date.getUTCDate(), 2) + "T" + pad(date.getUTCHours(), 2) + ":" + pad(date.getUTCMinutes(), 2) + ":" + pad(date.getUTCSeconds(), 2) + "." + pad(date.getUTCMilliseconds(), 3) + "Z";
|
|
}
|
|
};
|
|
var parsePatterns = [], nativeParse = Date.parse;
|
|
var parseWord = function(type, word, num) {
|
|
var ret = -1, translated = Date.getMsg(type + "s");
|
|
switch (typeOf(word)) {
|
|
case "object":
|
|
ret = translated[word.get(type)];
|
|
break;
|
|
|
|
case "number":
|
|
ret = translated[word];
|
|
if (!ret) throw new Error("Invalid " + type + " index: " + word);
|
|
break;
|
|
|
|
case "string":
|
|
var match = translated.filter(function(name) {
|
|
return this.test(name);
|
|
}, new RegExp("^" + word, "i"));
|
|
if (!match.length) throw new Error("Invalid " + type + " string");
|
|
if (match.length > 1) throw new Error("Ambiguous " + type);
|
|
ret = match[0];
|
|
}
|
|
return num ? translated.indexOf(ret) : ret;
|
|
};
|
|
var startCentury = 1900, startYear = 70;
|
|
Date.extend({
|
|
getMsg: function(key, args) {
|
|
return Locale.get("Date." + key, args);
|
|
},
|
|
units: {
|
|
ms: Function.from(1),
|
|
second: Function.from(1e3),
|
|
minute: Function.from(6e4),
|
|
hour: Function.from(36e5),
|
|
day: Function.from(864e5),
|
|
week: Function.from(6084e5),
|
|
month: function(month, year) {
|
|
var d = new Date();
|
|
return Date.daysInMonth(month != null ? month : d.get("mo"), year != null ? year : d.get("year")) * 864e5;
|
|
},
|
|
year: function(year) {
|
|
year = year || new Date().get("year");
|
|
return Date.isLeapYear(year) ? 316224e5 : 31536e6;
|
|
}
|
|
},
|
|
daysInMonth: function(month, year) {
|
|
return [ 31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ][month];
|
|
},
|
|
isLeapYear: function(year) {
|
|
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
},
|
|
parse: function(from) {
|
|
var t = typeOf(from);
|
|
if (t == "number") return new Date(from);
|
|
if (t != "string") return from;
|
|
from = from.clean();
|
|
if (!from.length) return null;
|
|
var parsed;
|
|
parsePatterns.some(function(pattern) {
|
|
var bits = pattern.re.exec(from);
|
|
return bits ? parsed = pattern.handler(bits) : false;
|
|
});
|
|
if (!(parsed && parsed.isValid())) {
|
|
parsed = new Date(nativeParse(from));
|
|
if (!(parsed && parsed.isValid())) parsed = new Date(from.toInt());
|
|
}
|
|
return parsed;
|
|
},
|
|
parseDay: function(day, num) {
|
|
return parseWord("day", day, num);
|
|
},
|
|
parseMonth: function(month, num) {
|
|
return parseWord("month", month, num);
|
|
},
|
|
parseUTC: function(value) {
|
|
var localDate = new Date(value);
|
|
var utcSeconds = Date.UTC(localDate.get("year"), localDate.get("mo"), localDate.get("date"), localDate.get("hr"), localDate.get("min"), localDate.get("sec"), localDate.get("ms"));
|
|
return new Date(utcSeconds);
|
|
},
|
|
orderIndex: function(unit) {
|
|
return Date.getMsg("dateOrder").indexOf(unit) + 1;
|
|
},
|
|
defineFormat: function(name, format) {
|
|
formats[name] = format;
|
|
return this;
|
|
},
|
|
defineParser: function(pattern) {
|
|
parsePatterns.push(pattern.re && pattern.handler ? pattern : build(pattern));
|
|
return this;
|
|
},
|
|
defineParsers: function() {
|
|
Array.flatten(arguments).each(Date.defineParser);
|
|
return this;
|
|
},
|
|
define2DigitYearStart: function(year) {
|
|
startYear = year % 100;
|
|
startCentury = year - startYear;
|
|
return this;
|
|
}
|
|
}).extend({
|
|
defineFormats: Date.defineFormat.overloadSetter()
|
|
});
|
|
var regexOf = function(type) {
|
|
return new RegExp("(?:" + Date.getMsg(type).map(function(name) {
|
|
return name.substr(0, 3);
|
|
}).join("|") + ")[a-z]*");
|
|
};
|
|
var replacers = function(key) {
|
|
switch (key) {
|
|
case "T":
|
|
return "%H:%M:%S";
|
|
|
|
case "x":
|
|
return (Date.orderIndex("month") == 1 ? "%m[-./]%d" : "%d[-./]%m") + "([-./]%y)?";
|
|
|
|
case "X":
|
|
return "%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?";
|
|
}
|
|
return null;
|
|
};
|
|
var keys = {
|
|
d: /[0-2]?[0-9]|3[01]/,
|
|
H: /[01]?[0-9]|2[0-3]/,
|
|
I: /0?[1-9]|1[0-2]/,
|
|
M: /[0-5]?\d/,
|
|
s: /\d+/,
|
|
o: /[a-z]*/,
|
|
p: /[ap]\.?m\.?/,
|
|
y: /\d{2}|\d{4}/,
|
|
Y: /\d{4}/,
|
|
z: /Z|[+-]\d{2}(?::?\d{2})?/
|
|
};
|
|
keys.m = keys.I;
|
|
keys.S = keys.M;
|
|
var currentLanguage;
|
|
var recompile = function(language) {
|
|
currentLanguage = language;
|
|
keys.a = keys.A = regexOf("days");
|
|
keys.b = keys.B = regexOf("months");
|
|
parsePatterns.each(function(pattern, i) {
|
|
if (pattern.format) parsePatterns[i] = build(pattern.format);
|
|
});
|
|
};
|
|
var build = function(format) {
|
|
if (!currentLanguage) return {
|
|
format: format
|
|
};
|
|
var parsed = [];
|
|
var re = (format.source || format).replace(/%([a-z])/gi, function($0, $1) {
|
|
return replacers($1) || $0;
|
|
}).replace(/\((?!\?)/g, "(?:").replace(/ (?!\?|\*)/g, ",? ").replace(/%([a-z%])/gi, function($0, $1) {
|
|
var p = keys[$1];
|
|
if (!p) return $1;
|
|
parsed.push($1);
|
|
return "(" + p.source + ")";
|
|
}).replace(/\[a-z\]/gi, "[a-z\\u00c0-\\uffff;&]");
|
|
return {
|
|
format: format,
|
|
re: new RegExp("^" + re + "$", "i"),
|
|
handler: function(bits) {
|
|
bits = bits.slice(1).associate(parsed);
|
|
var date = new Date().clearTime(), year = bits.y || bits.Y;
|
|
if (year != null) handle.call(date, "y", year);
|
|
if ("d" in bits) handle.call(date, "d", 1);
|
|
if ("m" in bits || bits.b || bits.B) handle.call(date, "m", 1);
|
|
for (var key in bits) handle.call(date, key, bits[key]);
|
|
return date;
|
|
}
|
|
};
|
|
};
|
|
var handle = function(key, value) {
|
|
if (!value) return this;
|
|
switch (key) {
|
|
case "a":
|
|
case "A":
|
|
return this.set("day", Date.parseDay(value, true));
|
|
|
|
case "b":
|
|
case "B":
|
|
return this.set("mo", Date.parseMonth(value, true));
|
|
|
|
case "d":
|
|
return this.set("date", value);
|
|
|
|
case "H":
|
|
case "I":
|
|
return this.set("hr", value);
|
|
|
|
case "m":
|
|
return this.set("mo", value - 1);
|
|
|
|
case "M":
|
|
return this.set("min", value);
|
|
|
|
case "p":
|
|
return this.set("ampm", value.replace(/\./g, ""));
|
|
|
|
case "S":
|
|
return this.set("sec", value);
|
|
|
|
case "s":
|
|
return this.set("ms", ("0." + value) * 1e3);
|
|
|
|
case "w":
|
|
return this.set("day", value);
|
|
|
|
case "Y":
|
|
return this.set("year", value);
|
|
|
|
case "y":
|
|
value = +value;
|
|
if (value < 100) value += startCentury + (value < startYear ? 100 : 0);
|
|
return this.set("year", value);
|
|
|
|
case "z":
|
|
if (value == "Z") value = "+00";
|
|
var offset = value.match(/([+-])(\d{2}):?(\d{2})?/);
|
|
offset = (offset[1] + "1") * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset();
|
|
return this.set("time", this - offset * 6e4);
|
|
}
|
|
return this;
|
|
};
|
|
Date.defineParsers("%Y([-./]%m([-./]%d((T| )%X)?)?)?", "%Y%m%d(T%H(%M%S?)?)?", "%x( %X)?", "%d%o( %b( %Y)?)?( %X)?", "%b( %d%o)?( %Y)?( %X)?", "%Y %b( %d%o( %X)?)?", "%o %b %d %X %z %Y", "%T", "%H:%M( ?%p)?");
|
|
Locale.addEvent("change", function(language) {
|
|
if (Locale.get("Date")) recompile(language);
|
|
}).fireEvent("change", Locale.getCurrent());
|
|
})();
|
|
|
|
(function() {
|
|
Fx.Scroll = new Class({
|
|
Extends: Fx,
|
|
options: {
|
|
offset: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
wheelStops: true
|
|
},
|
|
initialize: function(element, options) {
|
|
this.element = this.subject = document.id(element);
|
|
this.parent(options);
|
|
if (typeOf(this.element) != "element") this.element = document.id(this.element.getDocument().body);
|
|
if (this.options.wheelStops) {
|
|
var stopper = this.element, cancel = this.cancel.pass(false, this);
|
|
this.addEvent("start", function() {
|
|
stopper.addEvent("mousewheel", cancel);
|
|
}, true);
|
|
this.addEvent("complete", function() {
|
|
stopper.removeEvent("mousewheel", cancel);
|
|
}, true);
|
|
}
|
|
},
|
|
set: function() {
|
|
var now = Array.flatten(arguments);
|
|
this.element.scrollTo(now[0], now[1]);
|
|
return this;
|
|
},
|
|
compute: function(from, to, delta) {
|
|
return [ 0, 1 ].map(function(i) {
|
|
return Fx.compute(from[i], to[i], delta);
|
|
});
|
|
},
|
|
start: function(x, y) {
|
|
if (!this.check(x, y)) return this;
|
|
var scroll = this.element.getScroll();
|
|
return this.parent([ scroll.x, scroll.y ], [ x, y ]);
|
|
},
|
|
calculateScroll: function(x, y) {
|
|
var element = this.element, scrollSize = element.getScrollSize(), scroll = element.getScroll(), size = element.getSize(), offset = this.options.offset, values = {
|
|
x: x,
|
|
y: y
|
|
};
|
|
for (var z in values) {
|
|
if (!values[z] && values[z] !== 0) values[z] = scroll[z];
|
|
if (typeOf(values[z]) != "number") values[z] = scrollSize[z] - size[z];
|
|
values[z] += offset[z];
|
|
}
|
|
return [ values.x, values.y ];
|
|
},
|
|
toTop: function() {
|
|
return this.start.apply(this, this.calculateScroll(false, 0));
|
|
},
|
|
toLeft: function() {
|
|
return this.start.apply(this, this.calculateScroll(0, false));
|
|
},
|
|
toRight: function() {
|
|
return this.start.apply(this, this.calculateScroll("right", false));
|
|
},
|
|
toBottom: function() {
|
|
return this.start.apply(this, this.calculateScroll(false, "bottom"));
|
|
},
|
|
toElement: function(el, axes) {
|
|
axes = axes ? Array.from(axes) : [ "x", "y" ];
|
|
var scroll = isBody(this.element) ? {
|
|
x: 0,
|
|
y: 0
|
|
} : this.element.getScroll();
|
|
var position = Object.map(document.id(el).getPosition(this.element), function(value, axis) {
|
|
return axes.contains(axis) ? value + scroll[axis] : false;
|
|
});
|
|
return this.start.apply(this, this.calculateScroll(position.x, position.y));
|
|
},
|
|
toElementEdge: function(el, axes, offset) {
|
|
axes = axes ? Array.from(axes) : [ "x", "y" ];
|
|
el = document.id(el);
|
|
var to = {}, position = el.getPosition(this.element), size = el.getSize(), scroll = this.element.getScroll(), containerSize = this.element.getSize(), edge = {
|
|
x: position.x + size.x,
|
|
y: position.y + size.y
|
|
};
|
|
[ "x", "y" ].each(function(axis) {
|
|
if (axes.contains(axis)) {
|
|
if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
|
|
if (position[axis] < scroll[axis]) to[axis] = position[axis];
|
|
}
|
|
if (to[axis] == null) to[axis] = scroll[axis];
|
|
if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
|
|
}, this);
|
|
if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
|
|
return this;
|
|
},
|
|
toElementCenter: function(el, axes, offset) {
|
|
axes = axes ? Array.from(axes) : [ "x", "y" ];
|
|
el = document.id(el);
|
|
var to = {}, position = el.getPosition(this.element), size = el.getSize(), scroll = this.element.getScroll(), containerSize = this.element.getSize();
|
|
[ "x", "y" ].each(function(axis) {
|
|
if (axes.contains(axis)) {
|
|
to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2;
|
|
}
|
|
if (to[axis] == null) to[axis] = scroll[axis];
|
|
if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
|
|
}, this);
|
|
if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
|
|
return this;
|
|
}
|
|
});
|
|
function isBody(element) {
|
|
return /^(?:body|html)$/i.test(element.tagName);
|
|
}
|
|
})();
|
|
|
|
Fx.Slide = new Class({
|
|
Extends: Fx,
|
|
options: {
|
|
mode: "vertical",
|
|
wrapper: false,
|
|
hideOverflow: true,
|
|
resetHeight: false
|
|
},
|
|
initialize: function(element, options) {
|
|
element = this.element = this.subject = document.id(element);
|
|
this.parent(options);
|
|
options = this.options;
|
|
var wrapper = element.retrieve("wrapper"), styles = element.getStyles("margin", "position", "overflow");
|
|
if (options.hideOverflow) styles = Object.append(styles, {
|
|
overflow: "hidden"
|
|
});
|
|
if (options.wrapper) wrapper = document.id(options.wrapper).setStyles(styles);
|
|
if (!wrapper) wrapper = new Element("div", {
|
|
styles: styles
|
|
}).wraps(element);
|
|
element.store("wrapper", wrapper).setStyle("margin", 0);
|
|
if (element.getStyle("overflow") == "visible") element.setStyle("overflow", "hidden");
|
|
this.now = [];
|
|
this.open = true;
|
|
this.wrapper = wrapper;
|
|
this.addEvent("complete", function() {
|
|
this.open = wrapper["offset" + this.layout.capitalize()] != 0;
|
|
if (this.open && this.options.resetHeight) wrapper.setStyle("height", "");
|
|
}, true);
|
|
},
|
|
vertical: function() {
|
|
this.margin = "margin-top";
|
|
this.layout = "height";
|
|
this.offset = this.element.offsetHeight;
|
|
},
|
|
horizontal: function() {
|
|
this.margin = "margin-left";
|
|
this.layout = "width";
|
|
this.offset = this.element.offsetWidth;
|
|
},
|
|
set: function(now) {
|
|
this.element.setStyle(this.margin, now[0]);
|
|
this.wrapper.setStyle(this.layout, now[1]);
|
|
return this;
|
|
},
|
|
compute: function(from, to, delta) {
|
|
return [ 0, 1 ].map(function(i) {
|
|
return Fx.compute(from[i], to[i], delta);
|
|
});
|
|
},
|
|
start: function(how, mode) {
|
|
if (!this.check(how, mode)) return this;
|
|
this[mode || this.options.mode]();
|
|
var margin = this.element.getStyle(this.margin).toInt(), layout = this.wrapper.getStyle(this.layout).toInt(), caseIn = [ [ margin, layout ], [ 0, this.offset ] ], caseOut = [ [ margin, layout ], [ -this.offset, 0 ] ], start;
|
|
switch (how) {
|
|
case "in":
|
|
start = caseIn;
|
|
break;
|
|
|
|
case "out":
|
|
start = caseOut;
|
|
break;
|
|
|
|
case "toggle":
|
|
start = layout == 0 ? caseIn : caseOut;
|
|
}
|
|
return this.parent(start[0], start[1]);
|
|
},
|
|
slideIn: function(mode) {
|
|
return this.start("in", mode);
|
|
},
|
|
slideOut: function(mode) {
|
|
return this.start("out", mode);
|
|
},
|
|
hide: function(mode) {
|
|
this[mode || this.options.mode]();
|
|
this.open = false;
|
|
return this.set([ -this.offset, 0 ]);
|
|
},
|
|
show: function(mode) {
|
|
this[mode || this.options.mode]();
|
|
this.open = true;
|
|
return this.set([ 0, this.offset ]);
|
|
},
|
|
toggle: function(mode) {
|
|
return this.start("toggle", mode);
|
|
}
|
|
});
|
|
|
|
Element.Properties.slide = {
|
|
set: function(options) {
|
|
this.get("slide").cancel().setOptions(options);
|
|
return this;
|
|
},
|
|
get: function() {
|
|
var slide = this.retrieve("slide");
|
|
if (!slide) {
|
|
slide = new Fx.Slide(this, {
|
|
link: "cancel"
|
|
});
|
|
this.store("slide", slide);
|
|
}
|
|
return slide;
|
|
}
|
|
};
|
|
|
|
Element.implement({
|
|
slide: function(how, mode) {
|
|
how = how || "toggle";
|
|
var slide = this.get("slide"), toggle;
|
|
switch (how) {
|
|
case "hide":
|
|
slide.hide(mode);
|
|
break;
|
|
|
|
case "show":
|
|
slide.show(mode);
|
|
break;
|
|
|
|
case "toggle":
|
|
var flag = this.retrieve("slide:flag", slide.open);
|
|
slide[flag ? "slideOut" : "slideIn"](mode);
|
|
this.store("slide:flag", !flag);
|
|
toggle = true;
|
|
break;
|
|
|
|
default:
|
|
slide.start(how, mode);
|
|
}
|
|
if (!toggle) this.eliminate("slide:flag");
|
|
return this;
|
|
}
|
|
});
|
|
|
|
Request.JSONP = new Class({
|
|
Implements: [ Chain, Events, Options ],
|
|
options: {
|
|
onRequest: function(src) {
|
|
if (this.options.log && window.console && console.log) {
|
|
console.log("JSONP retrieving script with url:" + src);
|
|
}
|
|
},
|
|
onError: function(src) {
|
|
if (this.options.log && window.console && console.warn) {
|
|
console.warn("JSONP " + src + " will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs");
|
|
}
|
|
},
|
|
url: "",
|
|
callbackKey: "callback",
|
|
injectScript: document.head,
|
|
data: "",
|
|
link: "ignore",
|
|
timeout: 0,
|
|
log: false
|
|
},
|
|
initialize: function(options) {
|
|
this.setOptions(options);
|
|
},
|
|
send: function(options) {
|
|
if (!Request.prototype.check.call(this, options)) return this;
|
|
this.running = true;
|
|
var type = typeOf(options);
|
|
if (type == "string" || type == "element") options = {
|
|
data: options
|
|
};
|
|
options = Object.merge(this.options, options || {});
|
|
var data = options.data;
|
|
switch (typeOf(data)) {
|
|
case "element":
|
|
data = document.id(data).toQueryString();
|
|
break;
|
|
|
|
case "object":
|
|
case "hash":
|
|
data = Object.toQueryString(data);
|
|
}
|
|
var index = this.index = Request.JSONP.counter++;
|
|
var src = options.url + (options.url.test("\\?") ? "&" : "?") + options.callbackKey + "=Request.JSONP.request_map.request_" + index + (data ? "&" + data : "");
|
|
if (src.length > 2083) this.fireEvent("error", src);
|
|
Request.JSONP.request_map["request_" + index] = function() {
|
|
this.success(arguments, index);
|
|
}.bind(this);
|
|
var script = this.getScript(src).inject(options.injectScript);
|
|
this.fireEvent("request", [ src, script ]);
|
|
if (options.timeout) this.timeout.delay(options.timeout, this);
|
|
return this;
|
|
},
|
|
getScript: function(src) {
|
|
if (!this.script) this.script = new Element("script", {
|
|
type: "text/javascript",
|
|
async: true,
|
|
src: src
|
|
});
|
|
return this.script;
|
|
},
|
|
success: function(args, index) {
|
|
if (!this.running) return;
|
|
this.clear().fireEvent("complete", args).fireEvent("success", args).callChain();
|
|
},
|
|
cancel: function() {
|
|
if (this.running) this.clear().fireEvent("cancel");
|
|
return this;
|
|
},
|
|
isRunning: function() {
|
|
return !!this.running;
|
|
},
|
|
clear: function() {
|
|
this.running = false;
|
|
if (this.script) {
|
|
this.script.destroy();
|
|
this.script = null;
|
|
}
|
|
return this;
|
|
},
|
|
timeout: function() {
|
|
if (this.running) {
|
|
this.running = false;
|
|
this.fireEvent("timeout", [ this.script.get("src"), this.script ]).fireEvent("failure").cancel();
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
|
|
Request.JSONP.counter = 0;
|
|
|
|
Request.JSONP.request_map = {};
|
|
|
|
Request.implement({
|
|
options: {
|
|
initialDelay: 5e3,
|
|
delay: 5e3,
|
|
limit: 6e4
|
|
},
|
|
startTimer: function(data) {
|
|
var fn = function() {
|
|
if (!this.running) this.send({
|
|
data: data
|
|
});
|
|
};
|
|
this.lastDelay = this.options.initialDelay;
|
|
this.timer = fn.delay(this.lastDelay, this);
|
|
this.completeCheck = function(response) {
|
|
clearTimeout(this.timer);
|
|
this.lastDelay = response ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit);
|
|
this.timer = fn.delay(this.lastDelay, this);
|
|
};
|
|
return this.addEvent("complete", this.completeCheck);
|
|
},
|
|
stopTimer: function() {
|
|
clearTimeout(this.timer);
|
|
return this.removeEvent("complete", this.completeCheck);
|
|
}
|
|
});
|
|
|
|
Date.implement({
|
|
timeDiffInWords: function(to) {
|
|
return Date.distanceOfTimeInWords(this, to || new Date());
|
|
},
|
|
timeDiff: function(to, separator) {
|
|
if (to == null) to = new Date();
|
|
var delta = ((to - this) / 1e3).floor().abs();
|
|
var vals = [], durations = [ 60, 60, 24, 365, 0 ], names = [ "s", "m", "h", "d", "y" ], value, duration;
|
|
for (var item = 0; item < durations.length; item++) {
|
|
if (item && !delta) break;
|
|
value = delta;
|
|
if (duration = durations[item]) {
|
|
value = delta % duration;
|
|
delta = (delta / duration).floor();
|
|
}
|
|
vals.unshift(value + (names[item] || ""));
|
|
}
|
|
return vals.join(separator || ":");
|
|
}
|
|
}).extend({
|
|
distanceOfTimeInWords: function(from, to) {
|
|
return Date.getTimePhrase(((to - from) / 1e3).toInt());
|
|
},
|
|
getTimePhrase: function(delta) {
|
|
var suffix = delta < 0 ? "Until" : "Ago";
|
|
if (delta < 0) delta *= -1;
|
|
var units = {
|
|
minute: 60,
|
|
hour: 60,
|
|
day: 24,
|
|
week: 7,
|
|
month: 52 / 12,
|
|
year: 12,
|
|
eon: Infinity
|
|
};
|
|
var msg = "lessThanMinute";
|
|
for (var unit in units) {
|
|
var interval = units[unit];
|
|
if (delta < 1.5 * interval) {
|
|
if (delta > .75 * interval) msg = unit;
|
|
break;
|
|
}
|
|
delta /= interval;
|
|
msg = unit + "s";
|
|
}
|
|
delta = delta.round();
|
|
return Date.getMsg(msg + suffix, delta).substitute({
|
|
delta: delta
|
|
});
|
|
}
|
|
}).defineParsers({
|
|
re: /^(?:tod|tom|yes)/i,
|
|
handler: function(bits) {
|
|
var d = new Date().clearTime();
|
|
switch (bits[0]) {
|
|
case "tom":
|
|
return d.increment();
|
|
|
|
case "yes":
|
|
return d.decrement();
|
|
|
|
default:
|
|
return d;
|
|
}
|
|
}
|
|
}, {
|
|
re: /^(next|last) ([a-z]+)$/i,
|
|
handler: function(bits) {
|
|
var d = new Date().clearTime();
|
|
var day = d.getDay();
|
|
var newDay = Date.parseDay(bits[2], true);
|
|
var addDays = newDay - day;
|
|
if (newDay <= day) addDays += 7;
|
|
if (bits[1] == "last") addDays -= 7;
|
|
return d.set("date", d.getDate() + addDays);
|
|
}
|
|
}).alias("timeAgoInWords", "timeDiffInWords");
|
|
|
|
(function() {
|
|
var defaultSortFunction = function(a, b) {
|
|
return a > b ? 1 : a < b ? -1 : 0;
|
|
};
|
|
Array.implement({
|
|
stableSort: function(compare) {
|
|
return Browser.chrome || Browser.firefox2 || Browser.opera9 ? this.mergeSort(compare) : this.sort(compare);
|
|
},
|
|
mergeSort: function(compare, token) {
|
|
compare = compare || defaultSortFunction;
|
|
if (this.length > 1) {
|
|
var right = this.splice(Math.floor(this.length / 2)).mergeSort(compare);
|
|
var left = this.splice(0).mergeSort(compare);
|
|
while (left.length > 0 || right.length > 0) {
|
|
this.push(right.length === 0 ? left.shift() : left.length === 0 ? right.shift() : compare(left[0], right[0]) > 0 ? right.shift() : left.shift());
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
})();
|
|
|
|
Class.Binds = new Class({
|
|
$bound: {},
|
|
bound: function(name) {
|
|
return this.$bound[name] ? this.$bound[name] : this.$bound[name] = this[name].bind(this);
|
|
}
|
|
});
|
|
|
|
(function() {
|
|
var events = Element.NativeEvents, location = window.location, base = location.pathname, history = window.history, hasPushState = "pushState" in history, event = hasPushState ? "popstate" : "hashchange";
|
|
this.History = new new Class({
|
|
Implements: [ Class.Binds, Events ],
|
|
initialize: hasPushState ? function() {
|
|
events[event] = 2;
|
|
window.addEvent(event, this.bound("pop"));
|
|
} : function() {
|
|
events[event] = 1;
|
|
window.addEvent(event, this.bound("pop"));
|
|
this.hash = location.hash;
|
|
var hashchange = "onhashchange" in window;
|
|
if (!(hashchange && (document.documentMode === undefined || document.documentMode > 7))) this.timer = this.check.periodical(200, this);
|
|
},
|
|
push: hasPushState ? function(url, title, state) {
|
|
if (base && base != url) base = null;
|
|
history.pushState(state || null, title || null, url);
|
|
this.onChange(url, state);
|
|
} : function(url) {
|
|
location.hash = url;
|
|
},
|
|
replace: hasPushState ? function(url, title, state) {
|
|
history.replaceState(state || null, title || null, url);
|
|
} : function(url) {
|
|
this.hash = "#" + url;
|
|
this.push(url);
|
|
},
|
|
pop: hasPushState ? function(event) {
|
|
var url = location.pathname;
|
|
if (url == base) {
|
|
base = null;
|
|
return;
|
|
}
|
|
this.onChange(url, event.event.state);
|
|
} : function() {
|
|
var hash = location.hash;
|
|
if (this.hash == hash) return;
|
|
this.hash = hash;
|
|
this.onChange(hash.substr(1));
|
|
},
|
|
onChange: function(url, state) {
|
|
this.fireEvent("change", [ url, state || {} ]);
|
|
},
|
|
back: function() {
|
|
history.back();
|
|
},
|
|
forward: function() {
|
|
history.forward();
|
|
},
|
|
getPath: function() {
|
|
return hasPushState ? location.pathname : location.hash.substr(1);
|
|
},
|
|
hasPushState: function() {
|
|
return hasPushState;
|
|
},
|
|
check: function() {
|
|
if (this.hash != location.hash) this.pop();
|
|
}
|
|
})();
|
|
})();
|
|
|
|
History.handleInitialState = function(base) {
|
|
if (!base) base = "";
|
|
var location = window.location, pathname = location.pathname.substr(base.length), hash = location.hash, hasPushState = History.hasPushState();
|
|
if (!hasPushState && pathname.length > 1) {
|
|
window.location = (base || "/") + "#" + pathname;
|
|
return true;
|
|
}
|
|
if (!hash || hash.length <= 1) return false;
|
|
if (hasPushState) {
|
|
(function() {
|
|
History.push(hash.substr(1));
|
|
}).delay(1);
|
|
return false;
|
|
}
|
|
if (!pathname || pathname == "/") return false;
|
|
window.location = (base || "/") + hash;
|
|
return true;
|
|
};
|
|
|
|
(function() {
|
|
var Color, DecomposedMatrix, DecomposedMatrix2D, InterpolableArray, InterpolableColor, InterpolableObject, InterpolableWithUnit, Matrix, Matrix2D, Set, Vector, addTimeout, animationTick, animations, animationsTimeouts, applyDefaults, applyFrame, applyProperties, baseSVG, cacheFn, cancelTimeout, clone, createInterpolable, defaultValueForKey, degProperties, dynamics, getCurrentProperties, interpolate, isDocumentVisible, isSVGElement, lastTime, leftDelayForTimeout, makeArrayFn, observeVisibilityChange, parseProperties, prefixFor, propertyWithPrefix, pxProperties, rAF, roundf, runLoopPaused, runLoopRunning, runLoopTick, setRealTimeout, slow, slowRatio, startAnimation, startRunLoop, svgProperties, timeBeforeVisibilityChange, timeoutLastId, timeouts, toDashed, transformProperties, transformValueForProperty, unitForProperty, __bind = function(fn, me) {
|
|
return function() {
|
|
return fn.apply(me, arguments);
|
|
};
|
|
};
|
|
isDocumentVisible = function() {
|
|
return document.visibilityState === "visible" || dynamics.tests != null;
|
|
};
|
|
observeVisibilityChange = function() {
|
|
var fns;
|
|
fns = [];
|
|
if (typeof document !== "undefined" && document !== null) {
|
|
document.addEventListener("visibilitychange", function() {
|
|
var fn, _i, _len, _results;
|
|
_results = [];
|
|
for (_i = 0, _len = fns.length; _i < _len; _i++) {
|
|
fn = fns[_i];
|
|
_results.push(fn(isDocumentVisible()));
|
|
}
|
|
return _results;
|
|
});
|
|
}
|
|
return function(fn) {
|
|
return fns.push(fn);
|
|
};
|
|
}();
|
|
clone = function(o) {
|
|
var k, newO, v;
|
|
newO = {};
|
|
for (k in o) {
|
|
v = o[k];
|
|
newO[k] = v;
|
|
}
|
|
return newO;
|
|
};
|
|
cacheFn = function(func) {
|
|
var data;
|
|
data = {};
|
|
return function() {
|
|
var k, key, result, _i, _len;
|
|
key = "";
|
|
for (_i = 0, _len = arguments.length; _i < _len; _i++) {
|
|
k = arguments[_i];
|
|
key += k.toString() + ",";
|
|
}
|
|
result = data[key];
|
|
if (!result) {
|
|
data[key] = result = func.apply(this, arguments);
|
|
}
|
|
return result;
|
|
};
|
|
};
|
|
makeArrayFn = function(fn) {
|
|
return function(el) {
|
|
var args, i, res;
|
|
if (el instanceof Array || el instanceof NodeList || el instanceof HTMLCollection) {
|
|
res = function() {
|
|
var _i, _ref, _results;
|
|
_results = [];
|
|
for (i = _i = 0, _ref = el.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
|
args = Array.prototype.slice.call(arguments, 1);
|
|
args.splice(0, 0, el[i]);
|
|
_results.push(fn.apply(this, args));
|
|
}
|
|
return _results;
|
|
}.apply(this, arguments);
|
|
return res;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
};
|
|
};
|
|
applyDefaults = function(options, defaults) {
|
|
var k, v, _results;
|
|
_results = [];
|
|
for (k in defaults) {
|
|
v = defaults[k];
|
|
_results.push(options[k] != null ? options[k] : options[k] = v);
|
|
}
|
|
return _results;
|
|
};
|
|
applyFrame = function(el, properties) {
|
|
var k, v, _results;
|
|
if (el.style != null) {
|
|
return applyProperties(el, properties);
|
|
} else {
|
|
_results = [];
|
|
for (k in properties) {
|
|
v = properties[k];
|
|
_results.push(el[k] = v.format());
|
|
}
|
|
return _results;
|
|
}
|
|
};
|
|
applyProperties = function(el, properties) {
|
|
var isSVG, k, matrix, transforms, v;
|
|
properties = parseProperties(properties);
|
|
transforms = [];
|
|
isSVG = isSVGElement(el);
|
|
for (k in properties) {
|
|
v = properties[k];
|
|
if (transformProperties.contains(k)) {
|
|
transforms.push([ k, v ]);
|
|
} else {
|
|
if (v.format != null) {
|
|
v = v.format();
|
|
} else {
|
|
v = "" + v + unitForProperty(k, v);
|
|
}
|
|
if (isSVG && svgProperties.contains(k)) {
|
|
el.setAttribute(k, v);
|
|
} else {
|
|
el.style[propertyWithPrefix(k)] = v;
|
|
}
|
|
}
|
|
}
|
|
if (transforms.length > 0) {
|
|
if (isSVG) {
|
|
matrix = new Matrix2D();
|
|
matrix.applyProperties(transforms);
|
|
return el.setAttribute("transform", matrix.decompose().format());
|
|
} else {
|
|
v = transforms.map(function(transform) {
|
|
return transformValueForProperty(transform[0], transform[1]);
|
|
}).join(" ");
|
|
return el.style[propertyWithPrefix("transform")] = v;
|
|
}
|
|
}
|
|
};
|
|
isSVGElement = function(el) {
|
|
var _ref, _ref1;
|
|
if (typeof SVGElement !== "undefined" && SVGElement !== null && (typeof SVGSVGElement !== "undefined" && SVGSVGElement !== null)) {
|
|
return el instanceof SVGElement && !(el instanceof SVGSVGElement);
|
|
} else {
|
|
return (_ref = (_ref1 = dynamics.tests) != null ? typeof _ref1.isSVG === "function" ? _ref1.isSVG(el) : void 0 : void 0) != null ? _ref : false;
|
|
}
|
|
};
|
|
roundf = function(v, decimal) {
|
|
var d;
|
|
d = Math.pow(10, decimal);
|
|
return Math.round(v * d) / d;
|
|
};
|
|
Set = function() {
|
|
function Set(array) {
|
|
var v, _i, _len;
|
|
this.obj = {};
|
|
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
|
v = array[_i];
|
|
this.obj[v] = 1;
|
|
}
|
|
}
|
|
Set.prototype.contains = function(v) {
|
|
return this.obj[v] === 1;
|
|
};
|
|
return Set;
|
|
}();
|
|
toDashed = function(str) {
|
|
return str.replace(/([A-Z])/g, function($1) {
|
|
return "-" + $1.toLowerCase();
|
|
});
|
|
};
|
|
pxProperties = new Set("marginTop,marginLeft,marginBottom,marginRight,paddingTop,paddingLeft,paddingBottom,paddingRight,top,left,bottom,right,translateX,translateY,translateZ,perspectiveX,perspectiveY,perspectiveZ,width,height,maxWidth,maxHeight,minWidth,minHeight,borderRadius".split(","));
|
|
degProperties = new Set("rotate,rotateX,rotateY,rotateZ,skew,skewX,skewY,skewZ".split(","));
|
|
transformProperties = new Set("translate,translateX,translateY,translateZ,scale,scaleX,scaleY,scaleZ,rotate,rotateX,rotateY,rotateZ,rotateC,rotateCX,rotateCY,skew,skewX,skewY,skewZ,perspective".split(","));
|
|
svgProperties = new Set("accent-height,ascent,azimuth,baseFrequency,baseline-shift,bias,cx,cy,d,diffuseConstant,divisor,dx,dy,elevation,filterRes,fx,fy,gradientTransform,height,k1,k2,k3,k4,kernelMatrix,kernelUnitLength,letter-spacing,limitingConeAngle,markerHeight,markerWidth,numOctaves,order,overline-position,overline-thickness,pathLength,points,pointsAtX,pointsAtY,pointsAtZ,r,radius,rx,ry,seed,specularConstant,specularExponent,stdDeviation,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,surfaceScale,target,targetX,targetY,transform,underline-position,underline-thickness,viewBox,width,x,x1,x2,y,y1,y2,z".split(","));
|
|
unitForProperty = function(k, v) {
|
|
if (typeof v !== "number") {
|
|
return "";
|
|
}
|
|
if (pxProperties.contains(k)) {
|
|
return "px";
|
|
} else if (degProperties.contains(k)) {
|
|
return "deg";
|
|
}
|
|
return "";
|
|
};
|
|
transformValueForProperty = function(k, v) {
|
|
var match, unit;
|
|
match = ("" + v).match(/^([0-9.-]*)([^0-9]*)$/);
|
|
if (match != null) {
|
|
v = match[1];
|
|
unit = match[2];
|
|
} else {
|
|
v = parseFloat(v);
|
|
}
|
|
v = roundf(parseFloat(v), 10);
|
|
if (unit == null || unit === "") {
|
|
unit = unitForProperty(k, v);
|
|
}
|
|
return "" + k + "(" + v + unit + ")";
|
|
};
|
|
parseProperties = function(properties) {
|
|
var axis, match, parsed, property, value, _i, _len, _ref;
|
|
parsed = {};
|
|
for (property in properties) {
|
|
value = properties[property];
|
|
if (transformProperties.contains(property)) {
|
|
match = property.match(/(translate|rotateC|rotate|skew|scale|perspective)(X|Y|Z|)/);
|
|
if (match && match[2].length > 0) {
|
|
parsed[property] = value;
|
|
} else {
|
|
_ref = [ "X", "Y", "Z" ];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
axis = _ref[_i];
|
|
parsed[match[1] + axis] = value;
|
|
}
|
|
}
|
|
} else {
|
|
parsed[property] = value;
|
|
}
|
|
}
|
|
return parsed;
|
|
};
|
|
defaultValueForKey = function(key) {
|
|
var v;
|
|
v = key === "opacity" ? 1 : 0;
|
|
return "" + v + unitForProperty(key, v);
|
|
};
|
|
getCurrentProperties = function(el, keys) {
|
|
var isSVG, key, matrix, properties, style, v, _i, _j, _len, _len1, _ref;
|
|
properties = {};
|
|
isSVG = isSVGElement(el);
|
|
if (el.style != null) {
|
|
style = window.getComputedStyle(el, null);
|
|
for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
|
key = keys[_i];
|
|
if (transformProperties.contains(key)) {
|
|
if (properties["transform"] == null) {
|
|
if (isSVG) {
|
|
matrix = new Matrix2D((_ref = el.transform.baseVal.consolidate()) != null ? _ref.matrix : void 0);
|
|
} else {
|
|
matrix = Matrix.fromTransform(style[propertyWithPrefix("transform")]);
|
|
}
|
|
properties["transform"] = matrix.decompose();
|
|
}
|
|
} else {
|
|
v = style[key];
|
|
if (v == null && svgProperties.contains(key)) {
|
|
v = el.getAttribute(key);
|
|
}
|
|
if (v === "" || v == null) {
|
|
v = defaultValueForKey(key);
|
|
}
|
|
properties[key] = createInterpolable(v);
|
|
}
|
|
}
|
|
} else {
|
|
for (_j = 0, _len1 = keys.length; _j < _len1; _j++) {
|
|
key = keys[_j];
|
|
properties[key] = createInterpolable(el[key]);
|
|
}
|
|
}
|
|
return properties;
|
|
};
|
|
createInterpolable = function(value) {
|
|
var interpolable, klass, klasses, _i, _len;
|
|
klasses = [ InterpolableColor, InterpolableArray, InterpolableObject, InterpolableWithUnit ];
|
|
for (_i = 0, _len = klasses.length; _i < _len; _i++) {
|
|
klass = klasses[_i];
|
|
interpolable = klass.create(value);
|
|
if (interpolable != null) {
|
|
return interpolable;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
InterpolableObject = function() {
|
|
function InterpolableObject(obj) {
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
this.obj = obj;
|
|
}
|
|
InterpolableObject.prototype.interpolate = function(endInterpolable, t) {
|
|
var end, k, newObj, start, v;
|
|
start = this.obj;
|
|
end = endInterpolable.obj;
|
|
newObj = {};
|
|
for (k in start) {
|
|
v = start[k];
|
|
if (v.interpolate != null) {
|
|
newObj[k] = v.interpolate(end[k], t);
|
|
} else {
|
|
newObj[k] = v;
|
|
}
|
|
}
|
|
return new InterpolableObject(newObj);
|
|
};
|
|
InterpolableObject.prototype.format = function() {
|
|
return this.obj;
|
|
};
|
|
InterpolableObject.create = function(value) {
|
|
var k, obj, v;
|
|
if (value instanceof Object) {
|
|
obj = {};
|
|
for (k in value) {
|
|
v = value[k];
|
|
obj[k] = createInterpolable(v);
|
|
}
|
|
return new InterpolableObject(obj);
|
|
}
|
|
return null;
|
|
};
|
|
return InterpolableObject;
|
|
}();
|
|
InterpolableWithUnit = function() {
|
|
function InterpolableWithUnit(value, prefix, suffix) {
|
|
this.prefix = prefix;
|
|
this.suffix = suffix;
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
this.value = parseFloat(value);
|
|
}
|
|
InterpolableWithUnit.prototype.interpolate = function(endInterpolable, t) {
|
|
var end, start;
|
|
start = this.value;
|
|
end = endInterpolable.value;
|
|
return new InterpolableWithUnit((end - start) * t + start, endInterpolable.prefix || this.prefix, endInterpolable.suffix || this.suffix);
|
|
};
|
|
InterpolableWithUnit.prototype.format = function() {
|
|
if (this.prefix == null && this.suffix == null) {
|
|
return roundf(this.value, 5);
|
|
}
|
|
return this.prefix + roundf(this.value, 5) + this.suffix;
|
|
};
|
|
InterpolableWithUnit.create = function(value) {
|
|
var match;
|
|
if (typeof value !== "string") {
|
|
return new InterpolableWithUnit(value);
|
|
}
|
|
match = ("" + value).match("([^0-9.+-]*)([0-9.+-]+)([^0-9.+-]*)");
|
|
if (match != null) {
|
|
return new InterpolableWithUnit(match[2], match[1], match[3]);
|
|
}
|
|
return null;
|
|
};
|
|
return InterpolableWithUnit;
|
|
}();
|
|
InterpolableArray = function() {
|
|
function InterpolableArray(values, sep) {
|
|
this.values = values;
|
|
this.sep = sep;
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
}
|
|
InterpolableArray.prototype.interpolate = function(endInterpolable, t) {
|
|
var end, i, newValues, start, _i, _ref;
|
|
start = this.values;
|
|
end = endInterpolable.values;
|
|
newValues = [];
|
|
for (i = _i = 0, _ref = Math.min(start.length, end.length); 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
|
if (start[i].interpolate != null) {
|
|
newValues.push(start[i].interpolate(end[i], t));
|
|
} else {
|
|
newValues.push(start[i]);
|
|
}
|
|
}
|
|
return new InterpolableArray(newValues, this.sep);
|
|
};
|
|
InterpolableArray.prototype.format = function() {
|
|
var values;
|
|
values = this.values.map(function(val) {
|
|
if (val.format != null) {
|
|
return val.format();
|
|
} else {
|
|
return val;
|
|
}
|
|
});
|
|
if (this.sep != null) {
|
|
return values.join(this.sep);
|
|
} else {
|
|
return values;
|
|
}
|
|
};
|
|
InterpolableArray.createFromArray = function(arr, sep) {
|
|
var values;
|
|
values = arr.map(function(val) {
|
|
return createInterpolable(val) || val;
|
|
});
|
|
values = values.filter(function(val) {
|
|
return val != null;
|
|
});
|
|
return new InterpolableArray(values, sep);
|
|
};
|
|
InterpolableArray.create = function(value) {
|
|
var arr, sep, seps, _i, _len;
|
|
if (value instanceof Array) {
|
|
return InterpolableArray.createFromArray(value, null);
|
|
}
|
|
if (typeof value !== "string") {
|
|
return;
|
|
}
|
|
seps = [ " ", ",", "|", ";", "/", ":" ];
|
|
for (_i = 0, _len = seps.length; _i < _len; _i++) {
|
|
sep = seps[_i];
|
|
arr = value.split(sep);
|
|
if (arr.length > 1) {
|
|
return InterpolableArray.createFromArray(arr, sep);
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
return InterpolableArray;
|
|
}();
|
|
Color = function() {
|
|
function Color(rgb, format) {
|
|
this.rgb = rgb != null ? rgb : {};
|
|
this.format = format;
|
|
this.toRgba = __bind(this.toRgba, this);
|
|
this.toRgb = __bind(this.toRgb, this);
|
|
this.toHex = __bind(this.toHex, this);
|
|
}
|
|
Color.fromHex = function(hex) {
|
|
var hex3, result;
|
|
hex3 = hex.match(/^#([a-f\d]{1})([a-f\d]{1})([a-f\d]{1})$/i);
|
|
if (hex3 != null) {
|
|
hex = "#" + hex3[1] + hex3[1] + hex3[2] + hex3[2] + hex3[3] + hex3[3];
|
|
}
|
|
result = hex.match(/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
|
|
if (result != null) {
|
|
return new Color({
|
|
r: parseInt(result[1], 16),
|
|
g: parseInt(result[2], 16),
|
|
b: parseInt(result[3], 16),
|
|
a: 1
|
|
}, "hex");
|
|
}
|
|
return null;
|
|
};
|
|
Color.fromRgb = function(rgb) {
|
|
var match, _ref;
|
|
match = rgb.match(/^rgba?\(([0-9.]*), ?([0-9.]*), ?([0-9.]*)(?:, ?([0-9.]*))?\)$/);
|
|
if (match != null) {
|
|
return new Color({
|
|
r: parseFloat(match[1]),
|
|
g: parseFloat(match[2]),
|
|
b: parseFloat(match[3]),
|
|
a: parseFloat((_ref = match[4]) != null ? _ref : 1)
|
|
}, match[4] != null ? "rgba" : "rgb");
|
|
}
|
|
return null;
|
|
};
|
|
Color.componentToHex = function(c) {
|
|
var hex;
|
|
hex = c.toString(16);
|
|
if (hex.length === 1) {
|
|
return "0" + hex;
|
|
} else {
|
|
return hex;
|
|
}
|
|
};
|
|
Color.prototype.toHex = function() {
|
|
return "#" + Color.componentToHex(this.rgb.r) + Color.componentToHex(this.rgb.g) + Color.componentToHex(this.rgb.b);
|
|
};
|
|
Color.prototype.toRgb = function() {
|
|
return "rgb(" + this.rgb.r + ", " + this.rgb.g + ", " + this.rgb.b + ")";
|
|
};
|
|
Color.prototype.toRgba = function() {
|
|
return "rgba(" + this.rgb.r + ", " + this.rgb.g + ", " + this.rgb.b + ", " + this.rgb.a + ")";
|
|
};
|
|
return Color;
|
|
}();
|
|
InterpolableColor = function() {
|
|
function InterpolableColor(color) {
|
|
this.color = color;
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
}
|
|
InterpolableColor.prototype.interpolate = function(endInterpolable, t) {
|
|
var end, k, rgb, start, v, _i, _len, _ref;
|
|
start = this.color;
|
|
end = endInterpolable.color;
|
|
rgb = {};
|
|
_ref = [ "r", "g", "b" ];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
k = _ref[_i];
|
|
v = Math.round((end.rgb[k] - start.rgb[k]) * t + start.rgb[k]);
|
|
rgb[k] = Math.min(255, Math.max(0, v));
|
|
}
|
|
k = "a";
|
|
v = roundf((end.rgb[k] - start.rgb[k]) * t + start.rgb[k], 5);
|
|
rgb[k] = Math.min(1, Math.max(0, v));
|
|
return new InterpolableColor(new Color(rgb, end.format));
|
|
};
|
|
InterpolableColor.prototype.format = function() {
|
|
if (this.color.format === "hex") {
|
|
return this.color.toHex();
|
|
} else if (this.color.format === "rgb") {
|
|
return this.color.toRgb();
|
|
} else if (this.color.format === "rgba") {
|
|
return this.color.toRgba();
|
|
}
|
|
};
|
|
InterpolableColor.create = function(value) {
|
|
var color;
|
|
if (typeof value !== "string") {
|
|
return;
|
|
}
|
|
color = Color.fromHex(value) || Color.fromRgb(value);
|
|
if (color != null) {
|
|
return new InterpolableColor(color);
|
|
}
|
|
return null;
|
|
};
|
|
return InterpolableColor;
|
|
}();
|
|
DecomposedMatrix2D = function() {
|
|
function DecomposedMatrix2D(props) {
|
|
this.props = props;
|
|
this.applyRotateCenter = __bind(this.applyRotateCenter, this);
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
}
|
|
DecomposedMatrix2D.prototype.interpolate = function(endMatrix, t) {
|
|
var i, k, newProps, _i, _j, _k, _l, _len, _len1, _ref, _ref1, _ref2;
|
|
newProps = {};
|
|
_ref = [ "translate", "scale", "rotate" ];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
k = _ref[_i];
|
|
newProps[k] = [];
|
|
for (i = _j = 0, _ref1 = this.props[k].length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
|
newProps[k][i] = (endMatrix.props[k][i] - this.props[k][i]) * t + this.props[k][i];
|
|
}
|
|
}
|
|
for (i = _k = 1; _k <= 2; i = ++_k) {
|
|
newProps["rotate"][i] = endMatrix.props["rotate"][i];
|
|
}
|
|
_ref2 = [ "skew" ];
|
|
for (_l = 0, _len1 = _ref2.length; _l < _len1; _l++) {
|
|
k = _ref2[_l];
|
|
newProps[k] = (endMatrix.props[k] - this.props[k]) * t + this.props[k];
|
|
}
|
|
return new DecomposedMatrix2D(newProps);
|
|
};
|
|
DecomposedMatrix2D.prototype.format = function() {
|
|
return "translate(" + this.props.translate.join(",") + ") rotate(" + this.props.rotate.join(",") + ") skewX(" + this.props.skew + ") scale(" + this.props.scale.join(",") + ")";
|
|
};
|
|
DecomposedMatrix2D.prototype.applyRotateCenter = function(rotateC) {
|
|
var i, m, m2d, negativeTranslate, _i, _results;
|
|
m = baseSVG.createSVGMatrix();
|
|
m = m.translate(rotateC[0], rotateC[1]);
|
|
m = m.rotate(this.props.rotate[0]);
|
|
m = m.translate(-rotateC[0], -rotateC[1]);
|
|
m2d = new Matrix2D(m);
|
|
negativeTranslate = m2d.decompose().props.translate;
|
|
_results = [];
|
|
for (i = _i = 0; _i <= 1; i = ++_i) {
|
|
_results.push(this.props.translate[i] -= negativeTranslate[i]);
|
|
}
|
|
return _results;
|
|
};
|
|
return DecomposedMatrix2D;
|
|
}();
|
|
baseSVG = typeof document !== "undefined" && document !== null ? document.createElementNS("http://www.w3.org/2000/svg", "svg") : void 0;
|
|
Matrix2D = function() {
|
|
function Matrix2D(m) {
|
|
this.m = m;
|
|
this.applyProperties = __bind(this.applyProperties, this);
|
|
this.decompose = __bind(this.decompose, this);
|
|
if (!this.m) {
|
|
this.m = baseSVG.createSVGMatrix();
|
|
}
|
|
}
|
|
Matrix2D.prototype.decompose = function() {
|
|
var kx, ky, kz, r0, r1;
|
|
r0 = new Vector([ this.m.a, this.m.b ]);
|
|
r1 = new Vector([ this.m.c, this.m.d ]);
|
|
kx = r0.length();
|
|
kz = r0.dot(r1);
|
|
r0 = r0.normalize();
|
|
ky = r1.combine(r0, 1, -kz).length();
|
|
return new DecomposedMatrix2D({
|
|
translate: [ this.m.e, this.m.f ],
|
|
rotate: [ Math.atan2(this.m.b, this.m.a) * 180 / Math.PI, this.rotateCX, this.rotateCY ],
|
|
scale: [ kx, ky ],
|
|
skew: kz / ky * 180 / Math.PI
|
|
});
|
|
};
|
|
Matrix2D.prototype.applyProperties = function(properties) {
|
|
var hash, k, props, v, _i, _len, _ref, _ref1;
|
|
hash = {};
|
|
for (_i = 0, _len = properties.length; _i < _len; _i++) {
|
|
props = properties[_i];
|
|
hash[props[0]] = props[1];
|
|
}
|
|
for (k in hash) {
|
|
v = hash[k];
|
|
if (k === "translateX") {
|
|
this.m = this.m.translate(v, 0);
|
|
} else if (k === "translateY") {
|
|
this.m = this.m.translate(0, v);
|
|
} else if (k === "scaleX") {
|
|
this.m = this.m.scale(v, 1);
|
|
} else if (k === "scaleY") {
|
|
this.m = this.m.scale(1, v);
|
|
} else if (k === "rotateZ") {
|
|
this.m = this.m.rotate(v);
|
|
} else if (k === "skewX") {
|
|
this.m = this.m.skewX(v);
|
|
} else if (k === "skewY") {
|
|
this.m = this.m.skewY(v);
|
|
}
|
|
}
|
|
this.rotateCX = (_ref = hash.rotateCX) != null ? _ref : 0;
|
|
return this.rotateCY = (_ref1 = hash.rotateCY) != null ? _ref1 : 0;
|
|
};
|
|
return Matrix2D;
|
|
}();
|
|
Vector = function() {
|
|
function Vector(els) {
|
|
this.els = els;
|
|
this.combine = __bind(this.combine, this);
|
|
this.normalize = __bind(this.normalize, this);
|
|
this.length = __bind(this.length, this);
|
|
this.cross = __bind(this.cross, this);
|
|
this.dot = __bind(this.dot, this);
|
|
this.e = __bind(this.e, this);
|
|
}
|
|
Vector.prototype.e = function(i) {
|
|
if (i < 1 || i > this.els.length) {
|
|
return null;
|
|
} else {
|
|
return this.els[i - 1];
|
|
}
|
|
};
|
|
Vector.prototype.dot = function(vector) {
|
|
var V, n, product;
|
|
V = vector.els || vector;
|
|
product = 0;
|
|
n = this.els.length;
|
|
if (n !== V.length) {
|
|
return null;
|
|
}
|
|
n += 1;
|
|
while (--n) {
|
|
product += this.els[n - 1] * V[n - 1];
|
|
}
|
|
return product;
|
|
};
|
|
Vector.prototype.cross = function(vector) {
|
|
var A, B;
|
|
B = vector.els || vector;
|
|
if (this.els.length !== 3 || B.length !== 3) {
|
|
return null;
|
|
}
|
|
A = this.els;
|
|
return new Vector([ A[1] * B[2] - A[2] * B[1], A[2] * B[0] - A[0] * B[2], A[0] * B[1] - A[1] * B[0] ]);
|
|
};
|
|
Vector.prototype.length = function() {
|
|
var a, e, _i, _len, _ref;
|
|
a = 0;
|
|
_ref = this.els;
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
e = _ref[_i];
|
|
a += Math.pow(e, 2);
|
|
}
|
|
return Math.sqrt(a);
|
|
};
|
|
Vector.prototype.normalize = function() {
|
|
var e, i, length, newElements, _ref;
|
|
length = this.length();
|
|
newElements = [];
|
|
_ref = this.els;
|
|
for (i in _ref) {
|
|
e = _ref[i];
|
|
newElements[i] = e / length;
|
|
}
|
|
return new Vector(newElements);
|
|
};
|
|
Vector.prototype.combine = function(b, ascl, bscl) {
|
|
var i, result, _i, _ref;
|
|
result = [];
|
|
for (i = _i = 0, _ref = this.els.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
|
result[i] = ascl * this.els[i] + bscl * b.els[i];
|
|
}
|
|
return new Vector(result);
|
|
};
|
|
return Vector;
|
|
}();
|
|
DecomposedMatrix = function() {
|
|
function DecomposedMatrix() {
|
|
this.toMatrix = __bind(this.toMatrix, this);
|
|
this.format = __bind(this.format, this);
|
|
this.interpolate = __bind(this.interpolate, this);
|
|
}
|
|
DecomposedMatrix.prototype.interpolate = function(decomposedB, t, only) {
|
|
var angle, decomposed, decomposedA, i, invscale, invth, k, qa, qb, scale, th, _i, _j, _k, _l, _len, _ref, _ref1;
|
|
if (only == null) {
|
|
only = null;
|
|
}
|
|
decomposedA = this;
|
|
decomposed = new DecomposedMatrix();
|
|
_ref = [ "translate", "scale", "skew", "perspective" ];
|
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
k = _ref[_i];
|
|
decomposed[k] = [];
|
|
for (i = _j = 0, _ref1 = decomposedA[k].length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
|
if (only == null || only.indexOf(k) > -1 || only.indexOf("" + k + [ "x", "y", "z" ][i]) > -1) {
|
|
decomposed[k][i] = (decomposedB[k][i] - decomposedA[k][i]) * t + decomposedA[k][i];
|
|
} else {
|
|
decomposed[k][i] = decomposedA[k][i];
|
|
}
|
|
}
|
|
}
|
|
if (only == null || only.indexOf("rotate") !== -1) {
|
|
qa = decomposedA.quaternion;
|
|
qb = decomposedB.quaternion;
|
|
angle = qa[0] * qb[0] + qa[1] * qb[1] + qa[2] * qb[2] + qa[3] * qb[3];
|
|
if (angle < 0) {
|
|
for (i = _k = 0; _k <= 3; i = ++_k) {
|
|
qa[i] = -qa[i];
|
|
}
|
|
angle = -angle;
|
|
}
|
|
if (angle + 1 > .05) {
|
|
if (1 - angle >= .05) {
|
|
th = Math.acos(angle);
|
|
invth = 1 / Math.sin(th);
|
|
scale = Math.sin(th * (1 - t)) * invth;
|
|
invscale = Math.sin(th * t) * invth;
|
|
} else {
|
|
scale = 1 - t;
|
|
invscale = t;
|
|
}
|
|
} else {
|
|
qb[0] = -qa[1];
|
|
qb[1] = qa[0];
|
|
qb[2] = -qa[3];
|
|
qb[3] = qa[2];
|
|
scale = Math.sin(piDouble * (.5 - t));
|
|
invscale = Math.sin(piDouble * t);
|
|
}
|
|
decomposed.quaternion = [];
|
|
for (i = _l = 0; _l <= 3; i = ++_l) {
|
|
decomposed.quaternion[i] = qa[i] * scale + qb[i] * invscale;
|
|
}
|
|
} else {
|
|
decomposed.quaternion = decomposedA.quaternion;
|
|
}
|
|
return decomposed;
|
|
};
|
|
DecomposedMatrix.prototype.format = function() {
|
|
return this.toMatrix().toString();
|
|
};
|
|
DecomposedMatrix.prototype.toMatrix = function() {
|
|
var decomposedMatrix, i, j, match, matrix, quaternion, skew, temp, w, x, y, z, _i, _j, _k, _l;
|
|
decomposedMatrix = this;
|
|
matrix = Matrix.I(4);
|
|
for (i = _i = 0; _i <= 3; i = ++_i) {
|
|
matrix.els[i][3] = decomposedMatrix.perspective[i];
|
|
}
|
|
quaternion = decomposedMatrix.quaternion;
|
|
x = quaternion[0];
|
|
y = quaternion[1];
|
|
z = quaternion[2];
|
|
w = quaternion[3];
|
|
skew = decomposedMatrix.skew;
|
|
match = [ [ 1, 0 ], [ 2, 0 ], [ 2, 1 ] ];
|
|
for (i = _j = 2; _j >= 0; i = --_j) {
|
|
if (skew[i]) {
|
|
temp = Matrix.I(4);
|
|
temp.els[match[i][0]][match[i][1]] = skew[i];
|
|
matrix = matrix.multiply(temp);
|
|
}
|
|
}
|
|
matrix = matrix.multiply(new Matrix([ [ 1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w), 0 ], [ 2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w), 0 ], [ 2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y), 0 ], [ 0, 0, 0, 1 ] ]));
|
|
for (i = _k = 0; _k <= 2; i = ++_k) {
|
|
for (j = _l = 0; _l <= 2; j = ++_l) {
|
|
matrix.els[i][j] *= decomposedMatrix.scale[i];
|
|
}
|
|
matrix.els[3][i] = decomposedMatrix.translate[i];
|
|
}
|
|
return matrix;
|
|
};
|
|
return DecomposedMatrix;
|
|
}();
|
|
Matrix = function() {
|
|
function Matrix(els) {
|
|
this.els = els;
|
|
this.toString = __bind(this.toString, this);
|
|
this.decompose = __bind(this.decompose, this);
|
|
this.inverse = __bind(this.inverse, this);
|
|
this.augment = __bind(this.augment, this);
|
|
this.toRightTriangular = __bind(this.toRightTriangular, this);
|
|
this.transpose = __bind(this.transpose, this);
|
|
this.multiply = __bind(this.multiply, this);
|
|
this.dup = __bind(this.dup, this);
|
|
this.e = __bind(this.e, this);
|
|
}
|
|
Matrix.prototype.e = function(i, j) {
|
|
if (i < 1 || i > this.els.length || j < 1 || j > this.els[0].length) {
|
|
return null;
|
|
}
|
|
return this.els[i - 1][j - 1];
|
|
};
|
|
Matrix.prototype.dup = function() {
|
|
return new Matrix(this.els);
|
|
};
|
|
Matrix.prototype.multiply = function(matrix) {
|
|
var M, c, cols, elements, i, j, ki, kj, nc, ni, nj, returnVector, sum;
|
|
returnVector = matrix.modulus ? true : false;
|
|
M = matrix.els || matrix;
|
|
if (typeof M[0][0] === "undefined") {
|
|
M = new Matrix(M).els;
|
|
}
|
|
ni = this.els.length;
|
|
ki = ni;
|
|
kj = M[0].length;
|
|
cols = this.els[0].length;
|
|
elements = [];
|
|
ni += 1;
|
|
while (--ni) {
|
|
i = ki - ni;
|
|
elements[i] = [];
|
|
nj = kj;
|
|
nj += 1;
|
|
while (--nj) {
|
|
j = kj - nj;
|
|
sum = 0;
|
|
nc = cols;
|
|
nc += 1;
|
|
while (--nc) {
|
|
c = cols - nc;
|
|
sum += this.els[i][c] * M[c][j];
|
|
}
|
|
elements[i][j] = sum;
|
|
}
|
|
}
|
|
M = new Matrix(elements);
|
|
if (returnVector) {
|
|
return M.col(1);
|
|
} else {
|
|
return M;
|
|
}
|
|
};
|
|
Matrix.prototype.transpose = function() {
|
|
var cols, elements, i, j, ni, nj, rows;
|
|
rows = this.els.length;
|
|
cols = this.els[0].length;
|
|
elements = [];
|
|
ni = cols;
|
|
ni += 1;
|
|
while (--ni) {
|
|
i = cols - ni;
|
|
elements[i] = [];
|
|
nj = rows;
|
|
nj += 1;
|
|
while (--nj) {
|
|
j = rows - nj;
|
|
elements[i][j] = this.els[j][i];
|
|
}
|
|
}
|
|
return new Matrix(elements);
|
|
};
|
|
Matrix.prototype.toRightTriangular = function() {
|
|
var M, els, i, j, k, kp, multiplier, n, np, p, _i, _j, _ref, _ref1;
|
|
M = this.dup();
|
|
n = this.els.length;
|
|
k = n;
|
|
kp = this.els[0].length;
|
|
while (--n) {
|
|
i = k - n;
|
|
if (M.els[i][i] === 0) {
|
|
for (j = _i = _ref = i + 1; _ref <= k ? _i < k : _i > k; j = _ref <= k ? ++_i : --_i) {
|
|
if (M.els[j][i] !== 0) {
|
|
els = [];
|
|
np = kp;
|
|
np += 1;
|
|
while (--np) {
|
|
p = kp - np;
|
|
els.push(M.els[i][p] + M.els[j][p]);
|
|
}
|
|
M.els[i] = els;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (M.els[i][i] !== 0) {
|
|
for (j = _j = _ref1 = i + 1; _ref1 <= k ? _j < k : _j > k; j = _ref1 <= k ? ++_j : --_j) {
|
|
multiplier = M.els[j][i] / M.els[i][i];
|
|
els = [];
|
|
np = kp;
|
|
np += 1;
|
|
while (--np) {
|
|
p = kp - np;
|
|
els.push(p <= i ? 0 : M.els[j][p] - M.els[i][p] * multiplier);
|
|
}
|
|
M.els[j] = els;
|
|
}
|
|
}
|
|
}
|
|
return M;
|
|
};
|
|
Matrix.prototype.augment = function(matrix) {
|
|
var M, T, cols, i, j, ki, kj, ni, nj;
|
|
M = matrix.els || matrix;
|
|
if (typeof M[0][0] === "undefined") {
|
|
M = new Matrix(M).els;
|
|
}
|
|
T = this.dup();
|
|
cols = T.els[0].length;
|
|
ni = T.els.length;
|
|
ki = ni;
|
|
kj = M[0].length;
|
|
if (ni !== M.length) {
|
|
return null;
|
|
}
|
|
ni += 1;
|
|
while (--ni) {
|
|
i = ki - ni;
|
|
nj = kj;
|
|
nj += 1;
|
|
while (--nj) {
|
|
j = kj - nj;
|
|
T.els[i][cols + j] = M[i][j];
|
|
}
|
|
}
|
|
return T;
|
|
};
|
|
Matrix.prototype.inverse = function() {
|
|
var M, divisor, els, i, inverse_elements, j, ki, kp, new_element, ni, np, p, _i;
|
|
ni = this.els.length;
|
|
ki = ni;
|
|
M = this.augment(Matrix.I(ni)).toRightTriangular();
|
|
kp = M.els[0].length;
|
|
inverse_elements = [];
|
|
ni += 1;
|
|
while (--ni) {
|
|
i = ni - 1;
|
|
els = [];
|
|
np = kp;
|
|
inverse_elements[i] = [];
|
|
divisor = M.els[i][i];
|
|
np += 1;
|
|
while (--np) {
|
|
p = kp - np;
|
|
new_element = M.els[i][p] / divisor;
|
|
els.push(new_element);
|
|
if (p >= ki) {
|
|
inverse_elements[i].push(new_element);
|
|
}
|
|
}
|
|
M.els[i] = els;
|
|
for (j = _i = 0; 0 <= i ? _i < i : _i > i; j = 0 <= i ? ++_i : --_i) {
|
|
els = [];
|
|
np = kp;
|
|
np += 1;
|
|
while (--np) {
|
|
p = kp - np;
|
|
els.push(M.els[j][p] - M.els[i][p] * M.els[j][i]);
|
|
}
|
|
M.els[j] = els;
|
|
}
|
|
}
|
|
return new Matrix(inverse_elements);
|
|
};
|
|
Matrix.I = function(n) {
|
|
var els, i, j, k, nj;
|
|
els = [];
|
|
k = n;
|
|
n += 1;
|
|
while (--n) {
|
|
i = k - n;
|
|
els[i] = [];
|
|
nj = k;
|
|
nj += 1;
|
|
while (--nj) {
|
|
j = k - nj;
|
|
els[i][j] = i === j ? 1 : 0;
|
|
}
|
|
}
|
|
return new Matrix(els);
|
|
};
|
|
Matrix.prototype.decompose = function() {
|
|
var els, i, inversePerspectiveMatrix, j, k, matrix, pdum3, perspective, perspectiveMatrix, quaternion, result, rightHandSide, rotate, row, rowElement, s, scale, skew, t, translate, transposedInversePerspectiveMatrix, type, typeKey, v, w, x, y, z, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
matrix = this;
|
|
translate = [];
|
|
scale = [];
|
|
skew = [];
|
|
quaternion = [];
|
|
perspective = [];
|
|
els = [];
|
|
for (i = _i = 0; _i <= 3; i = ++_i) {
|
|
els[i] = [];
|
|
for (j = _j = 0; _j <= 3; j = ++_j) {
|
|
els[i][j] = matrix.els[i][j];
|
|
}
|
|
}
|
|
if (els[3][3] === 0) {
|
|
return false;
|
|
}
|
|
for (i = _k = 0; _k <= 3; i = ++_k) {
|
|
for (j = _l = 0; _l <= 3; j = ++_l) {
|
|
els[i][j] /= els[3][3];
|
|
}
|
|
}
|
|
perspectiveMatrix = matrix.dup();
|
|
for (i = _m = 0; _m <= 2; i = ++_m) {
|
|
perspectiveMatrix.els[i][3] = 0;
|
|
}
|
|
perspectiveMatrix.els[3][3] = 1;
|
|
if (els[0][3] !== 0 || els[1][3] !== 0 || els[2][3] !== 0) {
|
|
rightHandSide = new Vector(els.slice(0, 4)[3]);
|
|
inversePerspectiveMatrix = perspectiveMatrix.inverse();
|
|
transposedInversePerspectiveMatrix = inversePerspectiveMatrix.transpose();
|
|
perspective = transposedInversePerspectiveMatrix.multiply(rightHandSide).els;
|
|
for (i = _n = 0; _n <= 2; i = ++_n) {
|
|
els[i][3] = 0;
|
|
}
|
|
els[3][3] = 1;
|
|
} else {
|
|
perspective = [ 0, 0, 0, 1 ];
|
|
}
|
|
for (i = _o = 0; _o <= 2; i = ++_o) {
|
|
translate[i] = els[3][i];
|
|
els[3][i] = 0;
|
|
}
|
|
row = [];
|
|
for (i = _p = 0; _p <= 2; i = ++_p) {
|
|
row[i] = new Vector(els[i].slice(0, 3));
|
|
}
|
|
scale[0] = row[0].length();
|
|
row[0] = row[0].normalize();
|
|
skew[0] = row[0].dot(row[1]);
|
|
row[1] = row[1].combine(row[0], 1, -skew[0]);
|
|
scale[1] = row[1].length();
|
|
row[1] = row[1].normalize();
|
|
skew[0] /= scale[1];
|
|
skew[1] = row[0].dot(row[2]);
|
|
row[2] = row[2].combine(row[0], 1, -skew[1]);
|
|
skew[2] = row[1].dot(row[2]);
|
|
row[2] = row[2].combine(row[1], 1, -skew[2]);
|
|
scale[2] = row[2].length();
|
|
row[2] = row[2].normalize();
|
|
skew[1] /= scale[2];
|
|
skew[2] /= scale[2];
|
|
pdum3 = row[1].cross(row[2]);
|
|
if (row[0].dot(pdum3) < 0) {
|
|
for (i = _q = 0; _q <= 2; i = ++_q) {
|
|
scale[i] *= -1;
|
|
for (j = _r = 0; _r <= 2; j = ++_r) {
|
|
row[i].els[j] *= -1;
|
|
}
|
|
}
|
|
}
|
|
rowElement = function(index, elementIndex) {
|
|
return row[index].els[elementIndex];
|
|
};
|
|
rotate = [];
|
|
rotate[1] = Math.asin(-rowElement(0, 2));
|
|
if (Math.cos(rotate[1]) !== 0) {
|
|
rotate[0] = Math.atan2(rowElement(1, 2), rowElement(2, 2));
|
|
rotate[2] = Math.atan2(rowElement(0, 1), rowElement(0, 0));
|
|
} else {
|
|
rotate[0] = Math.atan2(-rowElement(2, 0), rowElement(1, 1));
|
|
rotate[1] = 0;
|
|
}
|
|
t = rowElement(0, 0) + rowElement(1, 1) + rowElement(2, 2) + 1;
|
|
if (t > 1e-4) {
|
|
s = .5 / Math.sqrt(t);
|
|
w = .25 / s;
|
|
x = (rowElement(2, 1) - rowElement(1, 2)) * s;
|
|
y = (rowElement(0, 2) - rowElement(2, 0)) * s;
|
|
z = (rowElement(1, 0) - rowElement(0, 1)) * s;
|
|
} else if (rowElement(0, 0) > rowElement(1, 1) && rowElement(0, 0) > rowElement(2, 2)) {
|
|
s = Math.sqrt(1 + rowElement(0, 0) - rowElement(1, 1) - rowElement(2, 2)) * 2;
|
|
x = .25 * s;
|
|
y = (rowElement(0, 1) + rowElement(1, 0)) / s;
|
|
z = (rowElement(0, 2) + rowElement(2, 0)) / s;
|
|
w = (rowElement(2, 1) - rowElement(1, 2)) / s;
|
|
} else if (rowElement(1, 1) > rowElement(2, 2)) {
|
|
s = Math.sqrt(1 + rowElement(1, 1) - rowElement(0, 0) - rowElement(2, 2)) * 2;
|
|
x = (rowElement(0, 1) + rowElement(1, 0)) / s;
|
|
y = .25 * s;
|
|
z = (rowElement(1, 2) + rowElement(2, 1)) / s;
|
|
w = (rowElement(0, 2) - rowElement(2, 0)) / s;
|
|
} else {
|
|
s = Math.sqrt(1 + rowElement(2, 2) - rowElement(0, 0) - rowElement(1, 1)) * 2;
|
|
x = (rowElement(0, 2) + rowElement(2, 0)) / s;
|
|
y = (rowElement(1, 2) + rowElement(2, 1)) / s;
|
|
z = .25 * s;
|
|
w = (rowElement(1, 0) - rowElement(0, 1)) / s;
|
|
}
|
|
quaternion = [ x, y, z, w ];
|
|
result = new DecomposedMatrix();
|
|
result.translate = translate;
|
|
result.scale = scale;
|
|
result.skew = skew;
|
|
result.quaternion = quaternion;
|
|
result.perspective = perspective;
|
|
result.rotate = rotate;
|
|
for (typeKey in result) {
|
|
type = result[typeKey];
|
|
for (k in type) {
|
|
v = type[k];
|
|
if (isNaN(v)) {
|
|
type[k] = 0;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
Matrix.prototype.toString = function() {
|
|
var i, j, str, _i, _j;
|
|
str = "matrix3d(";
|
|
for (i = _i = 0; _i <= 3; i = ++_i) {
|
|
for (j = _j = 0; _j <= 3; j = ++_j) {
|
|
str += roundf(this.els[i][j], 10);
|
|
if (!(i === 3 && j === 3)) {
|
|
str += ",";
|
|
}
|
|
}
|
|
}
|
|
str += ")";
|
|
return str;
|
|
};
|
|
Matrix.matrixForTransform = cacheFn(function(transform) {
|
|
var matrixEl, result, style, _ref, _ref1, _ref2;
|
|
matrixEl = document.createElement("div");
|
|
matrixEl.style.position = "absolute";
|
|
matrixEl.style.visibility = "hidden";
|
|
matrixEl.style[propertyWithPrefix("transform")] = transform;
|
|
document.body.appendChild(matrixEl);
|
|
style = window.getComputedStyle(matrixEl, null);
|
|
result = (_ref = (_ref1 = style.transform) != null ? _ref1 : style[propertyWithPrefix("transform")]) != null ? _ref : (_ref2 = dynamics.tests) != null ? _ref2.matrixForTransform(transform) : void 0;
|
|
document.body.removeChild(matrixEl);
|
|
return result;
|
|
});
|
|
Matrix.fromTransform = function(transform) {
|
|
var digits, elements, i, match, matrixElements, _i;
|
|
match = transform != null ? transform.match(/matrix3?d?\(([-0-9,e \.]*)\)/) : void 0;
|
|
if (match) {
|
|
digits = match[1].split(",");
|
|
digits = digits.map(parseFloat);
|
|
if (digits.length === 6) {
|
|
elements = [ digits[0], digits[1], 0, 0, digits[2], digits[3], 0, 0, 0, 0, 1, 0, digits[4], digits[5], 0, 1 ];
|
|
} else {
|
|
elements = digits;
|
|
}
|
|
} else {
|
|
elements = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ];
|
|
}
|
|
matrixElements = [];
|
|
for (i = _i = 0; _i <= 3; i = ++_i) {
|
|
matrixElements.push(elements.slice(i * 4, i * 4 + 4));
|
|
}
|
|
return new Matrix(matrixElements);
|
|
};
|
|
return Matrix;
|
|
}();
|
|
prefixFor = cacheFn(function(property) {
|
|
var k, prefix, prop, propArray, propertyName, _i, _j, _len, _len1, _ref;
|
|
if (document.body.style[property] !== void 0) {
|
|
return "";
|
|
}
|
|
propArray = property.split("-");
|
|
propertyName = "";
|
|
for (_i = 0, _len = propArray.length; _i < _len; _i++) {
|
|
prop = propArray[_i];
|
|
propertyName += prop.substring(0, 1).toUpperCase() + prop.substring(1);
|
|
}
|
|
_ref = [ "Webkit", "Moz", "ms" ];
|
|
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
|
prefix = _ref[_j];
|
|
k = prefix + propertyName;
|
|
if (document.body.style[k] !== void 0) {
|
|
return prefix;
|
|
}
|
|
}
|
|
return "";
|
|
});
|
|
propertyWithPrefix = cacheFn(function(property) {
|
|
var prefix;
|
|
prefix = prefixFor(property);
|
|
if (prefix === "Moz") {
|
|
return "" + prefix + (property.substring(0, 1).toUpperCase() + property.substring(1));
|
|
}
|
|
if (prefix !== "") {
|
|
return "-" + prefix.toLowerCase() + "-" + toDashed(property);
|
|
}
|
|
return toDashed(property);
|
|
});
|
|
rAF = typeof window !== "undefined" && window !== null ? window.requestAnimationFrame : void 0;
|
|
animations = [];
|
|
animationsTimeouts = [];
|
|
slow = false;
|
|
slowRatio = 1;
|
|
if (typeof window !== "undefined" && window !== null) {
|
|
window.addEventListener("keyup", function(e) {
|
|
if (e.keyCode === 68 && e.shiftKey && e.ctrlKey) {
|
|
return dynamics.toggleSlow();
|
|
}
|
|
});
|
|
}
|
|
if (rAF == null) {
|
|
lastTime = 0;
|
|
rAF = function(callback) {
|
|
var currTime, id, timeToCall;
|
|
currTime = Date.now();
|
|
timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
|
id = window.setTimeout(function() {
|
|
return callback(currTime + timeToCall);
|
|
}, timeToCall);
|
|
lastTime = currTime + timeToCall;
|
|
return id;
|
|
};
|
|
}
|
|
runLoopRunning = false;
|
|
runLoopPaused = false;
|
|
startRunLoop = function() {
|
|
if (!runLoopRunning) {
|
|
runLoopRunning = true;
|
|
return rAF(runLoopTick);
|
|
}
|
|
};
|
|
runLoopTick = function(t) {
|
|
var animation, toRemoveAnimations, _i, _len;
|
|
if (runLoopPaused) {
|
|
rAF(runLoopTick);
|
|
return;
|
|
}
|
|
toRemoveAnimations = [];
|
|
for (_i = 0, _len = animations.length; _i < _len; _i++) {
|
|
animation = animations[_i];
|
|
if (!animationTick(t, animation)) {
|
|
toRemoveAnimations.push(animation);
|
|
}
|
|
}
|
|
animations = animations.filter(function(animation) {
|
|
return toRemoveAnimations.indexOf(animation) === -1;
|
|
});
|
|
if (animations.length === 0) {
|
|
return runLoopRunning = false;
|
|
} else {
|
|
return rAF(runLoopTick);
|
|
}
|
|
};
|
|
animationTick = function(t, animation) {
|
|
var key, properties, property, tt, y, _base, _base1, _ref;
|
|
if (animation.tStart == null) {
|
|
animation.tStart = t;
|
|
}
|
|
tt = (t - animation.tStart) / animation.options.duration;
|
|
y = animation.curve(tt);
|
|
properties = {};
|
|
if (tt >= 1) {
|
|
if (animation.curve.initialForce) {
|
|
properties = animation.properties.start;
|
|
} else {
|
|
properties = animation.properties.end;
|
|
}
|
|
} else {
|
|
_ref = animation.properties.start;
|
|
for (key in _ref) {
|
|
property = _ref[key];
|
|
properties[key] = interpolate(property, animation.properties.end[key], y);
|
|
}
|
|
}
|
|
applyFrame(animation.el, properties);
|
|
if (typeof (_base = animation.options).change === "function") {
|
|
_base.change(animation.el);
|
|
}
|
|
if (tt >= 1) {
|
|
if (typeof (_base1 = animation.options).complete === "function") {
|
|
_base1.complete(animation.el);
|
|
}
|
|
}
|
|
return tt < 1;
|
|
};
|
|
interpolate = function(start, end, y) {
|
|
if (start != null && start.interpolate != null) {
|
|
return start.interpolate(end, y);
|
|
}
|
|
return null;
|
|
};
|
|
startAnimation = function(el, properties, options, timeoutId) {
|
|
var endProperties, isSVG, k, matrix, startProperties, transforms, v, _base;
|
|
if (timeoutId != null) {
|
|
animationsTimeouts = animationsTimeouts.filter(function(timeout) {
|
|
return timeout.id !== timeoutId;
|
|
});
|
|
}
|
|
dynamics.stop(el, {
|
|
timeout: false
|
|
});
|
|
if (!options.animated) {
|
|
dynamics.css(el, properties);
|
|
if (typeof options.complete === "function") {
|
|
options.complete(this);
|
|
}
|
|
return;
|
|
}
|
|
properties = parseProperties(properties);
|
|
startProperties = getCurrentProperties(el, Object.keys(properties));
|
|
endProperties = {};
|
|
transforms = [];
|
|
for (k in properties) {
|
|
v = properties[k];
|
|
if (transformProperties.contains(k)) {
|
|
transforms.push([ k, v ]);
|
|
} else {
|
|
endProperties[k] = createInterpolable(v);
|
|
if (endProperties[k] instanceof InterpolableWithUnit && el.style != null) {
|
|
endProperties[k].prefix = "";
|
|
if ((_base = endProperties[k]).suffix == null) {
|
|
_base.suffix = unitForProperty(k, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (transforms.length > 0) {
|
|
isSVG = isSVGElement(el);
|
|
if (isSVG) {
|
|
matrix = new Matrix2D();
|
|
matrix.applyProperties(transforms);
|
|
} else {
|
|
v = transforms.map(function(transform) {
|
|
return transformValueForProperty(transform[0], transform[1]);
|
|
}).join(" ");
|
|
matrix = Matrix.fromTransform(Matrix.matrixForTransform(v));
|
|
}
|
|
endProperties["transform"] = matrix.decompose();
|
|
if (isSVG) {
|
|
startProperties.transform.applyRotateCenter([ endProperties.transform.props.rotate[1], endProperties.transform.props.rotate[2] ]);
|
|
}
|
|
}
|
|
animations.push({
|
|
el: el,
|
|
properties: {
|
|
start: startProperties,
|
|
end: endProperties
|
|
},
|
|
options: options,
|
|
curve: options.type.call(options.type, options)
|
|
});
|
|
return startRunLoop();
|
|
};
|
|
timeouts = [];
|
|
timeoutLastId = 0;
|
|
setRealTimeout = function(timeout) {
|
|
if (!isDocumentVisible()) {
|
|
return;
|
|
}
|
|
return timeout.realTimeoutId = setTimeout(function() {
|
|
timeout.fn();
|
|
return cancelTimeout(timeout.id);
|
|
}, timeout.delay);
|
|
};
|
|
addTimeout = function(fn, delay) {
|
|
var timeout;
|
|
timeoutLastId += 1;
|
|
timeout = {
|
|
id: timeoutLastId,
|
|
tStart: Date.now(),
|
|
fn: fn,
|
|
delay: delay,
|
|
originalDelay: delay
|
|
};
|
|
setRealTimeout(timeout);
|
|
timeouts.push(timeout);
|
|
return timeoutLastId;
|
|
};
|
|
cancelTimeout = function(id) {
|
|
return timeouts = timeouts.filter(function(timeout) {
|
|
if (timeout.id === id) {
|
|
clearTimeout(timeout.realTimeoutId);
|
|
}
|
|
return timeout.id !== id;
|
|
});
|
|
};
|
|
leftDelayForTimeout = function(time, timeout) {
|
|
var consumedDelay;
|
|
if (time != null) {
|
|
consumedDelay = time - timeout.tStart;
|
|
return timeout.originalDelay - consumedDelay;
|
|
} else {
|
|
return timeout.originalDelay;
|
|
}
|
|
};
|
|
if (typeof window !== "undefined" && window !== null) {
|
|
window.addEventListener("unload", function() {});
|
|
}
|
|
timeBeforeVisibilityChange = null;
|
|
observeVisibilityChange(function(visible) {
|
|
var animation, difference, timeout, _i, _j, _k, _len, _len1, _len2, _results;
|
|
runLoopPaused = !visible;
|
|
if (!visible) {
|
|
timeBeforeVisibilityChange = Date.now();
|
|
_results = [];
|
|
for (_i = 0, _len = timeouts.length; _i < _len; _i++) {
|
|
timeout = timeouts[_i];
|
|
_results.push(clearTimeout(timeout.realTimeoutId));
|
|
}
|
|
return _results;
|
|
} else {
|
|
if (runLoopRunning) {
|
|
difference = Date.now() - timeBeforeVisibilityChange;
|
|
for (_j = 0, _len1 = animations.length; _j < _len1; _j++) {
|
|
animation = animations[_j];
|
|
if (animation.tStart != null) {
|
|
animation.tStart += difference;
|
|
}
|
|
}
|
|
}
|
|
for (_k = 0, _len2 = timeouts.length; _k < _len2; _k++) {
|
|
timeout = timeouts[_k];
|
|
timeout.delay = leftDelayForTimeout(timeBeforeVisibilityChange, timeout);
|
|
setRealTimeout(timeout);
|
|
}
|
|
return timeBeforeVisibilityChange = null;
|
|
}
|
|
});
|
|
dynamics = {};
|
|
dynamics.linear = function() {
|
|
return function(t) {
|
|
return t;
|
|
};
|
|
};
|
|
dynamics.spring = function(options) {
|
|
var A1, A2, decal, frequency, friction, s;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
applyDefaults(options, arguments.callee.defaults);
|
|
frequency = Math.max(1, options.frequency / 20);
|
|
friction = Math.pow(20, options.friction / 100);
|
|
s = options.anticipationSize / 1e3;
|
|
decal = Math.max(0, s);
|
|
A1 = function(t) {
|
|
var M, a, b, x0, x1;
|
|
M = .8;
|
|
x0 = s / (1 - s);
|
|
x1 = 0;
|
|
b = (x0 - M * x1) / (x0 - x1);
|
|
a = (M - b) / x0;
|
|
return a * t * options.anticipationStrength / 100 + b;
|
|
};
|
|
A2 = function(t) {
|
|
return Math.pow(friction / 10, -t) * (1 - t);
|
|
};
|
|
return function(t) {
|
|
var A, At, a, angle, b, frictionT, y0, yS;
|
|
frictionT = t / (1 - s) - s / (1 - s);
|
|
if (t < s) {
|
|
yS = s / (1 - s) - s / (1 - s);
|
|
y0 = 0 / (1 - s) - s / (1 - s);
|
|
b = Math.acos(1 / A1(yS));
|
|
a = (Math.acos(1 / A1(y0)) - b) / (frequency * -s);
|
|
A = A1;
|
|
} else {
|
|
A = A2;
|
|
b = 0;
|
|
a = 1;
|
|
}
|
|
At = A(frictionT);
|
|
angle = frequency * (t - s) * a + b;
|
|
return 1 - At * Math.cos(angle);
|
|
};
|
|
};
|
|
dynamics.bounce = function(options) {
|
|
var A, fn, frequency, friction;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
applyDefaults(options, arguments.callee.defaults);
|
|
frequency = Math.max(1, options.frequency / 20);
|
|
friction = Math.pow(20, options.friction / 100);
|
|
A = function(t) {
|
|
return Math.pow(friction / 10, -t) * (1 - t);
|
|
};
|
|
fn = function(t) {
|
|
var At, a, angle, b;
|
|
b = -3.14 / 2;
|
|
a = 1;
|
|
At = A(t);
|
|
angle = frequency * t * a + b;
|
|
return At * Math.cos(angle);
|
|
};
|
|
fn.initialForce = true;
|
|
return fn;
|
|
};
|
|
dynamics.gravity = function(options) {
|
|
var L, bounciness, curves, elasticity, fn, getPointInCurve, gravity;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
applyDefaults(options, arguments.callee.defaults);
|
|
bounciness = Math.min(options.bounciness / 1250, .8);
|
|
elasticity = options.elasticity / 1e3;
|
|
gravity = 100;
|
|
curves = [];
|
|
L = function() {
|
|
var b, curve;
|
|
b = Math.sqrt(2 / gravity);
|
|
curve = {
|
|
a: -b,
|
|
b: b,
|
|
H: 1
|
|
};
|
|
if (options.initialForce) {
|
|
curve.a = 0;
|
|
curve.b = curve.b * 2;
|
|
}
|
|
while (curve.H > .001) {
|
|
L = curve.b - curve.a;
|
|
curve = {
|
|
a: curve.b,
|
|
b: curve.b + L * bounciness,
|
|
H: curve.H * bounciness * bounciness
|
|
};
|
|
}
|
|
return curve.b;
|
|
}();
|
|
getPointInCurve = function(a, b, H, t) {
|
|
var c, t2;
|
|
L = b - a;
|
|
t2 = 2 / L * t - 1 - a * 2 / L;
|
|
c = t2 * t2 * H - H + 1;
|
|
if (options.initialForce) {
|
|
c = 1 - c;
|
|
}
|
|
return c;
|
|
};
|
|
(function() {
|
|
var L2, b, curve, _results;
|
|
b = Math.sqrt(2 / (gravity * L * L));
|
|
curve = {
|
|
a: -b,
|
|
b: b,
|
|
H: 1
|
|
};
|
|
if (options.initialForce) {
|
|
curve.a = 0;
|
|
curve.b = curve.b * 2;
|
|
}
|
|
curves.push(curve);
|
|
L2 = L;
|
|
_results = [];
|
|
while (curve.b < 1 && curve.H > .001) {
|
|
L2 = curve.b - curve.a;
|
|
curve = {
|
|
a: curve.b,
|
|
b: curve.b + L2 * bounciness,
|
|
H: curve.H * elasticity
|
|
};
|
|
_results.push(curves.push(curve));
|
|
}
|
|
return _results;
|
|
})();
|
|
fn = function(t) {
|
|
var curve, i, v;
|
|
i = 0;
|
|
curve = curves[i];
|
|
while (!(t >= curve.a && t <= curve.b)) {
|
|
i += 1;
|
|
curve = curves[i];
|
|
if (!curve) {
|
|
break;
|
|
}
|
|
}
|
|
if (!curve) {
|
|
v = options.initialForce ? 0 : 1;
|
|
} else {
|
|
v = getPointInCurve(curve.a, curve.b, curve.H, t);
|
|
}
|
|
return v;
|
|
};
|
|
fn.initialForce = options.initialForce;
|
|
return fn;
|
|
};
|
|
dynamics.forceWithGravity = function(options) {
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
applyDefaults(options, arguments.callee.defaults);
|
|
options.initialForce = true;
|
|
return dynamics.gravity(options);
|
|
};
|
|
dynamics.bezier = function() {
|
|
var Bezier, Bezier_, yForX;
|
|
Bezier_ = function(t, p0, p1, p2, p3) {
|
|
return Math.pow(1 - t, 3) * p0 + 3 * Math.pow(1 - t, 2) * t * p1 + 3 * (1 - t) * Math.pow(t, 2) * p2 + Math.pow(t, 3) * p3;
|
|
};
|
|
Bezier = function(t, p0, p1, p2, p3) {
|
|
return {
|
|
x: Bezier_(t, p0.x, p1.x, p2.x, p3.x),
|
|
y: Bezier_(t, p0.y, p1.y, p2.y, p3.y)
|
|
};
|
|
};
|
|
yForX = function(xTarget, Bs, returnsToSelf) {
|
|
var B, aB, i, lower, percent, upper, x, xTolerance, _i, _len;
|
|
B = null;
|
|
for (_i = 0, _len = Bs.length; _i < _len; _i++) {
|
|
aB = Bs[_i];
|
|
if (xTarget >= aB(0).x && xTarget <= aB(1).x) {
|
|
B = aB;
|
|
}
|
|
if (B !== null) {
|
|
break;
|
|
}
|
|
}
|
|
if (!B) {
|
|
if (returnsToSelf) {
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
xTolerance = 1e-4;
|
|
lower = 0;
|
|
upper = 1;
|
|
percent = (upper + lower) / 2;
|
|
x = B(percent).x;
|
|
i = 0;
|
|
while (Math.abs(xTarget - x) > xTolerance && i < 100) {
|
|
if (xTarget > x) {
|
|
lower = percent;
|
|
} else {
|
|
upper = percent;
|
|
}
|
|
percent = (upper + lower) / 2;
|
|
x = B(percent).x;
|
|
i += 1;
|
|
}
|
|
return B(percent).y;
|
|
};
|
|
return function(options) {
|
|
var Bs, points, returnsToSelf;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
points = options.points;
|
|
returnsToSelf = false;
|
|
Bs = function() {
|
|
var i, k, _fn;
|
|
Bs = [];
|
|
_fn = function(pointA, pointB) {
|
|
var B2;
|
|
B2 = function(t) {
|
|
return Bezier(t, pointA, pointA.cp[pointA.cp.length - 1], pointB.cp[0], pointB);
|
|
};
|
|
return Bs.push(B2);
|
|
};
|
|
for (i in points) {
|
|
k = parseInt(i);
|
|
if (k >= points.length - 1) {
|
|
break;
|
|
}
|
|
_fn(points[k], points[k + 1]);
|
|
}
|
|
return Bs;
|
|
}();
|
|
return function(t) {
|
|
if (t === 0) {
|
|
return 0;
|
|
} else if (t === 1) {
|
|
return 1;
|
|
} else {
|
|
return yForX(t, Bs, returnsToSelf);
|
|
}
|
|
};
|
|
};
|
|
}();
|
|
dynamics.easeInOut = function(options) {
|
|
var friction, _ref;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
friction = (_ref = options.friction) != null ? _ref : arguments.callee.defaults.friction;
|
|
return dynamics.bezier({
|
|
points: [ {
|
|
x: 0,
|
|
y: 0,
|
|
cp: [ {
|
|
x: .92 - friction / 1e3,
|
|
y: 0
|
|
} ]
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
cp: [ {
|
|
x: .08 + friction / 1e3,
|
|
y: 1
|
|
} ]
|
|
} ]
|
|
});
|
|
};
|
|
dynamics.easeIn = function(options) {
|
|
var friction, _ref;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
friction = (_ref = options.friction) != null ? _ref : arguments.callee.defaults.friction;
|
|
return dynamics.bezier({
|
|
points: [ {
|
|
x: 0,
|
|
y: 0,
|
|
cp: [ {
|
|
x: .92 - friction / 1e3,
|
|
y: 0
|
|
} ]
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
cp: [ {
|
|
x: 1,
|
|
y: 1
|
|
} ]
|
|
} ]
|
|
});
|
|
};
|
|
dynamics.easeOut = function(options) {
|
|
var friction, _ref;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
friction = (_ref = options.friction) != null ? _ref : arguments.callee.defaults.friction;
|
|
return dynamics.bezier({
|
|
points: [ {
|
|
x: 0,
|
|
y: 0,
|
|
cp: [ {
|
|
x: 0,
|
|
y: 0
|
|
} ]
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
cp: [ {
|
|
x: .08 + friction / 1e3,
|
|
y: 1
|
|
} ]
|
|
} ]
|
|
});
|
|
};
|
|
dynamics.spring.defaults = {
|
|
frequency: 300,
|
|
friction: 200,
|
|
anticipationSize: 0,
|
|
anticipationStrength: 0
|
|
};
|
|
dynamics.bounce.defaults = {
|
|
frequency: 300,
|
|
friction: 200
|
|
};
|
|
dynamics.forceWithGravity.defaults = dynamics.gravity.defaults = {
|
|
bounciness: 400,
|
|
elasticity: 200
|
|
};
|
|
dynamics.easeInOut.defaults = dynamics.easeIn.defaults = dynamics.easeOut.defaults = {
|
|
friction: 500
|
|
};
|
|
dynamics.css = makeArrayFn(function(el, properties) {
|
|
return applyProperties(el, properties, true);
|
|
});
|
|
dynamics.animate = makeArrayFn(function(el, properties, options) {
|
|
var id;
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
options = clone(options);
|
|
applyDefaults(options, {
|
|
type: dynamics.easeInOut,
|
|
duration: 1e3,
|
|
delay: 0,
|
|
animated: true
|
|
});
|
|
options.duration = Math.max(0, options.duration * slowRatio);
|
|
options.delay = Math.max(0, options.delay);
|
|
if (options.delay === 0) {
|
|
return startAnimation(el, properties, options);
|
|
} else {
|
|
id = dynamics.setTimeout(function() {
|
|
return startAnimation(el, properties, options, id);
|
|
}, options.delay);
|
|
return animationsTimeouts.push({
|
|
id: id,
|
|
el: el
|
|
});
|
|
}
|
|
});
|
|
dynamics.stop = makeArrayFn(function(el, options) {
|
|
if (options == null) {
|
|
options = {};
|
|
}
|
|
if (options.timeout == null) {
|
|
options.timeout = true;
|
|
}
|
|
if (options.timeout) {
|
|
animationsTimeouts = animationsTimeouts.filter(function(timeout) {
|
|
if (timeout.el === el && (options.filter == null || options.filter(timeout))) {
|
|
dynamics.clearTimeout(timeout.id);
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
return animations = animations.filter(function(animation) {
|
|
return animation.el !== el;
|
|
});
|
|
});
|
|
dynamics.setTimeout = function(fn, delay) {
|
|
return addTimeout(fn, delay * slowRatio);
|
|
};
|
|
dynamics.clearTimeout = function(id) {
|
|
return cancelTimeout(id);
|
|
};
|
|
dynamics.toggleSlow = function() {
|
|
slow = !slow;
|
|
if (slow) {
|
|
slowRatio = 3;
|
|
} else {
|
|
slowRatio = 1;
|
|
}
|
|
return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log("dynamics.js: slow animations " + (slow ? "enabled" : "disabled")) : void 0 : void 0;
|
|
};
|
|
if (typeof module === "object" && typeof module.exports === "object") {
|
|
module.exports = dynamics;
|
|
} else if (typeof define === "function") {
|
|
define("dynamics", function() {
|
|
return dynamics;
|
|
});
|
|
} else {
|
|
window.dynamics = dynamics;
|
|
}
|
|
}).call(this);
|
|
|
|
(function() {
|
|
"use strict";
|
|
function FastClick(layer, options) {
|
|
var oldOnClick;
|
|
options = options || {};
|
|
this.trackingClick = false;
|
|
this.trackingClickStart = 0;
|
|
this.targetElement = null;
|
|
this.touchStartX = 0;
|
|
this.touchStartY = 0;
|
|
this.lastTouchIdentifier = 0;
|
|
this.touchBoundary = options.touchBoundary || 10;
|
|
this.layer = layer;
|
|
this.tapDelay = options.tapDelay || 200;
|
|
this.tapTimeout = options.tapTimeout || 700;
|
|
if (FastClick.notNeeded(layer)) {
|
|
return;
|
|
}
|
|
function bind(method, context) {
|
|
return function() {
|
|
return method.apply(context, arguments);
|
|
};
|
|
}
|
|
var methods = [ "onMouse", "onClick", "onTouchStart", "onTouchMove", "onTouchEnd", "onTouchCancel" ];
|
|
var context = this;
|
|
for (var i = 0, l = methods.length; i < l; i++) {
|
|
context[methods[i]] = bind(context[methods[i]], context);
|
|
}
|
|
if (deviceIsAndroid) {
|
|
layer.addEventListener("mouseover", this.onMouse, true);
|
|
layer.addEventListener("mousedown", this.onMouse, true);
|
|
layer.addEventListener("mouseup", this.onMouse, true);
|
|
}
|
|
layer.addEventListener("click", this.onClick, true);
|
|
layer.addEventListener("touchstart", this.onTouchStart, false);
|
|
layer.addEventListener("touchmove", this.onTouchMove, false);
|
|
layer.addEventListener("touchend", this.onTouchEnd, false);
|
|
layer.addEventListener("touchcancel", this.onTouchCancel, false);
|
|
if (!Event.prototype.stopImmediatePropagation) {
|
|
layer.removeEventListener = function(type, callback, capture) {
|
|
var rmv = Node.prototype.removeEventListener;
|
|
if (type === "click") {
|
|
rmv.call(layer, type, callback.hijacked || callback, capture);
|
|
} else {
|
|
rmv.call(layer, type, callback, capture);
|
|
}
|
|
};
|
|
layer.addEventListener = function(type, callback, capture) {
|
|
var adv = Node.prototype.addEventListener;
|
|
if (type === "click") {
|
|
adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
|
|
if (!event.propagationStopped) {
|
|
callback(event);
|
|
}
|
|
}), capture);
|
|
} else {
|
|
adv.call(layer, type, callback, capture);
|
|
}
|
|
};
|
|
}
|
|
if (typeof layer.onclick === "function") {
|
|
oldOnClick = layer.onclick;
|
|
layer.addEventListener("click", function(event) {
|
|
oldOnClick(event);
|
|
}, false);
|
|
layer.onclick = null;
|
|
}
|
|
}
|
|
var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;
|
|
var deviceIsAndroid = navigator.userAgent.indexOf("Android") > 0 && !deviceIsWindowsPhone;
|
|
var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;
|
|
var deviceIsIOS4 = deviceIsIOS && /OS 4_\d(_\d)?/.test(navigator.userAgent);
|
|
var deviceIsIOSWithBadTarget = deviceIsIOS && /OS [6-7]_\d/.test(navigator.userAgent);
|
|
var deviceIsBlackBerry10 = navigator.userAgent.indexOf("BB10") > 0;
|
|
FastClick.prototype.needsClick = function(target) {
|
|
switch (target.nodeName.toLowerCase()) {
|
|
case "button":
|
|
case "select":
|
|
case "textarea":
|
|
if (target.disabled) {
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case "input":
|
|
if (deviceIsIOS && target.type === "file" || target.disabled) {
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case "label":
|
|
case "iframe":
|
|
case "video":
|
|
return true;
|
|
}
|
|
return /\bneedsclick\b/.test(target.className);
|
|
};
|
|
FastClick.prototype.needsFocus = function(target) {
|
|
switch (target.nodeName.toLowerCase()) {
|
|
case "textarea":
|
|
return true;
|
|
|
|
case "select":
|
|
return !deviceIsAndroid;
|
|
|
|
case "input":
|
|
switch (target.type) {
|
|
case "button":
|
|
case "checkbox":
|
|
case "file":
|
|
case "image":
|
|
case "radio":
|
|
case "submit":
|
|
return false;
|
|
}
|
|
return !target.disabled && !target.readOnly;
|
|
|
|
default:
|
|
return /\bneedsfocus\b/.test(target.className);
|
|
}
|
|
};
|
|
FastClick.prototype.sendClick = function(targetElement, event) {
|
|
var clickEvent, touch;
|
|
if (document.activeElement && document.activeElement !== targetElement) {
|
|
document.activeElement.blur();
|
|
}
|
|
touch = event.changedTouches[0];
|
|
clickEvent = document.createEvent("MouseEvents");
|
|
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
|
|
clickEvent.forwardedTouchEvent = true;
|
|
targetElement.dispatchEvent(clickEvent);
|
|
};
|
|
FastClick.prototype.determineEventType = function(targetElement) {
|
|
if (deviceIsAndroid && targetElement.tagName.toLowerCase() === "select") {
|
|
return "mousedown";
|
|
}
|
|
return "click";
|
|
};
|
|
FastClick.prototype.focus = function(targetElement) {
|
|
var length;
|
|
if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf("date") !== 0 && targetElement.type !== "time" && targetElement.type !== "month") {
|
|
length = targetElement.value.length;
|
|
targetElement.setSelectionRange(length, length);
|
|
} else {
|
|
targetElement.focus();
|
|
}
|
|
};
|
|
FastClick.prototype.updateScrollParent = function(targetElement) {
|
|
var scrollParent, parentElement;
|
|
scrollParent = targetElement.fastClickScrollParent;
|
|
if (!scrollParent || !scrollParent.contains(targetElement)) {
|
|
parentElement = targetElement;
|
|
do {
|
|
if (parentElement.scrollHeight > parentElement.offsetHeight) {
|
|
scrollParent = parentElement;
|
|
targetElement.fastClickScrollParent = parentElement;
|
|
break;
|
|
}
|
|
parentElement = parentElement.parentElement;
|
|
} while (parentElement);
|
|
}
|
|
if (scrollParent) {
|
|
scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
|
|
}
|
|
};
|
|
FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
|
|
if (eventTarget.nodeType === Node.TEXT_NODE) {
|
|
return eventTarget.parentNode;
|
|
}
|
|
return eventTarget;
|
|
};
|
|
FastClick.prototype.onTouchStart = function(event) {
|
|
var targetElement, touch, selection;
|
|
if (event.targetTouches.length > 1) {
|
|
return true;
|
|
}
|
|
targetElement = this.getTargetElementFromEventTarget(event.target);
|
|
touch = event.targetTouches[0];
|
|
if (deviceIsIOS) {
|
|
selection = window.getSelection();
|
|
if (selection.rangeCount && !selection.isCollapsed) {
|
|
return true;
|
|
}
|
|
if (!deviceIsIOS4) {
|
|
if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
this.lastTouchIdentifier = touch.identifier;
|
|
this.updateScrollParent(targetElement);
|
|
}
|
|
}
|
|
this.trackingClick = true;
|
|
this.trackingClickStart = event.timeStamp;
|
|
this.targetElement = targetElement;
|
|
this.touchStartX = touch.pageX;
|
|
this.touchStartY = touch.pageY;
|
|
if (event.timeStamp - this.lastClickTime < this.tapDelay) {
|
|
event.preventDefault();
|
|
}
|
|
return true;
|
|
};
|
|
FastClick.prototype.touchHasMoved = function(event) {
|
|
var touch = event.changedTouches[0], boundary = this.touchBoundary;
|
|
if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
FastClick.prototype.onTouchMove = function(event) {
|
|
if (!this.trackingClick) {
|
|
return true;
|
|
}
|
|
if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
|
|
this.trackingClick = false;
|
|
this.targetElement = null;
|
|
}
|
|
return true;
|
|
};
|
|
FastClick.prototype.findControl = function(labelElement) {
|
|
if (labelElement.control !== undefined) {
|
|
return labelElement.control;
|
|
}
|
|
if (labelElement.htmlFor) {
|
|
return document.getElementById(labelElement.htmlFor);
|
|
}
|
|
return labelElement.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea");
|
|
};
|
|
FastClick.prototype.onTouchEnd = function(event) {
|
|
var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
|
|
if (!this.trackingClick) {
|
|
return true;
|
|
}
|
|
if (event.timeStamp - this.lastClickTime < this.tapDelay) {
|
|
this.cancelNextClick = true;
|
|
return true;
|
|
}
|
|
if (event.timeStamp - this.trackingClickStart > this.tapTimeout) {
|
|
return true;
|
|
}
|
|
this.cancelNextClick = false;
|
|
this.lastClickTime = event.timeStamp;
|
|
trackingClickStart = this.trackingClickStart;
|
|
this.trackingClick = false;
|
|
this.trackingClickStart = 0;
|
|
if (deviceIsIOSWithBadTarget) {
|
|
touch = event.changedTouches[0];
|
|
targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
|
|
targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
|
|
}
|
|
targetTagName = targetElement.tagName.toLowerCase();
|
|
if (targetTagName === "label") {
|
|
forElement = this.findControl(targetElement);
|
|
if (forElement) {
|
|
this.focus(targetElement);
|
|
if (deviceIsAndroid) {
|
|
return false;
|
|
}
|
|
targetElement = forElement;
|
|
}
|
|
} else if (this.needsFocus(targetElement)) {
|
|
if (event.timeStamp - trackingClickStart > 100 || deviceIsIOS && window.top !== window && targetTagName === "input") {
|
|
this.targetElement = null;
|
|
return false;
|
|
}
|
|
this.focus(targetElement);
|
|
this.sendClick(targetElement, event);
|
|
if (!deviceIsIOS || targetTagName !== "select") {
|
|
this.targetElement = null;
|
|
event.preventDefault();
|
|
}
|
|
return false;
|
|
}
|
|
if (deviceIsIOS && !deviceIsIOS4) {
|
|
scrollParent = targetElement.fastClickScrollParent;
|
|
if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
|
|
return true;
|
|
}
|
|
}
|
|
if (!this.needsClick(targetElement)) {
|
|
event.preventDefault();
|
|
this.sendClick(targetElement, event);
|
|
}
|
|
return false;
|
|
};
|
|
FastClick.prototype.onTouchCancel = function() {
|
|
this.trackingClick = false;
|
|
this.targetElement = null;
|
|
};
|
|
FastClick.prototype.onMouse = function(event) {
|
|
if (!this.targetElement) {
|
|
return true;
|
|
}
|
|
if (event.forwardedTouchEvent) {
|
|
return true;
|
|
}
|
|
if (!event.cancelable) {
|
|
return true;
|
|
}
|
|
if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
|
|
if (event.stopImmediatePropagation) {
|
|
event.stopImmediatePropagation();
|
|
} else {
|
|
event.propagationStopped = true;
|
|
}
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
FastClick.prototype.onClick = function(event) {
|
|
var permitted;
|
|
if (this.trackingClick) {
|
|
this.targetElement = null;
|
|
this.trackingClick = false;
|
|
return true;
|
|
}
|
|
if (event.target.type === "submit" && event.detail === 0) {
|
|
return true;
|
|
}
|
|
permitted = this.onMouse(event);
|
|
if (!permitted) {
|
|
this.targetElement = null;
|
|
}
|
|
return permitted;
|
|
};
|
|
FastClick.prototype.destroy = function() {
|
|
var layer = this.layer;
|
|
if (deviceIsAndroid) {
|
|
layer.removeEventListener("mouseover", this.onMouse, true);
|
|
layer.removeEventListener("mousedown", this.onMouse, true);
|
|
layer.removeEventListener("mouseup", this.onMouse, true);
|
|
}
|
|
layer.removeEventListener("click", this.onClick, true);
|
|
layer.removeEventListener("touchstart", this.onTouchStart, false);
|
|
layer.removeEventListener("touchmove", this.onTouchMove, false);
|
|
layer.removeEventListener("touchend", this.onTouchEnd, false);
|
|
layer.removeEventListener("touchcancel", this.onTouchCancel, false);
|
|
};
|
|
FastClick.notNeeded = function(layer) {
|
|
var metaViewport;
|
|
var chromeVersion;
|
|
var blackberryVersion;
|
|
var firefoxVersion;
|
|
if (typeof window.ontouchstart === "undefined") {
|
|
return true;
|
|
}
|
|
chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [ , 0 ])[1];
|
|
if (chromeVersion) {
|
|
if (deviceIsAndroid) {
|
|
metaViewport = document.querySelector("meta[name=viewport]");
|
|
if (metaViewport) {
|
|
if (metaViewport.content.indexOf("user-scalable=no") !== -1) {
|
|
return true;
|
|
}
|
|
if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
|
|
return true;
|
|
}
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
if (deviceIsBlackBerry10) {
|
|
blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);
|
|
if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
|
|
metaViewport = document.querySelector("meta[name=viewport]");
|
|
if (metaViewport) {
|
|
if (metaViewport.content.indexOf("user-scalable=no") !== -1) {
|
|
return true;
|
|
}
|
|
if (document.documentElement.scrollWidth <= window.outerWidth) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (layer.style.msTouchAction === "none" || layer.style.touchAction === "manipulation") {
|
|
return true;
|
|
}
|
|
firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [ , 0 ])[1];
|
|
if (firefoxVersion >= 27) {
|
|
metaViewport = document.querySelector("meta[name=viewport]");
|
|
if (metaViewport && (metaViewport.content.indexOf("user-scalable=no") !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (layer.style.touchAction === "none" || layer.style.touchAction === "manipulation") {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
FastClick.attach = function(layer, options) {
|
|
return new FastClick(layer, options);
|
|
};
|
|
if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
|
|
define(function() {
|
|
return FastClick;
|
|
});
|
|
} else if (typeof module !== "undefined" && module.exports) {
|
|
module.exports = FastClick.attach;
|
|
module.exports.FastClick = FastClick;
|
|
} else {
|
|
window.FastClick = FastClick;
|
|
}
|
|
})();
|
|
|
|
window.requestAnimFrame = function() {
|
|
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
|
|
window.setTimeout(callback, 1e3 / 60);
|
|
};
|
|
}();
|
|
|
|
window.requestInterval = function(fn, delay) {
|
|
if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setInterval(fn, delay);
|
|
var start = new Date().getTime(), handle = new Object();
|
|
function loop() {
|
|
var current = new Date().getTime(), delta = current - start;
|
|
if (delta >= delay) {
|
|
fn.call();
|
|
start = new Date().getTime();
|
|
}
|
|
handle.value = requestAnimFrame(loop);
|
|
}
|
|
handle.value = requestAnimFrame(loop);
|
|
return handle;
|
|
};
|
|
|
|
window.clearRequestInterval = function(handle) {
|
|
window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearInterval(handle);
|
|
};
|
|
|
|
window.requestTimeout = function(fn, delay) {
|
|
if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setTimeout(fn, delay);
|
|
var start = new Date().getTime(), handle = new Object();
|
|
function loop() {
|
|
var current = new Date().getTime(), delta = current - start;
|
|
delta >= delay ? fn.call() : handle.value = requestAnimFrame(loop);
|
|
}
|
|
handle.value = requestAnimFrame(loop);
|
|
return handle;
|
|
};
|
|
|
|
window.clearRequestTimeout = function(handle) {
|
|
window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearTimeout(handle);
|
|
};
|