/*
---
mootools: the javascript framework
web build:
- http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0
packager build:
- packager build core/core core/array core/string core/number core/function core/object core/event core/browser core/class core/class.extras core/slick.parser core/slick.finder core/element core/element.style core/element.event core/element.delegation core/element.dimensions core/fx core/fx.css core/fx.tween core/fx.morph core/fx.transitions core/request core/request.html core/request.json core/cookie core/json core/domready core/swiff
...
*/
/*
---
name: core
description: the heart of mootools.
license: mit-style license.
copyright: copyright (c) 2006-2012 [valerio proietti](http://mad4milk.net/).
authors: the mootools production team (http://mootools.net/developers/)
inspiration:
- class implementation inspired by [base.js](http://dean.edwards.name/weblog/2006/03/base/) copyright (c) 2006 dean edwards, [gnu lesser general public license](http://opensource.org/licenses/lgpl-license.php)
- some functionality inspired by [prototype.js](http://prototypejs.org) copyright (c) 2005-2007 sam stephenson, [mit license](http://opensource.org/licenses/mit-license.php)
provides: [core, mootools, type, typeof, instanceof, native]
...
*/
(function(){
this.mootools = {
version: '1.4.5',
build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0'
};
// typeof, instanceof
var typeof = this.typeof = function(item){
if (item == null) return 'null';
if (item.$family != null) return item.$family();
if (item.nodename){
if (item.nodetype == 1) return 'element';
if (item.nodetype == 3) return (/\s/).test(item.nodevalue) ? 'textnode' : 'whitespace';
} else if (typeof item.length == 'number'){
if (item.callee) return 'arguments';
if ('item' in item) return 'collection';
}
return typeof item;
};
var instanceof = this.instanceof = function(item, object){
if (item == null) return false;
var constructor = item.$constructor || item.constructor;
while (constructor){
if (constructor === object) return true;
constructor = constructor.parent;
}
/**/
if (!item.hasownproperty) return false;
/**/
return item instanceof object;
};
// function overloading
var function = this.function;
var enumerables = true;
for (var i in {tostring: 1}) enumerables = null;
if (enumerables) enumerables = ['hasownproperty', 'valueof', 'isprototypeof', 'propertyisenumerable', 'tolocalestring', 'tostring', 'constructor'];
function.prototype.overloadsetter = function(useplural){
var self = this;
return function(a, b){
if (a == null) return this;
if (useplural || typeof a != 'string'){
for (var k in a) self.call(this, k, a[k]);
if (enumerables) for (var i = enumerables.length; i--;){
k = enumerables[i];
if (a.hasownproperty(k)) self.call(this, k, a[k]);
}
} else {
self.call(this, a, b);
}
return this;
};
};
function.prototype.overloadgetter = function(useplural){
var self = this;
return function(a){
var args, result;
if (typeof a != 'string') args = a;
else if (arguments.length > 1) args = arguments;
else if (useplural) args = [a];
if (args){
result = {};
for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
} else {
result = self.call(this, a);
}
return result;
};
};
function.prototype.extend = function(key, value){
this[key] = value;
}.overloadsetter();
function.prototype.implement = function(key, value){
this.prototype[key] = value;
}.overloadsetter();
// from
var slice = array.prototype.slice;
function.from = function(item){
return (typeof(item) == 'function') ? item : function(){
return item;
};
};
array.from = function(item){
if (item == null) return [];
return (type.isenumerable(item) && typeof item != 'string') ? (typeof(item) == 'array') ? item : slice.call(item) : [item];
};
number.from = function(item){
var number = parsefloat(item);
return isfinite(number) ? number : null;
};
string.from = function(item){
return item + '';
};
// hide, protect
function.implement({
hide: function(){
this.$hidden = true;
return this;
},
protect: function(){
this.$protected = true;
return this;
}
});
// type
var type = this.type = function(name, object){
if (name){
var lower = name.tolowercase();
var typecheck = function(item){
return (typeof(item) == lower);
};
type['is' + name] = typecheck;
if (object != null){
object.prototype.$family = (function(){
return lower;
}).hide();
//<1.2compat>
object.type = typecheck;
//1.2compat>
}
}
if (object == null) return null;
object.extend(this);
object.$constructor = type;
object.prototype.$constructor = object;
return object;
};
var tostring = object.prototype.tostring;
type.isenumerable = function(item){
return (item != null && typeof item.length == 'number' && tostring.call(item) != '[object function]' );
};
var hooks = {};
var hooksof = function(object){
var type = typeof(object.prototype);
return hooks[type] || (hooks[type] = []);
};
var implement = function(name, method){
if (method && method.$hidden) return;
var hooks = hooksof(this);
for (var i = 0; i < hooks.length; i++){
var hook = hooks[i];
if (typeof(hook) == 'type') implement.call(hook, name, method);
else hook.call(this, name, method);
}
var previous = this.prototype[name];
if (previous == null || !previous.$protected) this.prototype[name] = method;
if (this[name] == null && typeof(method) == 'function') extend.call(this, name, function(item){
return method.apply(item, slice.call(arguments, 1));
});
};
var extend = function(name, method){
if (method && method.$hidden) return;
var previous = this[name];
if (previous == null || !previous.$protected) this[name] = method;
};
type.implement({
implement: implement.overloadsetter(),
extend: extend.overloadsetter(),
alias: function(name, existing){
implement.call(this, name, this.prototype[existing]);
}.overloadsetter(),
mirror: function(hook){
hooksof(this).push(hook);
return this;
}
});
new type('type', type);
// default types
var force = function(name, object, methods){
var istype = (object != object),
prototype = object.prototype;
if (istype) object = new type(name, object);
for (var i = 0, l = methods.length; i < l; i++){
var key = methods[i],
generic = object[key],
proto = prototype[key];
if (generic) generic.protect();
if (istype && proto) 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', 'indexof', 'lastindexof', 'match', 'quote', 'replace', 'search',
'slice', 'split', 'substr', 'substring', 'trim', 'tolowercase', 'touppercase'
])('array', array, [
'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
'indexof', 'lastindexof', 'filter', 'foreach', 'every', 'map', 'some', 'reduce', 'reduceright'
])('number', number, [
'toexponential', 'tofixed', 'tolocalestring', 'toprecision'
])('function', function, [
'apply', 'call', 'bind'
])('regexp', regexp, [
'exec', 'test'
])('object', object, [
'create', 'defineproperty', 'defineproperties', 'keys',
'getprototypeof', 'getownpropertydescriptor', 'getownpropertynames',
'preventextensions', 'isextensible', 'seal', 'issealed', 'freeze', 'isfrozen'
])('date', date, ['now']);
object.extend = extend.overloadsetter();
date.extend('now', function(){
return +(new date);
});
new type('boolean', boolean);
// fixes nan returning as number
number.prototype.$family = function(){
return isfinite(this) ? 'number' : 'null';
}.hide();
// number.random
number.extend('random', function(min, max){
return math.floor(math.random() * (max - min + 1) + min);
});
// foreach, each
var hasownproperty = object.prototype.hasownproperty;
object.extend('foreach', function(object, fn, bind){
for (var key in object){
if (hasownproperty.call(object, key)) fn.call(bind, object[key], key, object);
}
});
object.each = object.foreach;
array.implement({
foreach: function(fn, bind){
for (var i = 0, l = this.length; i < l; i++){
if (i in this) fn.call(bind, this[i], i, this);
}
},
each: function(fn, bind){
array.foreach(this, fn, bind);
return this;
}
});
// array & object cloning, object merging and appending
var cloneof = function(item){
switch (typeof(item)){
case 'array': return item.clone();
case 'object': return object.clone(item);
default: return item;
}
};
array.implement('clone', function(){
var i = this.length, clone = new array(i);
while (i--) clone[i] = cloneof(this[i]);
return clone;
});
var mergeone = function(source, key, current){
switch (typeof(current)){
case 'object':
if (typeof(source[key]) == 'object') object.merge(source[key], current);
else source[key] = object.clone(current);
break;
case 'array': source[key] = current.clone(); break;
default: source[key] = current;
}
return source;
};
object.extend({
merge: function(source, k, v){
if (typeof(k) == 'string') return mergeone(source, k, v);
for (var i = 1, l = arguments.length; i < l; i++){
var object = arguments[i];
for (var key in object) mergeone(source, key, object[key]);
}
return source;
},
clone: function(object){
var clone = {};
for (var key in object) clone[key] = cloneof(object[key]);
return clone;
},
append: function(original){
for (var i = 1, l = arguments.length; i < l; i++){
var extended = arguments[i] || {};
for (var key in extended) original[key] = extended[key];
}
return original;
}
});
// object-less types
['object', 'whitespace', 'textnode', 'collection', 'arguments'].each(function(name){
new type(name);
});
// unique id
var uid = date.now();
string.extend('uniqueid', function(){
return (uid++).tostring(36);
});
//<1.2compat>
var hash = this.hash = new type('hash', function(object){
if (typeof(object) == 'hash') object = object.clone(object.getclean());
for (var key in object) this[key] = object[key];
return this;
});
hash.implement({
foreach: function(fn, bind){
object.foreach(this, fn, bind);
},
getclean: function(){
var clean = {};
for (var key in this){
if (this.hasownproperty(key)) clean[key] = this[key];
}
return clean;
},
getlength: function(){
var length = 0;
for (var key in this){
if (this.hasownproperty(key)) length++;
}
return length;
}
});
hash.alias('each', 'foreach');
object.type = type.isobject;
var native = this.native = function(properties){
return new type(properties.name, properties.initialize);
};
native.type = type.type;
native.implement = function(objects, methods){
for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
return native;
};
var arraytype = array.type;
array.type = function(item){
return instanceof(item, array) || arraytype(item);
};
this.$a = function(item){
return array.from(item).slice();
};
this.$arguments = function(i){
return function(){
return arguments[i];
};
};
this.$chk = function(obj){
return !!(obj || obj === 0);
};
this.$clear = function(timer){
cleartimeout(timer);
clearinterval(timer);
return null;
};
this.$defined = function(obj){
return (obj != null);
};
this.$each = function(iterable, fn, bind){
var type = typeof(iterable);
((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? array : object).each(iterable, fn, bind);
};
this.$empty = function(){};
this.$extend = function(original, extended){
return object.append(original, extended);
};
this.$h = function(object){
return new hash(object);
};
this.$merge = function(){
var args = array.slice(arguments);
args.unshift({});
return object.merge.apply(null, args);
};
this.$lambda = function.from;
this.$mixin = object.merge;
this.$random = number.random;
this.$splat = array.from;
this.$time = date.now;
this.$type = function(object){
var type = typeof(object);
if (type == 'elements') return 'array';
return (type == 'null') ? false : type;
};
this.$unlink = function(object){
switch (typeof(object)){
case 'object': return object.clone(object);
case 'array': return array.clone(object);
case 'hash': return new hash(object);
default: return object;
}
};
//1.2compat>
})();
/*
---
name: array
description: contains array prototypes like each, contains, and erase.
license: mit-style license.
requires: type
provides: array
...
*/
array.implement({
/**/
every: function(fn, bind){
for (var i = 0, l = this.length >>> 0; i < l; i++){
if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
}
return true;
},
filter: function(fn, bind){
var results = [];
for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){
value = this[i];
if (fn.call(bind, value, i, this)) results.push(value);
}
return results;
},
indexof: function(item, from){
var length = this.length >>> 0;
for (var i = (from < 0) ? math.max(0, length + from) : from || 0; i < length; i++){
if (this[i] === item) return i;
}
return -1;
},
map: function(fn, bind){
var length = this.length >>> 0, results = array(length);
for (var i = 0; i < length; i++){
if (i in this) results[i] = fn.call(bind, this[i], i, this);
}
return results;
},
some: function(fn, bind){
for (var i = 0, l = this.length >>> 0; i < l; i++){
if ((i in this) && fn.call(bind, this[i], i, this)) return true;
}
return false;
},
/*!es5>*/
clean: function(){
return this.filter(function(item){
return item != null;
});
},
invoke: function(methodname){
var args = array.slice(arguments, 1);
return this.map(function(item){
return item[methodname].apply(item, args);
});
},
associate: function(keys){
var obj = {}, length = math.min(this.length, keys.length);
for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
return obj;
},
link: function(object){
var result = {};
for (var i = 0, l = this.length; i < l; i++){
for (var key in object){
if (object[key](this[i])){
result[key] = this[i];
delete object[key];
break;
}
}
}
return result;
},
contains: function(item, from){
return this.indexof(item, from) != -1;
},
append: function(array){
this.push.apply(this, array);
return this;
},
getlast: function(){
return (this.length) ? this[this.length - 1] : null;
},
getrandom: function(){
return (this.length) ? this[number.random(0, this.length - 1)] : null;
},
include: function(item){
if (!this.contains(item)) this.push(item);
return this;
},
combine: function(array){
for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
return this;
},
erase: function(item){
for (var i = this.length; i--;){
if (this[i] === item) this.splice(i, 1);
}
return this;
},
empty: function(){
this.length = 0;
return this;
},
flatten: function(){
var array = [];
for (var i = 0, l = this.length; i < l; i++){
var type = typeof(this[i]);
if (type == 'null') continue;
array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceof(this[i], array)) ? array.flatten(this[i]) : this[i]);
}
return array;
},
pick: function(){
for (var i = 0, l = this.length; i < l; i++){
if (this[i] != null) return this[i];
}
return null;
},
hextorgb: function(array){
if (this.length != 3) return null;
var rgb = this.map(function(value){
if (value.length == 1) value += value;
return value.toint(16);
});
return (array) ? rgb : 'rgb(' + rgb + ')';
},
rgbtohex: function(array){
if (this.length < 3) return null;
if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
var hex = [];
for (var i = 0; i < 3; i++){
var bit = (this[i] - 0).tostring(16);
hex.push((bit.length == 1) ? '0' + bit : bit);
}
return (array) ? hex : '#' + hex.join('');
}
});
//<1.2compat>
array.alias('extend', 'append');
var $pick = function(){
return array.from(arguments).pick();
};
//1.2compat>
/*
---
name: string
description: contains string prototypes like camelcase, capitalize, test, and toint.
license: mit-style license.
requires: type
provides: string
...
*/
string.implement({
test: function(regex, params){
return ((typeof(regex) == 'regexp') ? regex : new regexp('' + regex, params)).test(this);
},
contains: function(string, separator){
return (separator) ? (separator + this + separator).indexof(separator + string + separator) > -1 : string(this).indexof(string) > -1;
},
trim: function(){
return string(this).replace(/^\s+|\s+$/g, '');
},
clean: function(){
return string(this).replace(/\s+/g, ' ').trim();
},
camelcase: function(){
return string(this).replace(/-\d/g, function(match){
return match.charat(1).touppercase();
});
},
hyphenate: function(){
return string(this).replace(/[a-z]/g, function(match){
return ('-' + match.charat(0).tolowercase());
});
},
capitalize: function(){
return string(this).replace(/\b[a-z]/g, function(match){
return match.touppercase();
});
},
escaperegexp: function(){
return string(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
},
toint: function(base){
return parseint(this, base || 10);
},
tofloat: function(){
return parsefloat(this);
},
hextorgb: function(array){
var hex = string(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
return (hex) ? hex.slice(1).hextorgb(array) : null;
},
rgbtohex: function(array){
var rgb = string(this).match(/\d{1,3}/g);
return (rgb) ? rgb.rgbtohex(array) : null;
},
substitute: function(object, regexp){
return string(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
if (match.charat(0) == '\\') return match.slice(1);
return (object[name] != null) ? object[name] : '';
});
}
});
/*
---
name: number
description: contains number prototypes like limit, round, times, and ceil.
license: mit-style license.
requires: type
provides: number
...
*/
number.implement({
limit: function(min, max){
return math.min(max, math.max(min, this));
},
round: function(precision){
precision = math.pow(10, precision || 0).tofixed(precision < 0 ? -precision : 0);
return math.round(this * precision) / precision;
},
times: function(fn, bind){
for (var i = 0; i < this; i++) fn.call(bind, i, this);
},
tofloat: function(){
return parsefloat(this);
},
toint: function(base){
return parseint(this, base || 10);
}
});
number.alias('each', 'times');
(function(math){
var methods = {};
math.each(function(name){
if (!number[name]) methods[name] = function(){
return math[name].apply(null, [this].concat(array.from(arguments)));
};
});
number.implement(methods);
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
/*
---
name: function
description: contains function prototypes like create, bind, pass, and delay.
license: mit-style license.
requires: type
provides: function
...
*/
function.extend({
attempt: function(){
for (var i = 0, l = arguments.length; i < l; i++){
try {
return arguments[i]();
} catch (e){}
}
return null;
}
});
function.implement({
attempt: function(args, bind){
try {
return this.apply(bind, array.from(args));
} catch (e){}
return null;
},
/**/
bind: function(that){
var self = this,
args = arguments.length > 1 ? array.slice(arguments, 1) : null,
f = function(){};
var bound = function(){
var context = that, length = arguments.length;
if (this instanceof bound){
f.prototype = self.prototype;
context = new f;
}
var result = (!args && !length)
? self.call(context)
: self.apply(context, args && length ? args.concat(array.slice(arguments)) : args || arguments);
return context == that ? result : context;
};
return bound;
},
/*!es5-bind>*/
pass: function(args, bind){
var self = this;
if (args != null) args = array.from(args);
return function(){
return self.apply(bind, args || arguments);
};
},
delay: function(delay, bind, args){
return settimeout(this.pass((args == null ? [] : args), bind), delay);
},
periodical: function(periodical, bind, args){
return setinterval(this.pass((args == null ? [] : args), bind), periodical);
}
});
//<1.2compat>
delete function.prototype.bind;
function.implement({
create: function(options){
var self = this;
options = options || {};
return function(event){
var args = options.arguments;
args = (args != null) ? array.from(args) : array.slice(arguments, (options.event) ? 1 : 0);
if (options.event) args = [event || window.event].extend(args);
var returns = function(){
return self.apply(options.bind || null, args);
};
if (options.delay) return settimeout(returns, options.delay);
if (options.periodical) return setinterval(returns, options.periodical);
if (options.attempt) return function.attempt(returns);
return returns();
};
},
bind: function(bind, args){
var self = this;
if (args != null) args = array.from(args);
return function(){
return self.apply(bind, args || arguments);
};
},
bindwithevent: function(bind, args){
var self = this;
if (args != null) args = array.from(args);
return function(event){
return self.apply(bind, (args == null) ? arguments : [event].concat(args));
};
},
run: function(args, bind){
return this.apply(bind, array.from(args));
}
});
if (object.create == function.prototype.create) object.create = null;
var $try = function.attempt;
//1.2compat>
/*
---
name: object
description: object generic methods
license: mit-style license.
requires: type
provides: [object, hash]
...
*/
(function(){
var hasownproperty = object.prototype.hasownproperty;
object.extend({
subset: function(object, keys){
var results = {};
for (var i = 0, l = keys.length; i < l; i++){
var k = keys[i];
if (k in object) results[k] = object[k];
}
return results;
},
map: function(object, fn, bind){
var results = {};
for (var key in object){
if (hasownproperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
}
return results;
},
filter: function(object, fn, bind){
var results = {};
for (var key in object){
var value = object[key];
if (hasownproperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
}
return results;
},
every: function(object, fn, bind){
for (var key in object){
if (hasownproperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
}
return true;
},
some: function(object, fn, bind){
for (var key in object){
if (hasownproperty.call(object, key) && fn.call(bind, object[key], key)) return true;
}
return false;
},
keys: function(object){
var keys = [];
for (var key in object){
if (hasownproperty.call(object, key)) keys.push(key);
}
return keys;
},
values: function(object){
var values = [];
for (var key in object){
if (hasownproperty.call(object, key)) values.push(object[key]);
}
return values;
},
getlength: function(object){
return object.keys(object).length;
},
keyof: function(object, value){
for (var key in object){
if (hasownproperty.call(object, key) && object[key] === value) return key;
}
return null;
},
contains: function(object, value){
return object.keyof(object, value) != null;
},
toquerystring: function(object, base){
var querystring = [];
object.each(object, function(value, key){
if (base) key = base + '[' + key + ']';
var result;
switch (typeof(value)){
case 'object': result = object.toquerystring(value, key); break;
case 'array':
var qs = {};
value.each(function(val, i){
qs[i] = val;
});
result = object.toquerystring(qs, key);
break;
default: result = key + '=' + encodeuricomponent(value);
}
if (value != null) querystring.push(result);
});
return querystring.join('&');
}
});
})();
//<1.2compat>
hash.implement({
has: object.prototype.hasownproperty,
keyof: function(value){
return object.keyof(this, value);
},
hasvalue: function(value){
return object.contains(this, value);
},
extend: function(properties){
hash.each(properties || {}, function(value, key){
hash.set(this, key, value);
}, this);
return this;
},
combine: function(properties){
hash.each(properties || {}, function(value, key){
hash.include(this, key, value);
}, this);
return this;
},
erase: function(key){
if (this.hasownproperty(key)) delete this[key];
return this;
},
get: function(key){
return (this.hasownproperty(key)) ? this[key] : null;
},
set: function(key, value){
if (!this[key] || this.hasownproperty(key)) this[key] = value;
return this;
},
empty: function(){
hash.each(this, function(value, key){
delete this[key];
}, this);
return this;
},
include: function(key, value){
if (this[key] == null) this[key] = value;
return this;
},
map: function(fn, bind){
return new hash(object.map(this, fn, bind));
},
filter: function(fn, bind){
return new hash(object.filter(this, fn, bind));
},
every: function(fn, bind){
return object.every(this, fn, bind);
},
some: function(fn, bind){
return object.some(this, fn, bind);
},
getkeys: function(){
return object.keys(this);
},
getvalues: function(){
return object.values(this);
},
toquerystring: function(base){
return object.toquerystring(this, base);
}
});
hash.extend = object.append;
hash.alias({indexof: 'keyof', contains: 'hasvalue'});
//1.2compat>
/*
---
name: browser
description: the browser object. contains browser initialization, window and document, and the browser hash.
license: mit-style license.
requires: [array, function, number, string]
provides: [browser, window, document]
...
*/
(function(){
var document = this.document;
var window = document.window = this;
var ua = navigator.useragent.tolowercase(),
platform = navigator.platform.tolowercase(),
ua = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
mode = ua[1] == 'ie' && document.documentmode;
var browser = this.browser = {
extend: function.prototype.extend,
name: (ua[1] == 'version') ? ua[3] : ua[1],
version: mode || parsefloat((ua[1] == 'opera' && ua[4]) ? ua[4] : ua[2]),
platform: {
name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
},
features: {
xpath: !!(document.evaluate),
air: !!(window.runtime),
query: !!(document.queryselector),
json: !!(window.json)
},
plugins: {}
};
browser[browser.name] = true;
browser[browser.name + parseint(browser.version, 10)] = true;
browser.platform[browser.platform.name] = true;
// request
browser.request = (function(){
var xmlhttp = function(){
return new xmlhttprequest();
};
var msxml2 = function(){
return new activexobject('msxml2.xmlhttp');
};
var msxml = function(){
return new activexobject('microsoft.xmlhttp');
};
return function.attempt(function(){
xmlhttp();
return xmlhttp;
}, function(){
msxml2();
return msxml2;
}, function(){
msxml();
return msxml;
});
})();
browser.features.xhr = !!(browser.request);
// flash detection
var version = (function.attempt(function(){
return navigator.plugins['shockwave flash'].description;
}, function(){
return new activexobject('shockwaveflash.shockwaveflash').getvariable('$version');
}) || '0 r0').match(/\d+/g);
browser.plugins.flash = {
version: number(version[0] || '0.' + version[1]) || 0,
build: number(version[2]) || 0
};
// string scripts
browser.exec = function(text){
if (!text) return text;
if (window.execscript){
window.execscript(text);
} else {
var script = document.createelement('script');
script.setattribute('type', 'text/javascript');
script.text = text;
document.head.appendchild(script);
document.head.removechild(script);
}
return text;
};
string.implement('stripscripts', function(exec){
var scripts = '';
var text = this.replace(/