var md7f2135ebcc48e7e96fdd6e88975f341e = '/*\n---\nMooTools: the javascript framework\n\nweb build:\n - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0\n\npackager build:\n - 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\n\n...\n*/\n\n/*\n---\n\nname: Core\n\ndescription: The heart of MooTools.\n\nlicense: MIT-style license.\n\ncopyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/).\n\nauthors: The MooTools production team (http://mootools.net/developers/)\n\ninspiration:\n - 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)\n - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)\n\nprovides: [Core, MooTools, Type, typeOf, instanceOf, Native]\n\n...\n*/\n\n(function(){\n\nthis.MooTools = {\n version: \'1.4.5\',\n build: \'74e34796f5f76640cdb98853004650aea1499d69\'\n};\n\n// typeOf, instanceOf\n\nvar typeOf = this.typeOf = function(item){\n if (item == null) return \'null\';\n if (item.$family != null) return item.$family();\n\n if (item.nodeName){\n if (item.nodeType == 1) return \'element\';\n if (item.nodeType == 3) return (/\\S/).test(item.nodeValue) ? \'textnode\' : \'whitespace\';\n } else if (typeof item.length == \'number\'){\n if (item.callee) return \'arguments\';\n if (\'item\' in item) return \'collection\';\n }\n\n return typeof item;\n};\n\nvar instanceOf = this.instanceOf = function(item, object){\n if (item == null) return false;\n var constructor = item.$constructor || item.constructor;\n while (constructor){\n if (constructor === object) return true;\n constructor = constructor.parent;\n }\n /**/\n if (!item.hasOwnProperty) return false;\n /**/\n return item instanceof object;\n};\n\n// Function overloading\n\nvar Function = this.Function;\n\nvar enumerables = true;\nfor (var i in {toString: 1}) enumerables = null;\nif (enumerables) enumerables = [\'hasOwnProperty\', \'valueOf\', \'isPrototypeOf\', \'propertyIsEnumerable\', \'toLocaleString\', \'toString\', \'constructor\'];\n\nFunction.prototype.overloadSetter = function(usePlural){\n var self = this;\n return function(a, b){\n if (a == null) return this;\n if (usePlural || typeof a != \'string\'){\n for (var k in a) self.call(this, k, a[k]);\n if (enumerables) for (var i = enumerables.length; i--;){\n k = enumerables[i];\n if (a.hasOwnProperty(k)) self.call(this, k, a[k]);\n }\n } else {\n self.call(this, a, b);\n }\n return this;\n };\n};\n\nFunction.prototype.overloadGetter = function(usePlural){\n var self = this;\n return function(a){\n var args, result;\n if (typeof a != \'string\') args = a;\n else if (arguments.length > 1) args = arguments;\n else if (usePlural) args = [a];\n if (args){\n result = {};\n for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);\n } else {\n result = self.call(this, a);\n }\n return result;\n };\n};\n\nFunction.prototype.extend = function(key, value){\n this[key] = value;\n}.overloadSetter();\n\nFunction.prototype.implement = function(key, value){\n this.prototype[key] = value;\n}.overloadSetter();\n\n// From\n\nvar slice = Array.prototype.slice;\n\nFunction.from = function(item){\n return (typeOf(item) == \'function\') ? item : function(){\n return item;\n };\n};\n\nArray.from = function(item){\n if (item == null) return [];\n return (Type.isEnumerable(item) && typeof item != \'string\') ? (typeOf(item) == \'array\') ? item : slice.call(item) : [item];\n};\n\nNumber.from = function(item){\n var number = parseFloat(item);\n return isFinite(number) ? number : null;\n};\n\nString.from = function(item){\n return item + \'\';\n};\n\n// hide, protect\n\nFunction.implement({\n\n hide: function(){\n this.$hidden = true;\n return this;\n },\n\n protect: function(){\n this.$protected = true;\n return this;\n }\n\n});\n\n// Type\n\nvar Type = this.Type = function(name, object){\n if (name){\n var lower = name.toLowerCase();\n var typeCheck = function(item){\n return (typeOf(item) == lower);\n };\n\n Type[\'is\' + name] = typeCheck;\n if (object != null){\n object.prototype.$family = (function(){\n return lower;\n }).hide();\n \n }\n }\n\n if (object == null) return null;\n\n object.extend(this);\n object.$constructor = Type;\n object.prototype.$constructor = object;\n\n return object;\n};\n\nvar toString = Object.prototype.toString;\n\nType.isEnumerable = function(item){\n return (item != null && typeof item.length == \'number\' && toString.call(item) != \'[object Function]\' );\n};\n\nvar hooks = {};\n\nvar hooksOf = function(object){\n var type = typeOf(object.prototype);\n return hooks[type] || (hooks[type] = []);\n};\n\nvar implement = function(name, method){\n if (method && method.$hidden) return;\n\n var hooks = hooksOf(this);\n\n for (var i = 0; i < hooks.length; i++){\n var hook = hooks[i];\n if (typeOf(hook) == \'type\') implement.call(hook, name, method);\n else hook.call(this, name, method);\n }\n\n var previous = this.prototype[name];\n if (previous == null || !previous.$protected) this.prototype[name] = method;\n\n if (this[name] == null && typeOf(method) == \'function\') extend.call(this, name, function(item){\n return method.apply(item, slice.call(arguments, 1));\n });\n};\n\nvar extend = function(name, method){\n if (method && method.$hidden) return;\n var previous = this[name];\n if (previous == null || !previous.$protected) this[name] = method;\n};\n\nType.implement({\n\n implement: implement.overloadSetter(),\n\n extend: extend.overloadSetter(),\n\n alias: function(name, existing){\n implement.call(this, name, this.prototype[existing]);\n }.overloadSetter(),\n\n mirror: function(hook){\n hooksOf(this).push(hook);\n return this;\n }\n\n});\n\nnew Type(\'Type\', Type);\n\n// Default Types\n\nvar force = function(name, object, methods){\n var isType = (object != Object),\n prototype = object.prototype;\n\n if (isType) object = new Type(name, object);\n\n for (var i = 0, l = methods.length; i < l; i++){\n var key = methods[i],\n generic = object[key],\n proto = prototype[key];\n\n if (generic) generic.protect();\n if (isType && proto) object.implement(key, proto.protect());\n }\n\n if (isType){\n var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]);\n object.forEachMethod = function(fn){\n if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){\n fn.call(prototype, prototype[methods[i]], methods[i]);\n }\n for (var key in prototype) fn.call(prototype, prototype[key], key)\n };\n }\n\n return force;\n};\n\nforce(\'String\', String, [\n \'charAt\', \'charCodeAt\', \'concat\', \'indexOf\', \'lastIndexOf\', \'match\', \'quote\', \'replace\', \'search\',\n \'slice\', \'split\', \'substr\', \'substring\', \'trim\', \'toLowerCase\', \'toUpperCase\'\n])(\'Array\', Array, [\n \'pop\', \'push\', \'reverse\', \'shift\', \'sort\', \'splice\', \'unshift\', \'concat\', \'join\', \'slice\',\n \'indexOf\', \'lastIndexOf\', \'filter\', \'forEach\', \'every\', \'map\', \'some\', \'reduce\', \'reduceRight\'\n])(\'Number\', Number, [\n \'toExponential\', \'toFixed\', \'toLocaleString\', \'toPrecision\'\n])(\'Function\', Function, [\n \'apply\', \'call\', \'bind\'\n])(\'RegExp\', RegExp, [\n \'exec\', \'test\'\n])(\'Object\', Object, [\n \'create\', \'defineProperty\', \'defineProperties\', \'keys\',\n \'getPrototypeOf\', \'getOwnPropertyDescriptor\', \'getOwnPropertyNames\',\n \'preventExtensions\', \'isExtensible\', \'seal\', \'isSealed\', \'freeze\', \'isFrozen\'\n])(\'Date\', Date, [\'now\']);\n\nObject.extend = extend.overloadSetter();\n\nDate.extend(\'now\', function(){\n return +(new Date);\n});\n\nnew Type(\'Boolean\', Boolean);\n\n// fixes NaN returning as Number\n\nNumber.prototype.$family = function(){\n return isFinite(this) ? \'number\' : \'null\';\n}.hide();\n\n// Number.random\n\nNumber.extend(\'random\', function(min, max){\n return Math.floor(Math.random() * (max - min + 1) + min);\n});\n\n// forEach, each\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nObject.extend(\'forEach\', function(object, fn, bind){\n for (var key in object){\n if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);\n }\n});\n\nObject.each = Object.forEach;\n\nArray.implement({\n\n forEach: function(fn, bind){\n for (var i = 0, l = this.length; i < l; i++){\n if (i in this) fn.call(bind, this[i], i, this);\n }\n },\n\n each: function(fn, bind){\n Array.forEach(this, fn, bind);\n return this;\n }\n\n});\n\n// Array & Object cloning, Object merging and appending\n\nvar cloneOf = function(item){\n switch (typeOf(item)){\n case \'array\': return item.clone();\n case \'object\': return Object.clone(item);\n default: return item;\n }\n};\n\nArray.implement(\'clone\', function(){\n var i = this.length, clone = new Array(i);\n while (i--) clone[i] = cloneOf(this[i]);\n return clone;\n});\n\nvar mergeOne = function(source, key, current){\n switch (typeOf(current)){\n case \'object\':\n if (typeOf(source[key]) == \'object\') Object.merge(source[key], current);\n else source[key] = Object.clone(current);\n break;\n case \'array\': source[key] = current.clone(); break;\n default: source[key] = current;\n }\n return source;\n};\n\nObject.extend({\n\n merge: function(source, k, v){\n if (typeOf(k) == \'string\') return mergeOne(source, k, v);\n for (var i = 1, l = arguments.length; i < l; i++){\n var object = arguments[i];\n for (var key in object) mergeOne(source, key, object[key]);\n }\n return source;\n },\n\n clone: function(object){\n var clone = {};\n for (var key in object) clone[key] = cloneOf(object[key]);\n return clone;\n },\n\n append: function(original){\n for (var i = 1, l = arguments.length; i < l; i++){\n var extended = arguments[i] || {};\n for (var key in extended) original[key] = extended[key];\n }\n return original;\n }\n\n});\n\n// Object-less types\n\n[\'Object\', \'WhiteSpace\', \'TextNode\', \'Collection\', \'Arguments\'].each(function(name){\n new Type(name);\n});\n\n// Unique ID\n\nvar UID = Date.now();\n\nString.extend(\'uniqueID\', function(){\n return (UID++).toString(36);\n});\n\n\n\n})();\n\n\n/*\n---\n\nname: Array\n\ndescription: Contains Array Prototypes like each, contains, and erase.\n\nlicense: MIT-style license.\n\nrequires: Type\n\nprovides: Array\n\n...\n*/\n\nArray.implement({\n\n /**/\n every: function(fn, bind){\n for (var i = 0, l = this.length >>> 0; i < l; i++){\n if ((i in this) && !fn.call(bind, this[i], i, this)) return false;\n }\n return true;\n },\n\n filter: function(fn, bind){\n var results = [];\n for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){\n value = this[i];\n if (fn.call(bind, value, i, this)) results.push(value);\n }\n return results;\n },\n\n indexOf: function(item, from){\n var length = this.length >>> 0;\n for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){\n if (this[i] === item) return i;\n }\n return -1;\n },\n\n map: function(fn, bind){\n var length = this.length >>> 0, results = Array(length);\n for (var i = 0; i < length; i++){\n if (i in this) results[i] = fn.call(bind, this[i], i, this);\n }\n return results;\n },\n\n some: function(fn, bind){\n for (var i = 0, l = this.length >>> 0; i < l; i++){\n if ((i in this) && fn.call(bind, this[i], i, this)) return true;\n }\n return false;\n },\n /*!ES5>*/\n\n clean: function(){\n return this.filter(function(item){\n return item != null;\n });\n },\n\n invoke: function(methodName){\n var args = Array.slice(arguments, 1);\n return this.map(function(item){\n return item[methodName].apply(item, args);\n });\n },\n\n associate: function(keys){\n var obj = {}, length = Math.min(this.length, keys.length);\n for (var i = 0; i < length; i++) obj[keys[i]] = this[i];\n return obj;\n },\n\n link: function(object){\n var result = {};\n for (var i = 0, l = this.length; i < l; i++){\n for (var key in object){\n if (object[key](this[i])){\n result[key] = this[i];\n delete object[key];\n break;\n }\n }\n }\n return result;\n },\n\n contains: function(item, from){\n return this.indexOf(item, from) != -1;\n },\n\n append: function(array){\n this.push.apply(this, array);\n return this;\n },\n\n getLast: function(){\n return (this.length) ? this[this.length - 1] : null;\n },\n\n getRandom: function(){\n return (this.length) ? this[Number.random(0, this.length - 1)] : null;\n },\n\n include: function(item){\n if (!this.contains(item)) this.push(item);\n return this;\n },\n\n combine: function(array){\n for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);\n return this;\n },\n\n erase: function(item){\n for (var i = this.length; i--;){\n if (this[i] === item) this.splice(i, 1);\n }\n return this;\n },\n\n empty: function(){\n this.length = 0;\n return this;\n },\n\n flatten: function(){\n var array = [];\n for (var i = 0, l = this.length; i < l; i++){\n var type = typeOf(this[i]);\n if (type == \'null\') continue;\n array = array.concat((type == \'array\' || type == \'collection\' || type == \'arguments\' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);\n }\n return array;\n },\n\n pick: function(){\n for (var i = 0, l = this.length; i < l; i++){\n if (this[i] != null) return this[i];\n }\n return null;\n },\n\n hexToRgb: function(array){\n if (this.length != 3) return null;\n var rgb = this.map(function(value){\n if (value.length == 1) value += value;\n return value.toInt(16);\n });\n return (array) ? rgb : \'rgb(\' + rgb + \')\';\n },\n\n rgbToHex: function(array){\n if (this.length < 3) return null;\n if (this.length == 4 && this[3] == 0 && !array) return \'transparent\';\n var hex = [];\n for (var i = 0; i < 3; i++){\n var bit = (this[i] - 0).toString(16);\n hex.push((bit.length == 1) ? \'0\' + bit : bit);\n }\n return (array) ? hex : \'#\' + hex.join(\'\');\n }\n\n});\n\n\n\n\n/*\n---\n\nname: String\n\ndescription: Contains String Prototypes like camelCase, capitalize, test, and toInt.\n\nlicense: MIT-style license.\n\nrequires: Type\n\nprovides: String\n\n...\n*/\n\nString.implement({\n\n test: function(regex, params){\n return ((typeOf(regex) == \'regexp\') ? regex : new RegExp(\'\' + regex, params)).test(this);\n },\n\n contains: function(string, separator){\n return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1;\n },\n\n trim: function(){\n return String(this).replace(/^\\s+|\\s+$/g, \'\');\n },\n\n clean: function(){\n return String(this).replace(/\\s+/g, \' \').trim();\n },\n\n camelCase: function(){\n return String(this).replace(/-\\D/g, function(match){\n return match.charAt(1).toUpperCase();\n });\n },\n\n hyphenate: function(){\n return String(this).replace(/[A-Z]/g, function(match){\n return (\'-\' + match.charAt(0).toLowerCase());\n });\n },\n\n capitalize: function(){\n return String(this).replace(/\\b[a-z]/g, function(match){\n return match.toUpperCase();\n });\n },\n\n escapeRegExp: function(){\n return String(this).replace(/[-[\\]{}()*+?.\\\\^$|,#\\s]/g, \'\\\\$1\');\n// return String(this).replace(/([-.*+?^${}()|[\\]\\/\\\\])/g, \'\\\\$1\');\n },\n\n toInt: function(base){\n return parseInt(this, base || 10);\n },\n\n toFloat: function(){\n return parseFloat(this);\n },\n\n hexToRgb: function(array){\n var hex = String(this).match(/^#?(\\w{1,2})(\\w{1,2})(\\w{1,2})$/);\n return (hex) ? hex.slice(1).hexToRgb(array) : null;\n },\n\n rgbToHex: function(array){\n var rgb = String(this).match(/\\d{1,3}/g);\n return (rgb) ? rgb.rgbToHex(array) : null;\n },\n\n substitute: function(object, regexp){\n return String(this).replace(regexp || (/\\\\?\\{([^{}]+)\\}/g), function(match, name){\n if (match.charAt(0) == \'\\\\\') return match.slice(1);\n return (object[name] != null) ? object[name] : \'\';\n });\n }\n\n});\n\n\n/*\n---\n\nname: Number\n\ndescription: Contains Number Prototypes like limit, round, times, and ceil.\n\nlicense: MIT-style license.\n\nrequires: Type\n\nprovides: Number\n\n...\n*/\n\nNumber.implement({\n\n limit: function(min, max){\n return Math.min(max, Math.max(min, this));\n },\n\n round: function(precision){\n precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);\n return Math.round(this * precision) / precision;\n },\n\n times: function(fn, bind){\n for (var i = 0; i < this; i++) fn.call(bind, i, this);\n },\n\n toFloat: function(){\n return parseFloat(this);\n },\n\n toInt: function(base){\n return parseInt(this, base || 10);\n }\n\n});\n\nNumber.alias(\'each\', \'times\');\n\n(function(math){\n var methods = {};\n math.each(function(name){\n if (!Number[name]) methods[name] = function(){\n return Math[name].apply(null, [this].concat(Array.from(arguments)));\n };\n });\n Number.implement(methods);\n})([\'abs\', \'acos\', \'asin\', \'atan\', \'atan2\', \'ceil\', \'cos\', \'exp\', \'floor\', \'log\', \'max\', \'min\', \'pow\', \'sin\', \'sqrt\', \'tan\']);\n\n\n/*\n---\n\nname: Function\n\ndescription: Contains Function Prototypes like create, bind, pass, and delay.\n\nlicense: MIT-style license.\n\nrequires: Type\n\nprovides: Function\n\n...\n*/\n\nFunction.extend({\n\n attempt: function(){\n for (var i = 0, l = arguments.length; i < l; i++){\n try {\n return arguments[i]();\n } catch (e){}\n }\n return null;\n }\n\n});\n\nFunction.implement({\n\n attempt: function(args, bind){\n try {\n return this.apply(bind, Array.from(args));\n } catch (e){}\n\n return null;\n },\n\n /**/\n bind: function(that){\n var self = this,\n args = arguments.length > 1 ? Array.slice(arguments, 1) : null,\n F = function(){};\n\n var bound = function(){\n var context = that, length = arguments.length;\n if (this instanceof bound){\n F.prototype = self.prototype;\n context = new F;\n }\n var result = (!args && !length)\n ? self.call(context)\n : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);\n return context == that ? result : context;\n };\n return bound;\n },\n /*!ES5-bind>*/\n\n pass: function(args, bind){\n var self = this;\n if (args != null) args = Array.from(args);\n return function(){\n return self.apply(bind, args || arguments);\n };\n },\n\n delay: function(delay, bind, args){\n return setTimeout(this.pass((args == null ? [] : args), bind), delay);\n },\n\n periodical: function(periodical, bind, args){\n return setInterval(this.pass((args == null ? [] : args), bind), periodical);\n }\n\n});\n\n\n\n\n/*\n---\n\nname: Object\n\ndescription: Object generic methods\n\nlicense: MIT-style license.\n\nrequires: Type\n\nprovides: [Object, Hash]\n\n...\n*/\n\n(function(){\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nObject.extend({\n\n subset: function(object, keys){\n var results = {};\n for (var i = 0, l = keys.length; i < l; i++){\n var k = keys[i];\n if (k in object) results[k] = object[k];\n }\n return results;\n },\n\n map: function(object, fn, bind){\n var results = {};\n for (var key in object){\n if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);\n }\n return results;\n },\n\n filter: function(object, fn, bind){\n var results = {};\n for (var key in object){\n var value = object[key];\n if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;\n }\n return results;\n },\n\n every: function(object, fn, bind){\n for (var key in object){\n if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;\n }\n return true;\n },\n\n some: function(object, fn, bind){\n for (var key in object){\n if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;\n }\n return false;\n },\n\n keys: function(object){\n var keys = [];\n for (var key in object){\n if (hasOwnProperty.call(object, key)) keys.push(key);\n }\n return keys;\n },\n\n values: function(object){\n var values = [];\n for (var key in object){\n if (hasOwnProperty.call(object, key)) values.push(object[key]);\n }\n return values;\n },\n\n getLength: function(object){\n return Object.keys(object).length;\n },\n\n keyOf: function(object, value){\n for (var key in object){\n if (hasOwnProperty.call(object, key) && object[key] === value) return key;\n }\n return null;\n },\n\n contains: function(object, value){\n return Object.keyOf(object, value) != null;\n },\n\n toQueryString: function(object, base){\n var queryString = [];\n\n Object.each(object, function(value, key){\n if (base) key = base + \'[\' + key + \']\';\n var result;\n switch (typeOf(value)){\n case \'object\': result = Object.toQueryString(value, key); break;\n case \'array\':\n var qs = {};\n value.each(function(val, i){\n qs[i] = val;\n });\n result = Object.toQueryString(qs, key);\n break;\n default: result = key + \'=\' + encodeURIComponent(value);\n }\n if (value != null) queryString.push(result);\n });\n\n return queryString.join(\'&\');\n }\n\n});\n\n})();\n\n\n\n\n/*\n---\n\nname: Browser\n\ndescription: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.\n\nlicense: MIT-style license.\n\nrequires: [Array, Function, Number, String]\n\nprovides: [Browser, Window, Document]\n\n...\n*/\n\n(function(){\n\nvar document = this.document;\nvar window = document.window = this;\n\nvar ua = navigator.userAgent.toLowerCase(),\n platform = navigator.platform.toLowerCase(),\n UA = ua.match(/(opera|ie|firefox|chrome|version)[\\s\\/:]([\\w\\d\\.]+)?.*?(safari|version[\\s\\/:]([\\w\\d\\.]+)|$)/) || [null, \'unknown\', 0],\n mode = UA[1] == \'ie\' && document.documentMode;\n\nvar Browser = this.Browser = {\n\n extend: Function.prototype.extend,\n\n name: (UA[1] == \'version\') ? UA[3] : UA[1],\n\n version: mode || parseFloat((UA[1] == \'opera\' && UA[4]) ? UA[4] : UA[2]),\n\n Platform: {\n name: ua.match(/ip(?:ad|od|hone)/) ? \'ios\' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || [\'other\'])[0]\n },\n\n Features: {\n xpath: !!(document.evaluate),\n air: !!(window.runtime),\n query: !!(document.querySelector),\n json: !!(window.JSON)\n },\n\n Plugins: {}\n\n};\n\nBrowser[Browser.name] = true;\nBrowser[Browser.name + parseInt(Browser.version, 10)] = true;\nBrowser.Platform[Browser.Platform.name] = true;\n\n// Request\n\nBrowser.Request = (function(){\n\n var XMLHTTP = function(){\n return new XMLHttpRequest();\n };\n\n var MSXML2 = function(){\n return new ActiveXObject(\'MSXML2.XMLHTTP\');\n };\n\n var MSXML = function(){\n return new ActiveXObject(\'Microsoft.XMLHTTP\');\n };\n\n return Function.attempt(function(){\n XMLHTTP();\n return XMLHTTP;\n }, function(){\n MSXML2();\n return MSXML2;\n }, function(){\n MSXML();\n return MSXML;\n });\n\n})();\n\nBrowser.Features.xhr = !!(Browser.Request);\n\n// Flash detection\n\nvar version = (Function.attempt(function(){\n return navigator.plugins[\'Shockwave Flash\'].description;\n}, function(){\n return new ActiveXObject(\'ShockwaveFlash.ShockwaveFlash\').GetVariable(\'$version\');\n}) || \'0 r0\').match(/\\d+/g);\n\nBrowser.Plugins.Flash = {\n version: Number(version[0] || \'0.\' + version[1]) || 0,\n build: Number(version[2]) || 0\n};\n\n// String scripts\n\nBrowser.exec = function(text){\n if (!text) return text;\n if (window.execScript){\n window.execScript(text);\n } else {\n var script = document.createElement(\'script\');\n script.setAttribute(\'type\', \'text/javascript\');\n script.text = text;\n document.head.appendChild(script);\n document.head.removeChild(script);\n }\n return text;\n};\n\nString.implement(\'stripScripts\', function(exec){\n var scripts = \'\';\n var text = this.replace(/