Greasy Fork is available in English.

MooTools for Greasemonkey

MooTools (http://mootools.net) with fixes for Greasemonkey. Pulled from http://github.com/swannodette/mootools-core

Ovu skriptu ne treba izravno instalirati. To je biblioteka za druge skripte koje se uključuju u meta direktivu // @require https://update.greatest.deepsurf.us/scripts/12447/74469/MooTools%20for%20Greasemonkey.js

  1. // ==UserScript==
  2. // @name MooTools for Greasemonkey
  3. // @version 1.0
  4. // @description MooTools (http://mootools.net) with fixes for Greasemonkey. Pulled from http://github.com/swannodette/mootools-core
  5. // @namespace https://greatest.deepsurf.us/en/users/15562
  6. // @author Unknown (was from http://userscripts.org/users/79579)
  7. // @license MIT-style license (http://opensource.org/licenses/mit-license.php), Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/)
  8. // ==/UserScript==
  9.  
  10. /*
  11. Script: Core.js
  12. MooTools - My Object Oriented JavaScript Tools.
  13.  
  14. License:
  15. MIT-style license.
  16.  
  17. Copyright:
  18. Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/).
  19.  
  20. Code & Documentation:
  21. [The MooTools production team](http://mootools.net/developers/).
  22.  
  23. Inspiration:
  24. - 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)
  25. - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
  26. */
  27.  
  28. var MooTools = {
  29. 'version': '1.2.1',
  30. 'build': 'e5d6d868f6f6089547dba4378df209debf2993d9'
  31. };
  32.  
  33. var Native = function(options){
  34. options = options || {};
  35. var name = options.name;
  36. var legacy = options.legacy;
  37. var protect = options.protect;
  38. var methods = options.implement;
  39. var generics = options.generics;
  40. var initialize = options.initialize;
  41. var afterImplement = options.afterImplement || function(){};
  42. var object = initialize || legacy;
  43. generics = generics !== false;
  44.  
  45. object.constructor = Native;
  46. object.$family = {name: 'native'};
  47. if (legacy && initialize) object.prototype = legacy.prototype;
  48. if (!object.prototype) object.prototype = {}; // CHANGE: fix for GM - David
  49. object.prototype.constructor = object;
  50.  
  51. if (name){
  52. var family = name.toLowerCase();
  53. object.prototype.$family = {name: family};
  54. Native.typize(object, family);
  55. }
  56.  
  57. var add = function(obj, name, method, force){
  58. if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
  59. if (generics) Native.genericize(obj, name, protect);
  60. afterImplement.call(obj, name, method);
  61. return obj;
  62. };
  63.  
  64. object.alias = function(a1, a2, a3){
  65. if (typeof a1 == 'string'){
  66. if ((a1 = this.prototype[a1])) return add(this, a2, a1, a3);
  67. }
  68. for (var a in a1) this.alias(a, a1[a], a2);
  69. return this;
  70. };
  71.  
  72. object.implement = function(a1, a2, a3){
  73. if (typeof a1 == 'string') return add(this, a1, a2, a3);
  74. for (var p in a1) add(this, p, a1[p], a2);
  75. return this;
  76. };
  77.  
  78. if (methods) object.implement(methods);
  79.  
  80. return object;
  81. };
  82.  
  83. Native.genericize = function(object, property, check){
  84. if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
  85. var args = Array.prototype.slice.call(arguments);
  86. return object.prototype[property].apply(args.shift(), args);
  87. };
  88. };
  89.  
  90. Native.implement = function(objects, properties){
  91. for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
  92. };
  93.  
  94. Native.typize = function(object, family){
  95. if (!object.type) object.type = function(item){
  96. return ($type(item) === family);
  97. };
  98. };
  99.  
  100. (function(){
  101. var natives = {'Array': Array, 'Date': Date, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'String': String};
  102. for (var n in natives) new Native({name: n, initialize: natives[n], protect: true});
  103.  
  104. var types = {'boolean': Boolean, 'native': Native, 'object': Object};
  105. for (var t in types) Native.typize(types[t], t);
  106.  
  107. var generics = {
  108. 'Array': ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"],
  109. 'String': ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"]
  110. };
  111. for (var g in generics){
  112. var aObject = (g == 'Array' && Array) || (g == 'String' && String) || window[g]; // CHANGE: Fix for GM & MT1.2.1 - David
  113. for (var i = generics[g].length; i--;) Native.genericize(aObject, generics[g][i], true);
  114. };
  115. })();
  116.  
  117. var Hash = new Native({
  118.  
  119. name: 'Hash',
  120.  
  121. initialize: function(object){
  122. if ($type(object) == 'hash') object = $unlink(object.getClean());
  123. for (var key in object) this[key] = object[key];
  124. return this;
  125. }
  126.  
  127. });
  128.  
  129. Hash.implement({
  130.  
  131. forEach: function(fn, bind){
  132. for (var key in this){
  133. if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
  134. }
  135. },
  136.  
  137. getClean: function(){
  138. var clean = {};
  139. for (var key in this){
  140. if (this.hasOwnProperty(key)) clean[key] = this[key];
  141. }
  142. return clean;
  143. },
  144.  
  145. getLength: function(){
  146. var length = 0;
  147. for (var key in this){
  148. if (this.hasOwnProperty(key)) length++;
  149. }
  150. return length;
  151. }
  152.  
  153. });
  154.  
  155. Hash.alias('forEach', 'each');
  156.  
  157. Array.implement({
  158.  
  159. forEach: function(fn, bind){
  160. for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);
  161. }
  162.  
  163. });
  164.  
  165. Array.alias('forEach', 'each');
  166.  
  167. function $A(iterable){
  168. if (iterable.item){
  169. var array = [];
  170. for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];
  171. return array;
  172. }
  173. return Array.prototype.slice.call(iterable);
  174. };
  175.  
  176. function $arguments(i){
  177. return function(){
  178. return arguments[i];
  179. };
  180. };
  181.  
  182. function $chk(obj){
  183. return !!(obj || obj === 0);
  184. };
  185.  
  186. function $clear(timer){
  187. clearTimeout(timer);
  188. clearInterval(timer);
  189. return null;
  190. };
  191.  
  192. function $defined(obj){
  193. return (obj != undefined);
  194. };
  195.  
  196. function $each(iterable, fn, bind){
  197. var type = $type(iterable);
  198. ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
  199. };
  200.  
  201. function $empty(){};
  202.  
  203. function $extend(original, extended){
  204. for (var key in (extended || {})) original[key] = extended[key];
  205. return original;
  206. };
  207.  
  208. function $H(object){
  209. return new Hash(object);
  210. };
  211.  
  212. function $lambda(value){
  213. return (typeof value == 'function') ? value : function(){
  214. return value;
  215. };
  216. };
  217.  
  218. function $merge(){
  219. var mix = {};
  220. for (var i = 0, l = arguments.length; i < l; i++){
  221. var object = arguments[i];
  222. if ($type(object) != 'object') continue;
  223. for (var key in object){
  224. var op = object[key], mp = mix[key];
  225. mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op);
  226. }
  227. }
  228. return mix;
  229. };
  230.  
  231. function $pick(){
  232. for (var i = 0, l = arguments.length; i < l; i++){
  233. if (arguments[i] != undefined) return arguments[i];
  234. }
  235. return null;
  236. };
  237.  
  238. function $random(min, max){
  239. return Math.floor(Math.random() * (max - min + 1) + min);
  240. };
  241.  
  242. function $splat(obj){
  243. var type = $type(obj);
  244. return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
  245. };
  246.  
  247. var $time = Date.now || function(){
  248. return +new Date;
  249. };
  250.  
  251. function $try(){
  252. for (var i = 0, l = arguments.length; i < l; i++){
  253. try {
  254. return arguments[i]();
  255. } catch(e){}
  256. }
  257. return null;
  258. };
  259.  
  260. function $type(obj){
  261. if (obj == undefined) return false;
  262. if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
  263. if (obj.nodeName){
  264. switch (obj.nodeType){
  265. case 1: return 'element';
  266. case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
  267. }
  268. } else if (typeof obj.length == 'number'){
  269. if (obj.callee) return 'arguments';
  270. else if (obj.item) return 'collection';
  271. }
  272. return typeof obj;
  273. };
  274.  
  275. function $unlink(object){
  276. var unlinked;
  277. switch ($type(object)){
  278. case 'object':
  279. unlinked = {};
  280. for (var p in object) unlinked[p] = $unlink(object[p]);
  281. break;
  282. case 'hash':
  283. unlinked = new Hash(object);
  284. break;
  285. case 'array':
  286. unlinked = [];
  287. for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
  288. break;
  289. default: return object;
  290. }
  291. return unlinked;
  292. };
  293.  
  294. /*
  295. Script: Browser.js
  296. The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.
  297.  
  298. License:
  299. MIT-style license.
  300. */
  301.  
  302. var Browser = $merge({
  303.  
  304. Engine: {name: 'unknown', version: 0},
  305.  
  306. Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
  307.  
  308. Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},
  309.  
  310. Plugins: {},
  311.  
  312. Engines: {
  313.  
  314. presto: function(){
  315. return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
  316. },
  317.  
  318. trident: function(){
  319. return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? 5 : 4);
  320. },
  321.  
  322. webkit: function(){
  323. return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
  324. },
  325.  
  326. gecko: function(){
  327. return (document.getBoxObjectFor == undefined) ? false : ((document.getElementsByClassName) ? 19 : 18);
  328. }
  329.  
  330. }
  331.  
  332. }, Browser || {});
  333.  
  334. Browser.Platform[Browser.Platform.name] = true;
  335.  
  336. Browser.detect = function(){
  337.  
  338. for (var engine in this.Engines){
  339. var version = this.Engines[engine]();
  340. if (version){
  341. this.Engine = {name: engine, version: version};
  342. this.Engine[engine] = this.Engine[engine + version] = true;
  343. break;
  344. }
  345. }
  346.  
  347. return {name: engine, version: version};
  348.  
  349. };
  350.  
  351. Browser.detect();
  352.  
  353. Browser.Request = function(){
  354. return $try(function(){
  355. return new XMLHttpRequest();
  356. }, function(){
  357. return new ActiveXObject('MSXML2.XMLHTTP');
  358. });
  359. };
  360.  
  361. Browser.Features.xhr = !!(Browser.Request());
  362.  
  363. Browser.Plugins.Flash = (function(){
  364. var version = ($try(function(){
  365. return navigator.plugins['Shockwave Flash'].description;
  366. }, function(){
  367. return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
  368. }) || '0 r0').match(/\d+/g);
  369. return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
  370. })();
  371.  
  372. function $exec(text){
  373. if (!text) return text;
  374. if (window.execScript){
  375. window.execScript(text);
  376. } else {
  377. var script = document.createElement('script');
  378. script.setAttribute('type', 'text/javascript');
  379. script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text;
  380. document.head.appendChild(script);
  381. document.head.removeChild(script);
  382. }
  383. return text;
  384. };
  385.  
  386. Native.UID = 1;
  387.  
  388. var $uid = (Browser.Engine.trident) ? function(item){
  389. return (item.uid || (item.uid = [Native.UID++]))[0];
  390. } : function(item){
  391. return item.uid || (item.uid = Native.UID++);
  392. };
  393.  
  394. var Window = new Native({
  395.  
  396. name: 'Window',
  397.  
  398. legacy: (Browser.Engine.trident) ? null: window.Window,
  399.  
  400. initialize: function(win){
  401. $uid(win);
  402. if (!win.Element){
  403. win.Element = $empty;
  404. if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2
  405. win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};
  406. }
  407. win.document.window = win;
  408. return $extend(win, Window.Prototype);
  409. },
  410.  
  411. afterImplement: function(property, value){
  412. window[property] = Window.Prototype[property] = value;
  413. }
  414.  
  415. });
  416.  
  417. Window.Prototype = {$family: {name: 'window'}};
  418.  
  419. new Window(window);
  420.  
  421. var Document = new Native({
  422.  
  423. name: 'Document',
  424.  
  425. legacy: (Browser.Engine.trident) ? null: window.Document,
  426.  
  427. initialize: function(doc){
  428. $uid(doc);
  429. doc.head = doc.getElementsByTagName('head')[0];
  430. doc.html = doc.getElementsByTagName('html')[0];
  431. if (Browser.Engine.trident && Browser.Engine.version <= 4) $try(function(){
  432. doc.execCommand("BackgroundImageCache", false, true);
  433. });
  434. if (Browser.Engine.trident) doc.window.attachEvent('onunload', function() {
  435. doc.window.detachEvent('onunload', arguments.callee);
  436. doc.head = doc.html = doc.window = null;
  437. });
  438. return $extend(doc, Document.Prototype);
  439. },
  440.  
  441. afterImplement: function(property, value){
  442. document[property] = Document.Prototype[property] = value;
  443. }
  444.  
  445. });
  446.  
  447. Document.Prototype = {$family: {name: 'document'}};
  448.  
  449. new Document(document);
  450.  
  451. /*
  452. Script: Array.js
  453. Contains Array Prototypes like each, contains, and erase.
  454.  
  455. License:
  456. MIT-style license.
  457. */
  458.  
  459. Array.implement({
  460.  
  461. every: function(fn, bind){
  462. for (var i = 0, l = this.length; i < l; i++){
  463. if (!fn.call(bind, this[i], i, this)) return false;
  464. }
  465. return true;
  466. },
  467.  
  468. filter: function(fn, bind){
  469. var results = [];
  470. for (var i = 0, l = this.length; i < l; i++){
  471. if (fn.call(bind, this[i], i, this)) results.push(this[i]);
  472. }
  473. return results;
  474. },
  475.  
  476. clean: function() {
  477. return this.filter($defined);
  478. },
  479.  
  480. indexOf: function(item, from){
  481. var len = this.length;
  482. for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
  483. if (this[i] === item) return i;
  484. }
  485. return -1;
  486. },
  487.  
  488. map: function(fn, bind){
  489. var results = [];
  490. for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
  491. return results;
  492. },
  493.  
  494. some: function(fn, bind){
  495. for (var i = 0, l = this.length; i < l; i++){
  496. if (fn.call(bind, this[i], i, this)) return true;
  497. }
  498. return false;
  499. },
  500.  
  501. associate: function(keys){
  502. var obj = {}, length = Math.min(this.length, keys.length);
  503. for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
  504. return obj;
  505. },
  506.  
  507. link: function(object){
  508. var result = {};
  509. for (var i = 0, l = this.length; i < l; i++){
  510. for (var key in object){
  511. if (object[key](this[i])){
  512. result[key] = this[i];
  513. delete object[key];
  514. break;
  515. }
  516. }
  517. }
  518. return result;
  519. },
  520.  
  521. contains: function(item, from){
  522. return this.indexOf(item, from) != -1;
  523. },
  524.  
  525. extend: function(array){
  526. for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
  527. return this;
  528. },
  529.  
  530. getLast: function(){
  531. return (this.length) ? this[this.length - 1] : null;
  532. },
  533.  
  534. getRandom: function(){
  535. return (this.length) ? this[$random(0, this.length - 1)] : null;
  536. },
  537.  
  538. include: function(item){
  539. if (!this.contains(item)) this.push(item);
  540. return this;
  541. },
  542.  
  543. combine: function(array){
  544. for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
  545. return this;
  546. },
  547.  
  548. erase: function(item){
  549. for (var i = this.length; i--; i){
  550. if (this[i] === item) this.splice(i, 1);
  551. }
  552. return this;
  553. },
  554.  
  555. empty: function(){
  556. this.length = 0;
  557. return this;
  558. },
  559.  
  560. flatten: function(){
  561. var array = [];
  562. for (var i = 0, l = this.length; i < l; i++){
  563. var type = $type(this[i]);
  564. if (!type) continue;
  565. array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
  566. }
  567. return array;
  568. },
  569.  
  570. hexToRgb: function(array){
  571. if (this.length != 3) return null;
  572. var rgb = this.map(function(value){
  573. if (value.length == 1) value += value;
  574. return value.toInt(16);
  575. });
  576. return (array) ? rgb : 'rgb(' + rgb + ')';
  577. },
  578.  
  579. rgbToHex: function(array){
  580. if (this.length < 3) return null;
  581. if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
  582. var hex = [];
  583. for (var i = 0; i < 3; i++){
  584. var bit = (this[i] - 0).toString(16);
  585. hex.push((bit.length == 1) ? '0' + bit : bit);
  586. }
  587. return (array) ? hex : '#' + hex.join('');
  588. },
  589. copy: function(){
  590. var results = [];
  591. for(var i = 0, l = this.length; i < l; i++) results[i] = this[i];
  592. return results;
  593. }
  594.  
  595. });
  596.  
  597. /*
  598. Script: String.js
  599. Contains String Prototypes like camelCase, capitalize, test, and toInt.
  600.  
  601. License:
  602. MIT-style license.
  603. */
  604.  
  605. String.implement({
  606.  
  607. test: function(regex, params){
  608. return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
  609. },
  610.  
  611. contains: function(string, separator){
  612. return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
  613. },
  614.  
  615. trim: function(){
  616. return this.replace(/^\s+|\s+$/g, '');
  617. },
  618.  
  619. clean: function(){
  620. return this.replace(/\s+/g, ' ').trim();
  621. },
  622.  
  623. camelCase: function(){
  624. return this.replace(/-\D/g, function(match){
  625. return match.charAt(1).toUpperCase();
  626. });
  627. },
  628.  
  629. hyphenate: function(){
  630. return this.replace(/[A-Z]/g, function(match){
  631. return ('-' + match.charAt(0).toLowerCase());
  632. });
  633. },
  634.  
  635. capitalize: function(){
  636. return this.replace(/\b[a-z]/g, function(match){
  637. return match.toUpperCase();
  638. });
  639. },
  640.  
  641. escapeRegExp: function(){
  642. return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
  643. },
  644.  
  645. toInt: function(base){
  646. return parseInt(this, base || 10);
  647. },
  648.  
  649. toFloat: function(){
  650. return parseFloat(this);
  651. },
  652.  
  653. hexToRgb: function(array){
  654. var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
  655. return (hex) ? hex.slice(1).hexToRgb(array) : null;
  656. },
  657.  
  658. rgbToHex: function(array){
  659. var rgb = this.match(/\d{1,3}/g);
  660. return (rgb) ? rgb.rgbToHex(array) : null;
  661. },
  662.  
  663. stripScripts: function(option){
  664. var scripts = '';
  665. var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
  666. scripts += arguments[1] + '\n';
  667. return '';
  668. });
  669. if (option === true) $exec(scripts);
  670. else if ($type(option) == 'function') option(scripts, text);
  671. return text;
  672. },
  673.  
  674. substitute: function(object, regexp){
  675. return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
  676. if (match.charAt(0) == '\\') return match.slice(1);
  677. return (object[name] != undefined) ? object[name] : '';
  678. });
  679. },
  680. repeat: function(times) {
  681. var result = "";
  682. for(var i = 0; i < times; i++) {
  683. result += this;
  684. }
  685. return result;
  686. }
  687.  
  688. });
  689.  
  690. /*
  691. Script: Function.js
  692. Contains Function Prototypes like create, bind, pass, and delay.
  693.  
  694. License:
  695. MIT-style license.
  696. */
  697.  
  698. Function.implement({
  699.  
  700. extend: function(properties){
  701. for (var property in properties) this[property] = properties[property];
  702. return this;
  703. },
  704.  
  705. create: function(options){
  706. var self = this;
  707. options = options || {};
  708. return function(event){
  709. var args = options.arguments;
  710. args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);
  711. if (options.event) args = [event || window.event].extend(args);
  712. var returns = function(){
  713. return self.apply(options.bind || null, args);
  714. };
  715. if (options.delay) return setTimeout(returns, options.delay);
  716. if (options.periodical) return setInterval(returns, options.periodical);
  717. if (options.attempt) return $try(returns);
  718. return returns();
  719. };
  720. },
  721.  
  722. run: function(args, bind){
  723. return this.apply(bind, $splat(args));
  724. },
  725.  
  726. pass: function(args, bind){
  727. return this.create({bind: bind, arguments: args});
  728. },
  729.  
  730. bind: function(bind, args){
  731. return this.create({bind: bind, arguments: args});
  732. },
  733.  
  734. bindWithEvent: function(bind, args){
  735. return this.create({bind: bind, arguments: args, event: true});
  736. },
  737.  
  738. attempt: function(args, bind){
  739. return this.create({bind: bind, arguments: args, attempt: true})();
  740. },
  741.  
  742. delay: function(delay, bind, args){
  743. return this.create({bind: bind, arguments: args, delay: delay})();
  744. },
  745.  
  746. periodical: function(periodical, bind, args){
  747. return this.create({bind: bind, arguments: args, periodical: periodical})();
  748. }
  749.  
  750. });
  751.  
  752. /*
  753. Script: Number.js
  754. Contains Number Prototypes like limit, round, times, and ceil.
  755.  
  756. License:
  757. MIT-style license.
  758. */
  759.  
  760. Number.implement({
  761.  
  762. limit: function(min, max){
  763. return Math.min(max, Math.max(min, this));
  764. },
  765.  
  766. round: function(precision){
  767. precision = Math.pow(10, precision || 0);
  768. return Math.round(this * precision) / precision;
  769. },
  770.  
  771. times: function(fn, bind){
  772. for (var i = 0; i < this; i++) fn.call(bind, i, this);
  773. },
  774.  
  775. toFloat: function(){
  776. return parseFloat(this);
  777. },
  778.  
  779. toInt: function(base){
  780. return parseInt(this, base || 10);
  781. }
  782.  
  783. });
  784.  
  785. Number.alias('times', 'each');
  786.  
  787. (function(math){
  788. var methods = {};
  789. math.each(function(name){
  790. if (!Number[name]) methods[name] = function(){
  791. return Math[name].apply(null, [this].concat($A(arguments)));
  792. };
  793. });
  794. Number.implement(methods);
  795. })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
  796.  
  797. /*
  798. Script: Hash.js
  799. Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
  800.  
  801. License:
  802. MIT-style license.
  803. */
  804.  
  805. Hash.implement({
  806.  
  807. has: Object.prototype.hasOwnProperty,
  808.  
  809. keyOf: function(value){
  810. for (var key in this){
  811. if (this.hasOwnProperty(key) && this[key] === value) return key;
  812. }
  813. return null;
  814. },
  815.  
  816. hasValue: function(value){
  817. return (Hash.keyOf(this, value) !== null);
  818. },
  819.  
  820. extend: function(properties){
  821. Hash.each(properties, function(value, key){
  822. Hash.set(this, key, value);
  823. }, this);
  824. return this;
  825. },
  826.  
  827. combine: function(properties){
  828. Hash.each(properties, function(value, key){
  829. Hash.include(this, key, value);
  830. }, this);
  831. return this;
  832. },
  833.  
  834. erase: function(key){
  835. if (this.hasOwnProperty(key)) delete this[key];
  836. return this;
  837. },
  838.  
  839. get: function(key){
  840. return (this.hasOwnProperty(key)) ? this[key] : null;
  841. },
  842.  
  843. set: function(key, value){
  844. if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
  845. return this;
  846. },
  847.  
  848. empty: function(){
  849. Hash.each(this, function(value, key){
  850. delete this[key];
  851. }, this);
  852. return this;
  853. },
  854.  
  855. include: function(key, value){
  856. if (this[key] == undefined) this[key] = value;
  857. return this;
  858. },
  859.  
  860. map: function(fn, bind){
  861. var results = new Hash;
  862. Hash.each(this, function(value, key){
  863. results.set(key, fn.call(bind, value, key, this));
  864. }, this);
  865. return results;
  866. },
  867.  
  868. filter: function(fn, bind){
  869. var results = new Hash;
  870. Hash.each(this, function(value, key){
  871. if (fn.call(bind, value, key, this)) results.set(key, value);
  872. }, this);
  873. return results;
  874. },
  875.  
  876. every: function(fn, bind){
  877. for (var key in this){
  878. if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
  879. }
  880. return true;
  881. },
  882.  
  883. some: function(fn, bind){
  884. for (var key in this){
  885. if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
  886. }
  887. return false;
  888. },
  889.  
  890. getKeys: function(){
  891. var keys = [];
  892. Hash.each(this, function(value, key){
  893. keys.push(key);
  894. });
  895. return keys;
  896. },
  897.  
  898. getValues: function(){
  899. var values = [];
  900. Hash.each(this, function(value){
  901. values.push(value);
  902. });
  903. return values;
  904. },
  905.  
  906. toQueryString: function(base){
  907. var queryString = [];
  908. Hash.each(this, function(value, key){
  909. if (base) key = base + '[' + key + ']';
  910. var result;
  911. switch ($type(value)){
  912. case 'object': result = Hash.toQueryString(value, key); break;
  913. case 'array':
  914. var qs = {};
  915. value.each(function(val, i){
  916. qs[i] = val;
  917. });
  918. result = Hash.toQueryString(qs, key);
  919. break;
  920. default: result = key + '=' + encodeURIComponent(value);
  921. }
  922. if (value != undefined) queryString.push(result);
  923. });
  924.  
  925. return queryString.join('&');
  926. }
  927.  
  928. });
  929.  
  930. Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
  931.  
  932. /*
  933. Script: Element.js
  934. One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser,
  935. time-saver methods to let you easily work with HTML Elements.
  936.  
  937. License:
  938. MIT-style license.
  939. */
  940.  
  941. var Element = new Native({
  942.  
  943. name: 'Element',
  944.  
  945. legacy: window.Element,
  946.  
  947. initialize: function(tag, props){
  948. var konstructor = Element.Constructors.get(tag);
  949. if (konstructor) return konstructor(props);
  950. if (typeof tag == 'string') return document.newElement(tag, props);
  951. return $(tag).set(props);
  952. },
  953.  
  954. afterImplement: function(key, value){
  955. Element.Prototype[key] = value;
  956. if (Array[key]) return;
  957. Elements.implement(key, function(){
  958. var items = [], elements = true;
  959. for (var i = 0, j = this.length; i < j; i++){
  960. var returns = this[i][key].apply(this[i], arguments);
  961. items.push(returns);
  962. if (elements) elements = ($type(returns) == 'element');
  963. }
  964. return (elements) ? new Elements(items) : items;
  965. });
  966. }
  967.  
  968. });
  969.  
  970. Element.Prototype = {$family: {name: 'element'}};
  971.  
  972. Element.Constructors = new Hash;
  973.  
  974. var IFrame = new Native({
  975.  
  976. name: 'IFrame',
  977.  
  978. generics: false,
  979.  
  980. initialize: function(){
  981. var params = Array.link(arguments, {properties: Object.type, iframe: $defined});
  982. var props = params.properties || {};
  983. var iframe = $(params.iframe) || false;
  984. var onload = props.onload || $empty;
  985. delete props.onload;
  986. props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time());
  987. iframe = new Element(iframe || 'iframe', props);
  988. var onFrameLoad = function(){
  989. var host = $try(function(){
  990. return iframe.contentWindow.location.host;
  991. });
  992. if ((host && host == window.location.host) || !host){ // CHANGE: so that frames with no host work - David
  993. var win = new Window(iframe.contentWindow);
  994. new Document(iframe.contentWindow.document);
  995. if(!win.Element.prototype) win.Element.prototype = {}; // CHANGE: fix for GM and MT1.2 IFrames - David
  996. $extend(win.Element.prototype, Element.Prototype);
  997. }
  998. onload.call(iframe.contentWindow, iframe.contentWindow.document);
  999. };
  1000. (window.frames[props.id]) ? onFrameLoad() : iframe.addListener('load', onFrameLoad);
  1001. return iframe;
  1002. }
  1003.  
  1004. });
  1005.  
  1006. var Elements = new Native({
  1007.  
  1008. initialize: function(elements, options){
  1009. options = $extend({ddup: true, cash: true}, options);
  1010. elements = elements || [];
  1011. if (options.ddup || options.cash){
  1012. var uniques = {}, returned = [];
  1013. for (var i = 0, l = elements.length; i < l; i++){
  1014. var el = $.element(elements[i], !options.cash);
  1015. if (options.ddup){
  1016. if (uniques[el.uid]) continue;
  1017. uniques[el.uid] = true;
  1018. }
  1019. returned.push(el);
  1020. }
  1021. elements = returned;
  1022. }
  1023. return (options.cash) ? $extend(elements, this) : elements;
  1024. }
  1025.  
  1026. });
  1027.  
  1028. Elements.implement({
  1029.  
  1030. filter: function(filter, bind){
  1031. if (!filter) return this;
  1032. return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){
  1033. return item.match(filter);
  1034. } : filter, bind));
  1035. }
  1036.  
  1037. });
  1038.  
  1039. Document.implement({
  1040.  
  1041. newElement: function(tag, props){
  1042. if (Browser.Engine.trident && props){
  1043. ['name', 'type', 'checked'].each(function(attribute){
  1044. if (!props[attribute]) return;
  1045. tag += ' ' + attribute + '="' + props[attribute] + '"';
  1046. if (attribute != 'checked') delete props[attribute];
  1047. });
  1048. tag = '<' + tag + '>';
  1049. }
  1050. return $.element(this.createElement(tag)).set(props);
  1051. },
  1052.  
  1053. newTextNode: function(text){
  1054. return this.createTextNode(text);
  1055. },
  1056.  
  1057. getDocument: function(){
  1058. return this;
  1059. },
  1060.  
  1061. getWindow: function(){
  1062. return (new Window(this.defaultView || this.parentWindow)); // CHANGE: GM Fix - David
  1063. }
  1064.  
  1065. });
  1066.  
  1067. Window.implement({
  1068.  
  1069. $: function(el, nocash){
  1070. if (el && el.$family && el.uid) return el;
  1071. var type = $type(el);
  1072. return ($[type]) ? $[type](el, nocash, this.document) : null;
  1073. },
  1074.  
  1075. $$: function(selector){
  1076. if (arguments.length == 1 && typeof selector == 'string') return (new Document(this.document)).getElements(selector); // CHANGE: For GM
  1077. var elements = [];
  1078. var args = Array.flatten(arguments);
  1079. for (var i = 0, l = args.length; i < l; i++){
  1080. var item = args[i];
  1081. switch ($type(item)){
  1082. case 'element': elements.push(item); break;
  1083. case 'string': (new Document(this.document)).getElements(item, true); break; // CHANGE: For GM - David
  1084. }
  1085. }
  1086. return new Elements(elements);
  1087. },
  1088.  
  1089. getDocument: function(){
  1090. return this.document;
  1091. },
  1092.  
  1093. getWindow: function(){
  1094. return this;
  1095. }
  1096.  
  1097. });
  1098.  
  1099. $.string = function(id, nocash, doc){
  1100. id = doc.getElementById(id);
  1101. return (id) ? $.element(id, nocash) : null;
  1102. };
  1103.  
  1104. $.element = function(el, nocash){
  1105. $uid(el);
  1106. if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){
  1107. var proto = Element.Prototype;
  1108. for (var p in proto) el[p] = proto[p];
  1109. };
  1110. return el;
  1111. };
  1112.  
  1113. $.object = function(obj, nocash, doc){
  1114. if (obj.toElement) return $.element(obj.toElement(doc), nocash);
  1115. return null;
  1116. };
  1117.  
  1118. $.textnode = $.whitespace = $.window = $.document = $arguments(0);
  1119.  
  1120. Native.implement([Element, Document], {
  1121.  
  1122. getElement: function(selector, nocash){
  1123. return $(this.getElements(selector, true)[0] || null, nocash);
  1124. },
  1125.  
  1126. getElements: function(tags, nocash){
  1127. tags = tags.split(',');
  1128. var elements = [];
  1129. var ddup = (tags.length > 1);
  1130. tags.each(function(tag){
  1131. var partial = this.getElementsByTagName(tag.trim());
  1132. (ddup) ? elements.extend(partial) : elements = partial;
  1133. }, this);
  1134. return new Elements(elements, {ddup: ddup, cash: !nocash});
  1135. }
  1136.  
  1137. });
  1138.  
  1139. (function(){
  1140.  
  1141. var collected = {}, storage = {};
  1142. var props = {input: 'checked', option: 'selected', textarea: (Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerHTML' : 'value'};
  1143.  
  1144. var get = function(uid){
  1145. return (storage[uid] || (storage[uid] = {}));
  1146. };
  1147.  
  1148. var clean = function(item, retain){
  1149. if (!item) return;
  1150. var uid = item.uid;
  1151. if (Browser.Engine.trident){
  1152. if (item.clearAttributes){
  1153. var clone = retain && item.cloneNode(false);
  1154. item.clearAttributes();
  1155. if (clone) item.mergeAttributes(clone);
  1156. } else if (item.removeEvents){
  1157. item.removeEvents();
  1158. }
  1159. if ((/object/i).test(item.tagName)){
  1160. for (var p in item){
  1161. if (typeof item[p] == 'function') item[p] = $empty;
  1162. }
  1163. Element.dispose(item);
  1164. }
  1165. }
  1166. if (!uid) return;
  1167. collected[uid] = storage[uid] = null;
  1168. };
  1169.  
  1170. var purge = function(){
  1171. Hash.each(collected, clean);
  1172. if (Browser.Engine.trident) $A(document.getElementsByTagName('object')).each(clean);
  1173. if (window.CollectGarbage) CollectGarbage();
  1174. collected = storage = null;
  1175. };
  1176.  
  1177. var walk = function(element, walk, start, match, all, nocash){
  1178. var el = element[start || walk];
  1179. var elements = [];
  1180. while (el){
  1181. if (el.nodeType == 1 && (!match || Element.match(el, match))){
  1182. if (!all) return $(el, nocash);
  1183. elements.push(el);
  1184. }
  1185. el = el[walk];
  1186. }
  1187. return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : null;
  1188. };
  1189.  
  1190. var attributes = {
  1191. 'html': 'innerHTML',
  1192. 'class': 'className',
  1193. 'for': 'htmlFor',
  1194. 'text': (Browser.Engine.trident || (Browser.Engine.webkit && Browser.Engine.version < 420)) ? 'innerText' : 'textContent'
  1195. };
  1196. var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'];
  1197. var camels = ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap'];
  1198.  
  1199. Hash.extend(attributes, bools.associate(bools));
  1200. Hash.extend(attributes, camels.associate(camels.map(String.toLowerCase)));
  1201.  
  1202. var inserters = {
  1203.  
  1204. before: function(context, element){
  1205. if (element.parentNode) element.parentNode.insertBefore(context, element);
  1206. },
  1207.  
  1208. after: function(context, element){
  1209. if (!element.parentNode) return;
  1210. var next = element.nextSibling;
  1211. (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);
  1212. },
  1213.  
  1214. bottom: function(context, element){
  1215. element.appendChild(context);
  1216. },
  1217.  
  1218. top: function(context, element){
  1219. var first = element.firstChild;
  1220. (first) ? element.insertBefore(context, first) : element.appendChild(context);
  1221. }
  1222.  
  1223. };
  1224.  
  1225. inserters.inside = inserters.bottom;
  1226.  
  1227. Hash.each(inserters, function(inserter, where){
  1228.  
  1229. where = where.capitalize();
  1230.  
  1231. Element.implement('inject' + where, function(el){
  1232. inserter(this, $(el, true));
  1233. return this;
  1234. });
  1235.  
  1236. Element.implement('grab' + where, function(el){
  1237. inserter($(el, true), this);
  1238. return this;
  1239. });
  1240.  
  1241. });
  1242.  
  1243. Element.implement({
  1244.  
  1245. set: function(prop, value){
  1246. switch ($type(prop)){
  1247. case 'object':
  1248. for (var p in prop) this.set(p, prop[p]);
  1249. break;
  1250. case 'string':
  1251. var property = Element.Properties.get(prop);
  1252. (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
  1253. }
  1254. return this;
  1255. },
  1256.  
  1257. get: function(prop){
  1258. var property = Element.Properties.get(prop);
  1259. return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
  1260. },
  1261.  
  1262. erase: function(prop){
  1263. var property = Element.Properties.get(prop);
  1264. (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
  1265. return this;
  1266. },
  1267.  
  1268. setProperty: function(attribute, value){
  1269. var key = attributes[attribute];
  1270. if (value == undefined) return this.removeProperty(attribute);
  1271. if (key && bools[attribute]) value = !!value;
  1272. (key) ? this[key] = value : this.setAttribute(attribute, '' + value);
  1273. return this;
  1274. },
  1275.  
  1276. setProperties: function(attributes){
  1277. for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
  1278. return this;
  1279. },
  1280.  
  1281. getProperty: function(attribute){
  1282. var key = attributes[attribute];
  1283. var value = (key) ? this[key] : this.getAttribute(attribute, 2);
  1284. return (bools[attribute]) ? !!value : (key) ? value : value || null;
  1285. },
  1286.  
  1287. getProperties: function(){
  1288. var args = $A(arguments);
  1289. return args.map(this.getProperty, this).associate(args);
  1290. },
  1291.  
  1292. removeProperty: function(attribute){
  1293. var key = attributes[attribute];
  1294. (key) ? this[key] = (key && bools[attribute]) ? false : '' : this.removeAttribute(attribute);
  1295. return this;
  1296. },
  1297.  
  1298. removeProperties: function(){
  1299. Array.each(arguments, this.removeProperty, this);
  1300. return this;
  1301. },
  1302.  
  1303. hasClass: function(className){
  1304. return this.className.contains(className, ' ');
  1305. },
  1306.  
  1307. addClass: function(className){
  1308. if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
  1309. return this;
  1310. },
  1311.  
  1312. removeClass: function(className){
  1313. this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
  1314. return this;
  1315. },
  1316.  
  1317. toggleClass: function(className){
  1318. return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
  1319. },
  1320.  
  1321. adopt: function(){
  1322. Array.flatten(arguments).each(function(element){
  1323. element = $(element, true);
  1324. if (element) this.appendChild(element);
  1325. }, this);
  1326. return this;
  1327. },
  1328.  
  1329. appendText: function(text, where){
  1330. return this.grab((new Document(this.getDocument())).newTextNode(text), where); // CHANGE: For GM - David
  1331. },
  1332.  
  1333. grab: function(el, where){
  1334. inserters[where || 'bottom']($(el, true), this);
  1335. return this;
  1336. },
  1337.  
  1338. inject: function(el, where){
  1339. inserters[where || 'bottom'](this, $(el, true));
  1340. return this;
  1341. },
  1342.  
  1343. replaces: function(el){
  1344. el = $(el, true);
  1345. el.parentNode.replaceChild(this, el);
  1346. return this;
  1347. },
  1348.  
  1349. wraps: function(el, where){
  1350. el = $(el, true);
  1351. return this.replaces(el).grab(el, where);
  1352. },
  1353.  
  1354. getPrevious: function(match, nocash){
  1355. return walk(this, 'previousSibling', null, match, false, nocash);
  1356. },
  1357.  
  1358. getAllPrevious: function(match, nocash){
  1359. return walk(this, 'previousSibling', null, match, true, nocash);
  1360. },
  1361.  
  1362. getNext: function(match, nocash){
  1363. return walk(this, 'nextSibling', null, match, false, nocash);
  1364. },
  1365.  
  1366. getAllNext: function(match, nocash){
  1367. return walk(this, 'nextSibling', null, match, true, nocash);
  1368. },
  1369.  
  1370. getFirst: function(match, nocash){
  1371. return walk(this, 'nextSibling', 'firstChild', match, false, nocash);
  1372. },
  1373.  
  1374. getLast: function(match, nocash){
  1375. return walk(this, 'previousSibling', 'lastChild', match, false, nocash);
  1376. },
  1377.  
  1378. getParent: function(match, nocash){
  1379. return walk(this, 'parentNode', null, match, false, nocash);
  1380. },
  1381.  
  1382. getParents: function(match, nocash){
  1383. return walk(this, 'parentNode', null, match, true, nocash);
  1384. },
  1385.  
  1386. getChildren: function(match, nocash){
  1387. return walk(this, 'nextSibling', 'firstChild', match, true, nocash);
  1388. },
  1389.  
  1390. getWindow: function(){
  1391. return (new Window(this.ownerDocument.defaultView || this.ownerDocument.parentWindow)); // CHANGE: For GM - David
  1392. },
  1393.  
  1394. getDocument: function(){
  1395. return this.ownerDocument;
  1396. },
  1397.  
  1398. getElementById: function(id, nocash){
  1399. var el = this.ownerDocument.getElementById(id);
  1400. if (!el) return null;
  1401. for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
  1402. if (!parent) return null;
  1403. }
  1404. return $.element(el, nocash);
  1405. },
  1406.  
  1407. getSelected: function(){
  1408. return new Elements($A(this.options).filter(function(option){
  1409. return option.selected;
  1410. }));
  1411. },
  1412.  
  1413. getComputedStyle: function(property){
  1414. if ($(this).currentStyle) return $(this).currentStyle[property.camelCase()]; // CHANGE: Fix for GM - David
  1415. var computed = $(this).getDocument().defaultView.getComputedStyle($(this), null); // CHANGE: ditto
  1416. return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null;
  1417. },
  1418.  
  1419. toQueryString: function(){
  1420. var queryString = [];
  1421. this.getElements('input, select, textarea', true).each(function(el){
  1422. if (!el.name || el.disabled) return;
  1423. var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){
  1424. return opt.value;
  1425. }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value;
  1426. $splat(value).each(function(val){
  1427. if (typeof val != 'undefined') queryString.push(el.name + '=' + encodeURIComponent(val));
  1428. });
  1429. });
  1430. return queryString.join('&');
  1431. },
  1432.  
  1433. clone: function(contents, keepid){
  1434. contents = contents !== false;
  1435. var clone = this.cloneNode(contents);
  1436. var clean = function(node, element){
  1437. if (!keepid) node.removeAttribute('id');
  1438. if (Browser.Engine.trident){
  1439. node.clearAttributes();
  1440. node.mergeAttributes(element);
  1441. node.removeAttribute('uid');
  1442. if (node.options){
  1443. var no = node.options, eo = element.options;
  1444. for (var j = no.length; j--;) no[j].selected = eo[j].selected;
  1445. }
  1446. }
  1447. var prop = props[element.tagName.toLowerCase()];
  1448. if (prop && element[prop]) node[prop] = element[prop];
  1449. };
  1450.  
  1451. if (contents){
  1452. var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*');
  1453. for (var i = ce.length; i--;) clean(ce[i], te[i]);
  1454. }
  1455.  
  1456. clean(clone, this);
  1457. return $(clone);
  1458. },
  1459.  
  1460. destroy: function(){
  1461. Element.empty(this);
  1462. Element.dispose(this);
  1463. clean(this, true);
  1464. return null;
  1465. },
  1466.  
  1467. empty: function(){
  1468. $A(this.childNodes).each(function(node){
  1469. Element.destroy(node);
  1470. });
  1471. return this;
  1472. },
  1473.  
  1474. dispose: function(){
  1475. return (this.parentNode) ? this.parentNode.removeChild(this) : this;
  1476. },
  1477.  
  1478. hasChild: function(el){
  1479. el = $(el, true);
  1480. if (!el) return false;
  1481. if (Browser.Engine.webkit && Browser.Engine.version < 420) return $A(this.getElementsByTagName(el.tagName)).contains(el);
  1482. return (this.contains) ? (this != el && this.contains(el)) : !!(this.compareDocumentPosition(el) & 16);
  1483. },
  1484.  
  1485. match: function(tag){
  1486. return (!tag || (tag == this) || (Element.get(this, 'tag') == tag));
  1487. }
  1488.  
  1489. });
  1490.  
  1491. Native.implement([Element, Window, Document], {
  1492.  
  1493. addListener: function(type, fn){
  1494. if (type == 'unload'){
  1495. var old = fn, self = this;
  1496. fn = function(){
  1497. self.removeListener('unload', fn);
  1498. old();
  1499. };
  1500. } else {
  1501. collected[this.uid] = this;
  1502. }
  1503. if (this.addEventListener) this.addEventListener(type, fn, false);
  1504. else this.attachEvent('on' + type, fn);
  1505. return this;
  1506. },
  1507.  
  1508. removeListener: function(type, fn){
  1509. if (this.removeEventListener) this.removeEventListener(type, fn, false);
  1510. else this.detachEvent('on' + type, fn);
  1511. return this;
  1512. },
  1513.  
  1514. retrieve: function(property, dflt){
  1515. var storage = get(this.uid), prop = storage[property];
  1516. if (dflt != undefined && prop == undefined) prop = storage[property] = dflt;
  1517. return $pick(prop);
  1518. },
  1519.  
  1520. store: function(property, value){
  1521. var storage = get(this.uid);
  1522. storage[property] = value;
  1523. return this;
  1524. },
  1525.  
  1526. eliminate: function(property){
  1527. var storage = get(this.uid);
  1528. delete storage[property];
  1529. return this;
  1530. }
  1531.  
  1532. });
  1533.  
  1534. window.addListener('unload', purge);
  1535.  
  1536. })();
  1537.  
  1538. Element.Properties = new Hash;
  1539.  
  1540. Element.Properties.style = {
  1541.  
  1542. set: function(style){
  1543. this.style.cssText = style;
  1544. },
  1545.  
  1546. get: function(){
  1547. return this.style.cssText;
  1548. },
  1549.  
  1550. erase: function(){
  1551. this.style.cssText = '';
  1552. }
  1553.  
  1554. };
  1555.  
  1556. Element.Properties.tag = {
  1557.  
  1558. get: function(){
  1559. return this.tagName.toLowerCase();
  1560. }
  1561.  
  1562. };
  1563.  
  1564. Element.Properties.html = (function(){
  1565. var wrapper = document.createElement('div');
  1566.  
  1567. var translations = {
  1568. table: [1, '<table>', '</table>'],
  1569. select: [1, '<select>', '</select>'],
  1570. tbody: [2, '<table><tbody>', '</tbody></table>'],
  1571. tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
  1572. };
  1573. translations.thead = translations.tfoot = translations.tbody;
  1574.  
  1575. var html = {
  1576. set: function(){
  1577. var html = Array.flatten(arguments).join('');
  1578. var wrap = Browser.Engine.trident && translations[this.get('tag')];
  1579. if (wrap){
  1580. var first = wrapper;
  1581. first.innerHTML = wrap[1] + html + wrap[2];
  1582. for (var i = wrap[0]; i--;) first = first.firstChild;
  1583. this.empty().adopt(first.childNodes);
  1584. } else {
  1585. this.innerHTML = html;
  1586. }
  1587. }
  1588. };
  1589.  
  1590. html.erase = html.set;
  1591.  
  1592. return html;
  1593. })();
  1594.  
  1595. if (Browser.Engine.webkit && Browser.Engine.version < 420) Element.Properties.text = {
  1596. get: function(){
  1597. if (this.innerText) return this.innerText;
  1598. var temp = this.ownerDocument.newElement('div', {html: this.innerHTML}).inject(this.ownerDocument.body);
  1599. var text = temp.innerText;
  1600. temp.destroy();
  1601. return text;
  1602. }
  1603. };
  1604.  
  1605. /*
  1606. Script: Element.Style.js
  1607. Contains methods for interacting with the styles of Elements in a fashionable way.
  1608.  
  1609. License:
  1610. MIT-style license.
  1611. */
  1612.  
  1613. Element.Properties.styles = {set: function(styles){
  1614. this.setStyles(styles);
  1615. }};
  1616.  
  1617. Element.Properties.opacity = {
  1618.  
  1619. set: function(opacity, novisibility){
  1620. if (!novisibility){
  1621. if (opacity == 0){
  1622. if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
  1623. } else {
  1624. if (this.style.visibility != 'visible') this.style.visibility = 'visible';
  1625. }
  1626. }
  1627. if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
  1628. if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
  1629. this.style.opacity = opacity;
  1630. this.store('opacity', opacity);
  1631. },
  1632.  
  1633. get: function(){
  1634. return this.retrieve('opacity', 1);
  1635. }
  1636.  
  1637. };
  1638.  
  1639. Element.implement({
  1640.  
  1641. setOpacity: function(value){
  1642. return this.set('opacity', value, true);
  1643. },
  1644.  
  1645. getOpacity: function(){
  1646. return this.get('opacity');
  1647. },
  1648.  
  1649. setStyle: function(property, value){
  1650. switch (property){
  1651. case 'opacity': return this.set('opacity', parseFloat(value));
  1652. case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
  1653. }
  1654. property = property.camelCase();
  1655. if ($type(value) != 'string'){
  1656. var map = (Element.Styles.get(property) || '@').split(' ');
  1657. value = $splat(value).map(function(val, i){
  1658. if (!map[i]) return '';
  1659. return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
  1660. }).join(' ');
  1661. } else if (value == String(Number(value))){
  1662. value = Math.round(value);
  1663. }
  1664. this.style[property] = value;
  1665. return this;
  1666. },
  1667.  
  1668. getStyle: function(property){
  1669. switch (property){
  1670. case 'opacity': return this.get('opacity');
  1671. case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
  1672. }
  1673. property = property.camelCase();
  1674. var result = this.style[property];
  1675. if (!$chk(result)){
  1676. result = [];
  1677. for (var style in Element.ShortStyles){
  1678. if (property != style) continue;
  1679. for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
  1680. return result.join(' ');
  1681. }
  1682. result = this.getComputedStyle(property);
  1683. }
  1684. if (result){
  1685. result = String(result);
  1686. var color = result.match(/rgba?\([\d\s,]+\)/);
  1687. if (color) result = result.replace(color[0], color[0].rgbToHex());
  1688. }
  1689. if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result, 10)))){
  1690. if (property.test(/^(height|width)$/)){
  1691. var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
  1692. values.each(function(value){
  1693. size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
  1694. }, this);
  1695. return this['offset' + property.capitalize()] - size + 'px';
  1696. }
  1697. if ((Browser.Engine.presto) && String(result).test('px')) return result;
  1698. if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
  1699. }
  1700. return result;
  1701. },
  1702.  
  1703. setStyles: function(styles){
  1704. for (var style in styles) this.setStyle(style, styles[style]);
  1705. return this;
  1706. },
  1707.  
  1708. getStyles: function(){
  1709. var result = {};
  1710. Array.each(arguments, function(key){
  1711. result[key] = this.getStyle(key);
  1712. }, this);
  1713. return result;
  1714. }
  1715.  
  1716. });
  1717.  
  1718. Element.Styles = new Hash({
  1719. left: '@px', top: '@px', bottom: '@px', right: '@px',
  1720. width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
  1721. backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
  1722. fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
  1723. margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
  1724. borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
  1725. zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
  1726. });
  1727.  
  1728. Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
  1729.  
  1730. ['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
  1731. var Short = Element.ShortStyles;
  1732. var All = Element.Styles;
  1733. ['margin', 'padding'].each(function(style){
  1734. var sd = style + direction;
  1735. Short[style][sd] = All[sd] = '@px';
  1736. });
  1737. var bd = 'border' + direction;
  1738. Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
  1739. var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
  1740. Short[bd] = {};
  1741. Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
  1742. Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
  1743. Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
  1744. });
  1745.  
  1746. /*
  1747. Script: Element.Dimensions.js
  1748. Contains methods to work with size, scroll, or positioning of Elements and the window object.
  1749.  
  1750. License:
  1751. MIT-style license.
  1752.  
  1753. Credits:
  1754. - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
  1755. - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
  1756. */
  1757.  
  1758. (function(){
  1759.  
  1760. Element.implement({
  1761.  
  1762. scrollTo: function(x, y){
  1763. if (isBody(this)){
  1764. this.getWindow().scrollTo(x, y);
  1765. } else {
  1766. this.scrollLeft = x;
  1767. this.scrollTop = y;
  1768. }
  1769. return this;
  1770. },
  1771.  
  1772. getSize: function(){
  1773. if (isBody(this)) return this.getWindow().getSize();
  1774. return {x: this.offsetWidth, y: this.offsetHeight};
  1775. },
  1776.  
  1777. getScrollSize: function(){
  1778. if (isBody(this)) return this.getWindow().getScrollSize();
  1779. return {x: this.scrollWidth, y: this.scrollHeight};
  1780. },
  1781.  
  1782. getScroll: function(){
  1783. if (isBody(this)) return this.getWindow().getScroll();
  1784. return {x: this.scrollLeft, y: this.scrollTop};
  1785. },
  1786.  
  1787. getScrolls: function(){
  1788. var element = this, position = {x: 0, y: 0};
  1789. while (element && !isBody(element)){
  1790. position.x += element.scrollLeft;
  1791. position.y += element.scrollTop;
  1792. element = element.parentNode;
  1793. }
  1794. return position;
  1795. },
  1796.  
  1797. getOffsetParent: function(){
  1798. var element = this;
  1799. if (isBody(element)) return null;
  1800. if (!Browser.Engine.trident) return element.offsetParent;
  1801. while ((element = element.parentNode) && !isBody(element)){
  1802. if (styleString(element, 'position') != 'static') return element;
  1803. }
  1804. return null;
  1805. },
  1806.  
  1807. getOffsets: function(){
  1808. if (Browser.Engine.trident){
  1809. var bound = this.getBoundingClientRect(), html = this.getDocument().documentElement;
  1810. return {
  1811. x: bound.left + html.scrollLeft - html.clientLeft,
  1812. y: bound.top + html.scrollTop - html.clientTop
  1813. };
  1814. }
  1815.  
  1816. var element = this, position = {x: 0, y: 0};
  1817. if (isBody(this)) return position;
  1818.  
  1819. while (element && !isBody(element)){
  1820. position.x += element.offsetLeft;
  1821. position.y += element.offsetTop;
  1822.  
  1823. if (Browser.Engine.gecko){
  1824. if (!borderBox(element)){
  1825. position.x += leftBorder(element);
  1826. position.y += topBorder(element);
  1827. }
  1828. var parent = element.parentNode;
  1829. if (parent && styleString(parent, 'overflow') != 'visible'){
  1830. position.x += leftBorder(parent);
  1831. position.y += topBorder(parent);
  1832. }
  1833. } else if (element != this && Browser.Engine.webkit){
  1834. position.x += leftBorder(element);
  1835. position.y += topBorder(element);
  1836. }
  1837.  
  1838. element = element.offsetParent;
  1839. }
  1840. if (Browser.Engine.gecko && !borderBox(this)){
  1841. position.x -= leftBorder(this);
  1842. position.y -= topBorder(this);
  1843. }
  1844. return position;
  1845. },
  1846.  
  1847. getPosition: function(relative){
  1848. if (isBody(this)) return {x: 0, y: 0};
  1849. var offset = this.getOffsets(), scroll = this.getScrolls();
  1850. var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};
  1851. var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};
  1852. return {x: position.x - relativePosition.x, y: position.y - relativePosition.y};
  1853. },
  1854.  
  1855. getCoordinates: function(element){
  1856. if (isBody(this)) return this.getWindow().getCoordinates();
  1857. var position = this.getPosition(element), size = this.getSize();
  1858. var obj = {left: position.x, top: position.y, width: size.x, height: size.y};
  1859. obj.right = obj.left + obj.width;
  1860. obj.bottom = obj.top + obj.height;
  1861. return obj;
  1862. },
  1863.  
  1864. computePosition: function(obj){
  1865. return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')};
  1866. },
  1867.  
  1868. position: function(obj){
  1869. return this.setStyles(this.computePosition(obj));
  1870. }
  1871.  
  1872. });
  1873.  
  1874. Native.implement([Document, Window], {
  1875.  
  1876. getSize: function(){
  1877. if (Browser.Engine.presto || Browser.Engine.webkit) {
  1878. var win = this.getWindow();
  1879. return {x: win.innerWidth, y: win.innerHeight};
  1880. }
  1881. var doc = getCompatElement(this);
  1882. return {x: doc.clientWidth, y: doc.clientHeight};
  1883. },
  1884.  
  1885. getScroll: function(){
  1886. var win = this.getWindow(), doc = getCompatElement(this);
  1887. return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
  1888. },
  1889.  
  1890. getScrollSize: function(){
  1891. var doc = getCompatElement(this), min = this.getSize();
  1892. return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
  1893. },
  1894.  
  1895. getPosition: function(){
  1896. return {x: 0, y: 0};
  1897. },
  1898.  
  1899. getCoordinates: function(){
  1900. var size = this.getSize();
  1901. return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
  1902. }
  1903.  
  1904. });
  1905.  
  1906. // private methods
  1907.  
  1908. var styleString = Element.getComputedStyle;
  1909.  
  1910. function styleNumber(element, style){
  1911. return styleString(element, style).toInt() || 0;
  1912. };
  1913.  
  1914. function borderBox(element){
  1915. return styleString(element, '-moz-box-sizing') == 'border-box';
  1916. };
  1917.  
  1918. function topBorder(element){
  1919. return styleNumber(element, 'border-top-width');
  1920. };
  1921.  
  1922. function leftBorder(element){
  1923. return styleNumber(element, 'border-left-width');
  1924. };
  1925.  
  1926. function isBody(element){
  1927. return (/^(?:body|html)$/i).test(element.tagName);
  1928. };
  1929.  
  1930. function getCompatElement(element){
  1931. var doc = element.getDocument();
  1932. return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
  1933. };
  1934.  
  1935. })();
  1936.  
  1937. //aliases
  1938.  
  1939. Native.implement([Window, Document, Element], {
  1940.  
  1941. getHeight: function(){
  1942. return this.getSize().y;
  1943. },
  1944.  
  1945. getWidth: function(){
  1946. return this.getSize().x;
  1947. },
  1948.  
  1949. getScrollTop: function(){
  1950. return this.getScroll().y;
  1951. },
  1952.  
  1953. getScrollLeft: function(){
  1954. return this.getScroll().x;
  1955. },
  1956.  
  1957. getScrollHeight: function(){
  1958. return this.getScrollSize().y;
  1959. },
  1960.  
  1961. getScrollWidth: function(){
  1962. return this.getScrollSize().x;
  1963. },
  1964.  
  1965. getTop: function(){
  1966. return this.getPosition().y;
  1967. },
  1968.  
  1969. getLeft: function(){
  1970. return this.getPosition().x;
  1971. }
  1972.  
  1973. });
  1974.  
  1975. /*
  1976. Script: Class.js
  1977. Contains the Class Function for easily creating, extending, and implementing reusable Classes.
  1978.  
  1979. License:
  1980. MIT-style license.
  1981. */
  1982.  
  1983. var Class = new Native({
  1984.  
  1985. name: 'Class',
  1986.  
  1987. initialize: function(properties){
  1988. properties = properties || {};
  1989. var klass = function(){
  1990. for (var key in this){
  1991. if ($type(this[key]) != 'function') this[key] = $unlink(this[key]);
  1992. }
  1993. this.constructor = klass;
  1994. if (Class.prototyping) return this;
  1995. var instance = (this.initialize) ? this.initialize.apply(this, arguments) : this;
  1996. if (this.options && this.options.initialize) this.options.initialize.call(this);
  1997. return instance;
  1998. };
  1999.  
  2000. for (var mutator in Class.Mutators){
  2001. if (!properties[mutator]) continue;
  2002. properties = Class.Mutators[mutator](properties, properties[mutator]);
  2003. delete properties[mutator];
  2004. }
  2005.  
  2006. $extend(klass, this);
  2007. klass.constructor = Class;
  2008. klass.prototype = properties;
  2009. return klass;
  2010. }
  2011.  
  2012. });
  2013.  
  2014. Class.Mutators = {
  2015.  
  2016. Extends: function(self, klass){
  2017. Class.prototyping = klass.prototype;
  2018. var subclass = new klass;
  2019. delete subclass.parent;
  2020. subclass = Class.inherit(subclass, self);
  2021. delete Class.prototyping;
  2022. return subclass;
  2023. },
  2024.  
  2025. Implements: function(self, klasses){
  2026. $splat(klasses).each(function(klass){
  2027. Class.prototying = klass;
  2028. $extend(self, ($type(klass) == 'class') ? new klass : klass);
  2029. delete Class.prototyping;
  2030. });
  2031. return self;
  2032. }
  2033.  
  2034. };
  2035.  
  2036. Class.extend({
  2037.  
  2038. inherit: function(object, properties){
  2039. var caller = arguments.callee.caller;
  2040. for (var key in properties){
  2041. var override = properties[key];
  2042. var previous = object[key];
  2043. var type = $type(override);
  2044. if (previous && type == 'function'){
  2045. if (override != previous){
  2046. if (caller){
  2047. override.__parent = previous;
  2048. object[key] = override;
  2049. } else {
  2050. Class.override(object, key, override);
  2051. }
  2052. }
  2053. } else if(type == 'object'){
  2054. object[key] = $merge(previous, override);
  2055. } else {
  2056. object[key] = override;
  2057. }
  2058. }
  2059.  
  2060. if (caller) object.parent = function(){
  2061. return arguments.callee.caller.__parent.apply(this, arguments);
  2062. };
  2063.  
  2064. return object;
  2065. },
  2066.  
  2067. override: function(object, name, method){
  2068. var parent = Class.prototyping;
  2069. if (parent && object[name] != parent[name]) parent = null;
  2070. var override = function(){
  2071. var previous = this.parent;
  2072. this.parent = parent ? parent[name] : object[name];
  2073. var value = method.apply(this, arguments);
  2074. this.parent = previous;
  2075. return value;
  2076. };
  2077. object[name] = override;
  2078. }
  2079.  
  2080. });
  2081.  
  2082. Class.implement({
  2083.  
  2084. implement: function(){
  2085. var proto = this.prototype;
  2086. $each(arguments, function(properties){
  2087. Class.inherit(proto, properties);
  2088. });
  2089. return this;
  2090. }
  2091.  
  2092. });
  2093.  
  2094. /*
  2095. Script: Class.Extras.js
  2096. Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
  2097.  
  2098. License:
  2099. MIT-style license.
  2100. */
  2101.  
  2102. var Chain = new Class({
  2103.  
  2104. $chain: [],
  2105.  
  2106. chain: function(){
  2107. this.$chain.extend(Array.flatten(arguments));
  2108. return this;
  2109. },
  2110.  
  2111. callChain: function(){
  2112. return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
  2113. },
  2114.  
  2115. clearChain: function(){
  2116. this.$chain.empty();
  2117. return this;
  2118. }
  2119.  
  2120. });
  2121.  
  2122. var Events = new Class({
  2123.  
  2124. $events: {},
  2125.  
  2126. addEvent: function(type, fn, internal){
  2127. type = Events.removeOn(type);
  2128. if (fn != $empty){
  2129. this.$events[type] = this.$events[type] || [];
  2130. this.$events[type].include(fn);
  2131. if (internal) fn.internal = true;
  2132. }
  2133. return this;
  2134. },
  2135.  
  2136. addEvents: function(events){
  2137. for (var type in events) this.addEvent(type, events[type]);
  2138. return this;
  2139. },
  2140.  
  2141. fireEvent: function(type, args, delay){
  2142. type = Events.removeOn(type);
  2143. if (!this.$events || !this.$events[type]) return this;
  2144. this.$events[type].each(function(fn){
  2145. fn.create({'bind': this, 'delay': delay, 'arguments': args})();
  2146. }, this);
  2147. return this;
  2148. },
  2149.  
  2150. removeEvent: function(type, fn){
  2151. type = Events.removeOn(type);
  2152. if (!this.$events[type]) return this;
  2153. if (!fn.internal) this.$events[type].erase(fn);
  2154. return this;
  2155. },
  2156.  
  2157. removeEvents: function(events){
  2158. if ($type(events) == 'object'){
  2159. for (var type in events) this.removeEvent(type, events[type]);
  2160. return this;
  2161. }
  2162. if (events) events = Events.removeOn(events);
  2163. for (var type in this.$events){
  2164. if (events && events != type) continue;
  2165. var fns = this.$events[type];
  2166. for (var i = fns.length; i--; i) this.removeEvent(type, fns[i]);
  2167. }
  2168. return this;
  2169. }
  2170.  
  2171. });
  2172.  
  2173. Events.removeOn = function(string){
  2174. return string.replace(/^on([A-Z])/, function(full, first) {
  2175. return first.toLowerCase();
  2176. });
  2177. };
  2178.  
  2179. var Options = new Class({
  2180.  
  2181. setOptions: function(){
  2182. this.options = $merge.run([this.options].extend(arguments));
  2183. if (!this.addEvent) return this;
  2184. for (var option in this.options){
  2185. if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
  2186. this.addEvent(option, this.options[option]);
  2187. delete this.options[option];
  2188. }
  2189. return this;
  2190. }
  2191.  
  2192. });
  2193.  
  2194. /*
  2195. Script: Request.js
  2196. Powerful all purpose Request Class. Uses XMLHTTPRequest.
  2197.  
  2198. License:
  2199. MIT-style license.
  2200. */
  2201.  
  2202. var Request = new Class({
  2203.  
  2204. Implements: [Chain, Events, Options],
  2205.  
  2206. options: {/*
  2207. onRequest: $empty,
  2208. onComplete: $empty,
  2209. onCancel: $empty,
  2210. onSuccess: $empty,
  2211. onFailure: $empty,
  2212. onException: $empty,*/
  2213. url: '',
  2214. data: '',
  2215. headers: {
  2216. 'X-Requested-With': 'XMLHttpRequest',
  2217. 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
  2218. },
  2219. async: true,
  2220. format: false,
  2221. method: 'post',
  2222. link: 'ignore',
  2223. isSuccess: null,
  2224. emulation: true,
  2225. urlEncoded: true,
  2226. encoding: 'utf-8',
  2227. evalScripts: false,
  2228. evalResponse: false
  2229. },
  2230.  
  2231. initialize: function(options){
  2232. this.xhr = new Browser.Request();
  2233. this.setOptions(options);
  2234. this.options.isSuccess = this.options.isSuccess || this.isSuccess;
  2235. this.headers = new Hash(this.options.headers);
  2236. },
  2237.  
  2238. onStateChange: function(){
  2239. if (this.xhr.readyState != 4 || !this.running) return;
  2240. this.running = false;
  2241. this.status = 0;
  2242. $try(function(){
  2243. this.status = this.xhr.status;
  2244. }.bind(this));
  2245. if (this.options.isSuccess.call(this, this.status)){
  2246. this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML};
  2247. this.success(this.response.text, this.response.xml);
  2248. } else {
  2249. this.response = {text: null, xml: null};
  2250. this.failure();
  2251. }
  2252. this.xhr.onreadystatechange = $empty;
  2253. },
  2254.  
  2255. isSuccess: function(){
  2256. return ((this.status >= 200) && (this.status < 300));
  2257. },
  2258.  
  2259. processScripts: function(text){
  2260. if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);
  2261. return text.stripScripts(this.options.evalScripts);
  2262. },
  2263.  
  2264. success: function(text, xml){
  2265. this.onSuccess(this.processScripts(text), xml);
  2266. },
  2267.  
  2268. onSuccess: function(){
  2269. this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
  2270. },
  2271.  
  2272. failure: function(){
  2273. this.onFailure();
  2274. },
  2275.  
  2276. onFailure: function(){
  2277. this.fireEvent('complete').fireEvent('failure', this.xhr);
  2278. },
  2279.  
  2280. setHeader: function(name, value){
  2281. this.headers.set(name, value);
  2282. return this;
  2283. },
  2284.  
  2285. getHeader: function(name){
  2286. return $try(function(){
  2287. return this.xhr.getResponseHeader(name);
  2288. }.bind(this));
  2289. },
  2290.  
  2291. check: function(caller){
  2292. if (!this.running) return true;
  2293. switch (this.options.link){
  2294. case 'cancel': this.cancel(); return true;
  2295. case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false;
  2296. }
  2297. return false;
  2298. },
  2299.  
  2300. send: function(options){
  2301. if (!this.check(arguments.callee, options)) return this;
  2302. this.running = true;
  2303.  
  2304. var type = $type(options);
  2305. if (type == 'string' || type == 'element') options = {data: options};
  2306.  
  2307. var old = this.options;
  2308. options = $extend({data: old.data, url: old.url, method: old.method}, options);
  2309. var data = options.data, url = options.url, method = options.method;
  2310.  
  2311. switch ($type(data)){
  2312. case 'element': data = $(data).toQueryString(); break;
  2313. case 'object': case 'hash': data = Hash.toQueryString(data);
  2314. }
  2315.  
  2316. if (this.options.format){
  2317. var format = 'format=' + this.options.format;
  2318. data = (data) ? format + '&' + data : format;
  2319. }
  2320.  
  2321. if (this.options.emulation && ['put', 'delete'].contains(method)){
  2322. var _method = '_method=' + method;
  2323. data = (data) ? _method + '&' + data : _method;
  2324. method = 'post';
  2325. }
  2326.  
  2327. if (this.options.urlEncoded && method == 'post'){
  2328. var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
  2329. this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding);
  2330. }
  2331.  
  2332. if (data && method == 'get'){
  2333. url = url + (url.contains('?') ? '&' : '?') + data;
  2334. data = null;
  2335. }
  2336.  
  2337. this.xhr.open(method.toUpperCase(), url, this.options.async);
  2338.  
  2339. this.xhr.onreadystatechange = this.onStateChange.bind(this);
  2340.  
  2341. this.headers.each(function(value, key){
  2342. try {
  2343. this.xhr.setRequestHeader(key, value);
  2344. } catch (e){
  2345. this.fireEvent('exception', [key, value]);
  2346. }
  2347. }, this);
  2348.  
  2349. this.fireEvent('request');
  2350. this.xhr.send(data);
  2351. if (!this.options.async) this.onStateChange();
  2352. return this;
  2353. },
  2354.  
  2355. cancel: function(){
  2356. if (!this.running) return this;
  2357. this.running = false;
  2358. this.xhr.abort();
  2359. this.xhr.onreadystatechange = $empty;
  2360. this.xhr = new Browser.Request();
  2361. this.fireEvent('cancel');
  2362. return this;
  2363. }
  2364.  
  2365. });
  2366.  
  2367. (function(){
  2368.  
  2369. var methods = {};
  2370. ['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
  2371. methods[method] = function(){
  2372. var params = Array.link(arguments, {url: String.type, data: $defined});
  2373. return this.send($extend(params, {method: method.toLowerCase()}));
  2374. };
  2375. });
  2376.  
  2377. Request.implement(methods);
  2378.  
  2379. })();
  2380.  
  2381. Element.Properties.send = {
  2382.  
  2383. set: function(options){
  2384. var send = this.retrieve('send');
  2385. if (send) send.cancel();
  2386. return this.eliminate('send').store('send:options', $extend({
  2387. data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
  2388. }, options));
  2389. },
  2390.  
  2391. get: function(options){
  2392. if (options || !this.retrieve('send')){
  2393. if (options || !this.retrieve('send:options')) this.set('send', options);
  2394. this.store('send', new Request(this.retrieve('send:options')));
  2395. }
  2396. return this.retrieve('send');
  2397. }
  2398.  
  2399. };
  2400.  
  2401. Element.implement({
  2402.  
  2403. send: function(url){
  2404. var sender = this.get('send');
  2405. sender.send({data: this, url: url || sender.options.url});
  2406. return this;
  2407. }
  2408.  
  2409. });
  2410.  
  2411. /*
  2412. Script: JSON.js
  2413. JSON encoder and decoder.
  2414.  
  2415. License:
  2416. MIT-style license.
  2417.  
  2418. See Also:
  2419. <http://www.json.org/>
  2420. */
  2421.  
  2422. var JSON = new Hash({
  2423.  
  2424. $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},
  2425.  
  2426. $replaceChars: function(chr){
  2427. return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
  2428. },
  2429.  
  2430. encode: function(obj){
  2431. switch ($type(obj)){
  2432. case 'string':
  2433. return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
  2434. case 'array':
  2435. return '[' + String(obj.map(JSON.encode).filter($defined)) + ']';
  2436. case 'object': case 'hash':
  2437. var string = [];
  2438. Hash.each(obj, function(value, key){
  2439. var json = JSON.encode(value);
  2440. if (json) string.push(JSON.encode(key) + ':' + json);
  2441. });
  2442. return '{' + string + '}';
  2443. case 'number': case 'boolean': return String(obj);
  2444. case false: return 'null';
  2445. }
  2446. return null;
  2447. },
  2448.  
  2449. decode: function(string, secure){
  2450. if ($type(string) != 'string' || !string.length) return null;
  2451. if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
  2452. return eval('(' + string + ')');
  2453. }
  2454.  
  2455. });
  2456.  
  2457. Native.implement([Hash, Array, String, Number], {
  2458.  
  2459. toJSON: function(){
  2460. return JSON.encode(this);
  2461. }
  2462.  
  2463. });
  2464.  
  2465. /*
  2466. Script: Request.JSON.js
  2467. Extends the basic Request Class with additional methods for sending and receiving JSON data.
  2468.  
  2469. License:
  2470. MIT-style license.
  2471. */
  2472.  
  2473. Request.JSON = new Class({
  2474.  
  2475. Extends: Request,
  2476.  
  2477. options: {
  2478. secure: true
  2479. },
  2480.  
  2481. initialize: function(options){
  2482. this.parent(options);
  2483. this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});
  2484. },
  2485.  
  2486. success: function(text){
  2487. this.response.json = JSON.decode(text, this.options.secure);
  2488. this.onSuccess(this.response.json, text);
  2489. }
  2490.  
  2491. });
  2492.  
  2493. /*
  2494. Script: Selectors.js
  2495. Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support.
  2496.  
  2497. License:
  2498. MIT-style license.
  2499. */
  2500.  
  2501. Native.implement([Document, Element], {
  2502.  
  2503. getElements: function(expression, nocash){
  2504. expression = expression.split(',');
  2505. var items, local = {};
  2506. for (var i = 0, l = expression.length; i < l; i++){
  2507. var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);
  2508. if (i != 0 && elements.item) elements = $A(elements);
  2509. items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);
  2510. }
  2511. return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});
  2512. }
  2513.  
  2514. });
  2515.  
  2516. Element.implement({
  2517.  
  2518. match: function(selector){
  2519. if (!selector || (selector == this)) return true;
  2520. var tagid = Selectors.Utils.parseTagAndID(selector);
  2521. var tag = tagid[0], id = tagid[1];
  2522. if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false;
  2523. var parsed = Selectors.Utils.parseSelector(selector);
  2524. return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true;
  2525. }
  2526.  
  2527. });
  2528.  
  2529. var Selectors = {Cache: {nth: {}, parsed: {}}};
  2530.  
  2531. Selectors.RegExps = {
  2532. id: (/#([\w-]+)/),
  2533. tag: (/^(\w+|\*)/),
  2534. quick: (/^(\w+|\*)$/),
  2535. splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),
  2536. combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)
  2537. };
  2538.  
  2539. Selectors.Utils = {
  2540.  
  2541. chk: function(item, uniques){
  2542. if (!uniques) return true;
  2543. var uid = $uid(item);
  2544. if (!uniques[uid]) return uniques[uid] = true;
  2545. return false;
  2546. },
  2547.  
  2548. parseNthArgument: function(argument){
  2549. if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument];
  2550. var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);
  2551. if (!parsed) return false;
  2552. var inta = parseInt(parsed[1], 10);
  2553. var a = (inta || inta === 0) ? inta : 1;
  2554. var special = parsed[2] || false;
  2555. var b = parseInt(parsed[3], 10) || 0;
  2556. if (a != 0){
  2557. b--;
  2558. while (b < 1) b += a;
  2559. while (b >= a) b -= a;
  2560. } else {
  2561. a = b;
  2562. special = 'index';
  2563. }
  2564. switch (special){
  2565. case 'n': parsed = {a: a, b: b, special: 'n'}; break;
  2566. case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break;
  2567. case 'even': parsed = {a: 2, b: 1, special: 'n'}; break;
  2568. case 'first': parsed = {a: 0, special: 'index'}; break;
  2569. case 'last': parsed = {special: 'last-child'}; break;
  2570. case 'only': parsed = {special: 'only-child'}; break;
  2571. default: parsed = {a: (a - 1), special: 'index'};
  2572. }
  2573.  
  2574. return Selectors.Cache.nth[argument] = parsed;
  2575. },
  2576.  
  2577. parseSelector: function(selector){
  2578. if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector];
  2579. var m, parsed = {classes: [], pseudos: [], attributes: []};
  2580. while ((m = Selectors.RegExps.combined.exec(selector))){
  2581. var cn = m[1], an = m[2], ao = m[3], av = m[5], pn = m[6], pa = m[7];
  2582. if (cn){
  2583. parsed.classes.push(cn);
  2584. } else if (pn){
  2585. var parser = Selectors.Pseudo.get(pn);
  2586. if (parser) parsed.pseudos.push({parser: parser, argument: pa});
  2587. else parsed.attributes.push({name: pn, operator: '=', value: pa});
  2588. } else if (an){
  2589. parsed.attributes.push({name: an, operator: ao, value: av});
  2590. }
  2591. }
  2592. if (!parsed.classes.length) delete parsed.classes;
  2593. if (!parsed.attributes.length) delete parsed.attributes;
  2594. if (!parsed.pseudos.length) delete parsed.pseudos;
  2595. if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null;
  2596. return Selectors.Cache.parsed[selector] = parsed;
  2597. },
  2598.  
  2599. parseTagAndID: function(selector){
  2600. var tag = selector.match(Selectors.RegExps.tag);
  2601. var id = selector.match(Selectors.RegExps.id);
  2602. return [(tag) ? tag[1] : '*', (id) ? id[1] : false];
  2603. },
  2604.  
  2605. filter: function(item, parsed, local){
  2606. var i;
  2607. if (parsed.classes){
  2608. for (i = parsed.classes.length; i--; i){
  2609. var cn = parsed.classes[i];
  2610. if (!Selectors.Filters.byClass(item, cn)) return false;
  2611. }
  2612. }
  2613. if (parsed.attributes){
  2614. for (i = parsed.attributes.length; i--; i){
  2615. var att = parsed.attributes[i];
  2616. if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;
  2617. }
  2618. }
  2619. if (parsed.pseudos){
  2620. for (i = parsed.pseudos.length; i--; i){
  2621. var psd = parsed.pseudos[i];
  2622. if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;
  2623. }
  2624. }
  2625. return true;
  2626. },
  2627.  
  2628. getByTagAndID: function(ctx, tag, id){
  2629. if (id){
  2630. var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true);
  2631. return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];
  2632. } else {
  2633. return ctx.getElementsByTagName(tag);
  2634. }
  2635. },
  2636.  
  2637. search: function(self, expression, local){
  2638. var splitters = [];
  2639.  
  2640. var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){
  2641. splitters.push(m1);
  2642. return ':)' + m2;
  2643. }).split(':)');
  2644.  
  2645. var items, filtered, item;
  2646.  
  2647. for (var i = 0, l = selectors.length; i < l; i++){
  2648.  
  2649. var selector = selectors[i];
  2650.  
  2651. if (i == 0 && Selectors.RegExps.quick.test(selector)){
  2652. items = self.getElementsByTagName(selector);
  2653. continue;
  2654. }
  2655.  
  2656. var splitter = splitters[i - 1];
  2657.  
  2658. var tagid = Selectors.Utils.parseTagAndID(selector);
  2659. var tag = tagid[0], id = tagid[1];
  2660.  
  2661. if (i == 0){
  2662. items = Selectors.Utils.getByTagAndID(self, tag, id);
  2663. } else {
  2664. var uniques = {}, found = [];
  2665. for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques);
  2666. items = found;
  2667. }
  2668.  
  2669. var parsed = Selectors.Utils.parseSelector(selector);
  2670.  
  2671. if (parsed){
  2672. filtered = [];
  2673. for (var m = 0, n = items.length; m < n; m++){
  2674. item = items[m];
  2675. if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);
  2676. }
  2677. items = filtered;
  2678. }
  2679.  
  2680. }
  2681.  
  2682. return items;
  2683.  
  2684. }
  2685.  
  2686. };
  2687.  
  2688. Selectors.Getters = {
  2689.  
  2690. ' ': function(found, self, tag, id, uniques){
  2691. var items = Selectors.Utils.getByTagAndID(self, tag, id);
  2692. for (var i = 0, l = items.length; i < l; i++){
  2693. var item = items[i];
  2694. if (Selectors.Utils.chk(item, uniques)) found.push(item);
  2695. }
  2696. return found;
  2697. },
  2698.  
  2699. '>': function(found, self, tag, id, uniques){
  2700. var children = Selectors.Utils.getByTagAndID(self, tag, id);
  2701. for (var i = 0, l = children.length; i < l; i++){
  2702. var child = children[i];
  2703. if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
  2704. }
  2705. return found;
  2706. },
  2707.  
  2708. '+': function(found, self, tag, id, uniques){
  2709. while ((self = self.nextSibling)){
  2710. if (self.nodeType == 1){
  2711. if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
  2712. break;
  2713. }
  2714. }
  2715. return found;
  2716. },
  2717.  
  2718. '~': function(found, self, tag, id, uniques){
  2719. while ((self = self.nextSibling)){
  2720. if (self.nodeType == 1){
  2721. if (!Selectors.Utils.chk(self, uniques)) break;
  2722. if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
  2723. }
  2724. }
  2725. return found;
  2726. }
  2727.  
  2728. };
  2729.  
  2730. Selectors.Filters = {
  2731.  
  2732. byTag: function(self, tag){
  2733. return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));
  2734. },
  2735.  
  2736. byID: function(self, id){
  2737. return (!id || (self.id && self.id == id));
  2738. },
  2739.  
  2740. byClass: function(self, klass){
  2741. return (self.className && self.className.contains(klass, ' '));
  2742. },
  2743.  
  2744. byPseudo: function(self, parser, argument, local){
  2745. return parser.call(self, argument, local);
  2746. },
  2747.  
  2748. byAttribute: function(self, name, operator, value){
  2749. var result = Element.prototype.getProperty.call(self, name);
  2750. if (!result) return (operator == '!=');
  2751. if (!operator || value == undefined) return true;
  2752. switch (operator){
  2753. case '=': return (result == value);
  2754. case '*=': return (result.contains(value));
  2755. case '^=': return (result.substr(0, value.length) == value);
  2756. case '$=': return (result.substr(result.length - value.length) == value);
  2757. case '!=': return (result != value);
  2758. case '~=': return result.contains(value, ' ');
  2759. case '|=': return result.contains(value, '-');
  2760. }
  2761. return false;
  2762. }
  2763.  
  2764. };
  2765.  
  2766. Selectors.Pseudo = new Hash({
  2767.  
  2768. // w3c pseudo selectors
  2769.  
  2770. checked: function(){
  2771. return this.checked;
  2772. },
  2773.  
  2774. empty: function(){
  2775. return !(this.innerText || this.textContent || '').length;
  2776. },
  2777.  
  2778. not: function(selector){
  2779. return !Element.match(this, selector);
  2780. },
  2781.  
  2782. contains: function(text){
  2783. return (this.innerText || this.textContent || '').contains(text);
  2784. },
  2785.  
  2786. 'first-child': function(){
  2787. return Selectors.Pseudo.index.call(this, 0);
  2788. },
  2789.  
  2790. 'last-child': function(){
  2791. var element = this;
  2792. while ((element = element.nextSibling)){
  2793. if (element.nodeType == 1) return false;
  2794. }
  2795. return true;
  2796. },
  2797.  
  2798. 'only-child': function(){
  2799. var prev = this;
  2800. while ((prev = prev.previousSibling)){
  2801. if (prev.nodeType == 1) return false;
  2802. }
  2803. var next = this;
  2804. while ((next = next.nextSibling)){
  2805. if (next.nodeType == 1) return false;
  2806. }
  2807. return true;
  2808. },
  2809.  
  2810. 'nth-child': function(argument, local){
  2811. argument = (argument == undefined) ? 'n' : argument;
  2812. var parsed = Selectors.Utils.parseNthArgument(argument);
  2813. if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
  2814. var count = 0;
  2815. local.positions = local.positions || {};
  2816. var uid = $uid(this);
  2817. if (!local.positions[uid]){
  2818. var self = this;
  2819. while ((self = self.previousSibling)){
  2820. if (self.nodeType != 1) continue;
  2821. count ++;
  2822. var position = local.positions[$uid(self)];
  2823. if (position != undefined){
  2824. count = position + count;
  2825. break;
  2826. }
  2827. }
  2828. local.positions[uid] = count;
  2829. }
  2830. return (local.positions[uid] % parsed.a == parsed.b);
  2831. },
  2832.  
  2833. // custom pseudo selectors
  2834.  
  2835. index: function(index){
  2836. var element = this, count = 0;
  2837. while ((element = element.previousSibling)){
  2838. if (element.nodeType == 1 && ++count > index) return false;
  2839. }
  2840. return (count == index);
  2841. },
  2842.  
  2843. even: function(argument, local){
  2844. return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);
  2845. },
  2846.  
  2847. odd: function(argument, local){
  2848. return Selectors.Pseudo['nth-child'].call(this, '2n', local);
  2849. }
  2850.  
  2851. });
  2852.  
  2853. /*
  2854. Script: Event.js
  2855. Contains the Event Native, to make the event object completely crossbrowser.
  2856.  
  2857. License:
  2858. MIT-style license.
  2859. */
  2860.  
  2861. var Event = new Native({
  2862.  
  2863. name: 'Event',
  2864.  
  2865. initialize: function(event, win){
  2866. win = win || window;
  2867. var doc = win.document;
  2868. event = event || win.event;
  2869. if (event.$extended) return event;
  2870. this.$extended = true;
  2871. var type = event.type;
  2872. var target = event.target || event.srcElement;
  2873. while (target && target.nodeType == 3) target = target.parentNode;
  2874.  
  2875. if (type.test(/key/)){
  2876. var code = event.which || event.keyCode;
  2877. var key = Event.Keys.keyOf(code);
  2878. if (type == 'keydown'){
  2879. var fKey = code - 111;
  2880. if (fKey > 0 && fKey < 13) key = 'f' + fKey;
  2881. }
  2882. key = key || String.fromCharCode(code).toLowerCase();
  2883. } else if (type.match(/(click|mouse|menu)/i)){
  2884. doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
  2885. var page = {
  2886. x: event.pageX || event.clientX + doc.scrollLeft,
  2887. y: event.pageY || event.clientY + doc.scrollTop
  2888. };
  2889. var client = {
  2890. x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,
  2891. y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY
  2892. };
  2893. if (type.match(/DOMMouseScroll|mousewheel/)){
  2894. var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
  2895. }
  2896. var rightClick = (event.which == 3) || (event.button == 2);
  2897. var related = null;
  2898. if (type.match(/over|out/)){
  2899. switch (type){
  2900. case 'mouseover': related = event.relatedTarget || event.fromElement; break;
  2901. case 'mouseout': related = event.relatedTarget || event.toElement;
  2902. }
  2903. if (!(function(){
  2904. while (related && related.nodeType == 3) related = related.parentNode;
  2905. return true;
  2906. }).create({attempt: Browser.Engine.gecko})()) related = false;
  2907. }
  2908. }
  2909.  
  2910. return $extend(this, {
  2911. event: event,
  2912. type: type,
  2913.  
  2914. page: page,
  2915. client: client,
  2916. rightClick: rightClick,
  2917.  
  2918. wheel: wheel,
  2919.  
  2920. relatedTarget: related,
  2921. target: target,
  2922.  
  2923. code: code,
  2924. key: key,
  2925.  
  2926. shift: event.shiftKey,
  2927. control: event.ctrlKey,
  2928. alt: event.altKey,
  2929. meta: event.metaKey
  2930. });
  2931. }
  2932.  
  2933. });
  2934.  
  2935. Event.Keys = new Hash({
  2936. 'enter': 13,
  2937. 'up': 38,
  2938. 'down': 40,
  2939. 'left': 37,
  2940. 'right': 39,
  2941. 'esc': 27,
  2942. 'space': 32,
  2943. 'backspace': 8,
  2944. 'tab': 9,
  2945. 'delete': 46
  2946. });
  2947.  
  2948. Event.implement({
  2949.  
  2950. stop: function(){
  2951. return this.stopPropagation().preventDefault();
  2952. },
  2953.  
  2954. stopPropagation: function(){
  2955. if (this.event.stopPropagation) this.event.stopPropagation();
  2956. else this.event.cancelBubble = true;
  2957. return this;
  2958. },
  2959.  
  2960. preventDefault: function(){
  2961. if (this.event.preventDefault) this.event.preventDefault();
  2962. else this.event.returnValue = false;
  2963. return this;
  2964. }
  2965.  
  2966. });
  2967.  
  2968. /*
  2969. Script: Element.Event.js
  2970. Contains Element methods for dealing with events, and custom Events.
  2971.  
  2972. License:
  2973. MIT-style license.
  2974. */
  2975.  
  2976. Element.Properties.events = {set: function(events){
  2977. this.addEvents(events);
  2978. }};
  2979.  
  2980. Native.implement([Element, Window, Document], {
  2981.  
  2982. addEvent: function(type, fn){
  2983. var events = this.retrieve('events', {});
  2984. events[type] = events[type] || {'keys': [], 'values': []};
  2985. if (events[type].keys.contains(fn)) return this;
  2986. events[type].keys.push(fn);
  2987. var realType = type, custom = Element.Events.get(type), condition = fn, self = this;
  2988. if (custom){
  2989. if (custom.onAdd) custom.onAdd.call(this, fn);
  2990. if (custom.condition){
  2991. condition = function(event){
  2992. if (custom.condition.call(this, event)) return fn.call(this, event);
  2993. return true;
  2994. };
  2995. }
  2996. realType = custom.base || realType;
  2997. }
  2998. var defn = function(){
  2999. return fn.call(self);
  3000. };
  3001. var nativeEvent = Element.NativeEvents[realType];
  3002. if (nativeEvent){
  3003. if (nativeEvent == 2){
  3004. defn = function(event){
  3005. event = new Event(event, self.getWindow());
  3006. if (condition.call(self, event) === false) event.stop();
  3007. };
  3008. }
  3009. this.addListener(realType, defn);
  3010. }
  3011. events[type].values.push(defn);
  3012. return this;
  3013. },
  3014.  
  3015. removeEvent: function(type, fn){
  3016. var events = this.retrieve('events');
  3017. if (!events || !events[type]) return this;
  3018. var pos = events[type].keys.indexOf(fn);
  3019. if (pos == -1) return this;
  3020. events[type].keys.splice(pos, 1);
  3021. var value = events[type].values.splice(pos, 1)[0];
  3022. var custom = Element.Events.get(type);
  3023. if (custom){
  3024. if (custom.onRemove) custom.onRemove.call(this, fn);
  3025. type = custom.base || type;
  3026. }
  3027. return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;
  3028. },
  3029.  
  3030. addEvents: function(events){
  3031. for (var event in events) this.addEvent(event, events[event]);
  3032. return this;
  3033. },
  3034.  
  3035. removeEvents: function(events){
  3036. if ($type(events) == 'object'){
  3037. for (var type in events) this.removeEvent(type, events[type]);
  3038. return this;
  3039. }
  3040. var attached = this.retrieve('events');
  3041. if (!attached) return this;
  3042. if (!events){
  3043. for (var type in attached) this.removeEvents(type);
  3044. this.eliminate('events');
  3045. } else if (attached[events]){
  3046. while (attached[events].keys[0]) this.removeEvent(events, attached[events].keys[0]);
  3047. attached[events] = null;
  3048. }
  3049. return this;
  3050. },
  3051.  
  3052. fireEvent: function(type, args, delay){
  3053. var events = this.retrieve('events');
  3054. if (!events || !events[type]) return this;
  3055. events[type].keys.each(function(fn){
  3056. fn.create({'bind': this, 'delay': delay, 'arguments': args})();
  3057. }, this);
  3058. return this;
  3059. },
  3060.  
  3061. cloneEvents: function(from, type){
  3062. from = $(from);
  3063. var fevents = from.retrieve('events');
  3064. if (!fevents) return this;
  3065. if (!type){
  3066. for (var evType in fevents) this.cloneEvents(from, evType);
  3067. } else if (fevents[type]){
  3068. fevents[type].keys.each(function(fn){
  3069. this.addEvent(type, fn);
  3070. }, this);
  3071. }
  3072. return this;
  3073. }
  3074.  
  3075. });
  3076.  
  3077. Element.NativeEvents = {
  3078. click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
  3079. mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
  3080. mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
  3081. keydown: 2, keypress: 2, keyup: 2, //keyboard
  3082. focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
  3083. load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
  3084. error: 1, abort: 1, scroll: 1 //misc
  3085. };
  3086.  
  3087. (function(){
  3088.  
  3089. var $check = function(event){
  3090. var related = event.relatedTarget;
  3091. if (related == undefined) return true;
  3092. if (related === false) return false;
  3093. return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related));
  3094. };
  3095.  
  3096. Element.Events = new Hash({
  3097.  
  3098. mouseenter: {
  3099. base: 'mouseover',
  3100. condition: $check
  3101. },
  3102.  
  3103. mouseleave: {
  3104. base: 'mouseout',
  3105. condition: $check
  3106. },
  3107.  
  3108. mousewheel: {
  3109. base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'
  3110. }
  3111.  
  3112. });
  3113.  
  3114. })();