PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/javascript/frameworks/mootools/mootools-1.3.1.js

https://github.com/quarkness/piwik
JavaScript | 2026 lines | 1372 code | 399 blank | 255 comment | 466 complexity | e0829f1f6183d88ae786bdee76db4661 MD5 | raw file
  1. /*
  2. ---
  3. MooTools: the javascript framework
  4. web build:
  5. - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7
  6. packager build:
  7. - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
  8. /*
  9. ---
  10. name: Core
  11. description: The heart of MooTools.
  12. license: MIT-style license.
  13. copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/).
  14. authors: The MooTools production team (http://mootools.net/developers/)
  15. inspiration:
  16. - 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)
  17. - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
  18. provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
  19. ...
  20. */
  21. (function(){
  22. this.MooTools = {
  23. version: '1.3.1',
  24. build: 'af48c8d589f43f32212f9bb8ff68a127e6a3ba6c'
  25. };
  26. // typeOf, instanceOf
  27. var typeOf = this.typeOf = function(item){
  28. if (item == null) return 'null';
  29. if (item.$family) return item.$family();
  30. if (item.nodeName){
  31. if (item.nodeType == 1) return 'element';
  32. if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
  33. } else if (typeof item.length == 'number'){
  34. if (item.callee) return 'arguments';
  35. if ('item' in item) return 'collection';
  36. }
  37. return typeof item;
  38. };
  39. var instanceOf = this.instanceOf = function(item, object){
  40. if (item == null) return false;
  41. var constructor = item.$constructor || item.constructor;
  42. while (constructor){
  43. if (constructor === object) return true;
  44. constructor = constructor.parent;
  45. }
  46. return item instanceof object;
  47. };
  48. // Function overloading
  49. var Function = this.Function;
  50. var enumerables = true;
  51. for (var i in {toString: 1}) enumerables = null;
  52. if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
  53. Function.prototype.overloadSetter = function(usePlural){
  54. var self = this;
  55. return function(a, b){
  56. if (a == null) return this;
  57. if (usePlural || typeof a != 'string'){
  58. for (var k in a) self.call(this, k, a[k]);
  59. if (enumerables) for (var i = enumerables.length; i--;){
  60. k = enumerables[i];
  61. if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
  62. }
  63. } else {
  64. self.call(this, a, b);
  65. }
  66. return this;
  67. };
  68. };
  69. Function.prototype.overloadGetter = function(usePlural){
  70. var self = this;
  71. return function(a){
  72. var args, result;
  73. if (usePlural || typeof a != 'string') args = a;
  74. else if (arguments.length > 1) args = arguments;
  75. if (args){
  76. result = {};
  77. for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
  78. } else {
  79. result = self.call(this, a);
  80. }
  81. return result;
  82. };
  83. };
  84. Function.prototype.extend = function(key, value){
  85. this[key] = value;
  86. }.overloadSetter();
  87. Function.prototype.implement = function(key, value){
  88. this.prototype[key] = value;
  89. }.overloadSetter();
  90. // From
  91. var slice = Array.prototype.slice;
  92. Function.from = function(item){
  93. return (typeOf(item) == 'function') ? item : function(){
  94. return item;
  95. };
  96. };
  97. Array.from = function(item){
  98. if (item == null) return [];
  99. return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
  100. };
  101. Number.from = function(item){
  102. var number = parseFloat(item);
  103. return isFinite(number) ? number : null;
  104. };
  105. String.from = function(item){
  106. return item + '';
  107. };
  108. // hide, protect
  109. Function.implement({
  110. hide: function(){
  111. this.$hidden = true;
  112. return this;
  113. },
  114. protect: function(){
  115. this.$protected = true;
  116. return this;
  117. }
  118. });
  119. // Type
  120. var Type = this.Type = function(name, object){
  121. if (name){
  122. var lower = name.toLowerCase();
  123. var typeCheck = function(item){
  124. return (typeOf(item) == lower);
  125. };
  126. Type['is' + name] = typeCheck;
  127. if (object != null){
  128. object.prototype.$family = (function(){
  129. return lower;
  130. }).hide();
  131. }
  132. }
  133. if (object == null) return null;
  134. object.extend(this);
  135. object.$constructor = Type;
  136. object.prototype.$constructor = object;
  137. return object;
  138. };
  139. var toString = Object.prototype.toString;
  140. Type.isEnumerable = function(item){
  141. return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
  142. };
  143. var hooks = {};
  144. var hooksOf = function(object){
  145. var type = typeOf(object.prototype);
  146. return hooks[type] || (hooks[type] = []);
  147. };
  148. var implement = function(name, method){
  149. if (method && method.$hidden) return;
  150. var hooks = hooksOf(this);
  151. for (var i = 0; i < hooks.length; i++){
  152. var hook = hooks[i];
  153. if (typeOf(hook) == 'type') implement.call(hook, name, method);
  154. else hook.call(this, name, method);
  155. }
  156. var previous = this.prototype[name];
  157. if (previous == null || !previous.$protected) this.prototype[name] = method;
  158. if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
  159. return method.apply(item, slice.call(arguments, 1));
  160. });
  161. };
  162. var extend = function(name, method){
  163. if (method && method.$hidden) return;
  164. var previous = this[name];
  165. if (previous == null || !previous.$protected) this[name] = method;
  166. };
  167. Type.implement({
  168. implement: implement.overloadSetter(),
  169. extend: extend.overloadSetter(),
  170. alias: function(name, existing){
  171. implement.call(this, name, this.prototype[existing]);
  172. }.overloadSetter(),
  173. mirror: function(hook){
  174. hooksOf(this).push(hook);
  175. return this;
  176. }
  177. });
  178. new Type('Type', Type);
  179. // Default Types
  180. var force = function(name, object, methods){
  181. var isType = (object != Object),
  182. prototype = object.prototype;
  183. if (isType) object = new Type(name, object);
  184. for (var i = 0, l = methods.length; i < l; i++){
  185. var key = methods[i],
  186. generic = object[key],
  187. proto = prototype[key];
  188. if (generic) generic.protect();
  189. if (isType && proto){
  190. delete prototype[key];
  191. prototype[key] = proto.protect();
  192. }
  193. }
  194. if (isType) object.implement(prototype);
  195. return force;
  196. };
  197. force('String', String, [
  198. 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
  199. 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase'
  200. ])('Array', Array, [
  201. 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
  202. 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
  203. ])('Number', Number, [
  204. 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
  205. ])('Function', Function, [
  206. 'apply', 'call', 'bind'
  207. ])('RegExp', RegExp, [
  208. 'exec', 'test'
  209. ])('Object', Object, [
  210. 'create', 'defineProperty', 'defineProperties', 'keys',
  211. 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
  212. 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
  213. ])('Date', Date, ['now']);
  214. Object.extend = extend.overloadSetter();
  215. Date.extend('now', function(){
  216. return +(new Date);
  217. });
  218. new Type('Boolean', Boolean);
  219. // fixes NaN returning as Number
  220. Number.prototype.$family = function(){
  221. return isFinite(this) ? 'number' : 'null';
  222. }.hide();
  223. // Number.random
  224. Number.extend('random', function(min, max){
  225. return Math.floor(Math.random() * (max - min + 1) + min);
  226. });
  227. // forEach, each
  228. var hasOwnProperty = Object.prototype.hasOwnProperty;
  229. Object.extend('forEach', function(object, fn, bind){
  230. for (var key in object){
  231. if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
  232. }
  233. });
  234. Object.each = Object.forEach;
  235. Array.implement({
  236. forEach: function(fn, bind){
  237. for (var i = 0, l = this.length; i < l; i++){
  238. if (i in this) fn.call(bind, this[i], i, this);
  239. }
  240. },
  241. each: function(fn, bind){
  242. Array.forEach(this, fn, bind);
  243. return this;
  244. }
  245. });
  246. // Array & Object cloning, Object merging and appending
  247. var cloneOf = function(item){
  248. switch (typeOf(item)){
  249. case 'array': return item.clone();
  250. case 'object': return Object.clone(item);
  251. default: return item;
  252. }
  253. };
  254. Array.implement('clone', function(){
  255. var i = this.length, clone = new Array(i);
  256. while (i--) clone[i] = cloneOf(this[i]);
  257. return clone;
  258. });
  259. var mergeOne = function(source, key, current){
  260. switch (typeOf(current)){
  261. case 'object':
  262. if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
  263. else source[key] = Object.clone(current);
  264. break;
  265. case 'array': source[key] = current.clone(); break;
  266. default: source[key] = current;
  267. }
  268. return source;
  269. };
  270. Object.extend({
  271. merge: function(source, k, v){
  272. if (typeOf(k) == 'string') return mergeOne(source, k, v);
  273. for (var i = 1, l = arguments.length; i < l; i++){
  274. var object = arguments[i];
  275. for (var key in object) mergeOne(source, key, object[key]);
  276. }
  277. return source;
  278. },
  279. clone: function(object){
  280. var clone = {};
  281. for (var key in object) clone[key] = cloneOf(object[key]);
  282. return clone;
  283. },
  284. append: function(original){
  285. for (var i = 1, l = arguments.length; i < l; i++){
  286. var extended = arguments[i] || {};
  287. for (var key in extended) original[key] = extended[key];
  288. }
  289. return original;
  290. }
  291. });
  292. // Object-less types
  293. ['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
  294. new Type(name);
  295. });
  296. // Unique ID
  297. var UID = Date.now();
  298. String.extend('uniqueID', function(){
  299. return (UID++).toString(36);
  300. });
  301. }).call(this);
  302. /*
  303. ---
  304. name: Array
  305. description: Contains Array Prototypes like each, contains, and erase.
  306. license: MIT-style license.
  307. requires: Type
  308. provides: Array
  309. ...
  310. */
  311. Array.implement({
  312. invoke: function(methodName){
  313. var args = Array.slice(arguments, 1);
  314. return this.map(function(item){
  315. return item[methodName].apply(item, args);
  316. });
  317. },
  318. every: function(fn, bind){
  319. for (var i = 0, l = this.length; i < l; i++){
  320. if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
  321. }
  322. return true;
  323. },
  324. filter: function(fn, bind){
  325. var results = [];
  326. for (var i = 0, l = this.length; i < l; i++){
  327. if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]);
  328. }
  329. return results;
  330. },
  331. clean: function(){
  332. return this.filter(function(item){
  333. return item != null;
  334. });
  335. },
  336. indexOf: function(item, from){
  337. var len = this.length;
  338. for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
  339. if (this[i] === item) return i;
  340. }
  341. return -1;
  342. },
  343. map: function(fn, bind){
  344. var results = [];
  345. for (var i = 0, l = this.length; i < l; i++){
  346. if (i in this) results[i] = fn.call(bind, this[i], i, this);
  347. }
  348. return results;
  349. },
  350. some: function(fn, bind){
  351. for (var i = 0, l = this.length; i < l; i++){
  352. if ((i in this) && fn.call(bind, this[i], i, this)) return true;
  353. }
  354. return false;
  355. },
  356. associate: function(keys){
  357. var obj = {}, length = Math.min(this.length, keys.length);
  358. for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
  359. return obj;
  360. },
  361. link: function(object){
  362. var result = {};
  363. for (var i = 0, l = this.length; i < l; i++){
  364. for (var key in object){
  365. if (object[key](this[i])){
  366. result[key] = this[i];
  367. delete object[key];
  368. break;
  369. }
  370. }
  371. }
  372. return result;
  373. },
  374. contains: function(item, from){
  375. return this.indexOf(item, from) != -1;
  376. },
  377. append: function(array){
  378. this.push.apply(this, array);
  379. return this;
  380. },
  381. getLast: function(){
  382. return (this.length) ? this[this.length - 1] : null;
  383. },
  384. getRandom: function(){
  385. return (this.length) ? this[Number.random(0, this.length - 1)] : null;
  386. },
  387. include: function(item){
  388. if (!this.contains(item)) this.push(item);
  389. return this;
  390. },
  391. combine: function(array){
  392. for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
  393. return this;
  394. },
  395. erase: function(item){
  396. for (var i = this.length; i--;){
  397. if (this[i] === item) this.splice(i, 1);
  398. }
  399. return this;
  400. },
  401. empty: function(){
  402. this.length = 0;
  403. return this;
  404. },
  405. flatten: function(){
  406. var array = [];
  407. for (var i = 0, l = this.length; i < l; i++){
  408. var type = typeOf(this[i]);
  409. if (type == 'null') continue;
  410. array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
  411. }
  412. return array;
  413. },
  414. pick: function(){
  415. for (var i = 0, l = this.length; i < l; i++){
  416. if (this[i] != null) return this[i];
  417. }
  418. return null;
  419. },
  420. hexToRgb: function(array){
  421. if (this.length != 3) return null;
  422. var rgb = this.map(function(value){
  423. if (value.length == 1) value += value;
  424. return value.toInt(16);
  425. });
  426. return (array) ? rgb : 'rgb(' + rgb + ')';
  427. },
  428. rgbToHex: function(array){
  429. if (this.length < 3) return null;
  430. if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
  431. var hex = [];
  432. for (var i = 0; i < 3; i++){
  433. var bit = (this[i] - 0).toString(16);
  434. hex.push((bit.length == 1) ? '0' + bit : bit);
  435. }
  436. return (array) ? hex : '#' + hex.join('');
  437. }
  438. });
  439. /*
  440. ---
  441. name: String
  442. description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
  443. license: MIT-style license.
  444. requires: Type
  445. provides: String
  446. ...
  447. */
  448. String.implement({
  449. test: function(regex, params){
  450. return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
  451. },
  452. contains: function(string, separator){
  453. return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
  454. },
  455. trim: function(){
  456. return this.replace(/^\s+|\s+$/g, '');
  457. },
  458. clean: function(){
  459. return this.replace(/\s+/g, ' ').trim();
  460. },
  461. camelCase: function(){
  462. return this.replace(/-\D/g, function(match){
  463. return match.charAt(1).toUpperCase();
  464. });
  465. },
  466. hyphenate: function(){
  467. return this.replace(/[A-Z]/g, function(match){
  468. return ('-' + match.charAt(0).toLowerCase());
  469. });
  470. },
  471. capitalize: function(){
  472. return this.replace(/\b[a-z]/g, function(match){
  473. return match.toUpperCase();
  474. });
  475. },
  476. escapeRegExp: function(){
  477. return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
  478. },
  479. toInt: function(base){
  480. return parseInt(this, base || 10);
  481. },
  482. toFloat: function(){
  483. return parseFloat(this);
  484. },
  485. hexToRgb: function(array){
  486. var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
  487. return (hex) ? hex.slice(1).hexToRgb(array) : null;
  488. },
  489. rgbToHex: function(array){
  490. var rgb = this.match(/\d{1,3}/g);
  491. return (rgb) ? rgb.rgbToHex(array) : null;
  492. },
  493. substitute: function(object, regexp){
  494. return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
  495. if (match.charAt(0) == '\\') return match.slice(1);
  496. return (object[name] != null) ? object[name] : '';
  497. });
  498. }
  499. });
  500. /*
  501. ---
  502. name: Number
  503. description: Contains Number Prototypes like limit, round, times, and ceil.
  504. license: MIT-style license.
  505. requires: Type
  506. provides: Number
  507. ...
  508. */
  509. Number.implement({
  510. limit: function(min, max){
  511. return Math.min(max, Math.max(min, this));
  512. },
  513. round: function(precision){
  514. precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
  515. return Math.round(this * precision) / precision;
  516. },
  517. times: function(fn, bind){
  518. for (var i = 0; i < this; i++) fn.call(bind, i, this);
  519. },
  520. toFloat: function(){
  521. return parseFloat(this);
  522. },
  523. toInt: function(base){
  524. return parseInt(this, base || 10);
  525. }
  526. });
  527. Number.alias('each', 'times');
  528. (function(math){
  529. var methods = {};
  530. math.each(function(name){
  531. if (!Number[name]) methods[name] = function(){
  532. return Math[name].apply(null, [this].concat(Array.from(arguments)));
  533. };
  534. });
  535. Number.implement(methods);
  536. })(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
  537. /*
  538. ---
  539. name: Function
  540. description: Contains Function Prototypes like create, bind, pass, and delay.
  541. license: MIT-style license.
  542. requires: Type
  543. provides: Function
  544. ...
  545. */
  546. Function.extend({
  547. attempt: function(){
  548. for (var i = 0, l = arguments.length; i < l; i++){
  549. try {
  550. return arguments[i]();
  551. } catch (e){}
  552. }
  553. return null;
  554. }
  555. });
  556. Function.implement({
  557. attempt: function(args, bind){
  558. try {
  559. return this.apply(bind, Array.from(args));
  560. } catch (e){}
  561. return null;
  562. },
  563. bind: function(bind){
  564. var self = this,
  565. args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
  566. return function(){
  567. if (!args && !arguments.length) return self.call(bind);
  568. if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments)));
  569. return self.apply(bind, args || arguments);
  570. };
  571. },
  572. pass: function(args, bind){
  573. var self = this;
  574. if (args != null) args = Array.from(args);
  575. return function(){
  576. return self.apply(bind, args || arguments);
  577. };
  578. },
  579. delay: function(delay, bind, args){
  580. return setTimeout(this.pass((args == null ? [] : args), bind), delay);
  581. },
  582. periodical: function(periodical, bind, args){
  583. return setInterval(this.pass((args == null ? [] : args), bind), periodical);
  584. }
  585. });
  586. /*
  587. ---
  588. name: Object
  589. description: Object generic methods
  590. license: MIT-style license.
  591. requires: Type
  592. provides: [Object, Hash]
  593. ...
  594. */
  595. (function(){
  596. var hasOwnProperty = Object.prototype.hasOwnProperty;
  597. Object.extend({
  598. subset: function(object, keys){
  599. var results = {};
  600. for (var i = 0, l = keys.length; i < l; i++){
  601. var k = keys[i];
  602. results[k] = object[k];
  603. }
  604. return results;
  605. },
  606. map: function(object, fn, bind){
  607. var results = {};
  608. for (var key in object){
  609. if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
  610. }
  611. return results;
  612. },
  613. filter: function(object, fn, bind){
  614. var results = {};
  615. Object.each(object, function(value, key){
  616. if (fn.call(bind, value, key, object)) results[key] = value;
  617. });
  618. return results;
  619. },
  620. every: function(object, fn, bind){
  621. for (var key in object){
  622. if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
  623. }
  624. return true;
  625. },
  626. some: function(object, fn, bind){
  627. for (var key in object){
  628. if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
  629. }
  630. return false;
  631. },
  632. keys: function(object){
  633. var keys = [];
  634. for (var key in object){
  635. if (hasOwnProperty.call(object, key)) keys.push(key);
  636. }
  637. return keys;
  638. },
  639. values: function(object){
  640. var values = [];
  641. for (var key in object){
  642. if (hasOwnProperty.call(object, key)) values.push(object[key]);
  643. }
  644. return values;
  645. },
  646. getLength: function(object){
  647. return Object.keys(object).length;
  648. },
  649. keyOf: function(object, value){
  650. for (var key in object){
  651. if (hasOwnProperty.call(object, key) && object[key] === value) return key;
  652. }
  653. return null;
  654. },
  655. contains: function(object, value){
  656. return Object.keyOf(object, value) != null;
  657. },
  658. toQueryString: function(object, base){
  659. var queryString = [];
  660. Object.each(object, function(value, key){
  661. if (base) key = base + '[' + key + ']';
  662. var result;
  663. switch (typeOf(value)){
  664. case 'object': result = Object.toQueryString(value, key); break;
  665. case 'array':
  666. var qs = {};
  667. value.each(function(val, i){
  668. qs[i] = val;
  669. });
  670. result = Object.toQueryString(qs, key);
  671. break;
  672. default: result = key + '=' + encodeURIComponent(value);
  673. }
  674. if (value != null) queryString.push(result);
  675. });
  676. return queryString.join('&');
  677. }
  678. });
  679. })();
  680. /*
  681. ---
  682. name: Browser
  683. description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
  684. license: MIT-style license.
  685. requires: [Array, Function, Number, String]
  686. provides: [Browser, Window, Document]
  687. ...
  688. */
  689. (function(){
  690. var document = this.document;
  691. var window = document.window = this;
  692. var UID = 1;
  693. this.$uid = (window.ActiveXObject) ? function(item){
  694. return (item.uid || (item.uid = [UID++]))[0];
  695. } : function(item){
  696. return item.uid || (item.uid = UID++);
  697. };
  698. $uid(window);
  699. $uid(document);
  700. var ua = navigator.userAgent.toLowerCase(),
  701. platform = navigator.platform.toLowerCase(),
  702. UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
  703. mode = UA[1] == 'ie' && document.documentMode;
  704. var Browser = this.Browser = {
  705. extend: Function.prototype.extend,
  706. name: (UA[1] == 'version') ? UA[3] : UA[1],
  707. version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
  708. Platform: {
  709. name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
  710. },
  711. Features: {
  712. xpath: !!(document.evaluate),
  713. air: !!(window.runtime),
  714. query: !!(document.querySelector),
  715. json: !!(window.JSON)
  716. },
  717. Plugins: {}
  718. };
  719. Browser[Browser.name] = true;
  720. Browser[Browser.name + parseInt(Browser.version, 10)] = true;
  721. Browser.Platform[Browser.Platform.name] = true;
  722. // Request
  723. Browser.Request = (function(){
  724. var XMLHTTP = function(){
  725. return new XMLHttpRequest();
  726. };
  727. var MSXML2 = function(){
  728. return new ActiveXObject('MSXML2.XMLHTTP');
  729. };
  730. var MSXML = function(){
  731. return new ActiveXObject('Microsoft.XMLHTTP');
  732. };
  733. return Function.attempt(function(){
  734. XMLHTTP();
  735. return XMLHTTP;
  736. }, function(){
  737. MSXML2();
  738. return MSXML2;
  739. }, function(){
  740. MSXML();
  741. return MSXML;
  742. });
  743. })();
  744. Browser.Features.xhr = !!(Browser.Request);
  745. // Flash detection
  746. var version = (Function.attempt(function(){
  747. return navigator.plugins['Shockwave Flash'].description;
  748. }, function(){
  749. return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
  750. }) || '0 r0').match(/\d+/g);
  751. Browser.Plugins.Flash = {
  752. version: Number(version[0] || '0.' + version[1]) || 0,
  753. build: Number(version[2]) || 0
  754. };
  755. // String scripts
  756. Browser.exec = function(text){
  757. if (!text) return text;
  758. if (window.execScript){
  759. window.execScript(text);
  760. } else {
  761. var script = document.createElement('script');
  762. script.setAttribute('type', 'text/javascript');
  763. script.text = text;
  764. document.head.appendChild(script);
  765. document.head.removeChild(script);
  766. }
  767. return text;
  768. };
  769. String.implement('stripScripts', function(exec){
  770. var scripts = '';
  771. var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
  772. scripts += code + '\n';
  773. return '';
  774. });
  775. if (exec === true) Browser.exec(scripts);
  776. else if (typeOf(exec) == 'function') exec(scripts, text);
  777. return text;
  778. });
  779. // Window, Document
  780. Browser.extend({
  781. Document: this.Document,
  782. Window: this.Window,
  783. Element: this.Element,
  784. Event: this.Event
  785. });
  786. this.Window = this.$constructor = new Type('Window', function(){});
  787. this.$family = Function.from('window').hide();
  788. Window.mirror(function(name, method){
  789. window[name] = method;
  790. });
  791. this.Document = document.$constructor = new Type('Document', function(){});
  792. document.$family = Function.from('document').hide();
  793. Document.mirror(function(name, method){
  794. document[name] = method;
  795. });
  796. document.html = document.documentElement;
  797. document.head = document.getElementsByTagName('head')[0];
  798. if (document.execCommand) try {
  799. document.execCommand("BackgroundImageCache", false, true);
  800. } catch (e){}
  801. if (this.attachEvent && !this.addEventListener){
  802. var unloadEvent = function(){
  803. this.detachEvent('onunload', unloadEvent);
  804. document.head = document.html = document.window = null;
  805. };
  806. this.attachEvent('onunload', unloadEvent);
  807. }
  808. // IE fails on collections and <select>.options (refers to <select>)
  809. var arrayFrom = Array.from;
  810. try {
  811. arrayFrom(document.html.childNodes);
  812. } catch(e){
  813. Array.from = function(item){
  814. if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
  815. var i = item.length, array = new Array(i);
  816. while (i--) array[i] = item[i];
  817. return array;
  818. }
  819. return arrayFrom(item);
  820. };
  821. var prototype = Array.prototype,
  822. slice = prototype.slice;
  823. ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
  824. var method = prototype[name];
  825. Array[name] = function(item){
  826. return method.apply(Array.from(item), slice.call(arguments, 1));
  827. };
  828. });
  829. }
  830. }).call(this);
  831. /*
  832. ---
  833. name: Event
  834. description: Contains the Event Class, to make the event object cross-browser.
  835. license: MIT-style license.
  836. requires: [Window, Document, Array, Function, String, Object]
  837. provides: Event
  838. ...
  839. */
  840. var Event = new Type('Event', function(event, win){
  841. if (!win) win = window;
  842. var doc = win.document;
  843. event = event || win.event;
  844. if (event.$extended) return event;
  845. this.$extended = true;
  846. var type = event.type,
  847. target = event.target || event.srcElement,
  848. page = {},
  849. client = {},
  850. related = null,
  851. rightClick, wheel, code, key;
  852. while (target && target.nodeType == 3) target = target.parentNode;
  853. if (type.indexOf('key') != -1){
  854. code = event.which || event.keyCode;
  855. key = Object.keyOf(Event.Keys, code);
  856. if (type == 'keydown'){
  857. var fKey = code - 111;
  858. if (fKey > 0 && fKey < 13) key = 'f' + fKey;
  859. }
  860. if (!key) key = String.fromCharCode(code).toLowerCase();
  861. } else if ((/click|mouse|menu/i).test(type)){
  862. doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
  863. page = {
  864. x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
  865. y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
  866. };
  867. client = {
  868. x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
  869. y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
  870. };
  871. if ((/DOMMouseScroll|mousewheel/).test(type)){
  872. wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
  873. }
  874. rightClick = (event.which == 3) || (event.button == 2);
  875. if ((/over|out/).test(type)){
  876. related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
  877. var testRelated = function(){
  878. while (related && related.nodeType == 3) related = related.parentNode;
  879. return true;
  880. };
  881. var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated();
  882. related = (hasRelated) ? related : null;
  883. }
  884. } else if ((/gesture|touch/i).test(type)){
  885. this.rotation = event.rotation;
  886. this.scale = event.scale;
  887. this.targetTouches = event.targetTouches;
  888. this.changedTouches = event.changedTouches;
  889. var touches = this.touches = event.touches;
  890. if (touches && touches[0]){
  891. var touch = touches[0];
  892. page = {x: touch.pageX, y: touch.pageY};
  893. client = {x: touch.clientX, y: touch.clientY};
  894. }
  895. }
  896. return Object.append(this, {
  897. event: event,
  898. type: type,
  899. page: page,
  900. client: client,
  901. rightClick: rightClick,
  902. wheel: wheel,
  903. relatedTarget: document.id(related),
  904. target: document.id(target),
  905. code: code,
  906. key: key,
  907. shift: event.shiftKey,
  908. control: event.ctrlKey,
  909. alt: event.altKey,
  910. meta: event.metaKey
  911. });
  912. });
  913. Event.Keys = {
  914. 'enter': 13,
  915. 'up': 38,
  916. 'down': 40,
  917. 'left': 37,
  918. 'right': 39,
  919. 'esc': 27,
  920. 'space': 32,
  921. 'backspace': 8,
  922. 'tab': 9,
  923. 'delete': 46
  924. };
  925. Event.implement({
  926. stop: function(){
  927. return this.stopPropagation().preventDefault();
  928. },
  929. stopPropagation: function(){
  930. if (this.event.stopPropagation) this.event.stopPropagation();
  931. else this.event.cancelBubble = true;
  932. return this;
  933. },
  934. preventDefault: function(){
  935. if (this.event.preventDefault) this.event.preventDefault();
  936. else this.event.returnValue = false;
  937. return this;
  938. }
  939. });
  940. /*
  941. ---
  942. name: Class
  943. description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
  944. license: MIT-style license.
  945. requires: [Array, String, Function, Number]
  946. provides: Class
  947. ...
  948. */
  949. (function(){
  950. var Class = this.Class = new Type('Class', function(params){
  951. if (instanceOf(params, Function)) params = {initialize: params};
  952. var newClass = function(){
  953. reset(this);
  954. if (newClass.$prototyping) return this;
  955. this.$caller = null;
  956. var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
  957. this.$caller = this.caller = null;
  958. return value;
  959. }.extend(this).implement(params);
  960. newClass.$constructor = Class;
  961. newClass.prototype.$constructor = newClass;
  962. newClass.prototype.parent = parent;
  963. return newClass;
  964. });
  965. var parent = function(){
  966. if (!this.$caller) throw new Error('The method "parent" cannot be called.');
  967. var name = this.$caller.$name,
  968. parent = this.$caller.$owner.parent,
  969. previous = (parent) ? parent.prototype[name] : null;
  970. if (!previous) throw new Error('The method "' + name + '" has no parent.');
  971. return previous.apply(this, arguments);
  972. };
  973. var reset = function(object){
  974. for (var key in object){
  975. var value = object[key];
  976. switch (typeOf(value)){
  977. case 'object':
  978. var F = function(){};
  979. F.prototype = value;
  980. object[key] = reset(new F);
  981. break;
  982. case 'array': object[key] = value.clone(); break;
  983. }
  984. }
  985. return object;
  986. };
  987. var wrap = function(self, key, method){
  988. if (method.$origin) method = method.$origin;
  989. var wrapper = function(){
  990. if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
  991. var caller = this.caller, current = this.$caller;
  992. this.caller = current; this.$caller = wrapper;
  993. var result = method.apply(this, arguments);
  994. this.$caller = current; this.caller = caller;
  995. return result;
  996. }.extend({$owner: self, $origin: method, $name: key});
  997. return wrapper;
  998. };
  999. var implement = function(key, value, retain){
  1000. if (Class.Mutators.hasOwnProperty(key)){
  1001. value = Class.Mutators[key].call(this, value);
  1002. if (value == null) return this;
  1003. }
  1004. if (typeOf(value) == 'function'){
  1005. if (value.$hidden) return this;
  1006. this.prototype[key] = (retain) ? value : wrap(this, key, value);
  1007. } else {
  1008. Object.merge(this.prototype, key, value);
  1009. }
  1010. return this;
  1011. };
  1012. var getInstance = function(klass){
  1013. klass.$prototyping = true;
  1014. var proto = new klass;
  1015. delete klass.$prototyping;
  1016. return proto;
  1017. };
  1018. Class.implement('implement', implement.overloadSetter());
  1019. Class.Mutators = {
  1020. Extends: function(parent){
  1021. this.parent = parent;
  1022. this.prototype = getInstance(parent);
  1023. },
  1024. Implements: function(items){
  1025. Array.from(items).each(function(item){
  1026. var instance = new item;
  1027. for (var key in instance) implement.call(this, key, instance[key], true);
  1028. }, this);
  1029. }
  1030. };
  1031. }).call(this);
  1032. /*
  1033. ---
  1034. name: Class.Extras
  1035. description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
  1036. license: MIT-style license.
  1037. requires: Class
  1038. provides: [Class.Extras, Chain, Events, Options]
  1039. ...
  1040. */
  1041. (function(){
  1042. this.Chain = new Class({
  1043. $chain: [],
  1044. chain: function(){
  1045. this.$chain.append(Array.flatten(arguments));
  1046. return this;
  1047. },
  1048. callChain: function(){
  1049. return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
  1050. },
  1051. clearChain: function(){
  1052. this.$chain.empty();
  1053. return this;
  1054. }
  1055. });
  1056. var removeOn = function(string){
  1057. return string.replace(/^on([A-Z])/, function(full, first){
  1058. return first.toLowerCase();
  1059. });
  1060. };
  1061. this.Events = new Class({
  1062. $events: {},
  1063. addEvent: function(type, fn, internal){
  1064. type = removeOn(type);
  1065. this.$events[type] = (this.$events[type] || []).include(fn);
  1066. if (internal) fn.internal = true;
  1067. return this;
  1068. },
  1069. addEvents: function(events){
  1070. for (var type in events) this.addEvent(type, events[type]);
  1071. return this;
  1072. },
  1073. fireEvent: function(type, args, delay){
  1074. type = removeOn(type);
  1075. var events = this.$events[type];
  1076. if (!events) return this;
  1077. args = Array.from(args);
  1078. events.each(function(fn){
  1079. if (delay) fn.delay(delay, this, args);
  1080. else fn.apply(this, args);
  1081. }, this);
  1082. return this;
  1083. },
  1084. removeEvent: function(type, fn){
  1085. type = removeOn(type);
  1086. var events = this.$events[type];
  1087. if (events && !fn.internal){
  1088. var index = events.indexOf(fn);
  1089. if (index != -1) delete events[index];
  1090. }
  1091. return this;
  1092. },
  1093. removeEvents: function(events){
  1094. var type;
  1095. if (typeOf(events) == 'object'){
  1096. for (type in events) this.removeEvent(type, events[type]);
  1097. return this;
  1098. }
  1099. if (events) events = removeOn(events);
  1100. for (type in this.$events){
  1101. if (events && events != type) continue;
  1102. var fns = this.$events[type];
  1103. for (var i = fns.length; i--;) if (i in fns){
  1104. this.removeEvent(type, fns[i]);
  1105. }
  1106. }
  1107. return this;
  1108. }
  1109. });
  1110. this.Options = new Class({
  1111. setOptions: function(){
  1112. var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
  1113. if (this.addEvent) for (var option in options){
  1114. if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
  1115. this.addEvent(option, options[option]);
  1116. delete options[option];
  1117. }
  1118. return this;
  1119. }
  1120. });
  1121. }).call(this);
  1122. /*
  1123. ---
  1124. name: Slick.Parser
  1125. description: Standalone CSS3 Selector parser
  1126. provides: Slick.Parser
  1127. ...
  1128. */
  1129. ;(function(){
  1130. var parsed,
  1131. separatorIndex,
  1132. combinatorIndex,
  1133. reversed,
  1134. cache = {},
  1135. reverseCache = {},
  1136. reUnescape = /\\/g;
  1137. var parse = function(expression, isReversed){
  1138. if (expression == null) return null;
  1139. if (expression.Slick === true) return expression;
  1140. expression = ('' + expression).replace(/^\s+|\s+$/g, '');
  1141. reversed = !!isReversed;
  1142. var currentCache = (reversed) ? reverseCache : cache;
  1143. if (currentCache[expression]) return currentCache[expression];
  1144. parsed = {
  1145. Slick: true,
  1146. expressions: [],
  1147. raw: expression,
  1148. reverse: function(){
  1149. return parse(this.raw, true);
  1150. }
  1151. };
  1152. separatorIndex = -1;
  1153. while (expression != (expression = expression.replace(regexp, parser)));
  1154. parsed.length = parsed.expressions.length;
  1155. return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
  1156. };
  1157. var reverseCombinator = function(combinator){
  1158. if (combinator === '!') return ' ';
  1159. else if (combinator === ' ') return '!';
  1160. else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
  1161. else return '!' + combinator;
  1162. };
  1163. var reverse = function(expression){
  1164. var expressions = expression.expressions;
  1165. for (var i = 0; i < expressions.length; i++){
  1166. var exp = expressions[i];
  1167. var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
  1168. for (var j = 0; j < exp.length; j++){
  1169. var cexp = exp[j];
  1170. if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
  1171. cexp.combinator = cexp.reverseCombinator;
  1172. delete cexp.reverseCombinator;
  1173. }
  1174. exp.reverse().push(last);
  1175. }
  1176. return expression;
  1177. };
  1178. var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
  1179. return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
  1180. return '\\' + match;
  1181. });
  1182. };
  1183. var regexp = new RegExp(
  1184. /*
  1185. #!/usr/bin/env ruby
  1186. puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
  1187. __END__
  1188. "(?x)^(?:\
  1189. \\s* ( , ) \\s* # Separator \n\
  1190. | \\s* ( <combinator>+ ) \\s* # Combinator \n\
  1191. | ( \\s+ ) # CombinatorChildren \n\
  1192. | ( <unicode>+ | \\* ) # Tag \n\
  1193. | \\# ( <unicode>+ ) # ID \n\
  1194. | \\. ( <unicode>+ ) # ClassName \n\
  1195. | # Attribute \n\
  1196. \\[ \
  1197. \\s* (<unicode1>+) (?: \
  1198. \\s* ([*^$!~|]?=) (?: \
  1199. \\s* (?:\
  1200. ([\"']?)(.*?)\\9 \
  1201. )\
  1202. ) \
  1203. )? \\s* \
  1204. \\](?!\\]) \n\
  1205. | :+ ( <unicode>+ )(?:\
  1206. \\( (?:\
  1207. (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
  1208. ) \\)\
  1209. )?\
  1210. )"
  1211. */
  1212. "^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
  1213. .replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
  1214. .replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
  1215. .replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
  1216. );
  1217. function parser(
  1218. rawMatch,
  1219. separator,
  1220. combinator,
  1221. combinatorChildren,
  1222. tagName,
  1223. id,
  1224. className,
  1225. attributeKey,
  1226. attributeOperator,
  1227. attributeQuote,
  1228. attributeValue,
  1229. pseudoMarker,
  1230. pseudoClass,
  1231. pseudoQuote,
  1232. pseudoClassQuotedValue,
  1233. pseudoClassValue
  1234. ){
  1235. if (separator || separatorIndex === -1){
  1236. parsed.expressions[++separatorIndex] = [];
  1237. combinatorIndex = -1;
  1238. if (separator) return '';
  1239. }
  1240. if (combinator || combinatorChildren || combinatorIndex === -1){
  1241. combinator = combinator || ' ';
  1242. var currentSeparator = parsed.expressions[separatorIndex];
  1243. if (reversed && currentSeparator[combinatorIndex])
  1244. currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
  1245. currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
  1246. }
  1247. var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
  1248. if (tagName){
  1249. currentParsed.tag = tagName.replace(reUnescape, '');
  1250. } else if (id){
  1251. currentParsed.id = id.replace(reUnescape, '');
  1252. } else if (className){
  1253. className = className.replace(reUnescape, '');
  1254. if (!currentParsed.classList) currentParsed.classList = [];
  1255. if (!currentParsed.classes) currentParsed.classes = [];
  1256. currentParsed.classList.push(className);
  1257. currentParsed.classes.push({
  1258. value: className,
  1259. regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
  1260. });
  1261. } else if (pseudoClass){
  1262. pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
  1263. pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
  1264. if (!currentParsed.pseudos) currentParsed.pseudos = [];
  1265. currentParsed.pseudos.push({
  1266. key: pseudoClass.replace(reUnescape, ''),
  1267. value: pseudoClassValue,
  1268. type: pseudoMarker.length == 1 ? 'class' : 'element'
  1269. });
  1270. } else if (attributeKey){
  1271. attributeKey = attributeKey.replace(reUnescape, '');
  1272. attributeValue = (attributeValue || '').replace(reUnescape, '');
  1273. var test, regexp;
  1274. switch (attributeOperator){
  1275. case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break;
  1276. case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break;
  1277. case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
  1278. case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break;
  1279. case '=' : test = function(value){
  1280. return attributeValue == value;
  1281. }; break;
  1282. case '*=' : test = function(value){
  1283. return value && value.indexOf(attributeValue) > -1;
  1284. }; break;
  1285. case '!=' : test = function(value){
  1286. return attributeValue != value;
  1287. }; break;
  1288. default : test = function(value){
  1289. return !!value;
  1290. };
  1291. }
  1292. if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
  1293. return false;
  1294. };
  1295. if (!test) test = function(value){
  1296. return value && regexp.test(value);
  1297. };
  1298. if (!currentParsed.attributes) currentParsed.attributes = [];
  1299. currentParsed.attributes.push({
  1300. key: attributeKey,
  1301. operator: attributeOperator,
  1302. value: attributeValue,
  1303. test: test
  1304. });
  1305. }
  1306. return '';
  1307. };
  1308. // Slick NS
  1309. var Slick = (this.Slick || {});
  1310. Slick.parse = function(expression){
  1311. return parse(expression);
  1312. };
  1313. Slick.escapeRegExp = escapeRegExp;
  1314. if (!this.Slick) this.Slick = Slick;
  1315. }).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
  1316. /*
  1317. ---
  1318. name: Slick.Finder
  1319. description: The new, superfast css selector engine.
  1320. provides: Slick.Finder
  1321. requires: Slick.Parser
  1322. ...
  1323. */
  1324. ;(function(){
  1325. var local = {},
  1326. featuresCache = {},
  1327. toString = Object.prototype.toString;
  1328. // Feature / Bug detection
  1329. local.isNativeCode = function(fn){
  1330. return (/\{\s*\[native code\]\s*\}/).test('' + fn);
  1331. };
  1332. local.isXML = function(document){
  1333. return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
  1334. (document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
  1335. };
  1336. local.setDocument = function(document){
  1337. // convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
  1338. var nodeType = document.nodeType;
  1339. if (nodeType == 9); // document
  1340. else if (nodeType) document = document.ownerDocument; // node
  1341. else if (document.navigator) document = document.document; // window
  1342. else return;
  1343. // check if it's the old document
  1344. if (this.document === document) return;
  1345. this.document = document;
  1346. // check if we have done feature detection on this document before
  1347. var root = document.documentElement,
  1348. rootUid = this.getUIDXML(root),
  1349. features = featuresCache[rootUid],
  1350. feature;
  1351. if (features){
  1352. for (feature in features){
  1353. this[feature] = features[feature];
  1354. }
  1355. return;
  1356. }
  1357. features = featuresCache[rootUid] = {};
  1358. features.root = root;
  1359. features.isXMLDocument = this.isXML(document);
  1360. features.brokenStarGEBTN
  1361. = features.starSelectsClosedQSA
  1362. = features.idGetsName
  1363. = features.brokenMixedCaseQSA
  1364. = features.brokenGEBCN
  1365. = features.brokenCheckedQSA
  1366. = features.brokenEmptyAttributeQSA
  1367. = features.isHTMLDocument
  1368. = features.nativeMatchesSelector
  1369. = false;
  1370. var starSelectsClosed, starSelectsComments,
  1371. brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
  1372. brokenFormAttributeGetter;
  1373. var selected, id = 'slick_uniqueid';
  1374. var testNode = document.createElement('div');
  1375. var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
  1376. testRoot.appendChild(testNode);
  1377. // on non-HTML documents innerHTML and getElementsById doesnt work properly
  1378. try {
  1379. testNode.innerHTML = '<a id="'+id+'"></a>';
  1380. features.isHTMLDocument = !!document.getElementById(id);
  1381. } catch(e){};
  1382. if (features.isHTMLDocument){
  1383. testNode.style.display = 'none';
  1384. // IE returns comment nodes for getElementsByTagName('*') for some documents
  1385. testNode.appendChild(document.createComment(''));
  1386. starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
  1387. // IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
  1388. try {
  1389. testNode.innerHTML = 'foo</foo>';
  1390. selected = testNode.getElementsByTagName('*');
  1391. starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
  1392. } catch(e){};
  1393. features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
  1394. // IE returns elements with the name instead of just id for getElementsById for some documents
  1395. try {
  1396. testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
  1397. features.idGetsName = document.getElementById(id) === testNode.firstChild;
  1398. } catch(e){};
  1399. if (testNode.getElementsByClassName){
  1400. // Safari 3.2 getElementsByClassName caches results
  1401. try {
  1402. testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
  1403. testNode.getElementsByClassName('b').length;
  1404. testNode.firstChild.className = 'b';
  1405. cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
  1406. } catch(e){};
  1407. // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
  1408. try {
  1409. testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
  1410. brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
  1411. } catch(e){};
  1412. features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
  1413. }
  1414. if (testNode.querySelectorAll){
  1415. // IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
  1416. try {
  1417. testNode.innerHTML = 'foo</foo>';
  1418. selected = testNode.querySelectorAll('*');
  1419. features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
  1420. } catch(e){};
  1421. // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
  1422. try {
  1423. testNode.innerHTML = '<a class="MiX"></a>';
  1424. features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
  1425. } catch(e){};
  1426. // Webkit and Opera dont return selected options on querySelectorAll
  1427. try {
  1428. testNode.innerHTML = '<select><option selected="selected">a</option></select>';
  1429. features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
  1430. } catch(e){};
  1431. // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
  1432. try {
  1433. testNode.innerHTML = '<a class=""></a>';
  1434. features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
  1435. } catch(e){};
  1436. }
  1437. // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
  1438. try {
  1439. testNode.innerHTML = '<form action="s"><input id="action"/></form>';
  1440. brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
  1441. } catch(e){};
  1442. // native matchesSelector function
  1443. features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
  1444. if (features.nativeMatchesSelector) try {
  1445. // if matchesSelector trows errors on incorrect sintaxes we can use it
  1446. features.nativeMatchesSelector.call(root, ':slick');
  1447. features.nativeMatchesSelector = null;
  1448. } catch(e){};
  1449. }
  1450. try {
  1451. root.slick_expando = 1;
  1452. delete root.slick_expando;
  1453. features.getUID = this.getUIDHTML;
  1454. } catch(e) {
  1455. features.getUID = this.getUIDXML;
  1456. }
  1457. testRoot.removeChild(testNode);
  1458. testNode = selected = testRoot = null;
  1459. // getAttribute
  1460. features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
  1461. var method = this.attributeGetters[name];
  1462. if (method) return method.call(node);
  1463. var attributeNode = node.getAttributeNode(name);
  1464. return (attributeNode) ? attributeNode.nodeValue : null;
  1465. } : function(node, name){
  1466. var method = this.attributeGetters[name];
  1467. return (method) ? method.call(node) : node.getAttribute(name);
  1468. };
  1469. // hasAttribute
  1470. features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
  1471. return node.hasAttribute(attribute);
  1472. } : function(node, attribute) {
  1473. node = node.getAttributeNode(attribute);
  1474. return !!(node && (node.specified || node.nodeValue));
  1475. };
  1476. // contains
  1477. // FIXME: Add specs: local.contains should be different for xml and html documents?
  1478. features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){
  1479. return context.contains(node);
  1480. } : (root && root.compareDocumentPosition) ? function(context, node){
  1481. return context === node || !!(context.compareDocumentPosition(node) & 16);
  1482. } : function(context, node){
  1483. if (node) do {
  1484. if (node === context) return true;
  1485. } while ((node = node.parentNode));
  1486. return false;
  1487. };
  1488. // document order sorting
  1489. // credits to Sizzle (http://sizzlejs.com/)
  1490. features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
  1491. if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
  1492. return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
  1493. } : ('sourceIndex' in root) ? function(a, b){
  1494. if (!a.sourceIndex || !b.sourceIndex) return 0;
  1495. return a.sourceIndex - b.sourceIndex;
  1496. } : (document.createRange) ? function(a, b){
  1497. if (!a.ownerDocument || !b.ownerDocument) return 0;
  1498. var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
  1499. aRange.setStart(a, 0);
  1500. aRange.setEnd(a, 0);
  1501. bRange.setStart(b, 0);
  1502. bRange.setEnd(b, 0);
  1503. return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
  1504. } : null ;
  1505. root = null;
  1506. for (feature in features){
  1507. this[feature] = features[feature];
  1508. }
  1509. };
  1510. // Main Method
  1511. var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
  1512. reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
  1513. qsaFailExpCache = {};
  1514. local.search = function(context, expression, append, first){
  1515. var found = this.found = (first) ? null : (append || []);
  1516. if (!context) return found;
  1517. else if (context.navigator) context = context.document; // Convert the node from a window to a document
  1518. else if (!context.nodeType) return found;
  1519. // setup
  1520. var parsed, i,
  1521. uniques = this.uniques = {},
  1522. hasOthers = !!(append && append.length),
  1523. contextIsDocument = (context.nodeType == 9);
  1524. if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
  1525. // avoid duplicating items already in the append array
  1526. if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
  1527. // expression checks
  1528. if (typeof expression == 'string'){ // expression is a string
  1529. /*<simple-selectors-override>*/
  1530. var simpleSelector = expression.match(reSimpleSelector);
  1531. simpleSelectors: if (simpleSelector) {
  1532. var symbol = simpleSelector[1],
  1533. name = simpleSelector[2],
  1534. node, nodes;
  1535. if (!symbol){
  1536. if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
  1537. nodes = context.getElementsByTagName(name);
  1538. if (first) return nodes[0] || null;
  1539. for (i = 0; node = nodes[i++];){
  1540. if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
  1541. }
  1542. } else if (symbol == '#'){
  1543. if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
  1544. node = context.getElementById(name);
  1545. if (!node) return found;
  1546. if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
  1547. if (first) return node || null;
  1548. if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
  1549. } else if (symbol == '.'){
  1550. if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
  1551. if (context.getElementsByClassName && !this.brokenGEBCN){
  1552. nodes = context.getElementsByClassName(name);
  1553. if (first) return nodes[0] || null;
  1554. for (i = 0; node = nodes[i++];){
  1555. if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
  1556. }
  1557. } else {
  1558. var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
  1559. nodes = context.getElementsByTagName('*');
  1560. for (i = 0; node = nodes[i++];){
  1561. className = node.className;
  1562. if (!(className &