map and chat and

That scripts add city map, which are located open buildings, marked with specials icons; shows player information in numbers (health, satiety, armor, free cells in inventory, number of PM), can display chat at game window, can stretch game window on browser window size for comfortable game.

  1. // ==UserScript==
  2. // @name map and chat and
  3. // @description That scripts add city map, which are located open buildings, marked with specials icons; shows player information in numbers (health, satiety, armor, free cells in inventory, number of PM), can display chat at game window, can stretch game window on browser window size for comfortable game.
  4. // @author TheDarkKRONOS & Haonik
  5. // @version 0.5.2.1
  6. // @include http://fairview.deadfrontier.com/onlinezombiemmo/index.php*
  7. // @namespace https://greasyfork.org/users/10968
  8. // ==/UserScript==
  9.  
  10. (function (window, document, undefined) {
  11. var urlFilter = /^http:\/\/fairview.deadfrontier.com\/onlinezombiemmo\/index\.php(|\?page=(15|21|22|24|25|28|29|35|38|49|50|53)|\?action=(forum|pm|profile))/i;
  12. if (!urlFilter.test(document.location.href))
  13. {
  14. return; // uncomment in release
  15. }
  16.  
  17. function supportsStorage()
  18. {
  19. try
  20. {
  21. return 'localStorage' in window && window['localStorage'] !== null;
  22. }
  23. catch (e)
  24. {
  25. return false;
  26. }
  27. }
  28.  
  29. var loadingScreen = new function()
  30. {
  31. var loadingScreen = this;
  32.  
  33. var backgroundElement = document.createElement('div');
  34. backgroundElement.style.cssText = 'position: absolute; display: block; z-index: 200; padding: 0; margin: 0; left: 0px; top: 0px; width: 100%; height: 100%;';
  35. backgroundElement.style.border = 'none';
  36. backgroundElement.style.backgroundColor = 'black';
  37. document.body.appendChild(backgroundElement);
  38.  
  39. var messageElement = document.createElement('div');
  40. messageElement.style.cssText = 'position: absolute; display: block; left: 50%; top: 50%; width: 100%; margin-left: -50%;' +
  41. 'color: #f7fe57 !important; letter-spacing: 2px !important; font-size: 20px !important; font-family: "Times New Roman", Arial !important;';
  42. messageElement.style.border = 'none';
  43. messageElement.style.backgroundColor = 'transparent';
  44. messageElement.innerHTML = 'Loading...';
  45. backgroundElement.appendChild(messageElement);
  46.  
  47. loadingScreen.hide = function()
  48. {
  49. document.body.removeChild(backgroundElement);
  50. };
  51.  
  52. loadingScreen.resetPosition = function()
  53. {
  54. document.body.appendChild(backgroundElement);
  55. };
  56. };
  57.  
  58. /*!
  59. * jQuery JavaScript Library v2.1.2-pre -ajax/jsonp,-ajax/script,-deprecated,-effects,-effects/animatedSelector,-effects/Tween,-wrap,-ajax/parseJSON,-ajax/parseXML,-ajax/load,-attributes/prop,-attributes/attr,-core/ready,-exports,-exports/amd
  60. * http://jquery.com/
  61. *
  62. * Includes Sizzle.js
  63. * http://sizzlejs.com/
  64. *
  65. * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
  66. * Released under the MIT license
  67. * http://jquery.org/license
  68. *
  69. * Date: 2014-05-07T05:46Z
  70. */
  71.  
  72. var $ = (function(global, factory)
  73. {
  74. if (typeof module === "object" && typeof module.exports === "object")
  75. {
  76. // For CommonJS and CommonJS-like environments where a proper window is present,
  77. // execute the factory and get jQuery
  78. // For environments that do not inherently posses a window with a document
  79. // (such as Node.js), expose a jQuery-making factory as module.exports
  80. // This accentuates the need for the creation of a real window
  81. // e.g. var jQuery = require("jquery")(window);
  82. // See ticket #14549 for more info
  83. module.exports = global.document ?
  84. factory(global, true) :
  85. function(w)
  86. {
  87. if (!w.document)
  88. {
  89. throw new Error("jQuery requires a window with a document");
  90. }
  91. return factory(w);
  92. };
  93. } else
  94. {
  95. return factory(global);
  96. }
  97.  
  98. // Pass this if window is not defined yet
  99. }(typeof window !== "undefined" ? window : this, function(window, noGlobal)
  100. {
  101. // Can't do this because several apps including ASP.NET trace
  102. // the stack via arguments.caller.callee and Firefox dies if
  103. // you try to trace through "use strict" call chains. (#13335)
  104. // Support: Firefox 18+
  105. //
  106.  
  107. var arr = [];
  108.  
  109. var slice = arr.slice;
  110.  
  111. var concat = arr.concat;
  112.  
  113. var push = arr.push;
  114.  
  115. var indexOf = arr.indexOf;
  116.  
  117. var class2type = {};
  118.  
  119. var toString = class2type.toString;
  120.  
  121. var hasOwn = class2type.hasOwnProperty;
  122.  
  123. var support = {};
  124.  
  125.  
  126.  
  127. var
  128. // Use the correct document accordingly with window argument (sandbox)
  129. document = window.document,
  130.  
  131. version = "2.1.2-pre -ajax/jsonp,-ajax/script,-deprecated,-effects,-effects/animatedSelector,-effects/Tween,-wrap,-ajax/parseJSON,-ajax/parseXML,-ajax/load,-attributes/prop,-attributes/attr,-core/ready,-exports,-exports/amd",
  132.  
  133. // Define a local copy of jQuery
  134. jQuery = function(selector, context)
  135. {
  136. // The jQuery object is actually just the init constructor 'enhanced'
  137. // Need init if jQuery is called (just allow error to be thrown if not included)
  138. return new jQuery.fn.init(selector, context);
  139. },
  140.  
  141. // Support: Android<4.1
  142. // Make sure we trim BOM and NBSP
  143. rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
  144.  
  145. // Matches dashed string for camelizing
  146. rmsPrefix = /^-ms-/,
  147. rdashAlpha = /-([\da-z])/gi,
  148.  
  149. // Used by jQuery.camelCase as callback to replace()
  150. fcamelCase = function(all, letter)
  151. {
  152. return letter.toUpperCase();
  153. };
  154.  
  155. jQuery.fn = jQuery.prototype = {
  156. // The current version of jQuery being used
  157. jquery: version,
  158.  
  159. constructor: jQuery,
  160.  
  161. // Start with an empty selector
  162. selector: "",
  163.  
  164. // The default length of a jQuery object is 0
  165. length: 0,
  166.  
  167. toArray: function()
  168. {
  169. return slice.call(this);
  170. },
  171.  
  172. // Get the Nth element in the matched element set OR
  173. // Get the whole matched element set as a clean array
  174. get: function(num)
  175. {
  176. return num != null ?
  177.  
  178. // Return just the one element from the set
  179. (num < 0 ? this[num + this.length] : this[num]) :
  180.  
  181. // Return all the elements in a clean array
  182. slice.call(this);
  183. },
  184.  
  185. // Take an array of elements and push it onto the stack
  186. // (returning the new matched element set)
  187. pushStack: function(elems)
  188. {
  189. // Build a new jQuery matched element set
  190. var ret = jQuery.merge(this.constructor(), elems);
  191.  
  192. // Add the old object onto the stack (as a reference)
  193. ret.prevObject = this;
  194. ret.context = this.context;
  195.  
  196. // Return the newly-formed element set
  197. return ret;
  198. },
  199.  
  200. // Execute a callback for every element in the matched set.
  201. // (You can seed the arguments with an array of args, but this is
  202. // only used internally.)
  203. each: function(callback, args)
  204. {
  205. return jQuery.each(this, callback, args);
  206. },
  207.  
  208. map: function(callback)
  209. {
  210. return this.pushStack(jQuery.map(this, function(elem, i)
  211. {
  212. return callback.call(elem, i, elem);
  213. }));
  214. },
  215.  
  216. slice: function()
  217. {
  218. return this.pushStack(slice.apply(this, arguments));
  219. },
  220.  
  221. first: function()
  222. {
  223. return this.eq(0);
  224. },
  225.  
  226. last: function()
  227. {
  228. return this.eq(-1);
  229. },
  230.  
  231. eq: function(i)
  232. {
  233. var len = this.length,
  234. j = +i + (i < 0 ? len : 0);
  235. return this.pushStack(j >= 0 && j < len ? [this[j]] : []);
  236. },
  237.  
  238. end: function()
  239. {
  240. return this.prevObject || this.constructor(null);
  241. },
  242.  
  243. // For internal use only.
  244. // Behaves like an Array's method, not like a jQuery method.
  245. push: push,
  246. sort: arr.sort,
  247. splice: arr.splice
  248. };
  249.  
  250. jQuery.extend = jQuery.fn.extend = function()
  251. {
  252. var options, name, src, copy, copyIsArray, clone,
  253. target = arguments[0] || {},
  254. i = 1,
  255. length = arguments.length,
  256. deep = false;
  257.  
  258. // Handle a deep copy situation
  259. if (typeof target === "boolean")
  260. {
  261. deep = target;
  262.  
  263. // skip the boolean and the target
  264. target = arguments[i] || {};
  265. i++;
  266. }
  267.  
  268. // Handle case when target is a string or something (possible in deep copy)
  269. if (typeof target !== "object" && !jQuery.isFunction(target))
  270. {
  271. target = {};
  272. }
  273.  
  274. // extend jQuery itself if only one argument is passed
  275. if (i === length)
  276. {
  277. target = this;
  278. i--;
  279. }
  280.  
  281. for (; i < length; i++)
  282. {
  283. // Only deal with non-null/undefined values
  284. if ((options = arguments[i]) != null)
  285. {
  286. // Extend the base object
  287. for (name in options)
  288. {
  289. src = target[name];
  290. copy = options[name];
  291.  
  292. // Prevent never-ending loop
  293. if (target === copy)
  294. {
  295. continue;
  296. }
  297.  
  298. // Recurse if we're merging plain objects or arrays
  299. if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy))))
  300. {
  301. if (copyIsArray)
  302. {
  303. copyIsArray = false;
  304. clone = src && jQuery.isArray(src) ? src : [];
  305. } else
  306. {
  307. clone = src && jQuery.isPlainObject(src) ? src : {};
  308. }
  309.  
  310. // Never move original objects, clone them
  311. target[name] = jQuery.extend(deep, clone, copy);
  312.  
  313. // Don't bring in undefined values
  314. } else if (copy !== undefined)
  315. {
  316. target[name] = copy;
  317. }
  318. }
  319. }
  320. }
  321.  
  322. // Return the modified object
  323. return target;
  324. };
  325.  
  326. jQuery.extend({
  327. // Unique for each copy of jQuery on the page
  328. expando: "jQuery" + (version + Math.random()).replace(/\D/g, ""),
  329.  
  330. // Assume jQuery is ready without the ready module
  331. isReady: true,
  332.  
  333. error: function(msg)
  334. {
  335. throw new Error(msg);
  336. },
  337.  
  338. noop: function() { },
  339.  
  340. // See test/unit/core.js for details concerning isFunction.
  341. // Since version 1.3, DOM methods and functions like alert
  342. // aren't supported. They return false on IE (#2968).
  343. isFunction: function(obj)
  344. {
  345. return jQuery.type(obj) === "function";
  346. },
  347.  
  348. isArray: Array.isArray,
  349.  
  350. isWindow: function(obj)
  351. {
  352. return obj != null && obj === obj.window;
  353. },
  354.  
  355. isNumeric: function(obj)
  356. {
  357. // parseFloat NaNs numeric-cast false positives (null|true|false|"")
  358. // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
  359. // subtraction forces infinities to NaN
  360. return !jQuery.isArray(obj) && obj - parseFloat(obj) >= 0;
  361. },
  362.  
  363. isPlainObject: function(obj)
  364. {
  365. // Not plain objects:
  366. // - Any object or value whose internal [[Class]] property is not "[object Object]"
  367. // - DOM nodes
  368. // - window
  369. if (jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj))
  370. {
  371. return false;
  372. }
  373.  
  374. if (obj.constructor &&
  375. !hasOwn.call(obj.constructor.prototype, "isPrototypeOf"))
  376. {
  377. return false;
  378. }
  379.  
  380. // If the function hasn't returned already, we're confident that
  381. // |obj| is a plain object, created by {} or constructed with new Object
  382. return true;
  383. },
  384.  
  385. isEmptyObject: function(obj)
  386. {
  387. var name;
  388. for (name in obj)
  389. {
  390. return false;
  391. }
  392. return true;
  393. },
  394.  
  395. type: function(obj)
  396. {
  397. if (obj == null)
  398. {
  399. return obj + "";
  400. }
  401. // Support: Android < 4.0, iOS < 6 (functionish RegExp)
  402. return typeof obj === "object" || typeof obj === "function" ?
  403. class2type[toString.call(obj)] || "object" :
  404. typeof obj;
  405. },
  406.  
  407. // Evaluates a script in a global context
  408. globalEval: function(code)
  409. {
  410. var script,
  411. indirect = eval;
  412.  
  413. code = jQuery.trim(code);
  414.  
  415. if (code)
  416. {
  417. // If the code includes a valid, prologue position
  418. // strict mode pragma, execute code by injecting a
  419. // script tag into the document.
  420. if (code.indexOf("use strict") === 1)
  421. {
  422. script = document.createElement("script");
  423. script.text = code;
  424. document.head.appendChild(script).parentNode.removeChild(script);
  425. } else
  426. {
  427. // Otherwise, avoid the DOM node creation, insertion
  428. // and removal by using an indirect global eval
  429. indirect(code);
  430. }
  431. }
  432. },
  433.  
  434. // Convert dashed to camelCase; used by the css and data modules
  435. // Microsoft forgot to hump their vendor prefix (#9572)
  436. camelCase: function(string)
  437. {
  438. return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase);
  439. },
  440.  
  441. nodeName: function(elem, name)
  442. {
  443. return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
  444. },
  445.  
  446. // args is for internal usage only
  447. each: function(obj, callback, args)
  448. {
  449. var value,
  450. i = 0,
  451. length = obj.length,
  452. isArray = isArraylike(obj);
  453.  
  454. if (args)
  455. {
  456. if (isArray)
  457. {
  458. for (; i < length; i++)
  459. {
  460. value = callback.apply(obj[i], args);
  461.  
  462. if (value === false)
  463. {
  464. break;
  465. }
  466. }
  467. } else
  468. {
  469. for (i in obj)
  470. {
  471. value = callback.apply(obj[i], args);
  472.  
  473. if (value === false)
  474. {
  475. break;
  476. }
  477. }
  478. }
  479.  
  480. // A special, fast, case for the most common use of each
  481. } else
  482. {
  483. if (isArray)
  484. {
  485. for (; i < length; i++)
  486. {
  487. value = callback.call(obj[i], i, obj[i]);
  488.  
  489. if (value === false)
  490. {
  491. break;
  492. }
  493. }
  494. } else
  495. {
  496. for (i in obj)
  497. {
  498. value = callback.call(obj[i], i, obj[i]);
  499.  
  500. if (value === false)
  501. {
  502. break;
  503. }
  504. }
  505. }
  506. }
  507.  
  508. return obj;
  509. },
  510.  
  511. // Support: Android<4.1
  512. trim: function(text)
  513. {
  514. return text == null ?
  515. "" :
  516. (text + "").replace(rtrim, "");
  517. },
  518.  
  519. // results is for internal usage only
  520. makeArray: function(arr, results)
  521. {
  522. var ret = results || [];
  523.  
  524. if (arr != null)
  525. {
  526. if (isArraylike(Object(arr)))
  527. {
  528. jQuery.merge(ret,
  529. typeof arr === "string" ?
  530. [arr] : arr
  531. );
  532. } else
  533. {
  534. push.call(ret, arr);
  535. }
  536. }
  537.  
  538. return ret;
  539. },
  540.  
  541. inArray: function(elem, arr, i)
  542. {
  543. return arr == null ? -1 : indexOf.call(arr, elem, i);
  544. },
  545.  
  546. merge: function(first, second)
  547. {
  548. var len = +second.length,
  549. j = 0,
  550. i = first.length;
  551.  
  552. for (; j < len; j++)
  553. {
  554. first[i++] = second[j];
  555. }
  556.  
  557. first.length = i;
  558.  
  559. return first;
  560. },
  561.  
  562. grep: function(elems, callback, invert)
  563. {
  564. var callbackInverse,
  565. matches = [],
  566. i = 0,
  567. length = elems.length,
  568. callbackExpect = !invert;
  569.  
  570. // Go through the array, only saving the items
  571. // that pass the validator function
  572. for (; i < length; i++)
  573. {
  574. callbackInverse = !callback(elems[i], i);
  575. if (callbackInverse !== callbackExpect)
  576. {
  577. matches.push(elems[i]);
  578. }
  579. }
  580.  
  581. return matches;
  582. },
  583.  
  584. // arg is for internal usage only
  585. map: function(elems, callback, arg)
  586. {
  587. var value,
  588. i = 0,
  589. length = elems.length,
  590. isArray = isArraylike(elems),
  591. ret = [];
  592.  
  593. // Go through the array, translating each of the items to their new values
  594. if (isArray)
  595. {
  596. for (; i < length; i++)
  597. {
  598. value = callback(elems[i], i, arg);
  599.  
  600. if (value != null)
  601. {
  602. ret.push(value);
  603. }
  604. }
  605.  
  606. // Go through every key on the object,
  607. } else
  608. {
  609. for (i in elems)
  610. {
  611. value = callback(elems[i], i, arg);
  612.  
  613. if (value != null)
  614. {
  615. ret.push(value);
  616. }
  617. }
  618. }
  619.  
  620. // Flatten any nested arrays
  621. return concat.apply([], ret);
  622. },
  623.  
  624. // A global GUID counter for objects
  625. guid: 1,
  626.  
  627. // Bind a function to a context, optionally partially applying any
  628. // arguments.
  629. proxy: function(fn, context)
  630. {
  631. var tmp, args, proxy;
  632.  
  633. if (typeof context === "string")
  634. {
  635. tmp = fn[context];
  636. context = fn;
  637. fn = tmp;
  638. }
  639.  
  640. // Quick check to determine if target is callable, in the spec
  641. // this throws a TypeError, but we will just return undefined.
  642. if (!jQuery.isFunction(fn))
  643. {
  644. return undefined;
  645. }
  646.  
  647. // Simulated bind
  648. args = slice.call(arguments, 2);
  649. proxy = function()
  650. {
  651. return fn.apply(context || this, args.concat(slice.call(arguments)));
  652. };
  653.  
  654. // Set the guid of unique handler to the same of original handler, so it can be removed
  655. proxy.guid = fn.guid = fn.guid || jQuery.guid++;
  656.  
  657. return proxy;
  658. },
  659.  
  660. now: Date.now,
  661.  
  662. // jQuery.support is not used in Core but other projects attach their
  663. // properties to it so it needs to exist.
  664. support: support
  665. });
  666.  
  667. // Populate the class2type map
  668. jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name)
  669. {
  670. class2type["[object " + name + "]"] = name.toLowerCase();
  671. });
  672.  
  673. function isArraylike(obj)
  674. {
  675. var length = obj.length,
  676. type = jQuery.type(obj);
  677.  
  678. if (type === "function" || jQuery.isWindow(obj))
  679. {
  680. return false;
  681. }
  682.  
  683. if (obj.nodeType === 1 && length)
  684. {
  685. return true;
  686. }
  687.  
  688. return type === "array" || length === 0 ||
  689. typeof length === "number" && length > 0 && (length - 1) in obj;
  690. }
  691. var Sizzle =
  692. /*!
  693. * Sizzle CSS Selector Engine v1.10.19
  694. * http://sizzlejs.com/
  695. *
  696. * Copyright 2013 jQuery Foundation, Inc. and other contributors
  697. * Released under the MIT license
  698. * http://jquery.org/license
  699. *
  700. * Date: 2014-04-18
  701. */
  702. (function(window)
  703. {
  704. var i,
  705. support,
  706. Expr,
  707. getText,
  708. isXML,
  709. tokenize,
  710. compile,
  711. select,
  712. outermostContext,
  713. sortInput,
  714. hasDuplicate,
  715.  
  716. // Local document vars
  717. setDocument,
  718. document,
  719. docElem,
  720. documentIsHTML,
  721. rbuggyQSA,
  722. rbuggyMatches,
  723. matches,
  724. contains,
  725.  
  726. // Instance-specific data
  727. expando = "sizzle" + -(new Date()),
  728. preferredDoc = window.document,
  729. dirruns = 0,
  730. done = 0,
  731. classCache = createCache(),
  732. tokenCache = createCache(),
  733. compilerCache = createCache(),
  734. sortOrder = function(a, b)
  735. {
  736. if (a === b)
  737. {
  738. hasDuplicate = true;
  739. }
  740. return 0;
  741. },
  742.  
  743. // General-purpose constants
  744. strundefined = typeof undefined,
  745. MAX_NEGATIVE = 1 << 31,
  746.  
  747. // Instance methods
  748. hasOwn = ({}).hasOwnProperty,
  749. arr = [],
  750. pop = arr.pop,
  751. push_native = arr.push,
  752. push = arr.push,
  753. slice = arr.slice,
  754. // Use a stripped-down indexOf if we can't use a native one
  755. indexOf = arr.indexOf || function(elem)
  756. {
  757. var i = 0,
  758. len = this.length;
  759. for (; i < len; i++)
  760. {
  761. if (this[i] === elem)
  762. {
  763. return i;
  764. }
  765. }
  766. return -1;
  767. },
  768.  
  769. booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  770.  
  771. // Regular expressions
  772.  
  773. // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
  774. whitespace = "[\\x20\\t\\r\\n\\f]",
  775. // http://www.w3.org/TR/css3-syntax/#characters
  776. characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
  777.  
  778. // Loosely modeled on CSS identifier characters
  779. // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
  780. // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  781. identifier = characterEncoding.replace("w", "w#"),
  782.  
  783. // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  784. attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
  785. // Operator (capture 2)
  786. "*([*^$|!~]?=)" + whitespace +
  787. // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  788. "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  789. "*\\]",
  790.  
  791. pseudos = ":(" + characterEncoding + ")(?:\\((" +
  792. // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  793. // 1. quoted (capture 3; capture 4 or capture 5)
  794. "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  795. // 2. simple (capture 6)
  796. "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  797. // 3. anything else (capture 2)
  798. ".*" +
  799. ")\\)|)",
  800.  
  801. // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  802. rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),
  803.  
  804. rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
  805. rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),
  806.  
  807. rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"),
  808.  
  809. rpseudo = new RegExp(pseudos),
  810. ridentifier = new RegExp("^" + identifier + "$"),
  811.  
  812. matchExpr = {
  813. "ID": new RegExp("^#(" + characterEncoding + ")"),
  814. "CLASS": new RegExp("^\\.(" + characterEncoding + ")"),
  815. "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
  816. "ATTR": new RegExp("^" + attributes),
  817. "PSEUDO": new RegExp("^" + pseudos),
  818. "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  819. "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  820. "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
  821. "bool": new RegExp("^(?:" + booleans + ")$", "i"),
  822. // For use in libraries implementing .is()
  823. // We use this for POS matching in `select`
  824. "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  825. whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
  826. },
  827.  
  828. rinputs = /^(?:input|select|textarea|button)$/i,
  829. rheader = /^h\d$/i,
  830.  
  831. rnative = /^[^{]+\{\s*\[native \w/,
  832.  
  833. // Easily-parseable/retrievable ID or TAG or CLASS selectors
  834. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  835.  
  836. rsibling = /[+~]/,
  837. rescape = /'|\\/g,
  838.  
  839. // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  840. runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"),
  841. funescape = function(_, escaped, escapedWhitespace)
  842. {
  843. var high = "0x" + escaped - 0x10000;
  844. // NaN means non-codepoint
  845. // Support: Firefox<24
  846. // Workaround erroneous numeric interpretation of +"0x"
  847. return high !== high || escapedWhitespace ?
  848. escaped :
  849. high < 0 ?
  850. // BMP codepoint
  851. String.fromCharCode(high + 0x10000) :
  852. // Supplemental Plane codepoint (surrogate pair)
  853. String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);
  854. };
  855.  
  856. // Optimize for push.apply( _, NodeList )
  857. try
  858. {
  859. push.apply(
  860. (arr = slice.call(preferredDoc.childNodes)),
  861. preferredDoc.childNodes
  862. );
  863. // Support: Android<4.0
  864. // Detect silently failing push.apply
  865. arr[preferredDoc.childNodes.length].nodeType;
  866. } catch (e)
  867. {
  868. push = {
  869. apply: arr.length ?
  870.  
  871. // Leverage slice if possible
  872. function(target, els)
  873. {
  874. push_native.apply(target, slice.call(els));
  875. } :
  876.  
  877. // Support: IE<9
  878. // Otherwise append directly
  879. function(target, els)
  880. {
  881. var j = target.length,
  882. i = 0;
  883. // Can't trust NodeList.length
  884. while ((target[j++] = els[i++])) { }
  885. target.length = j - 1;
  886. }
  887. };
  888. }
  889.  
  890. function Sizzle(selector, context, results, seed)
  891. {
  892. var match, elem, m, nodeType,
  893. // QSA vars
  894. i, groups, old, nid, newContext, newSelector;
  895.  
  896. if ((context ? context.ownerDocument || context : preferredDoc) !== document)
  897. {
  898. setDocument(context);
  899. }
  900.  
  901. context = context || document;
  902. results = results || [];
  903.  
  904. if (!selector || typeof selector !== "string")
  905. {
  906. return results;
  907. }
  908.  
  909. if ((nodeType = context.nodeType) !== 1 && nodeType !== 9)
  910. {
  911. return [];
  912. }
  913.  
  914. if (documentIsHTML && !seed)
  915. {
  916. // Shortcuts
  917. if ((match = rquickExpr.exec(selector)))
  918. {
  919. // Speed-up: Sizzle("#ID")
  920. if ((m = match[1]))
  921. {
  922. if (nodeType === 9)
  923. {
  924. elem = context.getElementById(m);
  925. // Check parentNode to catch when Blackberry 4.6 returns
  926. // nodes that are no longer in the document (jQuery #6963)
  927. if (elem && elem.parentNode)
  928. {
  929. // Handle the case where IE, Opera, and Webkit return items
  930. // by name instead of ID
  931. if (elem.id === m)
  932. {
  933. results.push(elem);
  934. return results;
  935. }
  936. } else
  937. {
  938. return results;
  939. }
  940. } else
  941. {
  942. // Context is not a document
  943. if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) &&
  944. contains(context, elem) && elem.id === m)
  945. {
  946. results.push(elem);
  947. return results;
  948. }
  949. }
  950.  
  951. // Speed-up: Sizzle("TAG")
  952. } else if (match[2])
  953. {
  954. push.apply(results, context.getElementsByTagName(selector));
  955. return results;
  956.  
  957. // Speed-up: Sizzle(".CLASS")
  958. } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName)
  959. {
  960. push.apply(results, context.getElementsByClassName(m));
  961. return results;
  962. }
  963. }
  964.  
  965. // QSA path
  966. if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector)))
  967. {
  968. nid = old = expando;
  969. newContext = context;
  970. newSelector = nodeType === 9 && selector;
  971.  
  972. // qSA works strangely on Element-rooted queries
  973. // We can work around this by specifying an extra ID on the root
  974. // and working up from there (Thanks to Andrew Dupont for the technique)
  975. // IE 8 doesn't work on object elements
  976. if (nodeType === 1 && context.nodeName.toLowerCase() !== "object")
  977. {
  978. groups = tokenize(selector);
  979.  
  980. if ((old = context.getAttribute("id")))
  981. {
  982. nid = old.replace(rescape, "\\$&");
  983. } else
  984. {
  985. context.setAttribute("id", nid);
  986. }
  987. nid = "[id='" + nid + "'] ";
  988.  
  989. i = groups.length;
  990. while (i--)
  991. {
  992. groups[i] = nid + toSelector(groups[i]);
  993. }
  994. newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
  995. newSelector = groups.join(",");
  996. }
  997.  
  998. if (newSelector)
  999. {
  1000. try
  1001. {
  1002. push.apply(results,
  1003. newContext.querySelectorAll(newSelector)
  1004. );
  1005. return results;
  1006. } catch (qsaError)
  1007. {
  1008. } finally
  1009. {
  1010. if (!old)
  1011. {
  1012. context.removeAttribute("id");
  1013. }
  1014. }
  1015. }
  1016. }
  1017. }
  1018.  
  1019. // All others
  1020. return select(selector.replace(rtrim, "$1"), context, results, seed);
  1021. }
  1022.  
  1023. /**
  1024. * Create key-value caches of limited size
  1025. * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
  1026. * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  1027. * deleting the oldest entry
  1028. */
  1029. function createCache()
  1030. {
  1031. var keys = [];
  1032.  
  1033. function cache(key, value)
  1034. {
  1035. // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  1036. if (keys.push(key + " ") > Expr.cacheLength)
  1037. {
  1038. // Only keep the most recent entries
  1039. delete cache[keys.shift()];
  1040. }
  1041. return (cache[key + " "] = value);
  1042. }
  1043. return cache;
  1044. }
  1045.  
  1046. /**
  1047. * Mark a function for special use by Sizzle
  1048. * @param {Function} fn The function to mark
  1049. */
  1050. function markFunction(fn)
  1051. {
  1052. fn[expando] = true;
  1053. return fn;
  1054. }
  1055.  
  1056. /**
  1057. * Support testing using an element
  1058. * @param {Function} fn Passed the created div and expects a boolean result
  1059. */
  1060. function assert(fn)
  1061. {
  1062. var div = document.createElement("div");
  1063.  
  1064. try
  1065. {
  1066. return !!fn(div);
  1067. } catch (e)
  1068. {
  1069. return false;
  1070. } finally
  1071. {
  1072. // Remove from its parent by default
  1073. if (div.parentNode)
  1074. {
  1075. div.parentNode.removeChild(div);
  1076. }
  1077. // release memory in IE
  1078. div = null;
  1079. }
  1080. }
  1081.  
  1082. /**
  1083. * Adds the same handler for all of the specified attrs
  1084. * @param {String} attrs Pipe-separated list of attributes
  1085. * @param {Function} handler The method that will be applied
  1086. */
  1087. function addHandle(attrs, handler)
  1088. {
  1089. var arr = attrs.split("|"),
  1090. i = attrs.length;
  1091.  
  1092. while (i--)
  1093. {
  1094. Expr.attrHandle[arr[i]] = handler;
  1095. }
  1096. }
  1097.  
  1098. /**
  1099. * Checks document order of two siblings
  1100. * @param {Element} a
  1101. * @param {Element} b
  1102. * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  1103. */
  1104. function siblingCheck(a, b)
  1105. {
  1106. var cur = b && a,
  1107. diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  1108. (~b.sourceIndex || MAX_NEGATIVE) -
  1109. (~a.sourceIndex || MAX_NEGATIVE);
  1110.  
  1111. // Use IE sourceIndex if available on both nodes
  1112. if (diff)
  1113. {
  1114. return diff;
  1115. }
  1116.  
  1117. // Check if b follows a
  1118. if (cur)
  1119. {
  1120. while ((cur = cur.nextSibling))
  1121. {
  1122. if (cur === b)
  1123. {
  1124. return -1;
  1125. }
  1126. }
  1127. }
  1128.  
  1129. return a ? 1 : -1;
  1130. }
  1131.  
  1132. /**
  1133. * Returns a function to use in pseudos for input types
  1134. * @param {String} type
  1135. */
  1136. function createInputPseudo(type)
  1137. {
  1138. return function(elem)
  1139. {
  1140. var name = elem.nodeName.toLowerCase();
  1141. return name === "input" && elem.type === type;
  1142. };
  1143. }
  1144.  
  1145. /**
  1146. * Returns a function to use in pseudos for buttons
  1147. * @param {String} type
  1148. */
  1149. function createButtonPseudo(type)
  1150. {
  1151. return function(elem)
  1152. {
  1153. var name = elem.nodeName.toLowerCase();
  1154. return (name === "input" || name === "button") && elem.type === type;
  1155. };
  1156. }
  1157.  
  1158. /**
  1159. * Returns a function to use in pseudos for positionals
  1160. * @param {Function} fn
  1161. */
  1162. function createPositionalPseudo(fn)
  1163. {
  1164. return markFunction(function(argument)
  1165. {
  1166. argument = +argument;
  1167. return markFunction(function(seed, matches)
  1168. {
  1169. var j,
  1170. matchIndexes = fn([], seed.length, argument),
  1171. i = matchIndexes.length;
  1172.  
  1173. // Match elements found at the specified indexes
  1174. while (i--)
  1175. {
  1176. if (seed[(j = matchIndexes[i])])
  1177. {
  1178. seed[j] = !(matches[j] = seed[j]);
  1179. }
  1180. }
  1181. });
  1182. });
  1183. }
  1184.  
  1185. /**
  1186. * Checks a node for validity as a Sizzle context
  1187. * @param {Element|Object=} context
  1188. * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  1189. */
  1190. function testContext(context)
  1191. {
  1192. return context && typeof context.getElementsByTagName !== strundefined && context;
  1193. }
  1194.  
  1195. // Expose support vars for convenience
  1196. support = Sizzle.support = {};
  1197.  
  1198. /**
  1199. * Detects XML nodes
  1200. * @param {Element|Object} elem An element or a document
  1201. * @returns {Boolean} True iff elem is a non-HTML XML node
  1202. */
  1203. isXML = Sizzle.isXML = function(elem)
  1204. {
  1205. // documentElement is verified for cases where it doesn't yet exist
  1206. // (such as loading iframes in IE - #4833)
  1207. var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  1208. return documentElement ? documentElement.nodeName !== "HTML" : false;
  1209. };
  1210.  
  1211. /**
  1212. * Sets document-related variables once based on the current document
  1213. * @param {Element|Object} [doc] An element or document object to use to set the document
  1214. * @returns {Object} Returns the current document
  1215. */
  1216. setDocument = Sizzle.setDocument = function(node)
  1217. {
  1218. var hasCompare,
  1219. doc = node ? node.ownerDocument || node : preferredDoc,
  1220. parent = doc.defaultView;
  1221.  
  1222. // If no document and documentElement is available, return
  1223. if (doc === document || doc.nodeType !== 9 || !doc.documentElement)
  1224. {
  1225. return document;
  1226. }
  1227.  
  1228. // Set our document
  1229. document = doc;
  1230. docElem = doc.documentElement;
  1231.  
  1232. // Support tests
  1233. documentIsHTML = !isXML(doc);
  1234.  
  1235. // Support: IE>8
  1236. // If iframe document is assigned to "document" variable and if iframe has been reloaded,
  1237. // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  1238. // IE6-8 do not support the defaultView property so parent will be undefined
  1239. if (parent && parent !== parent.top)
  1240. {
  1241. // IE11 does not have attachEvent, so all must suffer
  1242. if (parent.addEventListener)
  1243. {
  1244. parent.addEventListener("unload", function()
  1245. {
  1246. setDocument();
  1247. }, false);
  1248. } else if (parent.attachEvent)
  1249. {
  1250. parent.attachEvent("onunload", function()
  1251. {
  1252. setDocument();
  1253. });
  1254. }
  1255. }
  1256.  
  1257. /* Attributes
  1258. ---------------------------------------------------------------------- */
  1259.  
  1260. // Support: IE<8
  1261. // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
  1262. support.attributes = assert(function(div)
  1263. {
  1264. div.className = "i";
  1265. return !div.getAttribute("className");
  1266. });
  1267.  
  1268. /* getElement(s)By*
  1269. ---------------------------------------------------------------------- */
  1270.  
  1271. // Check if getElementsByTagName("*") returns only elements
  1272. support.getElementsByTagName = assert(function(div)
  1273. {
  1274. div.appendChild(doc.createComment(""));
  1275. return !div.getElementsByTagName("*").length;
  1276. });
  1277.  
  1278. // Check if getElementsByClassName can be trusted
  1279. support.getElementsByClassName = rnative.test(doc.getElementsByClassName) && assert(function(div)
  1280. {
  1281. div.innerHTML = "<div class='a'></div><div class='a i'></div>";
  1282.  
  1283. // Support: Safari<4
  1284. // Catch class over-caching
  1285. div.firstChild.className = "i";
  1286. // Support: Opera<10
  1287. // Catch gEBCN failure to find non-leading classes
  1288. return div.getElementsByClassName("i").length === 2;
  1289. });
  1290.  
  1291. // Support: IE<10
  1292. // Check if getElementById returns elements by name
  1293. // The broken getElementById methods don't pick up programatically-set names,
  1294. // so use a roundabout getElementsByName test
  1295. support.getById = assert(function(div)
  1296. {
  1297. docElem.appendChild(div).id = expando;
  1298. return !doc.getElementsByName || !doc.getElementsByName(expando).length;
  1299. });
  1300.  
  1301. // ID find and filter
  1302. if (support.getById)
  1303. {
  1304. Expr.find["ID"] = function(id, context)
  1305. {
  1306. if (typeof context.getElementById !== strundefined && documentIsHTML)
  1307. {
  1308. var m = context.getElementById(id);
  1309. // Check parentNode to catch when Blackberry 4.6 returns
  1310. // nodes that are no longer in the document #6963
  1311. return m && m.parentNode ? [m] : [];
  1312. }
  1313. };
  1314. Expr.filter["ID"] = function(id)
  1315. {
  1316. var attrId = id.replace(runescape, funescape);
  1317. return function(elem)
  1318. {
  1319. return elem.getAttribute("id") === attrId;
  1320. };
  1321. };
  1322. } else
  1323. {
  1324. // Support: IE6/7
  1325. // getElementById is not reliable as a find shortcut
  1326. delete Expr.find["ID"];
  1327.  
  1328. Expr.filter["ID"] = function(id)
  1329. {
  1330. var attrId = id.replace(runescape, funescape);
  1331. return function(elem)
  1332. {
  1333. var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
  1334. return node && node.value === attrId;
  1335. };
  1336. };
  1337. }
  1338.  
  1339. // Tag
  1340. Expr.find["TAG"] = support.getElementsByTagName ?
  1341. function(tag, context)
  1342. {
  1343. if (typeof context.getElementsByTagName !== strundefined)
  1344. {
  1345. return context.getElementsByTagName(tag);
  1346. }
  1347. } :
  1348. function(tag, context)
  1349. {
  1350. var elem,
  1351. tmp = [],
  1352. i = 0,
  1353. results = context.getElementsByTagName(tag);
  1354.  
  1355. // Filter out possible comments
  1356. if (tag === "*")
  1357. {
  1358. while ((elem = results[i++]))
  1359. {
  1360. if (elem.nodeType === 1)
  1361. {
  1362. tmp.push(elem);
  1363. }
  1364. }
  1365.  
  1366. return tmp;
  1367. }
  1368. return results;
  1369. };
  1370.  
  1371. // Class
  1372. Expr.find["CLASS"] = support.getElementsByClassName && function(className, context)
  1373. {
  1374. if (typeof context.getElementsByClassName !== strundefined && documentIsHTML)
  1375. {
  1376. return context.getElementsByClassName(className);
  1377. }
  1378. };
  1379.  
  1380. /* QSA/matchesSelector
  1381. ---------------------------------------------------------------------- */
  1382.  
  1383. // QSA and matchesSelector support
  1384.  
  1385. // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  1386. rbuggyMatches = [];
  1387.  
  1388. // qSa(:focus) reports false when true (Chrome 21)
  1389. // We allow this because of a bug in IE8/9 that throws an error
  1390. // whenever `document.activeElement` is accessed on an iframe
  1391. // So, we allow :focus to pass through QSA all the time to avoid the IE error
  1392. // See http://bugs.jquery.com/ticket/13378
  1393. rbuggyQSA = [];
  1394.  
  1395. if ((support.qsa = rnative.test(doc.querySelectorAll)))
  1396. {
  1397. // Build QSA regex
  1398. // Regex strategy adopted from Diego Perini
  1399. assert(function(div)
  1400. {
  1401. // Select is set to empty string on purpose
  1402. // This is to test IE's treatment of not explicitly
  1403. // setting a boolean content attribute,
  1404. // since its presence should be enough
  1405. // http://bugs.jquery.com/ticket/12359
  1406. div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
  1407.  
  1408. // Support: IE8, Opera 11-12.16
  1409. // Nothing should be selected when empty strings follow ^= or $= or *=
  1410. // The test attribute must be unknown in Opera but "safe" for WinRT
  1411. // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  1412. if (div.querySelectorAll("[msallowclip^='']").length)
  1413. {
  1414. rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")");
  1415. }
  1416.  
  1417. // Support: IE8
  1418. // Boolean attributes and "value" are not treated correctly
  1419. if (!div.querySelectorAll("[selected]").length)
  1420. {
  1421. rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")");
  1422. }
  1423.  
  1424. // Webkit/Opera - :checked should return selected option elements
  1425. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1426. // IE8 throws error here and will not see later tests
  1427. if (!div.querySelectorAll(":checked").length)
  1428. {
  1429. rbuggyQSA.push(":checked");
  1430. }
  1431. });
  1432.  
  1433. assert(function(div)
  1434. {
  1435. // Support: Windows 8 Native Apps
  1436. // The type and name attributes are restricted during .innerHTML assignment
  1437. var input = doc.createElement("input");
  1438. input.setAttribute("type", "hidden");
  1439. div.appendChild(input).setAttribute("name", "D");
  1440.  
  1441. // Support: IE8
  1442. // Enforce case-sensitivity of name attribute
  1443. if (div.querySelectorAll("[name=d]").length)
  1444. {
  1445. rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?=");
  1446. }
  1447.  
  1448. // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  1449. // IE8 throws error here and will not see later tests
  1450. if (!div.querySelectorAll(":enabled").length)
  1451. {
  1452. rbuggyQSA.push(":enabled", ":disabled");
  1453. }
  1454.  
  1455. // Opera 10-11 does not throw on post-comma invalid pseudos
  1456. div.querySelectorAll("*,:x");
  1457. rbuggyQSA.push(",.*:");
  1458. });
  1459. }
  1460.  
  1461. if ((support.matchesSelector = rnative.test((matches = docElem.matches ||
  1462. docElem.webkitMatchesSelector ||
  1463. docElem.mozMatchesSelector ||
  1464. docElem.oMatchesSelector ||
  1465. docElem.msMatchesSelector))))
  1466. {
  1467. assert(function(div)
  1468. {
  1469. // Check to see if it's possible to do matchesSelector
  1470. // on a disconnected node (IE 9)
  1471. support.disconnectedMatch = matches.call(div, "div");
  1472.  
  1473. // This should fail with an exception
  1474. // Gecko does not error, returns false instead
  1475. matches.call(div, "[s!='']:x");
  1476. rbuggyMatches.push("!=", pseudos);
  1477. });
  1478. }
  1479.  
  1480. rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|"));
  1481. rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|"));
  1482.  
  1483. /* Contains
  1484. ---------------------------------------------------------------------- */
  1485. hasCompare = rnative.test(docElem.compareDocumentPosition);
  1486.  
  1487. // Element contains another
  1488. // Purposefully does not implement inclusive descendent
  1489. // As in, an element does not contain itself
  1490. contains = hasCompare || rnative.test(docElem.contains) ?
  1491. function(a, b)
  1492. {
  1493. var adown = a.nodeType === 9 ? a.documentElement : a,
  1494. bup = b && b.parentNode;
  1495. return a === bup || !!(bup && bup.nodeType === 1 && (
  1496. adown.contains ?
  1497. adown.contains(bup) :
  1498. a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16
  1499. ));
  1500. } :
  1501. function(a, b)
  1502. {
  1503. if (b)
  1504. {
  1505. while ((b = b.parentNode))
  1506. {
  1507. if (b === a)
  1508. {
  1509. return true;
  1510. }
  1511. }
  1512. }
  1513. return false;
  1514. };
  1515.  
  1516. /* Sorting
  1517. ---------------------------------------------------------------------- */
  1518.  
  1519. // Document order sorting
  1520. sortOrder = hasCompare ?
  1521. function(a, b)
  1522. {
  1523. // Flag for duplicate removal
  1524. if (a === b)
  1525. {
  1526. hasDuplicate = true;
  1527. return 0;
  1528. }
  1529.  
  1530. // Sort on method existence if only one input has compareDocumentPosition
  1531. var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  1532. if (compare)
  1533. {
  1534. return compare;
  1535. }
  1536.  
  1537. // Calculate position if both inputs belong to the same document
  1538. compare = (a.ownerDocument || a) === (b.ownerDocument || b) ?
  1539. a.compareDocumentPosition(b) :
  1540.  
  1541. // Otherwise we know they are disconnected
  1542. 1;
  1543.  
  1544. // Disconnected nodes
  1545. if (compare & 1 ||
  1546. (!support.sortDetached && b.compareDocumentPosition(a) === compare))
  1547. {
  1548. // Choose the first element that is related to our preferred document
  1549. if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a))
  1550. {
  1551. return -1;
  1552. }
  1553. if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b))
  1554. {
  1555. return 1;
  1556. }
  1557.  
  1558. // Maintain original order
  1559. return sortInput ?
  1560. (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
  1561. 0;
  1562. }
  1563.  
  1564. return compare & 4 ? -1 : 1;
  1565. } :
  1566. function(a, b)
  1567. {
  1568. // Exit early if the nodes are identical
  1569. if (a === b)
  1570. {
  1571. hasDuplicate = true;
  1572. return 0;
  1573. }
  1574.  
  1575. var cur,
  1576. i = 0,
  1577. aup = a.parentNode,
  1578. bup = b.parentNode,
  1579. ap = [a],
  1580. bp = [b];
  1581.  
  1582. // Parentless nodes are either documents or disconnected
  1583. if (!aup || !bup)
  1584. {
  1585. return a === doc ? -1 :
  1586. b === doc ? 1 :
  1587. aup ? -1 :
  1588. bup ? 1 :
  1589. sortInput ?
  1590. (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) :
  1591. 0;
  1592.  
  1593. // If the nodes are siblings, we can do a quick check
  1594. } else if (aup === bup)
  1595. {
  1596. return siblingCheck(a, b);
  1597. }
  1598.  
  1599. // Otherwise we need full lists of their ancestors for comparison
  1600. cur = a;
  1601. while ((cur = cur.parentNode))
  1602. {
  1603. ap.unshift(cur);
  1604. }
  1605. cur = b;
  1606. while ((cur = cur.parentNode))
  1607. {
  1608. bp.unshift(cur);
  1609. }
  1610.  
  1611. // Walk down the tree looking for a discrepancy
  1612. while (ap[i] === bp[i])
  1613. {
  1614. i++;
  1615. }
  1616.  
  1617. return i ?
  1618. // Do a sibling check if the nodes have a common ancestor
  1619. siblingCheck(ap[i], bp[i]) :
  1620.  
  1621. // Otherwise nodes in our document sort first
  1622. ap[i] === preferredDoc ? -1 :
  1623. bp[i] === preferredDoc ? 1 :
  1624. 0;
  1625. };
  1626.  
  1627. return doc;
  1628. };
  1629.  
  1630. Sizzle.matches = function(expr, elements)
  1631. {
  1632. return Sizzle(expr, null, null, elements);
  1633. };
  1634.  
  1635. Sizzle.matchesSelector = function(elem, expr)
  1636. {
  1637. // Set document vars if needed
  1638. if ((elem.ownerDocument || elem) !== document)
  1639. {
  1640. setDocument(elem);
  1641. }
  1642.  
  1643. // Make sure that attribute selectors are quoted
  1644. expr = expr.replace(rattributeQuotes, "='$1']");
  1645.  
  1646. if (support.matchesSelector && documentIsHTML &&
  1647. (!rbuggyMatches || !rbuggyMatches.test(expr)) &&
  1648. (!rbuggyQSA || !rbuggyQSA.test(expr)))
  1649. {
  1650. try
  1651. {
  1652. var ret = matches.call(elem, expr);
  1653.  
  1654. // IE 9's matchesSelector returns false on disconnected nodes
  1655. if (ret || support.disconnectedMatch ||
  1656. // As well, disconnected nodes are said to be in a document
  1657. // fragment in IE 9
  1658. elem.document && elem.document.nodeType !== 11)
  1659. {
  1660. return ret;
  1661. }
  1662. } catch (e) { }
  1663. }
  1664.  
  1665. return Sizzle(expr, document, null, [elem]).length > 0;
  1666. };
  1667.  
  1668. Sizzle.contains = function(context, elem)
  1669. {
  1670. // Set document vars if needed
  1671. if ((context.ownerDocument || context) !== document)
  1672. {
  1673. setDocument(context);
  1674. }
  1675. return contains(context, elem);
  1676. };
  1677.  
  1678. Sizzle.attr = function(elem, name)
  1679. {
  1680. // Set document vars if needed
  1681. if ((elem.ownerDocument || elem) !== document)
  1682. {
  1683. setDocument(elem);
  1684. }
  1685.  
  1686. var fn = Expr.attrHandle[name.toLowerCase()],
  1687. // Don't get fooled by Object.prototype properties (jQuery #13807)
  1688. val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ?
  1689. fn(elem, name, !documentIsHTML) :
  1690. undefined;
  1691.  
  1692. return val !== undefined ?
  1693. val :
  1694. support.attributes || !documentIsHTML ?
  1695. elem.getAttribute(name) :
  1696. (val = elem.getAttributeNode(name)) && val.specified ?
  1697. val.value :
  1698. null;
  1699. };
  1700.  
  1701. Sizzle.error = function(msg)
  1702. {
  1703. throw new Error("Syntax error, unrecognized expression: " + msg);
  1704. };
  1705.  
  1706. /**
  1707. * Document sorting and removing duplicates
  1708. * @param {ArrayLike} results
  1709. */
  1710. Sizzle.uniqueSort = function(results)
  1711. {
  1712. var elem,
  1713. duplicates = [],
  1714. j = 0,
  1715. i = 0;
  1716.  
  1717. // Unless we *know* we can detect duplicates, assume their presence
  1718. hasDuplicate = !support.detectDuplicates;
  1719. sortInput = !support.sortStable && results.slice(0);
  1720. results.sort(sortOrder);
  1721.  
  1722. if (hasDuplicate)
  1723. {
  1724. while ((elem = results[i++]))
  1725. {
  1726. if (elem === results[i])
  1727. {
  1728. j = duplicates.push(i);
  1729. }
  1730. }
  1731. while (j--)
  1732. {
  1733. results.splice(duplicates[j], 1);
  1734. }
  1735. }
  1736.  
  1737. // Clear input after sorting to release objects
  1738. // See https://github.com/jquery/sizzle/pull/225
  1739. sortInput = null;
  1740.  
  1741. return results;
  1742. };
  1743.  
  1744. /**
  1745. * Utility function for retrieving the text value of an array of DOM nodes
  1746. * @param {Array|Element} elem
  1747. */
  1748. getText = Sizzle.getText = function(elem)
  1749. {
  1750. var node,
  1751. ret = "",
  1752. i = 0,
  1753. nodeType = elem.nodeType;
  1754.  
  1755. if (!nodeType)
  1756. {
  1757. // If no nodeType, this is expected to be an array
  1758. while ((node = elem[i++]))
  1759. {
  1760. // Do not traverse comment nodes
  1761. ret += getText(node);
  1762. }
  1763. } else if (nodeType === 1 || nodeType === 9 || nodeType === 11)
  1764. {
  1765. // Use textContent for elements
  1766. // innerText usage removed for consistency of new lines (jQuery #11153)
  1767. if (typeof elem.textContent === "string")
  1768. {
  1769. return elem.textContent;
  1770. } else
  1771. {
  1772. // Traverse its children
  1773. for (elem = elem.firstChild; elem; elem = elem.nextSibling)
  1774. {
  1775. ret += getText(elem);
  1776. }
  1777. }
  1778. } else if (nodeType === 3 || nodeType === 4)
  1779. {
  1780. return elem.nodeValue;
  1781. }
  1782. // Do not include comment or processing instruction nodes
  1783.  
  1784. return ret;
  1785. };
  1786.  
  1787. Expr = Sizzle.selectors = {
  1788. // Can be adjusted by the user
  1789. cacheLength: 50,
  1790.  
  1791. createPseudo: markFunction,
  1792.  
  1793. match: matchExpr,
  1794.  
  1795. attrHandle: {},
  1796.  
  1797. find: {},
  1798.  
  1799. relative: {
  1800. ">": { dir: "parentNode", first: true },
  1801. " ": { dir: "parentNode" },
  1802. "+": { dir: "previousSibling", first: true },
  1803. "~": { dir: "previousSibling" }
  1804. },
  1805.  
  1806. preFilter: {
  1807. "ATTR": function(match)
  1808. {
  1809. match[1] = match[1].replace(runescape, funescape);
  1810.  
  1811. // Move the given value to match[3] whether quoted or unquoted
  1812. match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape);
  1813.  
  1814. if (match[2] === "~=")
  1815. {
  1816. match[3] = " " + match[3] + " ";
  1817. }
  1818.  
  1819. return match.slice(0, 4);
  1820. },
  1821.  
  1822. "CHILD": function(match)
  1823. {
  1824. /* matches from matchExpr["CHILD"]
  1825. 1 type (only|nth|...)
  1826. 2 what (child|of-type)
  1827. 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  1828. 4 xn-component of xn+y argument ([+-]?\d*n|)
  1829. 5 sign of xn-component
  1830. 6 x of xn-component
  1831. 7 sign of y-component
  1832. 8 y of y-component
  1833. */
  1834. match[1] = match[1].toLowerCase();
  1835.  
  1836. if (match[1].slice(0, 3) === "nth")
  1837. {
  1838. // nth-* requires argument
  1839. if (!match[3])
  1840. {
  1841. Sizzle.error(match[0]);
  1842. }
  1843.  
  1844. // numeric x and y parameters for Expr.filter.CHILD
  1845. // remember that false/true cast respectively to 0/1
  1846. match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd"));
  1847. match[5] = +((match[7] + match[8]) || match[3] === "odd");
  1848.  
  1849. // other types prohibit arguments
  1850. } else if (match[3])
  1851. {
  1852. Sizzle.error(match[0]);
  1853. }
  1854.  
  1855. return match;
  1856. },
  1857.  
  1858. "PSEUDO": function(match)
  1859. {
  1860. var excess,
  1861. unquoted = !match[6] && match[2];
  1862.  
  1863. if (matchExpr["CHILD"].test(match[0]))
  1864. {
  1865. return null;
  1866. }
  1867.  
  1868. // Accept quoted arguments as-is
  1869. if (match[3])
  1870. {
  1871. match[2] = match[4] || match[5] || "";
  1872.  
  1873. // Strip excess characters from unquoted arguments
  1874. } else if (unquoted && rpseudo.test(unquoted) &&
  1875. // Get excess from tokenize (recursively)
  1876. (excess = tokenize(unquoted, true)) &&
  1877. // advance to the next closing parenthesis
  1878. (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length))
  1879. {
  1880. // excess is a negative index
  1881. match[0] = match[0].slice(0, excess);
  1882. match[2] = unquoted.slice(0, excess);
  1883. }
  1884.  
  1885. // Return only captures needed by the pseudo filter method (type and argument)
  1886. return match.slice(0, 3);
  1887. }
  1888. },
  1889.  
  1890. filter: {
  1891. "TAG": function(nodeNameSelector)
  1892. {
  1893. var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
  1894. return nodeNameSelector === "*" ?
  1895. function() { return true; } :
  1896. function(elem)
  1897. {
  1898. return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  1899. };
  1900. },
  1901.  
  1902. "CLASS": function(className)
  1903. {
  1904. var pattern = classCache[className + " "];
  1905.  
  1906. return pattern ||
  1907. (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) &&
  1908. classCache(className, function(elem)
  1909. {
  1910. return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "");
  1911. });
  1912. },
  1913.  
  1914. "ATTR": function(name, operator, check)
  1915. {
  1916. return function(elem)
  1917. {
  1918. var result = Sizzle.attr(elem, name);
  1919.  
  1920. if (result == null)
  1921. {
  1922. return operator === "!=";
  1923. }
  1924. if (!operator)
  1925. {
  1926. return true;
  1927. }
  1928.  
  1929. result += "";
  1930.  
  1931. return operator === "=" ? result === check :
  1932. operator === "!=" ? result !== check :
  1933. operator === "^=" ? check && result.indexOf(check) === 0 :
  1934. operator === "*=" ? check && result.indexOf(check) > -1 :
  1935. operator === "$=" ? check && result.slice(-check.length) === check :
  1936. operator === "~=" ? (" " + result + " ").indexOf(check) > -1 :
  1937. operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" :
  1938. false;
  1939. };
  1940. },
  1941.  
  1942. "CHILD": function(type, what, argument, first, last)
  1943. {
  1944. var simple = type.slice(0, 3) !== "nth",
  1945. forward = type.slice(-4) !== "last",
  1946. ofType = what === "of-type";
  1947.  
  1948. return first === 1 && last === 0 ?
  1949.  
  1950. // Shortcut for :nth-*(n)
  1951. function(elem)
  1952. {
  1953. return !!elem.parentNode;
  1954. } :
  1955.  
  1956. function(elem, context, xml)
  1957. {
  1958. var cache, outerCache, node, diff, nodeIndex, start,
  1959. dir = simple !== forward ? "nextSibling" : "previousSibling",
  1960. parent = elem.parentNode,
  1961. name = ofType && elem.nodeName.toLowerCase(),
  1962. useCache = !xml && !ofType;
  1963.  
  1964. if (parent)
  1965. {
  1966. // :(first|last|only)-(child|of-type)
  1967. if (simple)
  1968. {
  1969. while (dir)
  1970. {
  1971. node = elem;
  1972. while ((node = node[dir]))
  1973. {
  1974. if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1)
  1975. {
  1976. return false;
  1977. }
  1978. }
  1979. // Reverse direction for :only-* (if we haven't yet done so)
  1980. start = dir = type === "only" && !start && "nextSibling";
  1981. }
  1982. return true;
  1983. }
  1984.  
  1985. start = [forward ? parent.firstChild : parent.lastChild];
  1986.  
  1987. // non-xml :nth-child(...) stores cache data on `parent`
  1988. if (forward && useCache)
  1989. {
  1990. // Seek `elem` from a previously-cached index
  1991. outerCache = parent[expando] || (parent[expando] = {});
  1992. cache = outerCache[type] || [];
  1993. nodeIndex = cache[0] === dirruns && cache[1];
  1994. diff = cache[0] === dirruns && cache[2];
  1995. node = nodeIndex && parent.childNodes[nodeIndex];
  1996.  
  1997. while ((node = ++nodeIndex && node && node[dir] ||
  1998.  
  1999. // Fallback to seeking `elem` from the start
  2000. (diff = nodeIndex = 0) || start.pop()))
  2001. {
  2002. // When found, cache indexes on `parent` and break
  2003. if (node.nodeType === 1 && ++diff && node === elem)
  2004. {
  2005. outerCache[type] = [dirruns, nodeIndex, diff];
  2006. break;
  2007. }
  2008. }
  2009.  
  2010. // Use previously-cached element index if available
  2011. } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns)
  2012. {
  2013. diff = cache[1];
  2014.  
  2015. // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
  2016. } else
  2017. {
  2018. // Use the same loop as above to seek `elem` from the start
  2019. while ((node = ++nodeIndex && node && node[dir] ||
  2020. (diff = nodeIndex = 0) || start.pop()))
  2021. {
  2022. if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff)
  2023. {
  2024. // Cache the index of each encountered element
  2025. if (useCache)
  2026. {
  2027. (node[expando] || (node[expando] = {}))[type] = [dirruns, diff];
  2028. }
  2029.  
  2030. if (node === elem)
  2031. {
  2032. break;
  2033. }
  2034. }
  2035. }
  2036. }
  2037.  
  2038. // Incorporate the offset, then check against cycle size
  2039. diff -= last;
  2040. return diff === first || (diff % first === 0 && diff / first >= 0);
  2041. }
  2042. };
  2043. },
  2044.  
  2045. "PSEUDO": function(pseudo, argument)
  2046. {
  2047. // pseudo-class names are case-insensitive
  2048. // http://www.w3.org/TR/selectors/#pseudo-classes
  2049. // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  2050. // Remember that setFilters inherits from pseudos
  2051. var args,
  2052. fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] ||
  2053. Sizzle.error("unsupported pseudo: " + pseudo);
  2054.  
  2055. // The user may use createPseudo to indicate that
  2056. // arguments are needed to create the filter function
  2057. // just as Sizzle does
  2058. if (fn[expando])
  2059. {
  2060. return fn(argument);
  2061. }
  2062.  
  2063. // But maintain support for old signatures
  2064. if (fn.length > 1)
  2065. {
  2066. args = [pseudo, pseudo, "", argument];
  2067. return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ?
  2068. markFunction(function(seed, matches)
  2069. {
  2070. var idx,
  2071. matched = fn(seed, argument),
  2072. i = matched.length;
  2073. while (i--)
  2074. {
  2075. idx = indexOf.call(seed, matched[i]);
  2076. seed[idx] = !(matches[idx] = matched[i]);
  2077. }
  2078. }) :
  2079. function(elem)
  2080. {
  2081. return fn(elem, 0, args);
  2082. };
  2083. }
  2084.  
  2085. return fn;
  2086. }
  2087. },
  2088.  
  2089. pseudos: {
  2090. // Potentially complex pseudos
  2091. "not": markFunction(function(selector)
  2092. {
  2093. // Trim the selector passed to compile
  2094. // to avoid treating leading and trailing
  2095. // spaces as combinators
  2096. var input = [],
  2097. results = [],
  2098. matcher = compile(selector.replace(rtrim, "$1"));
  2099.  
  2100. return matcher[expando] ?
  2101. markFunction(function(seed, matches, context, xml)
  2102. {
  2103. var elem,
  2104. unmatched = matcher(seed, null, xml, []),
  2105. i = seed.length;
  2106.  
  2107. // Match elements unmatched by `matcher`
  2108. while (i--)
  2109. {
  2110. if ((elem = unmatched[i]))
  2111. {
  2112. seed[i] = !(matches[i] = elem);
  2113. }
  2114. }
  2115. }) :
  2116. function(elem, context, xml)
  2117. {
  2118. input[0] = elem;
  2119. matcher(input, null, xml, results);
  2120. return !results.pop();
  2121. };
  2122. }),
  2123.  
  2124. "has": markFunction(function(selector)
  2125. {
  2126. return function(elem)
  2127. {
  2128. return Sizzle(selector, elem).length > 0;
  2129. };
  2130. }),
  2131.  
  2132. "contains": markFunction(function(text)
  2133. {
  2134. return function(elem)
  2135. {
  2136. return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
  2137. };
  2138. }),
  2139.  
  2140. // "Whether an element is represented by a :lang() selector
  2141. // is based solely on the element's language value
  2142. // being equal to the identifier C,
  2143. // or beginning with the identifier C immediately followed by "-".
  2144. // The matching of C against the element's language value is performed case-insensitively.
  2145. // The identifier C does not have to be a valid language name."
  2146. // http://www.w3.org/TR/selectors/#lang-pseudo
  2147. "lang": markFunction(function(lang)
  2148. {
  2149. // lang value must be a valid identifier
  2150. if (!ridentifier.test(lang || ""))
  2151. {
  2152. Sizzle.error("unsupported lang: " + lang);
  2153. }
  2154. lang = lang.replace(runescape, funescape).toLowerCase();
  2155. return function(elem)
  2156. {
  2157. var elemLang;
  2158. do
  2159. {
  2160. if ((elemLang = documentIsHTML ?
  2161. elem.lang :
  2162. elem.getAttribute("xml:lang") || elem.getAttribute("lang")))
  2163. {
  2164. elemLang = elemLang.toLowerCase();
  2165. return elemLang === lang || elemLang.indexOf(lang + "-") === 0;
  2166. }
  2167. } while ((elem = elem.parentNode) && elem.nodeType === 1);
  2168. return false;
  2169. };
  2170. }),
  2171.  
  2172. // Miscellaneous
  2173. "target": function(elem)
  2174. {
  2175. var hash = window.location && window.location.hash;
  2176. return hash && hash.slice(1) === elem.id;
  2177. },
  2178.  
  2179. "root": function(elem)
  2180. {
  2181. return elem === docElem;
  2182. },
  2183.  
  2184. "focus": function(elem)
  2185. {
  2186. return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  2187. },
  2188.  
  2189. // Boolean properties
  2190. "enabled": function(elem)
  2191. {
  2192. return elem.disabled === false;
  2193. },
  2194.  
  2195. "disabled": function(elem)
  2196. {
  2197. return elem.disabled === true;
  2198. },
  2199.  
  2200. "checked": function(elem)
  2201. {
  2202. // In CSS3, :checked should return both checked and selected elements
  2203. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  2204. var nodeName = elem.nodeName.toLowerCase();
  2205. return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  2206. },
  2207.  
  2208. "selected": function(elem)
  2209. {
  2210. // Accessing this property makes selected-by-default
  2211. // options in Safari work properly
  2212. if (elem.parentNode)
  2213. {
  2214. elem.parentNode.selectedIndex;
  2215. }
  2216.  
  2217. return elem.selected === true;
  2218. },
  2219.  
  2220. // Contents
  2221. "empty": function(elem)
  2222. {
  2223. // http://www.w3.org/TR/selectors/#empty-pseudo
  2224. // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  2225. // but not by others (comment: 8; processing instruction: 7; etc.)
  2226. // nodeType < 6 works because attributes (2) do not appear as children
  2227. for (elem = elem.firstChild; elem; elem = elem.nextSibling)
  2228. {
  2229. if (elem.nodeType < 6)
  2230. {
  2231. return false;
  2232. }
  2233. }
  2234. return true;
  2235. },
  2236.  
  2237. "parent": function(elem)
  2238. {
  2239. return !Expr.pseudos["empty"](elem);
  2240. },
  2241.  
  2242. // Element/input types
  2243. "header": function(elem)
  2244. {
  2245. return rheader.test(elem.nodeName);
  2246. },
  2247.  
  2248. "input": function(elem)
  2249. {
  2250. return rinputs.test(elem.nodeName);
  2251. },
  2252.  
  2253. "button": function(elem)
  2254. {
  2255. var name = elem.nodeName.toLowerCase();
  2256. return name === "input" && elem.type === "button" || name === "button";
  2257. },
  2258.  
  2259. "text": function(elem)
  2260. {
  2261. var attr;
  2262. return elem.nodeName.toLowerCase() === "input" &&
  2263. elem.type === "text" &&
  2264.  
  2265. // Support: IE<8
  2266. // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  2267. ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text");
  2268. },
  2269.  
  2270. // Position-in-collection
  2271. "first": createPositionalPseudo(function()
  2272. {
  2273. return [0];
  2274. }),
  2275.  
  2276. "last": createPositionalPseudo(function(matchIndexes, length)
  2277. {
  2278. return [length - 1];
  2279. }),
  2280.  
  2281. "eq": createPositionalPseudo(function(matchIndexes, length, argument)
  2282. {
  2283. return [argument < 0 ? argument + length : argument];
  2284. }),
  2285.  
  2286. "even": createPositionalPseudo(function(matchIndexes, length)
  2287. {
  2288. var i = 0;
  2289. for (; i < length; i += 2)
  2290. {
  2291. matchIndexes.push(i);
  2292. }
  2293. return matchIndexes;
  2294. }),
  2295.  
  2296. "odd": createPositionalPseudo(function(matchIndexes, length)
  2297. {
  2298. var i = 1;
  2299. for (; i < length; i += 2)
  2300. {
  2301. matchIndexes.push(i);
  2302. }
  2303. return matchIndexes;
  2304. }),
  2305.  
  2306. "lt": createPositionalPseudo(function(matchIndexes, length, argument)
  2307. {
  2308. var i = argument < 0 ? argument + length : argument;
  2309. for (; --i >= 0;)
  2310. {
  2311. matchIndexes.push(i);
  2312. }
  2313. return matchIndexes;
  2314. }),
  2315.  
  2316. "gt": createPositionalPseudo(function(matchIndexes, length, argument)
  2317. {
  2318. var i = argument < 0 ? argument + length : argument;
  2319. for (; ++i < length;)
  2320. {
  2321. matchIndexes.push(i);
  2322. }
  2323. return matchIndexes;
  2324. })
  2325. }
  2326. };
  2327.  
  2328. Expr.pseudos["nth"] = Expr.pseudos["eq"];
  2329.  
  2330. // Add button/input type pseudos
  2331. for (i in { radio: true, checkbox: true, file: true, pazzwurd: true, image: true })
  2332. {
  2333. Expr.pseudos[i] = createInputPseudo(i);
  2334. }
  2335. for (i in { submit: true, reset: true })
  2336. {
  2337. Expr.pseudos[i] = createButtonPseudo(i);
  2338. }
  2339.  
  2340. // Easy API for creating new setFilters
  2341. function setFilters() { }
  2342. setFilters.prototype = Expr.filters = Expr.pseudos;
  2343. Expr.setFilters = new setFilters();
  2344.  
  2345. tokenize = Sizzle.tokenize = function(selector, parseOnly)
  2346. {
  2347. var matched, match, tokens, type,
  2348. soFar, groups, preFilters,
  2349. cached = tokenCache[selector + " "];
  2350.  
  2351. if (cached)
  2352. {
  2353. return parseOnly ? 0 : cached.slice(0);
  2354. }
  2355.  
  2356. soFar = selector;
  2357. groups = [];
  2358. preFilters = Expr.preFilter;
  2359.  
  2360. while (soFar)
  2361. {
  2362. // Comma and first run
  2363. if (!matched || (match = rcomma.exec(soFar)))
  2364. {
  2365. if (match)
  2366. {
  2367. // Don't consume trailing commas as valid
  2368. soFar = soFar.slice(match[0].length) || soFar;
  2369. }
  2370. groups.push((tokens = []));
  2371. }
  2372.  
  2373. matched = false;
  2374.  
  2375. // Combinators
  2376. if ((match = rcombinators.exec(soFar)))
  2377. {
  2378. matched = match.shift();
  2379. tokens.push({
  2380. value: matched,
  2381. // Cast descendant combinators to space
  2382. type: match[0].replace(rtrim, " ")
  2383. });
  2384. soFar = soFar.slice(matched.length);
  2385. }
  2386.  
  2387. // Filters
  2388. for (type in Expr.filter)
  2389. {
  2390. if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] ||
  2391. (match = preFilters[type](match))))
  2392. {
  2393. matched = match.shift();
  2394. tokens.push({
  2395. value: matched,
  2396. type: type,
  2397. matches: match
  2398. });
  2399. soFar = soFar.slice(matched.length);
  2400. }
  2401. }
  2402.  
  2403. if (!matched)
  2404. {
  2405. break;
  2406. }
  2407. }
  2408.  
  2409. // Return the length of the invalid excess
  2410. // if we're just parsing
  2411. // Otherwise, throw an error or return tokens
  2412. return parseOnly ?
  2413. soFar.length :
  2414. soFar ?
  2415. Sizzle.error(selector) :
  2416. // Cache the tokens
  2417. tokenCache(selector, groups).slice(0);
  2418. };
  2419.  
  2420. function toSelector(tokens)
  2421. {
  2422. var i = 0,
  2423. len = tokens.length,
  2424. selector = "";
  2425. for (; i < len; i++)
  2426. {
  2427. selector += tokens[i].value;
  2428. }
  2429. return selector;
  2430. }
  2431.  
  2432. function addCombinator(matcher, combinator, base)
  2433. {
  2434. var dir = combinator.dir,
  2435. checkNonElements = base && dir === "parentNode",
  2436. doneName = done++;
  2437.  
  2438. return combinator.first ?
  2439. // Check against closest ancestor/preceding element
  2440. function(elem, context, xml)
  2441. {
  2442. while ((elem = elem[dir]))
  2443. {
  2444. if (elem.nodeType === 1 || checkNonElements)
  2445. {
  2446. return matcher(elem, context, xml);
  2447. }
  2448. }
  2449. } :
  2450.  
  2451. // Check against all ancestor/preceding elements
  2452. function(elem, context, xml)
  2453. {
  2454. var oldCache, outerCache,
  2455. newCache = [dirruns, doneName];
  2456.  
  2457. // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
  2458. if (xml)
  2459. {
  2460. while ((elem = elem[dir]))
  2461. {
  2462. if (elem.nodeType === 1 || checkNonElements)
  2463. {
  2464. if (matcher(elem, context, xml))
  2465. {
  2466. return true;
  2467. }
  2468. }
  2469. }
  2470. } else
  2471. {
  2472. while ((elem = elem[dir]))
  2473. {
  2474. if (elem.nodeType === 1 || checkNonElements)
  2475. {
  2476. outerCache = elem[expando] || (elem[expando] = {});
  2477. if ((oldCache = outerCache[dir]) &&
  2478. oldCache[0] === dirruns && oldCache[1] === doneName)
  2479. {
  2480. // Assign to newCache so results back-propagate to previous elements
  2481. return (newCache[2] = oldCache[2]);
  2482. } else
  2483. {
  2484. // Reuse newcache so results back-propagate to previous elements
  2485. outerCache[dir] = newCache;
  2486.  
  2487. // A match means we're done; a fail means we have to keep checking
  2488. if ((newCache[2] = matcher(elem, context, xml)))
  2489. {
  2490. return true;
  2491. }
  2492. }
  2493. }
  2494. }
  2495. }
  2496. };
  2497. }
  2498.  
  2499. function elementMatcher(matchers)
  2500. {
  2501. return matchers.length > 1 ?
  2502. function(elem, context, xml)
  2503. {
  2504. var i = matchers.length;
  2505. while (i--)
  2506. {
  2507. if (!matchers[i](elem, context, xml))
  2508. {
  2509. return false;
  2510. }
  2511. }
  2512. return true;
  2513. } :
  2514. matchers[0];
  2515. }
  2516.  
  2517. function multipleContexts(selector, contexts, results)
  2518. {
  2519. var i = 0,
  2520. len = contexts.length;
  2521. for (; i < len; i++)
  2522. {
  2523. Sizzle(selector, contexts[i], results);
  2524. }
  2525. return results;
  2526. }
  2527.  
  2528. function condense(unmatched, map, filter, context, xml)
  2529. {
  2530. var elem,
  2531. newUnmatched = [],
  2532. i = 0,
  2533. len = unmatched.length,
  2534. mapped = map != null;
  2535.  
  2536. for (; i < len; i++)
  2537. {
  2538. if ((elem = unmatched[i]))
  2539. {
  2540. if (!filter || filter(elem, context, xml))
  2541. {
  2542. newUnmatched.push(elem);
  2543. if (mapped)
  2544. {
  2545. map.push(i);
  2546. }
  2547. }
  2548. }
  2549. }
  2550.  
  2551. return newUnmatched;
  2552. }
  2553.  
  2554. function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector)
  2555. {
  2556. if (postFilter && !postFilter[expando])
  2557. {
  2558. postFilter = setMatcher(postFilter);
  2559. }
  2560. if (postFinder && !postFinder[expando])
  2561. {
  2562. postFinder = setMatcher(postFinder, postSelector);
  2563. }
  2564. return markFunction(function(seed, results, context, xml)
  2565. {
  2566. var temp, i, elem,
  2567. preMap = [],
  2568. postMap = [],
  2569. preexisting = results.length,
  2570.  
  2571. // Get initial elements from seed or context
  2572. elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []),
  2573.  
  2574. // Prefilter to get matcher input, preserving a map for seed-results synchronization
  2575. matcherIn = preFilter && (seed || !selector) ?
  2576. condense(elems, preMap, preFilter, context, xml) :
  2577. elems,
  2578.  
  2579. matcherOut = matcher ?
  2580. // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  2581. postFinder || (seed ? preFilter : preexisting || postFilter) ?
  2582.  
  2583. // ...intermediate processing is necessary
  2584. [] :
  2585.  
  2586. // ...otherwise use results directly
  2587. results :
  2588. matcherIn;
  2589.  
  2590. // Find primary matches
  2591. if (matcher)
  2592. {
  2593. matcher(matcherIn, matcherOut, context, xml);
  2594. }
  2595.  
  2596. // Apply postFilter
  2597. if (postFilter)
  2598. {
  2599. temp = condense(matcherOut, postMap);
  2600. postFilter(temp, [], context, xml);
  2601.  
  2602. // Un-match failing elements by moving them back to matcherIn
  2603. i = temp.length;
  2604. while (i--)
  2605. {
  2606. if ((elem = temp[i]))
  2607. {
  2608. matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
  2609. }
  2610. }
  2611. }
  2612.  
  2613. if (seed)
  2614. {
  2615. if (postFinder || preFilter)
  2616. {
  2617. if (postFinder)
  2618. {
  2619. // Get the final matcherOut by condensing this intermediate into postFinder contexts
  2620. temp = [];
  2621. i = matcherOut.length;
  2622. while (i--)
  2623. {
  2624. if ((elem = matcherOut[i]))
  2625. {
  2626. // Restore matcherIn since elem is not yet a final match
  2627. temp.push((matcherIn[i] = elem));
  2628. }
  2629. }
  2630. postFinder(null, (matcherOut = []), temp, xml);
  2631. }
  2632.  
  2633. // Move matched elements from seed to results to keep them synchronized
  2634. i = matcherOut.length;
  2635. while (i--)
  2636. {
  2637. if ((elem = matcherOut[i]) &&
  2638. (temp = postFinder ? indexOf.call(seed, elem) : preMap[i]) > -1)
  2639. {
  2640. seed[temp] = !(results[temp] = elem);
  2641. }
  2642. }
  2643. }
  2644.  
  2645. // Add elements to results, through postFinder if defined
  2646. } else
  2647. {
  2648. matcherOut = condense(
  2649. matcherOut === results ?
  2650. matcherOut.splice(preexisting, matcherOut.length) :
  2651. matcherOut
  2652. );
  2653. if (postFinder)
  2654. {
  2655. postFinder(null, results, matcherOut, xml);
  2656. } else
  2657. {
  2658. push.apply(results, matcherOut);
  2659. }
  2660. }
  2661. });
  2662. }
  2663.  
  2664. function matcherFromTokens(tokens)
  2665. {
  2666. var checkContext, matcher, j,
  2667. len = tokens.length,
  2668. leadingRelative = Expr.relative[tokens[0].type],
  2669. implicitRelative = leadingRelative || Expr.relative[" "],
  2670. i = leadingRelative ? 1 : 0,
  2671.  
  2672. // The foundational matcher ensures that elements are reachable from top-level context(s)
  2673. matchContext = addCombinator(function(elem)
  2674. {
  2675. return elem === checkContext;
  2676. }, implicitRelative, true),
  2677. matchAnyContext = addCombinator(function(elem)
  2678. {
  2679. return indexOf.call(checkContext, elem) > -1;
  2680. }, implicitRelative, true),
  2681. matchers = [function(elem, context, xml)
  2682. {
  2683. return (!leadingRelative && (xml || context !== outermostContext)) || (
  2684. (checkContext = context).nodeType ?
  2685. matchContext(elem, context, xml) :
  2686. matchAnyContext(elem, context, xml));
  2687. }];
  2688.  
  2689. for (; i < len; i++)
  2690. {
  2691. if ((matcher = Expr.relative[tokens[i].type]))
  2692. {
  2693. matchers = [addCombinator(elementMatcher(matchers), matcher)];
  2694. } else
  2695. {
  2696. matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
  2697.  
  2698. // Return special upon seeing a positional matcher
  2699. if (matcher[expando])
  2700. {
  2701. // Find the next relative operator (if any) for proper handling
  2702. j = ++i;
  2703. for (; j < len; j++)
  2704. {
  2705. if (Expr.relative[tokens[j].type])
  2706. {
  2707. break;
  2708. }
  2709. }
  2710. return setMatcher(
  2711. i > 1 && elementMatcher(matchers),
  2712. i > 1 && toSelector(
  2713. // If the preceding token was a descendant combinator, insert an implicit any-element `*`
  2714. tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === " " ? "*" : "" })
  2715. ).replace(rtrim, "$1"),
  2716. matcher,
  2717. i < j && matcherFromTokens(tokens.slice(i, j)),
  2718. j < len && matcherFromTokens((tokens = tokens.slice(j))),
  2719. j < len && toSelector(tokens)
  2720. );
  2721. }
  2722. matchers.push(matcher);
  2723. }
  2724. }
  2725.  
  2726. return elementMatcher(matchers);
  2727. }
  2728.  
  2729. function matcherFromGroupMatchers(elementMatchers, setMatchers)
  2730. {
  2731. var bySet = setMatchers.length > 0,
  2732. byElement = elementMatchers.length > 0,
  2733. superMatcher = function(seed, context, xml, results, outermost)
  2734. {
  2735. var elem, j, matcher,
  2736. matchedCount = 0,
  2737. i = "0",
  2738. unmatched = seed && [],
  2739. setMatched = [],
  2740. contextBackup = outermostContext,
  2741. // We must always have either seed elements or outermost context
  2742. elems = seed || byElement && Expr.find["TAG"]("*", outermost),
  2743. // Use integer dirruns iff this is the outermost matcher
  2744. dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  2745. len = elems.length;
  2746.  
  2747. if (outermost)
  2748. {
  2749. outermostContext = context !== document && context;
  2750. }
  2751.  
  2752. // Add elements passing elementMatchers directly to results
  2753. // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
  2754. // Support: IE<9, Safari
  2755. // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  2756. for (; i !== len && (elem = elems[i]) != null; i++)
  2757. {
  2758. if (byElement && elem)
  2759. {
  2760. j = 0;
  2761. while ((matcher = elementMatchers[j++]))
  2762. {
  2763. if (matcher(elem, context, xml))
  2764. {
  2765. results.push(elem);
  2766. break;
  2767. }
  2768. }
  2769. if (outermost)
  2770. {
  2771. dirruns = dirrunsUnique;
  2772. }
  2773. }
  2774.  
  2775. // Track unmatched elements for set filters
  2776. if (bySet)
  2777. {
  2778. // They will have gone through all possible matchers
  2779. if ((elem = !matcher && elem))
  2780. {
  2781. matchedCount--;
  2782. }
  2783.  
  2784. // Lengthen the array for every element, matched or not
  2785. if (seed)
  2786. {
  2787. unmatched.push(elem);
  2788. }
  2789. }
  2790. }
  2791.  
  2792. // Apply set filters to unmatched elements
  2793. matchedCount += i;
  2794. if (bySet && i !== matchedCount)
  2795. {
  2796. j = 0;
  2797. while ((matcher = setMatchers[j++]))
  2798. {
  2799. matcher(unmatched, setMatched, context, xml);
  2800. }
  2801.  
  2802. if (seed)
  2803. {
  2804. // Reintegrate element matches to eliminate the need for sorting
  2805. if (matchedCount > 0)
  2806. {
  2807. while (i--)
  2808. {
  2809. if (!(unmatched[i] || setMatched[i]))
  2810. {
  2811. setMatched[i] = pop.call(results);
  2812. }
  2813. }
  2814. }
  2815.  
  2816. // Discard index placeholder values to get only actual matches
  2817. setMatched = condense(setMatched);
  2818. }
  2819.  
  2820. // Add matches to results
  2821. push.apply(results, setMatched);
  2822.  
  2823. // Seedless set matches succeeding multiple successful matchers stipulate sorting
  2824. if (outermost && !seed && setMatched.length > 0 &&
  2825. (matchedCount + setMatchers.length) > 1)
  2826. {
  2827. Sizzle.uniqueSort(results);
  2828. }
  2829. }
  2830.  
  2831. // Override manipulation of globals by nested matchers
  2832. if (outermost)
  2833. {
  2834. dirruns = dirrunsUnique;
  2835. outermostContext = contextBackup;
  2836. }
  2837.  
  2838. return unmatched;
  2839. };
  2840.  
  2841. return bySet ?
  2842. markFunction(superMatcher) :
  2843. superMatcher;
  2844. }
  2845.  
  2846. compile = Sizzle.compile = function(selector, match /* Internal Use Only */)
  2847. {
  2848. var i,
  2849. setMatchers = [],
  2850. elementMatchers = [],
  2851. cached = compilerCache[selector + " "];
  2852.  
  2853. if (!cached)
  2854. {
  2855. // Generate a function of recursive functions that can be used to check each element
  2856. if (!match)
  2857. {
  2858. match = tokenize(selector);
  2859. }
  2860. i = match.length;
  2861. while (i--)
  2862. {
  2863. cached = matcherFromTokens(match[i]);
  2864. if (cached[expando])
  2865. {
  2866. setMatchers.push(cached);
  2867. } else
  2868. {
  2869. elementMatchers.push(cached);
  2870. }
  2871. }
  2872.  
  2873. // Cache the compiled function
  2874. cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
  2875.  
  2876. // Save selector and tokenization
  2877. cached.selector = selector;
  2878. }
  2879. return cached;
  2880. };
  2881.  
  2882. /**
  2883. * A low-level selection function that works with Sizzle's compiled
  2884. * selector functions
  2885. * @param {String|Function} selector A selector or a pre-compiled
  2886. * selector function built with Sizzle.compile
  2887. * @param {Element} context
  2888. * @param {Array} [results]
  2889. * @param {Array} [seed] A set of elements to match against
  2890. */
  2891. select = Sizzle.select = function(selector, context, results, seed)
  2892. {
  2893. var i, tokens, token, type, find,
  2894. compiled = typeof selector === "function" && selector,
  2895. match = !seed && tokenize((selector = compiled.selector || selector));
  2896.  
  2897. results = results || [];
  2898.  
  2899. // Try to minimize operations if there is no seed and only one group
  2900. if (match.length === 1)
  2901. {
  2902. // Take a shortcut and set the context if the root selector is an ID
  2903. tokens = match[0] = match[0].slice(0);
  2904. if (tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  2905. support.getById && context.nodeType === 9 && documentIsHTML &&
  2906. Expr.relative[tokens[1].type])
  2907. {
  2908. context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0];
  2909. if (!context)
  2910. {
  2911. return results;
  2912.  
  2913. // Precompiled matchers will still verify ancestry, so step up a level
  2914. } else if (compiled)
  2915. {
  2916. context = context.parentNode;
  2917. }
  2918.  
  2919. selector = selector.slice(tokens.shift().value.length);
  2920. }
  2921.  
  2922. // Fetch a seed set for right-to-left matching
  2923. i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length;
  2924. while (i--)
  2925. {
  2926. token = tokens[i];
  2927.  
  2928. // Abort if we hit a combinator
  2929. if (Expr.relative[(type = token.type)])
  2930. {
  2931. break;
  2932. }
  2933. if ((find = Expr.find[type]))
  2934. {
  2935. // Search, expanding context for leading sibling combinators
  2936. if ((seed = find(
  2937. token.matches[0].replace(runescape, funescape),
  2938. rsibling.test(tokens[0].type) && testContext(context.parentNode) || context
  2939. )))
  2940. {
  2941. // If seed is empty or no tokens remain, we can return early
  2942. tokens.splice(i, 1);
  2943. selector = seed.length && toSelector(tokens);
  2944. if (!selector)
  2945. {
  2946. push.apply(results, seed);
  2947. return results;
  2948. }
  2949.  
  2950. break;
  2951. }
  2952. }
  2953. }
  2954. }
  2955.  
  2956. // Compile and execute a filtering function if one is not provided
  2957. // Provide `match` to avoid retokenization if we modified the selector above
  2958. (compiled || compile(selector, match))(
  2959. seed,
  2960. context,
  2961. !documentIsHTML,
  2962. results,
  2963. rsibling.test(selector) && testContext(context.parentNode) || context
  2964. );
  2965. return results;
  2966. };
  2967.  
  2968. // One-time assignments
  2969.  
  2970. // Sort stability
  2971. support.sortStable = expando.split("").sort(sortOrder).join("") === expando;
  2972.  
  2973. // Support: Chrome<14
  2974. // Always assume duplicates if they aren't passed to the comparison function
  2975. support.detectDuplicates = !!hasDuplicate;
  2976.  
  2977. // Initialize against the default document
  2978. setDocument();
  2979.  
  2980. // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  2981. // Detached nodes confoundingly follow *each other*
  2982. support.sortDetached = assert(function(div1)
  2983. {
  2984. // Should return 1, but returns 4 (following)
  2985. return div1.compareDocumentPosition(document.createElement("div")) & 1;
  2986. });
  2987.  
  2988. // Support: IE<8
  2989. // Prevent attribute/property "interpolation"
  2990. // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  2991. if (!assert(function(div)
  2992. {
  2993. div.innerHTML = "<a href='#'></a>";
  2994. return div.firstChild.getAttribute("href") === "#";
  2995. }))
  2996. {
  2997. addHandle("type|href|height|width", function(elem, name, isXML)
  2998. {
  2999. if (!isXML)
  3000. {
  3001. return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2);
  3002. }
  3003. });
  3004. }
  3005.  
  3006. // Support: IE<9
  3007. // Use defaultValue in place of getAttribute("value")
  3008. if (!support.attributes || !assert(function(div)
  3009. {
  3010. div.innerHTML = "<input/>";
  3011. div.firstChild.setAttribute("value", "");
  3012. return div.firstChild.getAttribute("value") === "";
  3013. }))
  3014. {
  3015. addHandle("value", function(elem, name, isXML)
  3016. {
  3017. if (!isXML && elem.nodeName.toLowerCase() === "input")
  3018. {
  3019. return elem.defaultValue;
  3020. }
  3021. });
  3022. }
  3023.  
  3024. // Support: IE<9
  3025. // Use getAttributeNode to fetch booleans when getAttribute lies
  3026. if (!assert(function(div)
  3027. {
  3028. return div.getAttribute("disabled") == null;
  3029. }))
  3030. {
  3031. addHandle(booleans, function(elem, name, isXML)
  3032. {
  3033. var val;
  3034. if (!isXML)
  3035. {
  3036. return elem[name] === true ? name.toLowerCase() :
  3037. (val = elem.getAttributeNode(name)) && val.specified ?
  3038. val.value :
  3039. null;
  3040. }
  3041. });
  3042. }
  3043.  
  3044. return Sizzle;
  3045. })(window);
  3046.  
  3047.  
  3048.  
  3049. jQuery.find = Sizzle;
  3050. jQuery.expr = Sizzle.selectors;
  3051. jQuery.expr[":"] = jQuery.expr.pseudos;
  3052. jQuery.unique = Sizzle.uniqueSort;
  3053. jQuery.text = Sizzle.getText;
  3054. jQuery.isXMLDoc = Sizzle.isXML;
  3055. jQuery.contains = Sizzle.contains;
  3056.  
  3057.  
  3058.  
  3059. var rneedsContext = jQuery.expr.match.needsContext;
  3060.  
  3061. var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
  3062.  
  3063.  
  3064.  
  3065. var risSimple = /^.[^:#\[\.,]*$/;
  3066.  
  3067. // Implement the identical functionality for filter and not
  3068. function winnow(elements, qualifier, not)
  3069. {
  3070. if (jQuery.isFunction(qualifier))
  3071. {
  3072. return jQuery.grep(elements, function(elem, i)
  3073. {
  3074. /* jshint -W018 */
  3075. return !!qualifier.call(elem, i, elem) !== not;
  3076. });
  3077. }
  3078.  
  3079. if (qualifier.nodeType)
  3080. {
  3081. return jQuery.grep(elements, function(elem)
  3082. {
  3083. return (elem === qualifier) !== not;
  3084. });
  3085. }
  3086.  
  3087. if (typeof qualifier === "string")
  3088. {
  3089. if (risSimple.test(qualifier))
  3090. {
  3091. return jQuery.filter(qualifier, elements, not);
  3092. }
  3093.  
  3094. qualifier = jQuery.filter(qualifier, elements);
  3095. }
  3096.  
  3097. return jQuery.grep(elements, function(elem)
  3098. {
  3099. return (indexOf.call(qualifier, elem) >= 0) !== not;
  3100. });
  3101. }
  3102.  
  3103. jQuery.filter = function(expr, elems, not)
  3104. {
  3105. var elem = elems[0];
  3106.  
  3107. if (not)
  3108. {
  3109. expr = ":not(" + expr + ")";
  3110. }
  3111.  
  3112. return elems.length === 1 && elem.nodeType === 1 ?
  3113. jQuery.find.matchesSelector(elem, expr) ? [elem] : [] :
  3114. jQuery.find.matches(expr, jQuery.grep(elems, function(elem)
  3115. {
  3116. return elem.nodeType === 1;
  3117. }));
  3118. };
  3119.  
  3120. jQuery.fn.extend({
  3121. find: function(selector)
  3122. {
  3123. var i,
  3124. len = this.length,
  3125. ret = [],
  3126. self = this;
  3127.  
  3128. if (typeof selector !== "string")
  3129. {
  3130. return this.pushStack(jQuery(selector).filter(function()
  3131. {
  3132. for (i = 0; i < len; i++)
  3133. {
  3134. if (jQuery.contains(self[i], this))
  3135. {
  3136. return true;
  3137. }
  3138. }
  3139. }));
  3140. }
  3141.  
  3142. for (i = 0; i < len; i++)
  3143. {
  3144. jQuery.find(selector, self[i], ret);
  3145. }
  3146.  
  3147. // Needed because $( selector, context ) becomes $( context ).find( selector )
  3148. ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret);
  3149. ret.selector = this.selector ? this.selector + " " + selector : selector;
  3150. return ret;
  3151. },
  3152. filter: function(selector)
  3153. {
  3154. return this.pushStack(winnow(this, selector || [], false));
  3155. },
  3156. not: function(selector)
  3157. {
  3158. return this.pushStack(winnow(this, selector || [], true));
  3159. },
  3160. is: function(selector)
  3161. {
  3162. return !!winnow(
  3163. this,
  3164.  
  3165. // If this is a positional/relative selector, check membership in the returned set
  3166. // so $("p:first").is("p:last") won't return true for a doc with two "p".
  3167. typeof selector === "string" && rneedsContext.test(selector) ?
  3168. jQuery(selector) :
  3169. selector || [],
  3170. false
  3171. ).length;
  3172. }
  3173. });
  3174.  
  3175.  
  3176. // Initialize a jQuery object
  3177.  
  3178.  
  3179. // A central reference to the root jQuery(document)
  3180. var rootjQuery,
  3181.  
  3182. // A simple way to check for HTML strings
  3183. // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  3184. // Strict HTML recognition (#11290: must start with <)
  3185. rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
  3186.  
  3187. init = jQuery.fn.init = function(selector, context)
  3188. {
  3189. var match, elem;
  3190.  
  3191. // HANDLE: $(""), $(null), $(undefined), $(false)
  3192. if (!selector)
  3193. {
  3194. return this;
  3195. }
  3196.  
  3197. // Handle HTML strings
  3198. if (typeof selector === "string")
  3199. {
  3200. if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3)
  3201. {
  3202. // Assume that strings that start and end with <> are HTML and skip the regex check
  3203. match = [null, selector, null];
  3204. } else
  3205. {
  3206. match = rquickExpr.exec(selector);
  3207. }
  3208.  
  3209. // Match html or make sure no context is specified for #id
  3210. if (match && (match[1] || !context))
  3211. {
  3212. // HANDLE: $(html) -> $(array)
  3213. if (match[1])
  3214. {
  3215. context = context instanceof jQuery ? context[0] : context;
  3216.  
  3217. // scripts is true for back-compat
  3218. // Intentionally let the error be thrown if parseHTML is not present
  3219. jQuery.merge(this, jQuery.parseHTML(
  3220. match[1],
  3221. context && context.nodeType ? context.ownerDocument || context : document,
  3222. true
  3223. ));
  3224.  
  3225. // HANDLE: $(html, props)
  3226. if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context))
  3227. {
  3228. for (match in context)
  3229. {
  3230. // Properties of context are called as methods if possible
  3231. if (jQuery.isFunction(this[match]))
  3232. {
  3233. this[match](context[match]);
  3234.  
  3235. // ...and otherwise set as attributes
  3236. } else
  3237. {
  3238. this.attr(match, context[match]);
  3239. }
  3240. }
  3241. }
  3242.  
  3243. return this;
  3244.  
  3245. // HANDLE: $(#id)
  3246. } else
  3247. {
  3248. elem = document.getElementById(match[2]);
  3249.  
  3250. // Check parentNode to catch when Blackberry 4.6 returns
  3251. // nodes that are no longer in the document #6963
  3252. if (elem && elem.parentNode)
  3253. {
  3254. // Inject the element directly into the jQuery object
  3255. this.length = 1;
  3256. this[0] = elem;
  3257. }
  3258.  
  3259. this.context = document;
  3260. this.selector = selector;
  3261. return this;
  3262. }
  3263.  
  3264. // HANDLE: $(expr, $(...))
  3265. } else if (!context || context.jquery)
  3266. {
  3267. return (context || rootjQuery).find(selector);
  3268.  
  3269. // HANDLE: $(expr, context)
  3270. // (which is just equivalent to: $(context).find(expr)
  3271. } else
  3272. {
  3273. return this.constructor(context).find(selector);
  3274. }
  3275.  
  3276. // HANDLE: $(DOMElement)
  3277. } else if (selector.nodeType)
  3278. {
  3279. this.context = this[0] = selector;
  3280. this.length = 1;
  3281. return this;
  3282.  
  3283. // HANDLE: $(function)
  3284. // Shortcut for document ready
  3285. } else if (jQuery.isFunction(selector))
  3286. {
  3287. return typeof rootjQuery.ready !== "undefined" ?
  3288. rootjQuery.ready(selector) :
  3289. // Execute immediately if ready is not present
  3290. selector(jQuery);
  3291. }
  3292.  
  3293. if (selector.selector !== undefined)
  3294. {
  3295. this.selector = selector.selector;
  3296. this.context = selector.context;
  3297. }
  3298.  
  3299. return jQuery.makeArray(selector, this);
  3300. };
  3301.  
  3302. // Give the init function the jQuery prototype for later instantiation
  3303. init.prototype = jQuery.fn;
  3304.  
  3305. // Initialize central reference
  3306. rootjQuery = jQuery(document);
  3307.  
  3308.  
  3309. var rparentsprev = /^(?:parents|prev(?:Until|All))/,
  3310. // methods guaranteed to produce a unique set when starting from a unique set
  3311. guaranteedUnique = {
  3312. children: true,
  3313. contents: true,
  3314. next: true,
  3315. prev: true
  3316. };
  3317.  
  3318. jQuery.extend({
  3319. dir: function(elem, dir, until)
  3320. {
  3321. var matched = [],
  3322. truncate = until !== undefined;
  3323.  
  3324. while ((elem = elem[dir]) && elem.nodeType !== 9)
  3325. {
  3326. if (elem.nodeType === 1)
  3327. {
  3328. if (truncate && jQuery(elem).is(until))
  3329. {
  3330. break;
  3331. }
  3332. matched.push(elem);
  3333. }
  3334. }
  3335. return matched;
  3336. },
  3337.  
  3338. sibling: function(n, elem)
  3339. {
  3340. var matched = [];
  3341.  
  3342. for (; n; n = n.nextSibling)
  3343. {
  3344. if (n.nodeType === 1 && n !== elem)
  3345. {
  3346. matched.push(n);
  3347. }
  3348. }
  3349.  
  3350. return matched;
  3351. }
  3352. });
  3353.  
  3354. jQuery.fn.extend({
  3355. has: function(target)
  3356. {
  3357. var targets = jQuery(target, this),
  3358. l = targets.length;
  3359.  
  3360. return this.filter(function()
  3361. {
  3362. var i = 0;
  3363. for (; i < l; i++)
  3364. {
  3365. if (jQuery.contains(this, targets[i]))
  3366. {
  3367. return true;
  3368. }
  3369. }
  3370. });
  3371. },
  3372.  
  3373. closest: function(selectors, context)
  3374. {
  3375. var cur,
  3376. i = 0,
  3377. l = this.length,
  3378. matched = [],
  3379. pos = rneedsContext.test(selectors) || typeof selectors !== "string" ?
  3380. jQuery(selectors, context || this.context) :
  3381. 0;
  3382.  
  3383. for (; i < l; i++)
  3384. {
  3385. for (cur = this[i]; cur && cur !== context; cur = cur.parentNode)
  3386. {
  3387. // Always skip document fragments
  3388. if (cur.nodeType < 11 && (pos ?
  3389. pos.index(cur) > -1 :
  3390.  
  3391. // Don't pass non-elements to Sizzle
  3392. cur.nodeType === 1 &&
  3393. jQuery.find.matchesSelector(cur, selectors)))
  3394. {
  3395. matched.push(cur);
  3396. break;
  3397. }
  3398. }
  3399. }
  3400.  
  3401. return this.pushStack(matched.length > 1 ? jQuery.unique(matched) : matched);
  3402. },
  3403.  
  3404. // Determine the position of an element within
  3405. // the matched set of elements
  3406. index: function(elem)
  3407. {
  3408. // No argument, return index in parent
  3409. if (!elem)
  3410. {
  3411. return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1;
  3412. }
  3413.  
  3414. // index in selector
  3415. if (typeof elem === "string")
  3416. {
  3417. return indexOf.call(jQuery(elem), this[0]);
  3418. }
  3419.  
  3420. // Locate the position of the desired element
  3421. return indexOf.call(this,
  3422.  
  3423. // If it receives a jQuery object, the first element is used
  3424. elem.jquery ? elem[0] : elem
  3425. );
  3426. },
  3427.  
  3428. add: function(selector, context)
  3429. {
  3430. return this.pushStack(
  3431. jQuery.unique(
  3432. jQuery.merge(this.get(), jQuery(selector, context))
  3433. )
  3434. );
  3435. },
  3436.  
  3437. addBack: function(selector)
  3438. {
  3439. return this.add(selector == null ?
  3440. this.prevObject : this.prevObject.filter(selector)
  3441. );
  3442. }
  3443. });
  3444.  
  3445. function sibling(cur, dir)
  3446. {
  3447. while ((cur = cur[dir]) && cur.nodeType !== 1) { }
  3448. return cur;
  3449. }
  3450.  
  3451. jQuery.each({
  3452. parent: function(elem)
  3453. {
  3454. var parent = elem.parentNode;
  3455. return parent && parent.nodeType !== 11 ? parent : null;
  3456. },
  3457. parents: function(elem)
  3458. {
  3459. return jQuery.dir(elem, "parentNode");
  3460. },
  3461. parentsUntil: function(elem, i, until)
  3462. {
  3463. return jQuery.dir(elem, "parentNode", until);
  3464. },
  3465. next: function(elem)
  3466. {
  3467. return sibling(elem, "nextSibling");
  3468. },
  3469. prev: function(elem)
  3470. {
  3471. return sibling(elem, "previousSibling");
  3472. },
  3473. nextAll: function(elem)
  3474. {
  3475. return jQuery.dir(elem, "nextSibling");
  3476. },
  3477. prevAll: function(elem)
  3478. {
  3479. return jQuery.dir(elem, "previousSibling");
  3480. },
  3481. nextUntil: function(elem, i, until)
  3482. {
  3483. return jQuery.dir(elem, "nextSibling", until);
  3484. },
  3485. prevUntil: function(elem, i, until)
  3486. {
  3487. return jQuery.dir(elem, "previousSibling", until);
  3488. },
  3489. siblings: function(elem)
  3490. {
  3491. return jQuery.sibling((elem.parentNode || {}).firstChild, elem);
  3492. },
  3493. children: function(elem)
  3494. {
  3495. return jQuery.sibling(elem.firstChild);
  3496. },
  3497. contents: function(elem)
  3498. {
  3499. return elem.contentDocument || jQuery.merge([], elem.childNodes);
  3500. }
  3501. }, function(name, fn)
  3502. {
  3503. jQuery.fn[name] = function(until, selector)
  3504. {
  3505. var matched = jQuery.map(this, fn, until);
  3506.  
  3507. if (name.slice(-5) !== "Until")
  3508. {
  3509. selector = until;
  3510. }
  3511.  
  3512. if (selector && typeof selector === "string")
  3513. {
  3514. matched = jQuery.filter(selector, matched);
  3515. }
  3516.  
  3517. if (this.length > 1)
  3518. {
  3519. // Remove duplicates
  3520. if (!guaranteedUnique[name])
  3521. {
  3522. jQuery.unique(matched);
  3523. }
  3524.  
  3525. // Reverse order for parents* and prev-derivatives
  3526. if (rparentsprev.test(name))
  3527. {
  3528. matched.reverse();
  3529. }
  3530. }
  3531.  
  3532. return this.pushStack(matched);
  3533. };
  3534. });
  3535. var rnotwhite = (/\S+/g);
  3536.  
  3537.  
  3538.  
  3539. // String to Object options format cache
  3540. var optionsCache = {};
  3541.  
  3542. // Convert String-formatted options into Object-formatted ones and store in cache
  3543. function createOptions(options)
  3544. {
  3545. var object = optionsCache[options] = {};
  3546. jQuery.each(options.match(rnotwhite) || [], function(_, flag)
  3547. {
  3548. object[flag] = true;
  3549. });
  3550. return object;
  3551. }
  3552.  
  3553. /*
  3554. * Create a callback list using the following parameters:
  3555. *
  3556. * options: an optional list of space-separated options that will change how
  3557. * the callback list behaves or a more traditional option object
  3558. *
  3559. * By default a callback list will act like an event callback list and can be
  3560. * "fired" multiple times.
  3561. *
  3562. * Possible options:
  3563. *
  3564. * once: will ensure the callback list can only be fired once (like a Deferred)
  3565. *
  3566. * memory: will keep track of previous values and will call any callback added
  3567. * after the list has been fired right away with the latest "memorized"
  3568. * values (like a Deferred)
  3569. *
  3570. * unique: will ensure a callback can only be added once (no duplicate in the list)
  3571. *
  3572. * stopOnFalse: interrupt callings when a callback returns false
  3573. *
  3574. */
  3575. jQuery.Callbacks = function(options)
  3576. {
  3577. // Convert options from String-formatted to Object-formatted if needed
  3578. // (we check in cache first)
  3579. options = typeof options === "string" ?
  3580. (optionsCache[options] || createOptions(options)) :
  3581. jQuery.extend({}, options);
  3582.  
  3583. var // Last fire value (for non-forgettable lists)
  3584. memory,
  3585. // Flag to know if list was already fired
  3586. fired,
  3587. // Flag to know if list is currently firing
  3588. firing,
  3589. // First callback to fire (used internally by add and fireWith)
  3590. firingStart,
  3591. // End of the loop when firing
  3592. firingLength,
  3593. // Index of currently firing callback (modified by remove if needed)
  3594. firingIndex,
  3595. // Actual callback list
  3596. list = [],
  3597. // Stack of fire calls for repeatable lists
  3598. stack = !options.once && [],
  3599. // Fire callbacks
  3600. fire = function(data)
  3601. {
  3602. memory = options.memory && data;
  3603. fired = true;
  3604. firingIndex = firingStart || 0;
  3605. firingStart = 0;
  3606. firingLength = list.length;
  3607. firing = true;
  3608. for (; list && firingIndex < firingLength; firingIndex++)
  3609. {
  3610. if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse)
  3611. {
  3612. memory = false; // To prevent further calls using add
  3613. break;
  3614. }
  3615. }
  3616. firing = false;
  3617. if (list)
  3618. {
  3619. if (stack)
  3620. {
  3621. if (stack.length)
  3622. {
  3623. fire(stack.shift());
  3624. }
  3625. } else if (memory)
  3626. {
  3627. list = [];
  3628. } else
  3629. {
  3630. self.disable();
  3631. }
  3632. }
  3633. },
  3634. // Actual Callbacks object
  3635. self = {
  3636. // Add a callback or a collection of callbacks to the list
  3637. add: function()
  3638. {
  3639. if (list)
  3640. {
  3641. // First, we save the current length
  3642. var start = list.length;
  3643. (function add(args)
  3644. {
  3645. jQuery.each(args, function(_, arg)
  3646. {
  3647. var type = jQuery.type(arg);
  3648. if (type === "function")
  3649. {
  3650. if (!options.unique || !self.has(arg))
  3651. {
  3652. list.push(arg);
  3653. }
  3654. } else if (arg && arg.length && type !== "string")
  3655. {
  3656. // Inspect recursively
  3657. add(arg);
  3658. }
  3659. });
  3660. })(arguments);
  3661. // Do we need to add the callbacks to the
  3662. // current firing batch?
  3663. if (firing)
  3664. {
  3665. firingLength = list.length;
  3666. // With memory, if we're not firing then
  3667. // we should call right away
  3668. } else if (memory)
  3669. {
  3670. firingStart = start;
  3671. fire(memory);
  3672. }
  3673. }
  3674. return this;
  3675. },
  3676. // Remove a callback from the list
  3677. remove: function()
  3678. {
  3679. if (list)
  3680. {
  3681. jQuery.each(arguments, function(_, arg)
  3682. {
  3683. var index;
  3684. while ((index = jQuery.inArray(arg, list, index)) > -1)
  3685. {
  3686. list.splice(index, 1);
  3687. // Handle firing indexes
  3688. if (firing)
  3689. {
  3690. if (index <= firingLength)
  3691. {
  3692. firingLength--;
  3693. }
  3694. if (index <= firingIndex)
  3695. {
  3696. firingIndex--;
  3697. }
  3698. }
  3699. }
  3700. });
  3701. }
  3702. return this;
  3703. },
  3704. // Check if a given callback is in the list.
  3705. // If no argument is given, return whether or not list has callbacks attached.
  3706. has: function(fn)
  3707. {
  3708. return fn ? jQuery.inArray(fn, list) > -1 : !!(list && list.length);
  3709. },
  3710. // Remove all callbacks from the list
  3711. empty: function()
  3712. {
  3713. list = [];
  3714. firingLength = 0;
  3715. return this;
  3716. },
  3717. // Have the list do nothing anymore
  3718. disable: function()
  3719. {
  3720. list = stack = memory = undefined;
  3721. return this;
  3722. },
  3723. // Is it disabled?
  3724. disabled: function()
  3725. {
  3726. return !list;
  3727. },
  3728. // Lock the list in its current state
  3729. lock: function()
  3730. {
  3731. stack = undefined;
  3732. if (!memory)
  3733. {
  3734. self.disable();
  3735. }
  3736. return this;
  3737. },
  3738. // Is it locked?
  3739. locked: function()
  3740. {
  3741. return !stack;
  3742. },
  3743. // Call all callbacks with the given context and arguments
  3744. fireWith: function(context, args)
  3745. {
  3746. if (list && (!fired || stack))
  3747. {
  3748. args = args || [];
  3749. args = [context, args.slice ? args.slice() : args];
  3750. if (firing)
  3751. {
  3752. stack.push(args);
  3753. } else
  3754. {
  3755. fire(args);
  3756. }
  3757. }
  3758. return this;
  3759. },
  3760. // Call all the callbacks with the given arguments
  3761. fire: function()
  3762. {
  3763. self.fireWith(this, arguments);
  3764. return this;
  3765. },
  3766. // To know if the callbacks have already been called at least once
  3767. fired: function()
  3768. {
  3769. return !!fired;
  3770. }
  3771. };
  3772.  
  3773. return self;
  3774. };
  3775.  
  3776.  
  3777. jQuery.extend({
  3778. Deferred: function(func)
  3779. {
  3780. var tuples = [
  3781. // action, add listener, listener list, final state
  3782. ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"],
  3783. ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"],
  3784. ["notify", "progress", jQuery.Callbacks("memory")]
  3785. ],
  3786. state = "pending",
  3787. promise = {
  3788. state: function()
  3789. {
  3790. return state;
  3791. },
  3792. always: function()
  3793. {
  3794. deferred.done(arguments).fail(arguments);
  3795. return this;
  3796. },
  3797. then: function( /* fnDone, fnFail, fnProgress */)
  3798. {
  3799. var fns = arguments;
  3800. return jQuery.Deferred(function(newDefer)
  3801. {
  3802. jQuery.each(tuples, function(i, tuple)
  3803. {
  3804. var fn = jQuery.isFunction(fns[i]) && fns[i];
  3805. // deferred[ done | fail | progress ] for forwarding actions to newDefer
  3806. deferred[tuple[1]](function()
  3807. {
  3808. var returned = fn && fn.apply(this, arguments);
  3809. if (returned && jQuery.isFunction(returned.promise))
  3810. {
  3811. returned.promise()
  3812. .done(newDefer.resolve)
  3813. .fail(newDefer.reject)
  3814. .progress(newDefer.notify);
  3815. } else
  3816. {
  3817. newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments);
  3818. }
  3819. });
  3820. });
  3821. fns = null;
  3822. }).promise();
  3823. },
  3824. // Get a promise for this deferred
  3825. // If obj is provided, the promise aspect is added to the object
  3826. promise: function(obj)
  3827. {
  3828. return obj != null ? jQuery.extend(obj, promise) : promise;
  3829. }
  3830. },
  3831. deferred = {};
  3832.  
  3833. // Keep pipe for back-compat
  3834. promise.pipe = promise.then;
  3835.  
  3836. // Add list-specific methods
  3837. jQuery.each(tuples, function(i, tuple)
  3838. {
  3839. var list = tuple[2],
  3840. stateString = tuple[3];
  3841.  
  3842. // promise[ done | fail | progress ] = list.add
  3843. promise[tuple[1]] = list.add;
  3844.  
  3845. // Handle state
  3846. if (stateString)
  3847. {
  3848. list.add(function()
  3849. {
  3850. // state = [ resolved | rejected ]
  3851. state = stateString;
  3852.  
  3853. // [ reject_list | resolve_list ].disable; progress_list.lock
  3854. }, tuples[i ^ 1][2].disable, tuples[2][2].lock);
  3855. }
  3856.  
  3857. // deferred[ resolve | reject | notify ]
  3858. deferred[tuple[0]] = function()
  3859. {
  3860. deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
  3861. return this;
  3862. };
  3863. deferred[tuple[0] + "With"] = list.fireWith;
  3864. });
  3865.  
  3866. // Make the deferred a promise
  3867. promise.promise(deferred);
  3868.  
  3869. // Call given func if any
  3870. if (func)
  3871. {
  3872. func.call(deferred, deferred);
  3873. }
  3874.  
  3875. // All done!
  3876. return deferred;
  3877. },
  3878.  
  3879. // Deferred helper
  3880. when: function(subordinate /* , ..., subordinateN */)
  3881. {
  3882. var i = 0,
  3883. resolveValues = slice.call(arguments),
  3884. length = resolveValues.length,
  3885.  
  3886. // the count of uncompleted subordinates
  3887. remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0,
  3888.  
  3889. // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
  3890. deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
  3891.  
  3892. // Update function for both resolve and progress values
  3893. updateFunc = function(i, contexts, values)
  3894. {
  3895. return function(value)
  3896. {
  3897. contexts[i] = this;
  3898. values[i] = arguments.length > 1 ? slice.call(arguments) : value;
  3899. if (values === progressValues)
  3900. {
  3901. deferred.notifyWith(contexts, values);
  3902. } else if (!(--remaining))
  3903. {
  3904. deferred.resolveWith(contexts, values);
  3905. }
  3906. };
  3907. },
  3908.  
  3909. progressValues, progressContexts, resolveContexts;
  3910.  
  3911. // add listeners to Deferred subordinates; treat others as resolved
  3912. if (length > 1)
  3913. {
  3914. progressValues = new Array(length);
  3915. progressContexts = new Array(length);
  3916. resolveContexts = new Array(length);
  3917. for (; i < length; i++)
  3918. {
  3919. if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise))
  3920. {
  3921. resolveValues[i].promise()
  3922. .done(updateFunc(i, resolveContexts, resolveValues))
  3923. .fail(deferred.reject)
  3924. .progress(updateFunc(i, progressContexts, progressValues));
  3925. } else
  3926. {
  3927. --remaining;
  3928. }
  3929. }
  3930. }
  3931.  
  3932. // if we're not waiting on anything, resolve the master
  3933. if (!remaining)
  3934. {
  3935. deferred.resolveWith(resolveContexts, resolveValues);
  3936. }
  3937.  
  3938. return deferred.promise();
  3939. }
  3940. });
  3941.  
  3942.  
  3943. // Multifunctional method to get and set values of a collection
  3944. // The value/s can optionally be executed if it's a function
  3945. var access = jQuery.access = function(elems, fn, key, value, chainable, emptyGet, raw)
  3946. {
  3947. var i = 0,
  3948. len = elems.length,
  3949. bulk = key == null;
  3950.  
  3951. // Sets many values
  3952. if (jQuery.type(key) === "object")
  3953. {
  3954. chainable = true;
  3955. for (i in key)
  3956. {
  3957. jQuery.access(elems, fn, i, key[i], true, emptyGet, raw);
  3958. }
  3959.  
  3960. // Sets one value
  3961. } else if (value !== undefined)
  3962. {
  3963. chainable = true;
  3964.  
  3965. if (!jQuery.isFunction(value))
  3966. {
  3967. raw = true;
  3968. }
  3969.  
  3970. if (bulk)
  3971. {
  3972. // Bulk operations run against the entire set
  3973. if (raw)
  3974. {
  3975. fn.call(elems, value);
  3976. fn = null;
  3977.  
  3978. // ...except when executing function values
  3979. } else
  3980. {
  3981. bulk = fn;
  3982. fn = function(elem, key, value)
  3983. {
  3984. return bulk.call(jQuery(elem), value);
  3985. };
  3986. }
  3987. }
  3988.  
  3989. if (fn)
  3990. {
  3991. for (; i < len; i++)
  3992. {
  3993. fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)));
  3994. }
  3995. }
  3996. }
  3997.  
  3998. return chainable ?
  3999. elems :
  4000.  
  4001. // Gets
  4002. bulk ?
  4003. fn.call(elems) :
  4004. len ? fn(elems[0], key) : emptyGet;
  4005. };
  4006.  
  4007.  
  4008. /**
  4009. * Determines whether an object can have data
  4010. */
  4011. jQuery.acceptData = function(owner)
  4012. {
  4013. // Accepts only:
  4014. // - Node
  4015. // - Node.ELEMENT_NODE
  4016. // - Node.DOCUMENT_NODE
  4017. // - Object
  4018. // - Any
  4019. /* jshint -W018 */
  4020. return owner.nodeType === 1 || owner.nodeType === 9 || !(+owner.nodeType);
  4021. };
  4022.  
  4023.  
  4024. function Data()
  4025. {
  4026. // Support: Android < 4,
  4027. // Old WebKit does not have Object.preventExtensions/freeze method,
  4028. // return new empty object instead with no [[set]] accessor
  4029. Object.defineProperty(this.cache = {}, 0, {
  4030. get: function()
  4031. {
  4032. return {};
  4033. }
  4034. });
  4035.  
  4036. this.expando = jQuery.expando + Math.random();
  4037. }
  4038.  
  4039. Data.uid = 1;
  4040. Data.accepts = jQuery.acceptData;
  4041.  
  4042. Data.prototype = {
  4043. key: function(owner)
  4044. {
  4045. // We can accept data for non-element nodes in modern browsers,
  4046. // but we should not, see #8335.
  4047. // Always return the key for a frozen object.
  4048. if (!Data.accepts(owner))
  4049. {
  4050. return 0;
  4051. }
  4052.  
  4053. var descriptor = {},
  4054. // Check if the owner object already has a cache key
  4055. unlock = owner[this.expando];
  4056.  
  4057. // If not, create one
  4058. if (!unlock)
  4059. {
  4060. unlock = Data.uid++;
  4061.  
  4062. // Secure it in a non-enumerable, non-writable property
  4063. try
  4064. {
  4065. descriptor[this.expando] = { value: unlock };
  4066. Object.defineProperties(owner, descriptor);
  4067.  
  4068. // Support: Android < 4
  4069. // Fallback to a less secure definition
  4070. } catch (e)
  4071. {
  4072. descriptor[this.expando] = unlock;
  4073. jQuery.extend(owner, descriptor);
  4074. }
  4075. }
  4076.  
  4077. // Ensure the cache object
  4078. if (!this.cache[unlock])
  4079. {
  4080. this.cache[unlock] = {};
  4081. }
  4082.  
  4083. return unlock;
  4084. },
  4085. set: function(owner, data, value)
  4086. {
  4087. var prop,
  4088. // There may be an unlock assigned to this node,
  4089. // if there is no entry for this "owner", create one inline
  4090. // and set the unlock as though an owner entry had always existed
  4091. unlock = this.key(owner),
  4092. cache = this.cache[unlock];
  4093.  
  4094. // Handle: [ owner, key, value ] args
  4095. if (typeof data === "string")
  4096. {
  4097. cache[data] = value;
  4098.  
  4099. // Handle: [ owner, { properties } ] args
  4100. } else
  4101. {
  4102. // Fresh assignments by object are shallow copied
  4103. if (jQuery.isEmptyObject(cache))
  4104. {
  4105. jQuery.extend(this.cache[unlock], data);
  4106. // Otherwise, copy the properties one-by-one to the cache object
  4107. } else
  4108. {
  4109. for (prop in data)
  4110. {
  4111. cache[prop] = data[prop];
  4112. }
  4113. }
  4114. }
  4115. return cache;
  4116. },
  4117. get: function(owner, key)
  4118. {
  4119. // Either a valid cache is found, or will be created.
  4120. // New caches will be created and the unlock returned,
  4121. // allowing direct access to the newly created
  4122. // empty data object. A valid owner object must be provided.
  4123. var cache = this.cache[this.key(owner)];
  4124.  
  4125. return key === undefined ?
  4126. cache : cache[key];
  4127. },
  4128. access: function(owner, key, value)
  4129. {
  4130. var stored;
  4131. // In cases where either:
  4132. //
  4133. // 1. No key was specified
  4134. // 2. A string key was specified, but no value provided
  4135. //
  4136. // Take the "read" path and allow the get method to determine
  4137. // which value to return, respectively either:
  4138. //
  4139. // 1. The entire cache object
  4140. // 2. The data stored at the key
  4141. //
  4142. if (key === undefined ||
  4143. ((key && typeof key === "string") && value === undefined))
  4144. {
  4145. stored = this.get(owner, key);
  4146.  
  4147. return stored !== undefined ?
  4148. stored : this.get(owner, jQuery.camelCase(key));
  4149. }
  4150.  
  4151. // [*]When the key is not a string, or both a key and value
  4152. // are specified, set or extend (existing objects) with either:
  4153. //
  4154. // 1. An object of properties
  4155. // 2. A key and value
  4156. //
  4157. this.set(owner, key, value);
  4158.  
  4159. // Since the "set" path can have two possible entry points
  4160. // return the expected data based on which path was taken[*]
  4161. return value !== undefined ? value : key;
  4162. },
  4163. remove: function(owner, key)
  4164. {
  4165. var i, name, camel,
  4166. unlock = this.key(owner),
  4167. cache = this.cache[unlock];
  4168.  
  4169. if (key === undefined)
  4170. {
  4171. this.cache[unlock] = {};
  4172. } else
  4173. {
  4174. // Support array or space separated string of keys
  4175. if (jQuery.isArray(key))
  4176. {
  4177. // If "name" is an array of keys...
  4178. // When data is initially created, via ("key", "val") signature,
  4179. // keys will be converted to camelCase.
  4180. // Since there is no way to tell _how_ a key was added, remove
  4181. // both plain key and camelCase key. #12786
  4182. // This will only penalize the array argument path.
  4183. name = key.concat(key.map(jQuery.camelCase));
  4184. } else
  4185. {
  4186. camel = jQuery.camelCase(key);
  4187. // Try the string as a key before any manipulation
  4188. if (key in cache)
  4189. {
  4190. name = [key, camel];
  4191. } else
  4192. {
  4193. // If a key with the spaces exists, use it.
  4194. // Otherwise, create an array by matching non-whitespace
  4195. name = camel;
  4196. name = name in cache ?
  4197. [name] : (name.match(rnotwhite) || []);
  4198. }
  4199. }
  4200.  
  4201. i = name.length;
  4202. while (i--)
  4203. {
  4204. delete cache[name[i]];
  4205. }
  4206. }
  4207. },
  4208. hasData: function(owner)
  4209. {
  4210. return !jQuery.isEmptyObject(
  4211. this.cache[owner[this.expando]] || {}
  4212. );
  4213. },
  4214. discard: function(owner)
  4215. {
  4216. if (owner[this.expando])
  4217. {
  4218. delete this.cache[owner[this.expando]];
  4219. }
  4220. }
  4221. };
  4222. var data_priv = new Data();
  4223.  
  4224. var data_user = new Data();
  4225.  
  4226.  
  4227.  
  4228. /*
  4229. Implementation Summary
  4230.  
  4231. 1. Enforce API surface and semantic compatibility with 1.9.x branch
  4232. 2. Improve the module's maintainability by reducing the storage
  4233. paths to a single mechanism.
  4234. 3. Use the same single mechanism to support "private" and "user" data.
  4235. 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  4236. 5. Avoid exposing implementation details on user objects (eg. expando properties)
  4237. 6. Provide a clear path for implementation upgrade to WeakMap in 2014
  4238. */
  4239. var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
  4240. rmultiDash = /([A-Z])/g;
  4241.  
  4242. function dataAttr(elem, key, data)
  4243. {
  4244. var name;
  4245.  
  4246. // If nothing was found internally, try to fetch any
  4247. // data from the HTML5 data-* attribute
  4248. if (data === undefined && elem.nodeType === 1)
  4249. {
  4250. name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase();
  4251. data = elem.getAttribute(name);
  4252.  
  4253. if (typeof data === "string")
  4254. {
  4255. try
  4256. {
  4257. data = data === "true" ? true :
  4258. data === "false" ? false :
  4259. data === "null" ? null :
  4260. // Only convert to a number if it doesn't change the string
  4261. +data + "" === data ? +data :
  4262. rbrace.test(data) ? jQuery.parseJSON(data) :
  4263. data;
  4264. } catch (e) { }
  4265.  
  4266. // Make sure we set the data so it isn't changed later
  4267. data_user.set(elem, key, data);
  4268. } else
  4269. {
  4270. data = undefined;
  4271. }
  4272. }
  4273. return data;
  4274. }
  4275.  
  4276. jQuery.extend({
  4277. hasData: function(elem)
  4278. {
  4279. return data_user.hasData(elem) || data_priv.hasData(elem);
  4280. },
  4281.  
  4282. data: function(elem, name, data)
  4283. {
  4284. return data_user.access(elem, name, data);
  4285. },
  4286.  
  4287. removeData: function(elem, name)
  4288. {
  4289. data_user.remove(elem, name);
  4290. },
  4291.  
  4292. // TODO: Now that all calls to _data and _removeData have been replaced
  4293. // with direct calls to data_priv methods, these can be deprecated.
  4294. _data: function(elem, name, data)
  4295. {
  4296. return data_priv.access(elem, name, data);
  4297. },
  4298.  
  4299. _removeData: function(elem, name)
  4300. {
  4301. data_priv.remove(elem, name);
  4302. }
  4303. });
  4304.  
  4305. jQuery.fn.extend({
  4306. data: function(key, value)
  4307. {
  4308. var i, name, data,
  4309. elem = this[0],
  4310. attrs = elem && elem.attributes;
  4311.  
  4312. // Gets all values
  4313. if (key === undefined)
  4314. {
  4315. if (this.length)
  4316. {
  4317. data = data_user.get(elem);
  4318.  
  4319. if (elem.nodeType === 1 && !data_priv.get(elem, "hasDataAttrs"))
  4320. {
  4321. i = attrs.length;
  4322. while (i--)
  4323. {
  4324. // Support: IE11+
  4325. // The attrs elements can be null (#14894)
  4326. if (attrs[i])
  4327. {
  4328. name = attrs[i].name;
  4329. if (name.indexOf("data-") === 0)
  4330. {
  4331. name = jQuery.camelCase(name.slice(5));
  4332. dataAttr(elem, name, data[name]);
  4333. }
  4334. }
  4335. }
  4336. data_priv.set(elem, "hasDataAttrs", true);
  4337. }
  4338. }
  4339.  
  4340. return data;
  4341. }
  4342.  
  4343. // Sets multiple values
  4344. if (typeof key === "object")
  4345. {
  4346. return this.each(function()
  4347. {
  4348. data_user.set(this, key);
  4349. });
  4350. }
  4351.  
  4352. return access(this, function(value)
  4353. {
  4354. var data,
  4355. camelKey = jQuery.camelCase(key);
  4356.  
  4357. // The calling jQuery object (element matches) is not empty
  4358. // (and therefore has an element appears at this[ 0 ]) and the
  4359. // `value` parameter was not undefined. An empty jQuery object
  4360. // will result in `undefined` for elem = this[ 0 ] which will
  4361. // throw an exception if an attempt to read a data cache is made.
  4362. if (elem && value === undefined)
  4363. {
  4364. // Attempt to get data from the cache
  4365. // with the key as-is
  4366. data = data_user.get(elem, key);
  4367. if (data !== undefined)
  4368. {
  4369. return data;
  4370. }
  4371.  
  4372. // Attempt to get data from the cache
  4373. // with the key camelized
  4374. data = data_user.get(elem, camelKey);
  4375. if (data !== undefined)
  4376. {
  4377. return data;
  4378. }
  4379.  
  4380. // Attempt to "discover" the data in
  4381. // HTML5 custom data-* attrs
  4382. data = dataAttr(elem, camelKey, undefined);
  4383. if (data !== undefined)
  4384. {
  4385. return data;
  4386. }
  4387.  
  4388. // We tried really hard, but the data doesn't exist.
  4389. return;
  4390. }
  4391.  
  4392. // Set the data...
  4393. this.each(function()
  4394. {
  4395. // First, attempt to store a copy or reference of any
  4396. // data that might've been store with a camelCased key.
  4397. var data = data_user.get(this, camelKey);
  4398.  
  4399. // For HTML5 data-* attribute interop, we have to
  4400. // store property names with dashes in a camelCase form.
  4401. // This might not apply to all properties...*
  4402. data_user.set(this, camelKey, value);
  4403.  
  4404. // *... In the case of properties that might _actually_
  4405. // have dashes, we need to also store a copy of that
  4406. // unchanged property.
  4407. if (key.indexOf("-") !== -1 && data !== undefined)
  4408. {
  4409. data_user.set(this, key, value);
  4410. }
  4411. });
  4412. }, null, value, arguments.length > 1, null, true);
  4413. },
  4414.  
  4415. removeData: function(key)
  4416. {
  4417. return this.each(function()
  4418. {
  4419. data_user.remove(this, key);
  4420. });
  4421. }
  4422. });
  4423.  
  4424.  
  4425. jQuery.extend({
  4426. queue: function(elem, type, data)
  4427. {
  4428. var queue;
  4429.  
  4430. if (elem)
  4431. {
  4432. type = (type || "fx") + "queue";
  4433. queue = data_priv.get(elem, type);
  4434.  
  4435. // Speed up dequeue by getting out quickly if this is just a lookup
  4436. if (data)
  4437. {
  4438. if (!queue || jQuery.isArray(data))
  4439. {
  4440. queue = data_priv.access(elem, type, jQuery.makeArray(data));
  4441. } else
  4442. {
  4443. queue.push(data);
  4444. }
  4445. }
  4446. return queue || [];
  4447. }
  4448. },
  4449.  
  4450. dequeue: function(elem, type)
  4451. {
  4452. type = type || "fx";
  4453.  
  4454. var queue = jQuery.queue(elem, type),
  4455. startLength = queue.length,
  4456. fn = queue.shift(),
  4457. hooks = jQuery._queueHooks(elem, type),
  4458. next = function()
  4459. {
  4460. jQuery.dequeue(elem, type);
  4461. };
  4462.  
  4463. // If the fx queue is dequeued, always remove the progress sentinel
  4464. if (fn === "inprogress")
  4465. {
  4466. fn = queue.shift();
  4467. startLength--;
  4468. }
  4469.  
  4470. if (fn)
  4471. {
  4472. // Add a progress sentinel to prevent the fx queue from being
  4473. // automatically dequeued
  4474. if (type === "fx")
  4475. {
  4476. queue.unshift("inprogress");
  4477. }
  4478.  
  4479. // clear up the last queue stop function
  4480. delete hooks.stop;
  4481. fn.call(elem, next, hooks);
  4482. }
  4483.  
  4484. if (!startLength && hooks)
  4485. {
  4486. hooks.empty.fire();
  4487. }
  4488. },
  4489.  
  4490. // not intended for public consumption - generates a queueHooks object, or returns the current one
  4491. _queueHooks: function(elem, type)
  4492. {
  4493. var key = type + "queueHooks";
  4494. return data_priv.get(elem, key) || data_priv.access(elem, key, {
  4495. empty: jQuery.Callbacks("once memory").add(function()
  4496. {
  4497. data_priv.remove(elem, [type + "queue", key]);
  4498. })
  4499. });
  4500. }
  4501. });
  4502.  
  4503. jQuery.fn.extend({
  4504. queue: function(type, data)
  4505. {
  4506. var setter = 2;
  4507.  
  4508. if (typeof type !== "string")
  4509. {
  4510. data = type;
  4511. type = "fx";
  4512. setter--;
  4513. }
  4514.  
  4515. if (arguments.length < setter)
  4516. {
  4517. return jQuery.queue(this[0], type);
  4518. }
  4519.  
  4520. return data === undefined ?
  4521. this :
  4522. this.each(function()
  4523. {
  4524. var queue = jQuery.queue(this, type, data);
  4525.  
  4526. // ensure a hooks for this queue
  4527. jQuery._queueHooks(this, type);
  4528.  
  4529. if (type === "fx" && queue[0] !== "inprogress")
  4530. {
  4531. jQuery.dequeue(this, type);
  4532. }
  4533. });
  4534. },
  4535. dequeue: function(type)
  4536. {
  4537. return this.each(function()
  4538. {
  4539. jQuery.dequeue(this, type);
  4540. });
  4541. },
  4542. clearQueue: function(type)
  4543. {
  4544. return this.queue(type || "fx", []);
  4545. },
  4546. // Get a promise resolved when queues of a certain type
  4547. // are emptied (fx is the type by default)
  4548. promise: function(type, obj)
  4549. {
  4550. var tmp,
  4551. count = 1,
  4552. defer = jQuery.Deferred(),
  4553. elements = this,
  4554. i = this.length,
  4555. resolve = function()
  4556. {
  4557. if (!(--count))
  4558. {
  4559. defer.resolveWith(elements, [elements]);
  4560. }
  4561. };
  4562.  
  4563. if (typeof type !== "string")
  4564. {
  4565. obj = type;
  4566. type = undefined;
  4567. }
  4568. type = type || "fx";
  4569.  
  4570. while (i--)
  4571. {
  4572. tmp = data_priv.get(elements[i], type + "queueHooks");
  4573. if (tmp && tmp.empty)
  4574. {
  4575. count++;
  4576. tmp.empty.add(resolve);
  4577. }
  4578. }
  4579. resolve();
  4580. return defer.promise(obj);
  4581. }
  4582. });
  4583. var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
  4584.  
  4585. var cssExpand = ["Top", "Right", "Bottom", "Left"];
  4586.  
  4587. var isHidden = function(elem, el)
  4588. {
  4589. // isHidden might be called from jQuery#filter function;
  4590. // in that case, element will be second argument
  4591. elem = el || elem;
  4592. return jQuery.css(elem, "display") === "none" || !jQuery.contains(elem.ownerDocument, elem);
  4593. };
  4594.  
  4595. var rcheckableType = (/^(?:checkbox|radio)$/i);
  4596.  
  4597.  
  4598.  
  4599. (function()
  4600. {
  4601. var fragment = document.createDocumentFragment(),
  4602. div = fragment.appendChild(document.createElement("div")),
  4603. input = document.createElement("input");
  4604.  
  4605. // #11217 - WebKit loses check when the name is after the checked attribute
  4606. // Support: Windows Web Apps (WWA)
  4607. // `name` and `type` need .setAttribute for WWA
  4608. input.setAttribute("type", "radio");
  4609. input.setAttribute("checked", "checked");
  4610. input.setAttribute("name", "t");
  4611.  
  4612. div.appendChild(input);
  4613.  
  4614. // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
  4615. // old WebKit doesn't clone checked state correctly in fragments
  4616. support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked;
  4617.  
  4618. // Make sure textarea (and checkbox) defaultValue is properly cloned
  4619. // Support: IE9-IE11+
  4620. div.innerHTML = "<textarea>x</textarea>";
  4621. support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue;
  4622. })();
  4623. var strundefined = typeof undefined;
  4624.  
  4625.  
  4626.  
  4627. support.focusinBubbles = "onfocusin" in window;
  4628.  
  4629.  
  4630. var
  4631. rkeyEvent = /^key/,
  4632. rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
  4633. rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  4634. rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  4635.  
  4636. function returnTrue()
  4637. {
  4638. return true;
  4639. }
  4640.  
  4641. function returnFalse()
  4642. {
  4643. return false;
  4644. }
  4645.  
  4646. function safeActiveElement()
  4647. {
  4648. try
  4649. {
  4650. return document.activeElement;
  4651. } catch (err) { }
  4652. }
  4653.  
  4654. /*
  4655. * Helper functions for managing events -- not part of the public interface.
  4656. * Props to Dean Edwards' addEvent library for many of the ideas.
  4657. */
  4658. jQuery.event = {
  4659. global: {},
  4660.  
  4661. add: function(elem, types, handler, data, selector)
  4662. {
  4663. var handleObjIn, eventHandle, tmp,
  4664. events, t, handleObj,
  4665. special, handlers, type, namespaces, origType,
  4666. elemData = data_priv.get(elem);
  4667.  
  4668. // Don't attach events to noData or text/comment nodes (but allow plain objects)
  4669. if (!elemData)
  4670. {
  4671. return;
  4672. }
  4673.  
  4674. // Caller can pass in an object of custom data in lieu of the handler
  4675. if (handler.handler)
  4676. {
  4677. handleObjIn = handler;
  4678. handler = handleObjIn.handler;
  4679. selector = handleObjIn.selector;
  4680. }
  4681.  
  4682. // Make sure that the handler has a unique ID, used to find/remove it later
  4683. if (!handler.guid)
  4684. {
  4685. handler.guid = jQuery.guid++;
  4686. }
  4687.  
  4688. // Init the element's event structure and main handler, if this is the first
  4689. if (!(events = elemData.events))
  4690. {
  4691. events = elemData.events = {};
  4692. }
  4693. if (!(eventHandle = elemData.handle))
  4694. {
  4695. eventHandle = elemData.handle = function(e)
  4696. {
  4697. // Discard the second event of a jQuery.event.trigger() and
  4698. // when an event is called after a page has unloaded
  4699. return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
  4700. jQuery.event.dispatch.apply(elem, arguments) : undefined;
  4701. };
  4702. }
  4703.  
  4704. // Handle multiple events separated by a space
  4705. types = (types || "").match(rnotwhite) || [""];
  4706. t = types.length;
  4707. while (t--)
  4708. {
  4709. tmp = rtypenamespace.exec(types[t]) || [];
  4710. type = origType = tmp[1];
  4711. namespaces = (tmp[2] || "").split(".").sort();
  4712.  
  4713. // There *must* be a type, no attaching namespace-only handlers
  4714. if (!type)
  4715. {
  4716. continue;
  4717. }
  4718.  
  4719. // If event changes its type, use the special event handlers for the changed type
  4720. special = jQuery.event.special[type] || {};
  4721.  
  4722. // If selector defined, determine special event api type, otherwise given type
  4723. type = (selector ? special.delegateType : special.bindType) || type;
  4724.  
  4725. // Update special based on newly reset type
  4726. special = jQuery.event.special[type] || {};
  4727.  
  4728. // handleObj is passed to all event handlers
  4729. handleObj = jQuery.extend({
  4730. type: type,
  4731. origType: origType,
  4732. data: data,
  4733. handler: handler,
  4734. guid: handler.guid,
  4735. selector: selector,
  4736. needsContext: selector && jQuery.expr.match.needsContext.test(selector),
  4737. namespace: namespaces.join(".")
  4738. }, handleObjIn);
  4739.  
  4740. // Init the event handler queue if we're the first
  4741. if (!(handlers = events[type]))
  4742. {
  4743. handlers = events[type] = [];
  4744. handlers.delegateCount = 0;
  4745.  
  4746. // Only use addEventListener if the special events handler returns false
  4747. if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false)
  4748. {
  4749. if (elem.addEventListener)
  4750. {
  4751. elem.addEventListener(type, eventHandle, false);
  4752. }
  4753. }
  4754. }
  4755.  
  4756. if (special.add)
  4757. {
  4758. special.add.call(elem, handleObj);
  4759.  
  4760. if (!handleObj.handler.guid)
  4761. {
  4762. handleObj.handler.guid = handler.guid;
  4763. }
  4764. }
  4765.  
  4766. // Add to the element's handler list, delegates in front
  4767. if (selector)
  4768. {
  4769. handlers.splice(handlers.delegateCount++, 0, handleObj);
  4770. } else
  4771. {
  4772. handlers.push(handleObj);
  4773. }
  4774.  
  4775. // Keep track of which events have ever been used, for event optimization
  4776. jQuery.event.global[type] = true;
  4777. }
  4778. },
  4779.  
  4780. // Detach an event or set of events from an element
  4781. remove: function(elem, types, handler, selector, mappedTypes)
  4782. {
  4783. var j, origCount, tmp,
  4784. events, t, handleObj,
  4785. special, handlers, type, namespaces, origType,
  4786. elemData = data_priv.hasData(elem) && data_priv.get(elem);
  4787.  
  4788. if (!elemData || !(events = elemData.events))
  4789. {
  4790. return;
  4791. }
  4792.  
  4793. // Once for each type.namespace in types; type may be omitted
  4794. types = (types || "").match(rnotwhite) || [""];
  4795. t = types.length;
  4796. while (t--)
  4797. {
  4798. tmp = rtypenamespace.exec(types[t]) || [];
  4799. type = origType = tmp[1];
  4800. namespaces = (tmp[2] || "").split(".").sort();
  4801.  
  4802. // Unbind all events (on this namespace, if provided) for the element
  4803. if (!type)
  4804. {
  4805. for (type in events)
  4806. {
  4807. jQuery.event.remove(elem, type + types[t], handler, selector, true);
  4808. }
  4809. continue;
  4810. }
  4811.  
  4812. special = jQuery.event.special[type] || {};
  4813. type = (selector ? special.delegateType : special.bindType) || type;
  4814. handlers = events[type] || [];
  4815. tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)");
  4816.  
  4817. // Remove matching events
  4818. origCount = j = handlers.length;
  4819. while (j--)
  4820. {
  4821. handleObj = handlers[j];
  4822.  
  4823. if ((mappedTypes || origType === handleObj.origType) &&
  4824. (!handler || handler.guid === handleObj.guid) &&
  4825. (!tmp || tmp.test(handleObj.namespace)) &&
  4826. (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector))
  4827. {
  4828. handlers.splice(j, 1);
  4829.  
  4830. if (handleObj.selector)
  4831. {
  4832. handlers.delegateCount--;
  4833. }
  4834. if (special.remove)
  4835. {
  4836. special.remove.call(elem, handleObj);
  4837. }
  4838. }
  4839. }
  4840.  
  4841. // Remove generic event handler if we removed something and no more handlers exist
  4842. // (avoids potential for endless recursion during removal of special event handlers)
  4843. if (origCount && !handlers.length)
  4844. {
  4845. if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false)
  4846. {
  4847. jQuery.removeEvent(elem, type, elemData.handle);
  4848. }
  4849.  
  4850. delete events[type];
  4851. }
  4852. }
  4853.  
  4854. // Remove the expando if it's no longer used
  4855. if (jQuery.isEmptyObject(events))
  4856. {
  4857. delete elemData.handle;
  4858. data_priv.remove(elem, "events");
  4859. }
  4860. },
  4861.  
  4862. trigger: function(event, data, elem, onlyHandlers)
  4863. {
  4864. var i, cur, tmp, bubbleType, ontype, handle, special,
  4865. eventPath = [elem || document],
  4866. type = hasOwn.call(event, "type") ? event.type : event,
  4867. namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : [];
  4868.  
  4869. cur = tmp = elem = elem || document;
  4870.  
  4871. // Don't do events on text and comment nodes
  4872. if (elem.nodeType === 3 || elem.nodeType === 8)
  4873. {
  4874. return;
  4875. }
  4876.  
  4877. // focus/blur morphs to focusin/out; ensure we're not firing them right now
  4878. if (rfocusMorph.test(type + jQuery.event.triggered))
  4879. {
  4880. return;
  4881. }
  4882.  
  4883. if (type.indexOf(".") >= 0)
  4884. {
  4885. // Namespaced trigger; create a regexp to match event type in handle()
  4886. namespaces = type.split(".");
  4887. type = namespaces.shift();
  4888. namespaces.sort();
  4889. }
  4890. ontype = type.indexOf(":") < 0 && "on" + type;
  4891.  
  4892. // Caller can pass in a jQuery.Event object, Object, or just an event type string
  4893. event = event[jQuery.expando] ?
  4894. event :
  4895. new jQuery.Event(type, typeof event === "object" && event);
  4896.  
  4897. // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  4898. event.isTrigger = onlyHandlers ? 2 : 3;
  4899. event.namespace = namespaces.join(".");
  4900. event.namespace_re = event.namespace ?
  4901. new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") :
  4902. null;
  4903.  
  4904. // Clean up the event in case it is being reused
  4905. event.result = undefined;
  4906. if (!event.target)
  4907. {
  4908. event.target = elem;
  4909. }
  4910.  
  4911. // Clone any incoming data and prepend the event, creating the handler arg list
  4912. data = data == null ?
  4913. [event] :
  4914. jQuery.makeArray(data, [event]);
  4915.  
  4916. // Allow special events to draw outside the lines
  4917. special = jQuery.event.special[type] || {};
  4918. if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false)
  4919. {
  4920. return;
  4921. }
  4922.  
  4923. // Determine event propagation path in advance, per W3C events spec (#9951)
  4924. // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  4925. if (!onlyHandlers && !special.noBubble && !jQuery.isWindow(elem))
  4926. {
  4927. bubbleType = special.delegateType || type;
  4928. if (!rfocusMorph.test(bubbleType + type))
  4929. {
  4930. cur = cur.parentNode;
  4931. }
  4932. for (; cur; cur = cur.parentNode)
  4933. {
  4934. eventPath.push(cur);
  4935. tmp = cur;
  4936. }
  4937.  
  4938. // Only add window if we got to document (e.g., not plain obj or detached DOM)
  4939. if (tmp === (elem.ownerDocument || document))
  4940. {
  4941. eventPath.push(tmp.defaultView || tmp.parentWindow || window);
  4942. }
  4943. }
  4944.  
  4945. // Fire handlers on the event path
  4946. i = 0;
  4947. while ((cur = eventPath[i++]) && !event.isPropagationStopped())
  4948. {
  4949. event.type = i > 1 ?
  4950. bubbleType :
  4951. special.bindType || type;
  4952.  
  4953. // jQuery handler
  4954. handle = (data_priv.get(cur, "events") || {})[event.type] && data_priv.get(cur, "handle");
  4955. if (handle)
  4956. {
  4957. handle.apply(cur, data);
  4958. }
  4959.  
  4960. // Native handler
  4961. handle = ontype && cur[ontype];
  4962. if (handle && handle.apply && jQuery.acceptData(cur))
  4963. {
  4964. event.result = handle.apply(cur, data);
  4965. if (event.result === false)
  4966. {
  4967. event.preventDefault();
  4968. }
  4969. }
  4970. }
  4971. event.type = type;
  4972.  
  4973. // If nobody prevented the default action, do it now
  4974. if (!onlyHandlers && !event.isDefaultPrevented())
  4975. {
  4976. if ((!special._default || special._default.apply(eventPath.pop(), data) === false) &&
  4977. jQuery.acceptData(elem))
  4978. {
  4979. // Call a native DOM method on the target with the same name name as the event.
  4980. // Don't do default actions on window, that's where global variables be (#6170)
  4981. if (ontype && jQuery.isFunction(elem[type]) && !jQuery.isWindow(elem))
  4982. {
  4983. // Don't re-trigger an onFOO event when we call its FOO() method
  4984. tmp = elem[ontype];
  4985.  
  4986. if (tmp)
  4987. {
  4988. elem[ontype] = null;
  4989. }
  4990.  
  4991. // Prevent re-triggering of the same event, since we already bubbled it above
  4992. jQuery.event.triggered = type;
  4993. elem[type]();
  4994. jQuery.event.triggered = undefined;
  4995.  
  4996. if (tmp)
  4997. {
  4998. elem[ontype] = tmp;
  4999. }
  5000. }
  5001. }
  5002. }
  5003.  
  5004. return event.result;
  5005. },
  5006.  
  5007. dispatch: function(event)
  5008. {
  5009. // Make a writable jQuery.Event from the native event object
  5010. event = jQuery.event.fix(event);
  5011.  
  5012. var i, j, ret, matched, handleObj,
  5013. handlerQueue = [],
  5014. args = slice.call(arguments),
  5015. handlers = (data_priv.get(this, "events") || {})[event.type] || [],
  5016. special = jQuery.event.special[event.type] || {};
  5017.  
  5018. // Use the fix-ed jQuery.Event rather than the (read-only) native event
  5019. args[0] = event;
  5020. event.delegateTarget = this;
  5021.  
  5022. // Call the preDispatch hook for the mapped type, and let it bail if desired
  5023. if (special.preDispatch && special.preDispatch.call(this, event) === false)
  5024. {
  5025. return;
  5026. }
  5027.  
  5028. // Determine handlers
  5029. handlerQueue = jQuery.event.handlers.call(this, event, handlers);
  5030.  
  5031. // Run delegates first; they may want to stop propagation beneath us
  5032. i = 0;
  5033. while ((matched = handlerQueue[i++]) && !event.isPropagationStopped())
  5034. {
  5035. event.currentTarget = matched.elem;
  5036.  
  5037. j = 0;
  5038. while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped())
  5039. {
  5040. // Triggered event must either 1) have no namespace, or
  5041. // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
  5042. if (!event.namespace_re || event.namespace_re.test(handleObj.namespace))
  5043. {
  5044. event.handleObj = handleObj;
  5045. event.data = handleObj.data;
  5046.  
  5047. ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler)
  5048. .apply(matched.elem, args);
  5049.  
  5050. if (ret !== undefined)
  5051. {
  5052. if ((event.result = ret) === false)
  5053. {
  5054. event.preventDefault();
  5055. event.stopPropagation();
  5056. }
  5057. }
  5058. }
  5059. }
  5060. }
  5061.  
  5062. // Call the postDispatch hook for the mapped type
  5063. if (special.postDispatch)
  5064. {
  5065. special.postDispatch.call(this, event);
  5066. }
  5067.  
  5068. return event.result;
  5069. },
  5070.  
  5071. handlers: function(event, handlers)
  5072. {
  5073. var i, matches, sel, handleObj,
  5074. handlerQueue = [],
  5075. delegateCount = handlers.delegateCount,
  5076. cur = event.target;
  5077.  
  5078. // Find delegate handlers
  5079. // Black-hole SVG <use> instance trees (#13180)
  5080. // Avoid non-left-click bubbling in Firefox (#3861)
  5081. if (delegateCount && cur.nodeType && (!event.button || event.type !== "click"))
  5082. {
  5083. for (; cur !== this; cur = cur.parentNode || this)
  5084. {
  5085. // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  5086. if (cur.disabled !== true || event.type !== "click")
  5087. {
  5088. matches = [];
  5089. for (i = 0; i < delegateCount; i++)
  5090. {
  5091. handleObj = handlers[i];
  5092.  
  5093. // Don't conflict with Object.prototype properties (#13203)
  5094. sel = handleObj.selector + " ";
  5095.  
  5096. if (matches[sel] === undefined)
  5097. {
  5098. matches[sel] = handleObj.needsContext ?
  5099. jQuery(sel, this).index(cur) >= 0 :
  5100. jQuery.find(sel, this, null, [cur]).length;
  5101. }
  5102. if (matches[sel])
  5103. {
  5104. matches.push(handleObj);
  5105. }
  5106. }
  5107. if (matches.length)
  5108. {
  5109. handlerQueue.push({ elem: cur, handlers: matches });
  5110. }
  5111. }
  5112. }
  5113. }
  5114.  
  5115. // Add the remaining (directly-bound) handlers
  5116. if (delegateCount < handlers.length)
  5117. {
  5118. handlerQueue.push({ elem: this, handlers: handlers.slice(delegateCount) });
  5119. }
  5120.  
  5121. return handlerQueue;
  5122. },
  5123.  
  5124. // Includes some event props shared by KeyEvent and MouseEvent
  5125. props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  5126.  
  5127. fixHooks: {},
  5128.  
  5129. keyHooks: {
  5130. props: "char charCode key keyCode".split(" "),
  5131. filter: function(event, original)
  5132. {
  5133. // Add which for key events
  5134. if (event.which == null)
  5135. {
  5136. event.which = original.charCode != null ? original.charCode : original.keyCode;
  5137. }
  5138.  
  5139. return event;
  5140. }
  5141. },
  5142.  
  5143. mouseHooks: {
  5144. props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  5145. filter: function(event, original)
  5146. {
  5147. var eventDoc, doc, body,
  5148. button = original.button;
  5149.  
  5150. // Calculate pageX/Y if missing and clientX/Y available
  5151. if (event.pageX == null && original.clientX != null)
  5152. {
  5153. eventDoc = event.target.ownerDocument || document;
  5154. doc = eventDoc.documentElement;
  5155. body = eventDoc.body;
  5156.  
  5157. event.pageX = original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
  5158. event.pageY = original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
  5159. }
  5160.  
  5161. // Add which for click: 1 === left; 2 === middle; 3 === right
  5162. // Note: button is not normalized, so don't use it
  5163. if (!event.which && button !== undefined)
  5164. {
  5165. event.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
  5166. }
  5167.  
  5168. return event;
  5169. }
  5170. },
  5171.  
  5172. fix: function(event)
  5173. {
  5174. if (event[jQuery.expando])
  5175. {
  5176. return event;
  5177. }
  5178.  
  5179. // Create a writable copy of the event object and normalize some properties
  5180. var i, prop, copy,
  5181. type = event.type,
  5182. originalEvent = event,
  5183. fixHook = this.fixHooks[type];
  5184.  
  5185. if (!fixHook)
  5186. {
  5187. this.fixHooks[type] = fixHook =
  5188. rmouseEvent.test(type) ? this.mouseHooks :
  5189. rkeyEvent.test(type) ? this.keyHooks :
  5190. {};
  5191. }
  5192. copy = fixHook.props ? this.props.concat(fixHook.props) : this.props;
  5193.  
  5194. event = new jQuery.Event(originalEvent);
  5195.  
  5196. i = copy.length;
  5197. while (i--)
  5198. {
  5199. prop = copy[i];
  5200. event[prop] = originalEvent[prop];
  5201. }
  5202.  
  5203. // Support: Cordova 2.5 (WebKit) (#13255)
  5204. // All events should have a target; Cordova deviceready doesn't
  5205. if (!event.target)
  5206. {
  5207. event.target = document;
  5208. }
  5209.  
  5210. // Support: Safari 6.0+, Chrome < 28
  5211. // Target should not be a text node (#504, #13143)
  5212. if (event.target.nodeType === 3)
  5213. {
  5214. event.target = event.target.parentNode;
  5215. }
  5216.  
  5217. return fixHook.filter ? fixHook.filter(event, originalEvent) : event;
  5218. },
  5219.  
  5220. special: {
  5221. load: {
  5222. // Prevent triggered image.load events from bubbling to window.load
  5223. noBubble: true
  5224. },
  5225. focus: {
  5226. // Fire native event if possible so blur/focus sequence is correct
  5227. trigger: function()
  5228. {
  5229. if (this !== safeActiveElement() && this.focus)
  5230. {
  5231. this.focus();
  5232. return false;
  5233. }
  5234. },
  5235. delegateType: "focusin"
  5236. },
  5237. blur: {
  5238. trigger: function()
  5239. {
  5240. if (this === safeActiveElement() && this.blur)
  5241. {
  5242. this.blur();
  5243. return false;
  5244. }
  5245. },
  5246. delegateType: "focusout"
  5247. },
  5248. click: {
  5249. // For checkbox, fire native event so checked state will be right
  5250. trigger: function()
  5251. {
  5252. if (this.type === "checkbox" && this.click && jQuery.nodeName(this, "input"))
  5253. {
  5254. this.click();
  5255. return false;
  5256. }
  5257. },
  5258.  
  5259. // For cross-browser consistency, don't fire native .click() on links
  5260. _default: function(event)
  5261. {
  5262. return jQuery.nodeName(event.target, "a");
  5263. }
  5264. },
  5265.  
  5266. beforeunload: {
  5267. postDispatch: function(event)
  5268. {
  5269. // Support: Firefox 20+
  5270. // Firefox doesn't alert if the returnValue field is not set.
  5271. if (event.result !== undefined && event.originalEvent)
  5272. {
  5273. event.originalEvent.returnValue = event.result;
  5274. }
  5275. }
  5276. }
  5277. },
  5278.  
  5279. simulate: function(type, elem, event, bubble)
  5280. {
  5281. // Piggyback on a donor event to simulate a different one.
  5282. // Fake originalEvent to avoid donor's stopPropagation, but if the
  5283. // simulated event prevents default then we do the same on the donor.
  5284. var e = jQuery.extend(
  5285. new jQuery.Event(),
  5286. event,
  5287. {
  5288. type: type,
  5289. isSimulated: true,
  5290. originalEvent: {}
  5291. }
  5292. );
  5293. if (bubble)
  5294. {
  5295. jQuery.event.trigger(e, null, elem);
  5296. } else
  5297. {
  5298. jQuery.event.dispatch.call(elem, e);
  5299. }
  5300. if (e.isDefaultPrevented())
  5301. {
  5302. event.preventDefault();
  5303. }
  5304. }
  5305. };
  5306.  
  5307. jQuery.removeEvent = function(elem, type, handle)
  5308. {
  5309. if (elem.removeEventListener)
  5310. {
  5311. elem.removeEventListener(type, handle, false);
  5312. }
  5313. };
  5314.  
  5315. jQuery.Event = function(src, props)
  5316. {
  5317. // Allow instantiation without the 'new' keyword
  5318. if (!(this instanceof jQuery.Event))
  5319. {
  5320. return new jQuery.Event(src, props);
  5321. }
  5322.  
  5323. // Event object
  5324. if (src && src.type)
  5325. {
  5326. this.originalEvent = src;
  5327. this.type = src.type;
  5328.  
  5329. // Events bubbling up the document may have been marked as prevented
  5330. // by a handler lower down the tree; reflect the correct value.
  5331. this.isDefaultPrevented = src.defaultPrevented ||
  5332. src.defaultPrevented === undefined &&
  5333. // Support: Android < 4.0
  5334. src.returnValue === false ?
  5335. returnTrue :
  5336. returnFalse;
  5337.  
  5338. // Event type
  5339. } else
  5340. {
  5341. this.type = src;
  5342. }
  5343.  
  5344. // Put explicitly provided properties onto the event object
  5345. if (props)
  5346. {
  5347. jQuery.extend(this, props);
  5348. }
  5349.  
  5350. // Create a timestamp if incoming event doesn't have one
  5351. this.timeStamp = src && src.timeStamp || jQuery.now();
  5352.  
  5353. // Mark it as fixed
  5354. this[jQuery.expando] = true;
  5355. };
  5356.  
  5357. // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  5358. // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  5359. jQuery.Event.prototype = {
  5360. isDefaultPrevented: returnFalse,
  5361. isPropagationStopped: returnFalse,
  5362. isImmediatePropagationStopped: returnFalse,
  5363.  
  5364. preventDefault: function()
  5365. {
  5366. var e = this.originalEvent;
  5367.  
  5368. this.isDefaultPrevented = returnTrue;
  5369.  
  5370. if (e && e.preventDefault)
  5371. {
  5372. e.preventDefault();
  5373. }
  5374. },
  5375. stopPropagation: function()
  5376. {
  5377. var e = this.originalEvent;
  5378.  
  5379. this.isPropagationStopped = returnTrue;
  5380.  
  5381. if (e && e.stopPropagation)
  5382. {
  5383. e.stopPropagation();
  5384. }
  5385. },
  5386. stopImmediatePropagation: function()
  5387. {
  5388. var e = this.originalEvent;
  5389.  
  5390. this.isImmediatePropagationStopped = returnTrue;
  5391.  
  5392. if (e && e.stopImmediatePropagation)
  5393. {
  5394. e.stopImmediatePropagation();
  5395. }
  5396.  
  5397. this.stopPropagation();
  5398. }
  5399. };
  5400.  
  5401. // Create mouseenter/leave events using mouseover/out and event-time checks
  5402. // Support: Chrome 15+
  5403. jQuery.each({
  5404. mouseenter: "mouseover",
  5405. mouseleave: "mouseout",
  5406. pointerenter: "pointerover",
  5407. pointerleave: "pointerout"
  5408. }, function(orig, fix)
  5409. {
  5410. jQuery.event.special[orig] = {
  5411. delegateType: fix,
  5412. bindType: fix,
  5413.  
  5414. handle: function(event)
  5415. {
  5416. var ret,
  5417. target = this,
  5418. related = event.relatedTarget,
  5419. handleObj = event.handleObj;
  5420.  
  5421. // For mousenter/leave call the handler if related is outside the target.
  5422. // NB: No relatedTarget if the mouse left/entered the browser window
  5423. if (!related || (related !== target && !jQuery.contains(target, related)))
  5424. {
  5425. event.type = handleObj.origType;
  5426. ret = handleObj.handler.apply(this, arguments);
  5427. event.type = fix;
  5428. }
  5429. return ret;
  5430. }
  5431. };
  5432. });
  5433.  
  5434. // Create "bubbling" focus and blur events
  5435. // Support: Firefox, Chrome, Safari
  5436. if (!support.focusinBubbles)
  5437. {
  5438. jQuery.each({ focus: "focusin", blur: "focusout" }, function(orig, fix)
  5439. {
  5440. // Attach a single capturing handler on the document while someone wants focusin/focusout
  5441. var handler = function(event)
  5442. {
  5443. jQuery.event.simulate(fix, event.target, jQuery.event.fix(event), true);
  5444. };
  5445.  
  5446. jQuery.event.special[fix] = {
  5447. setup: function()
  5448. {
  5449. var doc = this.ownerDocument || this,
  5450. attaches = data_priv.access(doc, fix);
  5451.  
  5452. if (!attaches)
  5453. {
  5454. doc.addEventListener(orig, handler, true);
  5455. }
  5456. data_priv.access(doc, fix, (attaches || 0) + 1);
  5457. },
  5458. teardown: function()
  5459. {
  5460. var doc = this.ownerDocument || this,
  5461. attaches = data_priv.access(doc, fix) - 1;
  5462.  
  5463. if (!attaches)
  5464. {
  5465. doc.removeEventListener(orig, handler, true);
  5466. data_priv.remove(doc, fix);
  5467. } else
  5468. {
  5469. data_priv.access(doc, fix, attaches);
  5470. }
  5471. }
  5472. };
  5473. });
  5474. }
  5475.  
  5476. jQuery.fn.extend({
  5477. on: function(types, selector, data, fn, /*INTERNAL*/ one)
  5478. {
  5479. var origFn, type;
  5480.  
  5481. // Types can be a map of types/handlers
  5482. if (typeof types === "object")
  5483. {
  5484. // ( types-Object, selector, data )
  5485. if (typeof selector !== "string")
  5486. {
  5487. // ( types-Object, data )
  5488. data = data || selector;
  5489. selector = undefined;
  5490. }
  5491. for (type in types)
  5492. {
  5493. this.on(type, selector, data, types[type], one);
  5494. }
  5495. return this;
  5496. }
  5497.  
  5498. if (data == null && fn == null)
  5499. {
  5500. // ( types, fn )
  5501. fn = selector;
  5502. data = selector = undefined;
  5503. } else if (fn == null)
  5504. {
  5505. if (typeof selector === "string")
  5506. {
  5507. // ( types, selector, fn )
  5508. fn = data;
  5509. data = undefined;
  5510. } else
  5511. {
  5512. // ( types, data, fn )
  5513. fn = data;
  5514. data = selector;
  5515. selector = undefined;
  5516. }
  5517. }
  5518. if (fn === false)
  5519. {
  5520. fn = returnFalse;
  5521. } else if (!fn)
  5522. {
  5523. return this;
  5524. }
  5525.  
  5526. if (one === 1)
  5527. {
  5528. origFn = fn;
  5529. fn = function(event)
  5530. {
  5531. // Can use an empty set, since event contains the info
  5532. jQuery().off(event);
  5533. return origFn.apply(this, arguments);
  5534. };
  5535. // Use same guid so caller can remove using origFn
  5536. fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);
  5537. }
  5538. return this.each(function()
  5539. {
  5540. jQuery.event.add(this, types, fn, data, selector);
  5541. });
  5542. },
  5543. one: function(types, selector, data, fn)
  5544. {
  5545. return this.on(types, selector, data, fn, 1);
  5546. },
  5547. off: function(types, selector, fn)
  5548. {
  5549. var handleObj, type;
  5550. if (types && types.preventDefault && types.handleObj)
  5551. {
  5552. // ( event ) dispatched jQuery.Event
  5553. handleObj = types.handleObj;
  5554. jQuery(types.delegateTarget).off(
  5555. handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  5556. handleObj.selector,
  5557. handleObj.handler
  5558. );
  5559. return this;
  5560. }
  5561. if (typeof types === "object")
  5562. {
  5563. // ( types-object [, selector] )
  5564. for (type in types)
  5565. {
  5566. this.off(type, selector, types[type]);
  5567. }
  5568. return this;
  5569. }
  5570. if (selector === false || typeof selector === "function")
  5571. {
  5572. // ( types [, fn] )
  5573. fn = selector;
  5574. selector = undefined;
  5575. }
  5576. if (fn === false)
  5577. {
  5578. fn = returnFalse;
  5579. }
  5580. return this.each(function()
  5581. {
  5582. jQuery.event.remove(this, types, fn, selector);
  5583. });
  5584. },
  5585.  
  5586. trigger: function(type, data)
  5587. {
  5588. return this.each(function()
  5589. {
  5590. jQuery.event.trigger(type, data, this);
  5591. });
  5592. },
  5593. triggerHandler: function(type, data)
  5594. {
  5595. var elem = this[0];
  5596. if (elem)
  5597. {
  5598. return jQuery.event.trigger(type, data, elem, true);
  5599. }
  5600. }
  5601. });
  5602.  
  5603.  
  5604. var
  5605. rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
  5606. rtagName = /<([\w:]+)/,
  5607. rhtml = /<|&#?\w+;/,
  5608. rnoInnerhtml = /<(?:script|style|link)/i,
  5609. // checked="checked" or checked
  5610. rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
  5611. rscriptType = /^$|\/(?:java|ecma)script/i,
  5612. rscriptTypeMasked = /^true\/(.*)/,
  5613. rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  5614.  
  5615. // We have to close these tags to support XHTML (#13200)
  5616. wrapMap = {
  5617. // Support: IE 9
  5618. option: [1, "<select multiple='multiple'>", "</select>"],
  5619.  
  5620. thead: [1, "<table>", "</table>"],
  5621. col: [2, "<table><colgroup>", "</colgroup></table>"],
  5622. tr: [2, "<table><tbody>", "</tbody></table>"],
  5623. td: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
  5624.  
  5625. _default: [0, "", ""]
  5626. };
  5627.  
  5628. // Support: IE 9
  5629. wrapMap.optgroup = wrapMap.option;
  5630.  
  5631. wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  5632. wrapMap.th = wrapMap.td;
  5633.  
  5634. // Support: 1.x compatibility
  5635. // Manipulating tables requires a tbody
  5636. function manipulationTarget(elem, content)
  5637. {
  5638. return jQuery.nodeName(elem, "table") &&
  5639. jQuery.nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr") ?
  5640.  
  5641. elem.getElementsByTagName("tbody")[0] ||
  5642. elem.appendChild(elem.ownerDocument.createElement("tbody")) :
  5643. elem;
  5644. }
  5645.  
  5646. // Replace/restore the type attribute of script elements for safe DOM manipulation
  5647. function disableScript(elem)
  5648. {
  5649. elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
  5650. return elem;
  5651. }
  5652. function restoreScript(elem)
  5653. {
  5654. var match = rscriptTypeMasked.exec(elem.type);
  5655.  
  5656. if (match)
  5657. {
  5658. elem.type = match[1];
  5659. } else
  5660. {
  5661. elem.removeAttribute("type");
  5662. }
  5663.  
  5664. return elem;
  5665. }
  5666.  
  5667. // Mark scripts as having already been evaluated
  5668. function setGlobalEval(elems, refElements)
  5669. {
  5670. var i = 0,
  5671. l = elems.length;
  5672.  
  5673. for (; i < l; i++)
  5674. {
  5675. data_priv.set(
  5676. elems[i], "globalEval", !refElements || data_priv.get(refElements[i], "globalEval")
  5677. );
  5678. }
  5679. }
  5680.  
  5681. function cloneCopyEvent(src, dest)
  5682. {
  5683. var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
  5684.  
  5685. if (dest.nodeType !== 1)
  5686. {
  5687. return;
  5688. }
  5689.  
  5690. // 1. Copy private data: events, handlers, etc.
  5691. if (data_priv.hasData(src))
  5692. {
  5693. pdataOld = data_priv.access(src);
  5694. pdataCur = data_priv.set(dest, pdataOld);
  5695. events = pdataOld.events;
  5696.  
  5697. if (events)
  5698. {
  5699. delete pdataCur.handle;
  5700. pdataCur.events = {};
  5701.  
  5702. for (type in events)
  5703. {
  5704. for (i = 0, l = events[type].length; i < l; i++)
  5705. {
  5706. jQuery.event.add(dest, type, events[type][i]);
  5707. }
  5708. }
  5709. }
  5710. }
  5711.  
  5712. // 2. Copy user data
  5713. if (data_user.hasData(src))
  5714. {
  5715. udataOld = data_user.access(src);
  5716. udataCur = jQuery.extend({}, udataOld);
  5717.  
  5718. data_user.set(dest, udataCur);
  5719. }
  5720. }
  5721.  
  5722. function getAll(context, tag)
  5723. {
  5724. var ret = context.getElementsByTagName ? context.getElementsByTagName(tag || "*") :
  5725. context.querySelectorAll ? context.querySelectorAll(tag || "*") :
  5726. [];
  5727.  
  5728. return tag === undefined || tag && jQuery.nodeName(context, tag) ?
  5729. jQuery.merge([context], ret) :
  5730. ret;
  5731. }
  5732.  
  5733. // Support: IE >= 9
  5734. function fixInput(src, dest)
  5735. {
  5736. var nodeName = dest.nodeName.toLowerCase();
  5737.  
  5738. // Fails to persist the checked state of a cloned checkbox or radio button.
  5739. if (nodeName === "input" && rcheckableType.test(src.type))
  5740. {
  5741. dest.checked = src.checked;
  5742.  
  5743. // Fails to return the selected option to the default selected state when cloning options
  5744. } else if (nodeName === "input" || nodeName === "textarea")
  5745. {
  5746. dest.defaultValue = src.defaultValue;
  5747. }
  5748. }
  5749.  
  5750. jQuery.extend({
  5751. clone: function(elem, dataAndEvents, deepDataAndEvents)
  5752. {
  5753. var i, l, srcElements, destElements,
  5754. clone = elem.cloneNode(true),
  5755. inPage = jQuery.contains(elem.ownerDocument, elem);
  5756.  
  5757. // Support: IE >= 9
  5758. // Fix Cloning issues
  5759. if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) &&
  5760. !jQuery.isXMLDoc(elem))
  5761. {
  5762. // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  5763. destElements = getAll(clone);
  5764. srcElements = getAll(elem);
  5765.  
  5766. for (i = 0, l = srcElements.length; i < l; i++)
  5767. {
  5768. fixInput(srcElements[i], destElements[i]);
  5769. }
  5770. }
  5771.  
  5772. // Copy the events from the original to the clone
  5773. if (dataAndEvents)
  5774. {
  5775. if (deepDataAndEvents)
  5776. {
  5777. srcElements = srcElements || getAll(elem);
  5778. destElements = destElements || getAll(clone);
  5779.  
  5780. for (i = 0, l = srcElements.length; i < l; i++)
  5781. {
  5782. cloneCopyEvent(srcElements[i], destElements[i]);
  5783. }
  5784. } else
  5785. {
  5786. cloneCopyEvent(elem, clone);
  5787. }
  5788. }
  5789.  
  5790. // Preserve script evaluation history
  5791. destElements = getAll(clone, "script");
  5792. if (destElements.length > 0)
  5793. {
  5794. setGlobalEval(destElements, !inPage && getAll(elem, "script"));
  5795. }
  5796.  
  5797. // Return the cloned set
  5798. return clone;
  5799. },
  5800.  
  5801. buildFragment: function(elems, context, scripts, selection)
  5802. {
  5803. var elem, tmp, tag, wrap, contains, j,
  5804. fragment = context.createDocumentFragment(),
  5805. nodes = [],
  5806. i = 0,
  5807. l = elems.length;
  5808.  
  5809. for (; i < l; i++)
  5810. {
  5811. elem = elems[i];
  5812.  
  5813. if (elem || elem === 0)
  5814. {
  5815. // Add nodes directly
  5816. if (jQuery.type(elem) === "object")
  5817. {
  5818. // Support: QtWebKit
  5819. // jQuery.merge because push.apply(_, arraylike) throws
  5820. jQuery.merge(nodes, elem.nodeType ? [elem] : elem);
  5821.  
  5822. // Convert non-html into a text node
  5823. } else if (!rhtml.test(elem))
  5824. {
  5825. nodes.push(context.createTextNode(elem));
  5826.  
  5827. // Convert html into DOM nodes
  5828. } else
  5829. {
  5830. tmp = tmp || fragment.appendChild(context.createElement("div"));
  5831.  
  5832. // Deserialize a standard representation
  5833. tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase();
  5834. wrap = wrapMap[tag] || wrapMap._default;
  5835. tmp.innerHTML = wrap[1] + elem.replace(rxhtmlTag, "<$1></$2>") + wrap[2];
  5836.  
  5837. // Descend through wrappers to the right content
  5838. j = wrap[0];
  5839. while (j--)
  5840. {
  5841. tmp = tmp.lastChild;
  5842. }
  5843.  
  5844. // Support: QtWebKit
  5845. // jQuery.merge because push.apply(_, arraylike) throws
  5846. jQuery.merge(nodes, tmp.childNodes);
  5847.  
  5848. // Remember the top-level container
  5849. tmp = fragment.firstChild;
  5850.  
  5851. // Fixes #12346
  5852. // Support: Webkit, IE
  5853. tmp.textContent = "";
  5854. }
  5855. }
  5856. }
  5857.  
  5858. // Remove wrapper from fragment
  5859. fragment.textContent = "";
  5860.  
  5861. i = 0;
  5862. while ((elem = nodes[i++]))
  5863. {
  5864. // #4087 - If origin and destination elements are the same, and this is
  5865. // that element, do not do anything
  5866. if (selection && jQuery.inArray(elem, selection) !== -1)
  5867. {
  5868. continue;
  5869. }
  5870.  
  5871. contains = jQuery.contains(elem.ownerDocument, elem);
  5872.  
  5873. // Append to fragment
  5874. tmp = getAll(fragment.appendChild(elem), "script");
  5875.  
  5876. // Preserve script evaluation history
  5877. if (contains)
  5878. {
  5879. setGlobalEval(tmp);
  5880. }
  5881.  
  5882. // Capture executables
  5883. if (scripts)
  5884. {
  5885. j = 0;
  5886. while ((elem = tmp[j++]))
  5887. {
  5888. if (rscriptType.test(elem.type || ""))
  5889. {
  5890. scripts.push(elem);
  5891. }
  5892. }
  5893. }
  5894. }
  5895.  
  5896. return fragment;
  5897. },
  5898.  
  5899. cleanData: function(elems)
  5900. {
  5901. var data, elem, type, key,
  5902. special = jQuery.event.special,
  5903. i = 0;
  5904.  
  5905. for (; (elem = elems[i]) !== undefined; i++)
  5906. {
  5907. if (jQuery.acceptData(elem))
  5908. {
  5909. key = elem[data_priv.expando];
  5910.  
  5911. if (key && (data = data_priv.cache[key]))
  5912. {
  5913. if (data.events)
  5914. {
  5915. for (type in data.events)
  5916. {
  5917. if (special[type])
  5918. {
  5919. jQuery.event.remove(elem, type);
  5920.  
  5921. // This is a shortcut to avoid jQuery.event.remove's overhead
  5922. } else
  5923. {
  5924. jQuery.removeEvent(elem, type, data.handle);
  5925. }
  5926. }
  5927. }
  5928. if (data_priv.cache[key])
  5929. {
  5930. // Discard any remaining `private` data
  5931. delete data_priv.cache[key];
  5932. }
  5933. }
  5934. }
  5935. // Discard any remaining `user` data
  5936. delete data_user.cache[elem[data_user.expando]];
  5937. }
  5938. }
  5939. });
  5940.  
  5941. jQuery.fn.extend({
  5942. text: function(value)
  5943. {
  5944. return access(this, function(value)
  5945. {
  5946. return value === undefined ?
  5947. jQuery.text(this) :
  5948. this.empty().each(function()
  5949. {
  5950. if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9)
  5951. {
  5952. this.textContent = value;
  5953. }
  5954. });
  5955. }, null, value, arguments.length);
  5956. },
  5957.  
  5958. append: function()
  5959. {
  5960. return this.domManip(arguments, function(elem)
  5961. {
  5962. if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9)
  5963. {
  5964. var target = manipulationTarget(this, elem);
  5965. target.appendChild(elem);
  5966. }
  5967. });
  5968. },
  5969.  
  5970. prepend: function()
  5971. {
  5972. return this.domManip(arguments, function(elem)
  5973. {
  5974. if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9)
  5975. {
  5976. var target = manipulationTarget(this, elem);
  5977. target.insertBefore(elem, target.firstChild);
  5978. }
  5979. });
  5980. },
  5981.  
  5982. before: function()
  5983. {
  5984. return this.domManip(arguments, function(elem)
  5985. {
  5986. if (this.parentNode)
  5987. {
  5988. this.parentNode.insertBefore(elem, this);
  5989. }
  5990. });
  5991. },
  5992.  
  5993. after: function()
  5994. {
  5995. return this.domManip(arguments, function(elem)
  5996. {
  5997. if (this.parentNode)
  5998. {
  5999. this.parentNode.insertBefore(elem, this.nextSibling);
  6000. }
  6001. });
  6002. },
  6003.  
  6004. remove: function(selector, keepData /* Internal Use Only */)
  6005. {
  6006. var elem,
  6007. elems = selector ? jQuery.filter(selector, this) : this,
  6008. i = 0;
  6009.  
  6010. for (; (elem = elems[i]) != null; i++)
  6011. {
  6012. if (!keepData && elem.nodeType === 1)
  6013. {
  6014. jQuery.cleanData(getAll(elem));
  6015. }
  6016.  
  6017. if (elem.parentNode)
  6018. {
  6019. if (keepData && jQuery.contains(elem.ownerDocument, elem))
  6020. {
  6021. setGlobalEval(getAll(elem, "script"));
  6022. }
  6023. elem.parentNode.removeChild(elem);
  6024. }
  6025. }
  6026.  
  6027. return this;
  6028. },
  6029.  
  6030. empty: function()
  6031. {
  6032. var elem,
  6033. i = 0;
  6034.  
  6035. for (; (elem = this[i]) != null; i++)
  6036. {
  6037. if (elem.nodeType === 1)
  6038. {
  6039. // Prevent memory leaks
  6040. jQuery.cleanData(getAll(elem, false));
  6041.  
  6042. // Remove any remaining nodes
  6043. elem.textContent = "";
  6044. }
  6045. }
  6046.  
  6047. return this;
  6048. },
  6049.  
  6050. clone: function(dataAndEvents, deepDataAndEvents)
  6051. {
  6052. dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
  6053. deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
  6054.  
  6055. return this.map(function()
  6056. {
  6057. return jQuery.clone(this, dataAndEvents, deepDataAndEvents);
  6058. });
  6059. },
  6060.  
  6061. html: function(value)
  6062. {
  6063. return access(this, function(value)
  6064. {
  6065. var elem = this[0] || {},
  6066. i = 0,
  6067. l = this.length;
  6068.  
  6069. if (value === undefined && elem.nodeType === 1)
  6070. {
  6071. return elem.innerHTML;
  6072. }
  6073.  
  6074. // See if we can take a shortcut and just use innerHTML
  6075. if (typeof value === "string" && !rnoInnerhtml.test(value) &&
  6076. !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()])
  6077. {
  6078. value = value.replace(rxhtmlTag, "<$1></$2>");
  6079.  
  6080. try
  6081. {
  6082. for (; i < l; i++)
  6083. {
  6084. elem = this[i] || {};
  6085.  
  6086. // Remove element nodes and prevent memory leaks
  6087. if (elem.nodeType === 1)
  6088. {
  6089. jQuery.cleanData(getAll(elem, false));
  6090. elem.innerHTML = value;
  6091. }
  6092. }
  6093.  
  6094. elem = 0;
  6095.  
  6096. // If using innerHTML throws an exception, use the fallback method
  6097. } catch (e) { }
  6098. }
  6099.  
  6100. if (elem)
  6101. {
  6102. this.empty().append(value);
  6103. }
  6104. }, null, value, arguments.length);
  6105. },
  6106.  
  6107. replaceWith: function()
  6108. {
  6109. var arg = arguments[0];
  6110.  
  6111. // Make the changes, replacing each context element with the new content
  6112. this.domManip(arguments, function(elem)
  6113. {
  6114. arg = this.parentNode;
  6115.  
  6116. jQuery.cleanData(getAll(this));
  6117.  
  6118. if (arg)
  6119. {
  6120. arg.replaceChild(elem, this);
  6121. }
  6122. });
  6123.  
  6124. // Force removal if there was no new content (e.g., from empty arguments)
  6125. return arg && (arg.length || arg.nodeType) ? this : this.remove();
  6126. },
  6127.  
  6128. detach: function(selector)
  6129. {
  6130. return this.remove(selector, true);
  6131. },
  6132.  
  6133. domManip: function(args, callback)
  6134. {
  6135. // Flatten any nested arrays
  6136. args = concat.apply([], args);
  6137.  
  6138. var fragment, first, scripts, hasScripts, node, doc,
  6139. i = 0,
  6140. l = this.length,
  6141. set = this,
  6142. iNoClone = l - 1,
  6143. value = args[0],
  6144. isFunction = jQuery.isFunction(value);
  6145.  
  6146. // We can't cloneNode fragments that contain checked, in WebKit
  6147. if (isFunction ||
  6148. (l > 1 && typeof value === "string" &&
  6149. !support.checkClone && rchecked.test(value)))
  6150. {
  6151. return this.each(function(index)
  6152. {
  6153. var self = set.eq(index);
  6154. if (isFunction)
  6155. {
  6156. args[0] = value.call(this, index, self.html());
  6157. }
  6158. self.domManip(args, callback);
  6159. });
  6160. }
  6161.  
  6162. if (l)
  6163. {
  6164. fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this);
  6165. first = fragment.firstChild;
  6166.  
  6167. if (fragment.childNodes.length === 1)
  6168. {
  6169. fragment = first;
  6170. }
  6171.  
  6172. if (first)
  6173. {
  6174. scripts = jQuery.map(getAll(fragment, "script"), disableScript);
  6175. hasScripts = scripts.length;
  6176.  
  6177. // Use the original fragment for the last item instead of the first because it can end up
  6178. // being emptied incorrectly in certain situations (#8070).
  6179. for (; i < l; i++)
  6180. {
  6181. node = fragment;
  6182.  
  6183. if (i !== iNoClone)
  6184. {
  6185. node = jQuery.clone(node, true, true);
  6186.  
  6187. // Keep references to cloned scripts for later restoration
  6188. if (hasScripts)
  6189. {
  6190. // Support: QtWebKit
  6191. // jQuery.merge because push.apply(_, arraylike) throws
  6192. jQuery.merge(scripts, getAll(node, "script"));
  6193. }
  6194. }
  6195.  
  6196. callback.call(this[i], node, i);
  6197. }
  6198.  
  6199. if (hasScripts)
  6200. {
  6201. doc = scripts[scripts.length - 1].ownerDocument;
  6202.  
  6203. // Reenable scripts
  6204. jQuery.map(scripts, restoreScript);
  6205.  
  6206. // Evaluate executable scripts on first document insertion
  6207. for (i = 0; i < hasScripts; i++)
  6208. {
  6209. node = scripts[i];
  6210. if (rscriptType.test(node.type || "") &&
  6211. !data_priv.access(node, "globalEval") && jQuery.contains(doc, node))
  6212. {
  6213. if (node.src)
  6214. {
  6215. // Optional AJAX dependency, but won't run scripts if not present
  6216. if (jQuery._evalUrl)
  6217. {
  6218. jQuery._evalUrl(node.src);
  6219. }
  6220. } else
  6221. {
  6222. jQuery.globalEval(node.textContent.replace(rcleanScript, ""));
  6223. }
  6224. }
  6225. }
  6226. }
  6227. }
  6228. }
  6229.  
  6230. return this;
  6231. }
  6232. });
  6233.  
  6234. jQuery.each({
  6235. appendTo: "append",
  6236. prependTo: "prepend",
  6237. insertBefore: "before",
  6238. insertAfter: "after",
  6239. replaceAll: "replaceWith"
  6240. }, function(name, original)
  6241. {
  6242. jQuery.fn[name] = function(selector)
  6243. {
  6244. var elems,
  6245. ret = [],
  6246. insert = jQuery(selector),
  6247. last = insert.length - 1,
  6248. i = 0;
  6249.  
  6250. for (; i <= last; i++)
  6251. {
  6252. elems = i === last ? this : this.clone(true);
  6253. jQuery(insert[i])[original](elems);
  6254.  
  6255. // Support: QtWebKit
  6256. // .get() because push.apply(_, arraylike) throws
  6257. push.apply(ret, elems.get());
  6258. }
  6259.  
  6260. return this.pushStack(ret);
  6261. };
  6262. });
  6263.  
  6264.  
  6265. var iframe,
  6266. elemdisplay = {};
  6267.  
  6268. /**
  6269. * Retrieve the actual display of a element
  6270. * @param {String} name nodeName of the element
  6271. * @param {Object} doc Document object
  6272. */
  6273. // Called only from within defaultDisplay
  6274. function actualDisplay(name, doc)
  6275. {
  6276. var style,
  6277. elem = jQuery(doc.createElement(name)).appendTo(doc.body),
  6278.  
  6279. // getDefaultComputedStyle might be reliably used only on attached element
  6280. display = window.getDefaultComputedStyle && (style = window.getDefaultComputedStyle(elem[0])) ?
  6281.  
  6282. // Use of this method is a temporary fix (more like optmization) until something better comes along,
  6283. // since it was removed from specification and supported only in FF
  6284. style.display : jQuery.css(elem[0], "display");
  6285.  
  6286. // We don't have any data stored on the element,
  6287. // so use "detach" method as fast way to get rid of the element
  6288. elem.detach();
  6289.  
  6290. return display;
  6291. }
  6292.  
  6293. /**
  6294. * Try to determine the default display value of an element
  6295. * @param {String} nodeName
  6296. */
  6297. function defaultDisplay(nodeName)
  6298. {
  6299. var doc = document,
  6300. display = elemdisplay[nodeName];
  6301.  
  6302. if (!display)
  6303. {
  6304. display = actualDisplay(nodeName, doc);
  6305.  
  6306. // If the simple way fails, read from inside an iframe
  6307. if (display === "none" || !display)
  6308. {
  6309. // Use the already-created iframe if possible
  6310. iframe = (iframe || jQuery("<iframe frameborder='0' width='0' height='0'/>")).appendTo(doc.documentElement);
  6311.  
  6312. // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
  6313. doc = iframe[0].contentDocument;
  6314.  
  6315. // Support: IE
  6316. doc.write();
  6317. doc.close();
  6318.  
  6319. display = actualDisplay(nodeName, doc);
  6320. iframe.detach();
  6321. }
  6322.  
  6323. // Store the correct default display
  6324. elemdisplay[nodeName] = display;
  6325. }
  6326.  
  6327. return display;
  6328. }
  6329. var rmargin = (/^margin/);
  6330.  
  6331. var rnumnonpx = new RegExp("^(" + pnum + ")(?!px)[a-z%]+$", "i");
  6332.  
  6333. var getStyles = function(elem)
  6334. {
  6335. return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
  6336. };
  6337.  
  6338.  
  6339.  
  6340. function curCSS(elem, name, computed)
  6341. {
  6342. var width, minWidth, maxWidth, ret,
  6343. style = elem.style;
  6344.  
  6345. computed = computed || getStyles(elem);
  6346.  
  6347. // Support: IE9
  6348. // getPropertyValue is only needed for .css('filter') in IE9, see #12537
  6349. if (computed)
  6350. {
  6351. ret = computed.getPropertyValue(name) || computed[name];
  6352. }
  6353.  
  6354. if (computed)
  6355. {
  6356. if (ret === "" && !jQuery.contains(elem.ownerDocument, elem))
  6357. {
  6358. ret = jQuery.style(elem, name);
  6359. }
  6360.  
  6361. // Support: iOS < 6
  6362. // A tribute to the "awesome hack by Dean Edwards"
  6363. // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
  6364. // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
  6365. if (rnumnonpx.test(ret) && rmargin.test(name))
  6366. {
  6367. // Remember the original values
  6368. width = style.width;
  6369. minWidth = style.minWidth;
  6370. maxWidth = style.maxWidth;
  6371.  
  6372. // Put in the new values to get a computed value out
  6373. style.minWidth = style.maxWidth = style.width = ret;
  6374. ret = computed.width;
  6375.  
  6376. // Revert the changed values
  6377. style.width = width;
  6378. style.minWidth = minWidth;
  6379. style.maxWidth = maxWidth;
  6380. }
  6381. }
  6382.  
  6383. return ret !== undefined ?
  6384. // Support: IE
  6385. // IE returns zIndex value as an integer.
  6386. ret + "" :
  6387. ret;
  6388. }
  6389.  
  6390.  
  6391. function addGetHookIf(conditionFn, hookFn)
  6392. {
  6393. // Define the hook, we'll check on the first run if it's really needed.
  6394. return {
  6395. get: function()
  6396. {
  6397. if (conditionFn())
  6398. {
  6399. // Hook not needed (or it's not possible to use it due to missing dependency),
  6400. // remove it.
  6401. // Since there are no other hooks for marginRight, remove the whole object.
  6402. delete this.get;
  6403. return;
  6404. }
  6405.  
  6406. // Hook needed; redefine it so that the support test is not executed again.
  6407.  
  6408. return (this.get = hookFn).apply(this, arguments);
  6409. }
  6410. };
  6411. }
  6412.  
  6413.  
  6414. (function()
  6415. {
  6416. var pixelPositionVal, boxSizingReliableVal,
  6417. docElem = document.documentElement,
  6418. container = document.createElement("div"),
  6419. div = document.createElement("div");
  6420.  
  6421. if (!div.style)
  6422. {
  6423. return;
  6424. }
  6425.  
  6426. div.style.backgroundClip = "content-box";
  6427. div.cloneNode(true).style.backgroundClip = "";
  6428. support.clearCloneStyle = div.style.backgroundClip === "content-box";
  6429.  
  6430. container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
  6431. "position:absolute";
  6432. container.appendChild(div);
  6433.  
  6434. // Executing both pixelPosition & boxSizingReliable tests require only one layout
  6435. // so they're executed at the same time to save the second computation.
  6436. function computePixelPositionAndBoxSizingReliable()
  6437. {
  6438. div.style.cssText =
  6439. // Support: Firefox<29, Android 2.3
  6440. // Vendor-prefix box-sizing
  6441. "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
  6442. "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
  6443. "border:1px;padding:1px;width:4px;position:absolute";
  6444. div.innerHTML = "";
  6445. docElem.appendChild(container);
  6446.  
  6447. var divStyle = window.getComputedStyle(div, null);
  6448. pixelPositionVal = divStyle.top !== "1%";
  6449. boxSizingReliableVal = divStyle.width === "4px";
  6450.  
  6451. docElem.removeChild(container);
  6452. }
  6453.  
  6454. // Support: node.js jsdom
  6455. // Don't assume that getComputedStyle is a property of the global object
  6456. if (window.getComputedStyle)
  6457. {
  6458. jQuery.extend(support, {
  6459. pixelPosition: function()
  6460. {
  6461. // This test is executed only once but we still do memoizing
  6462. // since we can use the boxSizingReliable pre-computing.
  6463. // No need to check if the test was already performed, though.
  6464. computePixelPositionAndBoxSizingReliable();
  6465. return pixelPositionVal;
  6466. },
  6467. boxSizingReliable: function()
  6468. {
  6469. if (boxSizingReliableVal == null)
  6470. {
  6471. computePixelPositionAndBoxSizingReliable();
  6472. }
  6473. return boxSizingReliableVal;
  6474. },
  6475. reliableMarginRight: function()
  6476. {
  6477. // Support: Android 2.3
  6478. // Check if div with explicit width and no margin-right incorrectly
  6479. // gets computed margin-right based on width of container. (#3333)
  6480. // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  6481. // This support function is only executed once so no memoizing is needed.
  6482. var ret,
  6483. marginDiv = div.appendChild(document.createElement("div"));
  6484.  
  6485. // Reset CSS: box-sizing; display; margin; border; padding
  6486. marginDiv.style.cssText = div.style.cssText =
  6487. // Support: Firefox<29, Android 2.3
  6488. // Vendor-prefix box-sizing
  6489. "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
  6490. "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
  6491. marginDiv.style.marginRight = marginDiv.style.width = "0";
  6492. div.style.width = "1px";
  6493. docElem.appendChild(container);
  6494.  
  6495. ret = !parseFloat(window.getComputedStyle(marginDiv, null).marginRight);
  6496.  
  6497. docElem.removeChild(container);
  6498.  
  6499. return ret;
  6500. }
  6501. });
  6502. }
  6503. })();
  6504.  
  6505.  
  6506. // A method for quickly swapping in/out CSS properties to get correct calculations.
  6507. jQuery.swap = function(elem, options, callback, args)
  6508. {
  6509. var ret, name,
  6510. old = {};
  6511.  
  6512. // Remember the old values, and insert the new ones
  6513. for (name in options)
  6514. {
  6515. old[name] = elem.style[name];
  6516. elem.style[name] = options[name];
  6517. }
  6518.  
  6519. ret = callback.apply(elem, args || []);
  6520.  
  6521. // Revert the old values
  6522. for (name in options)
  6523. {
  6524. elem.style[name] = old[name];
  6525. }
  6526.  
  6527. return ret;
  6528. };
  6529.  
  6530.  
  6531. var
  6532. // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  6533. // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  6534. rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  6535. rnumsplit = new RegExp("^(" + pnum + ")(.*)$", "i"),
  6536. rrelNum = new RegExp("^([+-])=(" + pnum + ")", "i"),
  6537.  
  6538. cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  6539. cssNormalTransform = {
  6540. letterSpacing: "0",
  6541. fontWeight: "400"
  6542. },
  6543.  
  6544. cssPrefixes = ["Webkit", "O", "Moz", "ms"];
  6545.  
  6546. // return a css property mapped to a potentially vendor prefixed property
  6547. function vendorPropName(style, name)
  6548. {
  6549. // shortcut for names that are not vendor prefixed
  6550. if (name in style)
  6551. {
  6552. return name;
  6553. }
  6554.  
  6555. // check for vendor prefixed names
  6556. var capName = name[0].toUpperCase() + name.slice(1),
  6557. origName = name,
  6558. i = cssPrefixes.length;
  6559.  
  6560. while (i--)
  6561. {
  6562. name = cssPrefixes[i] + capName;
  6563. if (name in style)
  6564. {
  6565. return name;
  6566. }
  6567. }
  6568.  
  6569. return origName;
  6570. }
  6571.  
  6572. function setPositiveNumber(elem, value, subtract)
  6573. {
  6574. var matches = rnumsplit.exec(value);
  6575. return matches ?
  6576. // Guard against undefined "subtract", e.g., when used as in cssHooks
  6577. Math.max(0, matches[1] - (subtract || 0)) + (matches[2] || "px") :
  6578. value;
  6579. }
  6580.  
  6581. function augmentWidthOrHeight(elem, name, extra, isBorderBox, styles)
  6582. {
  6583. var i = extra === (isBorderBox ? "border" : "content") ?
  6584. // If we already have the right measurement, avoid augmentation
  6585. 4 :
  6586. // Otherwise initialize for horizontal or vertical properties
  6587. name === "width" ? 1 : 0,
  6588.  
  6589. val = 0;
  6590.  
  6591. for (; i < 4; i += 2)
  6592. {
  6593. // both box models exclude margin, so add it if we want it
  6594. if (extra === "margin")
  6595. {
  6596. val += jQuery.css(elem, extra + cssExpand[i], true, styles);
  6597. }
  6598.  
  6599. if (isBorderBox)
  6600. {
  6601. // border-box includes padding, so remove it if we want content
  6602. if (extra === "content")
  6603. {
  6604. val -= jQuery.css(elem, "padding" + cssExpand[i], true, styles);
  6605. }
  6606.  
  6607. // at this point, extra isn't border nor margin, so remove border
  6608. if (extra !== "margin")
  6609. {
  6610. val -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
  6611. }
  6612. } else
  6613. {
  6614. // at this point, extra isn't content, so add padding
  6615. val += jQuery.css(elem, "padding" + cssExpand[i], true, styles);
  6616.  
  6617. // at this point, extra isn't content nor padding, so add border
  6618. if (extra !== "padding")
  6619. {
  6620. val += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
  6621. }
  6622. }
  6623. }
  6624.  
  6625. return val;
  6626. }
  6627.  
  6628. function getWidthOrHeight(elem, name, extra)
  6629. {
  6630. // Start with offset property, which is equivalent to the border-box value
  6631. var valueIsBorderBox = true,
  6632. val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  6633. styles = getStyles(elem),
  6634. isBorderBox = jQuery.css(elem, "boxSizing", false, styles) === "border-box";
  6635.  
  6636. // some non-html elements return undefined for offsetWidth, so check for null/undefined
  6637. // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  6638. // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  6639. if (val <= 0 || val == null)
  6640. {
  6641. // Fall back to computed then uncomputed css if necessary
  6642. val = curCSS(elem, name, styles);
  6643. if (val < 0 || val == null)
  6644. {
  6645. val = elem.style[name];
  6646. }
  6647.  
  6648. // Computed unit is not pixels. Stop here and return.
  6649. if (rnumnonpx.test(val))
  6650. {
  6651. return val;
  6652. }
  6653.  
  6654. // we need the check for style in case a browser which returns unreliable values
  6655. // for getComputedStyle silently falls back to the reliable elem.style
  6656. valueIsBorderBox = isBorderBox &&
  6657. (support.boxSizingReliable() || val === elem.style[name]);
  6658.  
  6659. // Normalize "", auto, and prepare for extra
  6660. val = parseFloat(val) || 0;
  6661. }
  6662.  
  6663. // use the active box-sizing model to add/subtract irrelevant styles
  6664. return (val +
  6665. augmentWidthOrHeight(
  6666. elem,
  6667. name,
  6668. extra || (isBorderBox ? "border" : "content"),
  6669. valueIsBorderBox,
  6670. styles
  6671. )
  6672. ) + "px";
  6673. }
  6674.  
  6675. function showHide(elements, show)
  6676. {
  6677. var display, elem, hidden,
  6678. values = [],
  6679. index = 0,
  6680. length = elements.length;
  6681.  
  6682. for (; index < length; index++)
  6683. {
  6684. elem = elements[index];
  6685. if (!elem.style)
  6686. {
  6687. continue;
  6688. }
  6689.  
  6690. values[index] = data_priv.get(elem, "olddisplay");
  6691. display = elem.style.display;
  6692. if (show)
  6693. {
  6694. // Reset the inline display of this element to learn if it is
  6695. // being hidden by cascaded rules or not
  6696. if (!values[index] && display === "none")
  6697. {
  6698. elem.style.display = "";
  6699. }
  6700.  
  6701. // Set elements which have been overridden with display: none
  6702. // in a stylesheet to whatever the default browser style is
  6703. // for such an element
  6704. if (elem.style.display === "" && isHidden(elem))
  6705. {
  6706. values[index] = data_priv.access(elem, "olddisplay", defaultDisplay(elem.nodeName));
  6707. }
  6708. } else
  6709. {
  6710. hidden = isHidden(elem);
  6711.  
  6712. if (display !== "none" || !hidden)
  6713. {
  6714. data_priv.set(elem, "olddisplay", hidden ? display : jQuery.css(elem, "display"));
  6715. }
  6716. }
  6717. }
  6718.  
  6719. // Set the display of most of the elements in a second loop
  6720. // to avoid the constant reflow
  6721. for (index = 0; index < length; index++)
  6722. {
  6723. elem = elements[index];
  6724. if (!elem.style)
  6725. {
  6726. continue;
  6727. }
  6728. if (!show || elem.style.display === "none" || elem.style.display === "")
  6729. {
  6730. elem.style.display = show ? values[index] || "" : "none";
  6731. }
  6732. }
  6733.  
  6734. return elements;
  6735. }
  6736.  
  6737. jQuery.extend({
  6738. // Add in style property hooks for overriding the default
  6739. // behavior of getting and setting a style property
  6740. cssHooks: {
  6741. opacity: {
  6742. get: function(elem, computed)
  6743. {
  6744. if (computed)
  6745. {
  6746. // We should always get a number back from opacity
  6747. var ret = curCSS(elem, "opacity");
  6748. return ret === "" ? "1" : ret;
  6749. }
  6750. }
  6751. }
  6752. },
  6753.  
  6754. // Don't automatically add "px" to these possibly-unitless properties
  6755. cssNumber: {
  6756. "columnCount": true,
  6757. "fillOpacity": true,
  6758. "flexGrow": true,
  6759. "flexShrink": true,
  6760. "fontWeight": true,
  6761. "lineHeight": true,
  6762. "opacity": true,
  6763. "order": true,
  6764. "orphans": true,
  6765. "widows": true,
  6766. "zIndex": true,
  6767. "zoom": true
  6768. },
  6769.  
  6770. // Add in properties whose names you wish to fix before
  6771. // setting or getting the value
  6772. cssProps: {
  6773. // normalize float css property
  6774. "float": "cssFloat"
  6775. },
  6776.  
  6777. // Get and set the style property on a DOM Node
  6778. style: function(elem, name, value, extra)
  6779. {
  6780. // Don't set styles on text and comment nodes
  6781. if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)
  6782. {
  6783. return;
  6784. }
  6785.  
  6786. // Make sure that we're working with the right name
  6787. var ret, type, hooks,
  6788. origName = jQuery.camelCase(name),
  6789. style = elem.style;
  6790.  
  6791. name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(style, origName));
  6792.  
  6793. // gets hook for the prefixed version
  6794. // followed by the unprefixed version
  6795. hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
  6796.  
  6797. // Check if we're setting a value
  6798. if (value !== undefined)
  6799. {
  6800. type = typeof value;
  6801.  
  6802. // convert relative number strings (+= or -=) to relative numbers. #7345
  6803. if (type === "string" && (ret = rrelNum.exec(value)))
  6804. {
  6805. value = (ret[1] + 1) * ret[2] + parseFloat(jQuery.css(elem, name));
  6806. // Fixes bug #9237
  6807. type = "number";
  6808. }
  6809.  
  6810. // Make sure that null and NaN values aren't set. See: #7116
  6811. if (value == null || value !== value)
  6812. {
  6813. return;
  6814. }
  6815.  
  6816. // If a number was passed in, add 'px' to the (except for certain CSS properties)
  6817. if (type === "number" && !jQuery.cssNumber[origName])
  6818. {
  6819. value += "px";
  6820. }
  6821.  
  6822. // Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
  6823. // but it would mean to define eight (for every problematic property) identical functions
  6824. if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0)
  6825. {
  6826. style[name] = "inherit";
  6827. }
  6828.  
  6829. // If a hook was provided, use that value, otherwise just set the specified value
  6830. if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined)
  6831. {
  6832. style[name] = value;
  6833. }
  6834. } else
  6835. {
  6836. // If a hook was provided get the non-computed value from there
  6837. if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined)
  6838. {
  6839. return ret;
  6840. }
  6841.  
  6842. // Otherwise just get the value from the style object
  6843. return style[name];
  6844. }
  6845. },
  6846.  
  6847. css: function(elem, name, extra, styles)
  6848. {
  6849. var val, num, hooks,
  6850. origName = jQuery.camelCase(name);
  6851.  
  6852. // Make sure that we're working with the right name
  6853. name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));
  6854.  
  6855. // gets hook for the prefixed version
  6856. // followed by the unprefixed version
  6857. hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
  6858.  
  6859. // If a hook was provided get the computed value from there
  6860. if (hooks && "get" in hooks)
  6861. {
  6862. val = hooks.get(elem, true, extra);
  6863. }
  6864.  
  6865. // Otherwise, if a way to get the computed value exists, use that
  6866. if (val === undefined)
  6867. {
  6868. val = curCSS(elem, name, styles);
  6869. }
  6870.  
  6871. //convert "normal" to computed value
  6872. if (val === "normal" && name in cssNormalTransform)
  6873. {
  6874. val = cssNormalTransform[name];
  6875. }
  6876.  
  6877. // Return, converting to number if forced or a qualifier was provided and val looks numeric
  6878. if (extra === "" || extra)
  6879. {
  6880. num = parseFloat(val);
  6881. return extra === true || jQuery.isNumeric(num) ? num || 0 : val;
  6882. }
  6883. return val;
  6884. }
  6885. });
  6886.  
  6887. jQuery.each(["height", "width"], function(i, name)
  6888. {
  6889. jQuery.cssHooks[name] = {
  6890. get: function(elem, computed, extra)
  6891. {
  6892. if (computed)
  6893. {
  6894. // certain elements can have dimension info if we invisibly show them
  6895. // however, it must have a current display style that would benefit from this
  6896. return rdisplayswap.test(jQuery.css(elem, "display")) && elem.offsetWidth === 0 ?
  6897. jQuery.swap(elem, cssShow, function()
  6898. {
  6899. return getWidthOrHeight(elem, name, extra);
  6900. }) :
  6901. getWidthOrHeight(elem, name, extra);
  6902. }
  6903. },
  6904.  
  6905. set: function(elem, value, extra)
  6906. {
  6907. var styles = extra && getStyles(elem);
  6908. return setPositiveNumber(elem, value, extra ?
  6909. augmentWidthOrHeight(
  6910. elem,
  6911. name,
  6912. extra,
  6913. jQuery.css(elem, "boxSizing", false, styles) === "border-box",
  6914. styles
  6915. ) : 0
  6916. );
  6917. }
  6918. };
  6919. });
  6920.  
  6921. // Support: Android 2.3
  6922. jQuery.cssHooks.marginRight = addGetHookIf(support.reliableMarginRight,
  6923. function(elem, computed)
  6924. {
  6925. if (computed)
  6926. {
  6927. // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  6928. // Work around by temporarily setting element display to inline-block
  6929. return jQuery.swap(elem, { "display": "inline-block" },
  6930. curCSS, [elem, "marginRight"]);
  6931. }
  6932. }
  6933. );
  6934.  
  6935. // These hooks are used by animate to expand properties
  6936. jQuery.each({
  6937. margin: "",
  6938. padding: "",
  6939. border: "Width"
  6940. }, function(prefix, suffix)
  6941. {
  6942. jQuery.cssHooks[prefix + suffix] = {
  6943. expand: function(value)
  6944. {
  6945. var i = 0,
  6946. expanded = {},
  6947.  
  6948. // assumes a single number if not a string
  6949. parts = typeof value === "string" ? value.split(" ") : [value];
  6950.  
  6951. for (; i < 4; i++)
  6952. {
  6953. expanded[prefix + cssExpand[i] + suffix] =
  6954. parts[i] || parts[i - 2] || parts[0];
  6955. }
  6956.  
  6957. return expanded;
  6958. }
  6959. };
  6960.  
  6961. if (!rmargin.test(prefix))
  6962. {
  6963. jQuery.cssHooks[prefix + suffix].set = setPositiveNumber;
  6964. }
  6965. });
  6966.  
  6967. jQuery.fn.extend({
  6968. css: function(name, value)
  6969. {
  6970. return access(this, function(elem, name, value)
  6971. {
  6972. var styles, len,
  6973. map = {},
  6974. i = 0;
  6975.  
  6976. if (jQuery.isArray(name))
  6977. {
  6978. styles = getStyles(elem);
  6979. len = name.length;
  6980.  
  6981. for (; i < len; i++)
  6982. {
  6983. map[name[i]] = jQuery.css(elem, name[i], false, styles);
  6984. }
  6985.  
  6986. return map;
  6987. }
  6988.  
  6989. return value !== undefined ?
  6990. jQuery.style(elem, name, value) :
  6991. jQuery.css(elem, name);
  6992. }, name, value, arguments.length > 1);
  6993. },
  6994. show: function()
  6995. {
  6996. return showHide(this, true);
  6997. },
  6998. hide: function()
  6999. {
  7000. return showHide(this);
  7001. },
  7002. toggle: function(state)
  7003. {
  7004. if (typeof state === "boolean")
  7005. {
  7006. return state ? this.show() : this.hide();
  7007. }
  7008.  
  7009. return this.each(function()
  7010. {
  7011. if (isHidden(this))
  7012. {
  7013. jQuery(this).show();
  7014. } else
  7015. {
  7016. jQuery(this).hide();
  7017. }
  7018. });
  7019. }
  7020. });
  7021.  
  7022.  
  7023. // Based off of the plugin by Clint Helfers, with permission.
  7024. // http://blindsignals.com/index.php/2009/07/jquery-delay/
  7025. jQuery.fn.delay = function(time, type)
  7026. {
  7027. time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
  7028. type = type || "fx";
  7029.  
  7030. return this.queue(type, function(next, hooks)
  7031. {
  7032. var timeout = setTimeout(next, time);
  7033. hooks.stop = function()
  7034. {
  7035. clearTimeout(timeout);
  7036. };
  7037. });
  7038. };
  7039.  
  7040.  
  7041. (function()
  7042. {
  7043. var input = document.createElement("input"),
  7044. select = document.createElement("select"),
  7045. opt = select.appendChild(document.createElement("option"));
  7046.  
  7047. input.type = "checkbox";
  7048.  
  7049. // Support: iOS 5.1, Android 4.x, Android 2.3
  7050. // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
  7051. support.checkOn = input.value !== "";
  7052.  
  7053. // Must access the parent to make an option select properly
  7054. // Support: IE9, IE10
  7055. support.optSelected = opt.selected;
  7056.  
  7057. // Make sure that the options inside disabled selects aren't marked as disabled
  7058. // (WebKit marks them as disabled)
  7059. select.disabled = true;
  7060. support.optDisabled = !opt.disabled;
  7061.  
  7062. // Check if an input maintains its value after becoming a radio
  7063. // Support: IE9, IE10
  7064. input = document.createElement("input");
  7065. input.value = "t";
  7066. input.type = "radio";
  7067. support.radioValue = input.value === "t";
  7068. })();
  7069.  
  7070.  
  7071. var rclass = /[\t\r\n\f]/g;
  7072.  
  7073. jQuery.fn.extend({
  7074. addClass: function(value)
  7075. {
  7076. var classes, elem, cur, clazz, j, finalValue,
  7077. proceed = typeof value === "string" && value,
  7078. i = 0,
  7079. len = this.length;
  7080.  
  7081. if (jQuery.isFunction(value))
  7082. {
  7083. return this.each(function(j)
  7084. {
  7085. jQuery(this).addClass(value.call(this, j, this.className));
  7086. });
  7087. }
  7088.  
  7089. if (proceed)
  7090. {
  7091. // The disjunction here is for better compressibility (see removeClass)
  7092. classes = (value || "").match(rnotwhite) || [];
  7093.  
  7094. for (; i < len; i++)
  7095. {
  7096. elem = this[i];
  7097. cur = elem.nodeType === 1 && (elem.className ?
  7098. (" " + elem.className + " ").replace(rclass, " ") :
  7099. " "
  7100. );
  7101.  
  7102. if (cur)
  7103. {
  7104. j = 0;
  7105. while ((clazz = classes[j++]))
  7106. {
  7107. if (cur.indexOf(" " + clazz + " ") < 0)
  7108. {
  7109. cur += clazz + " ";
  7110. }
  7111. }
  7112.  
  7113. // only assign if different to avoid unneeded rendering.
  7114. finalValue = jQuery.trim(cur);
  7115. if (elem.className !== finalValue)
  7116. {
  7117. elem.className = finalValue;
  7118. }
  7119. }
  7120. }
  7121. }
  7122.  
  7123. return this;
  7124. },
  7125.  
  7126. removeClass: function(value)
  7127. {
  7128. var classes, elem, cur, clazz, j, finalValue,
  7129. proceed = arguments.length === 0 || typeof value === "string" && value,
  7130. i = 0,
  7131. len = this.length;
  7132.  
  7133. if (jQuery.isFunction(value))
  7134. {
  7135. return this.each(function(j)
  7136. {
  7137. jQuery(this).removeClass(value.call(this, j, this.className));
  7138. });
  7139. }
  7140. if (proceed)
  7141. {
  7142. classes = (value || "").match(rnotwhite) || [];
  7143.  
  7144. for (; i < len; i++)
  7145. {
  7146. elem = this[i];
  7147. // This expression is here for better compressibility (see addClass)
  7148. cur = elem.nodeType === 1 && (elem.className ?
  7149. (" " + elem.className + " ").replace(rclass, " ") :
  7150. ""
  7151. );
  7152.  
  7153. if (cur)
  7154. {
  7155. j = 0;
  7156. while ((clazz = classes[j++]))
  7157. {
  7158. // Remove *all* instances
  7159. while (cur.indexOf(" " + clazz + " ") >= 0)
  7160. {
  7161. cur = cur.replace(" " + clazz + " ", " ");
  7162. }
  7163. }
  7164.  
  7165. // only assign if different to avoid unneeded rendering.
  7166. finalValue = value ? jQuery.trim(cur) : "";
  7167. if (elem.className !== finalValue)
  7168. {
  7169. elem.className = finalValue;
  7170. }
  7171. }
  7172. }
  7173. }
  7174.  
  7175. return this;
  7176. },
  7177.  
  7178. toggleClass: function(value, stateVal)
  7179. {
  7180. var type = typeof value;
  7181.  
  7182. if (typeof stateVal === "boolean" && type === "string")
  7183. {
  7184. return stateVal ? this.addClass(value) : this.removeClass(value);
  7185. }
  7186.  
  7187. if (jQuery.isFunction(value))
  7188. {
  7189. return this.each(function(i)
  7190. {
  7191. jQuery(this).toggleClass(value.call(this, i, this.className, stateVal), stateVal);
  7192. });
  7193. }
  7194.  
  7195. return this.each(function()
  7196. {
  7197. if (type === "string")
  7198. {
  7199. // toggle individual class names
  7200. var className,
  7201. i = 0,
  7202. self = jQuery(this),
  7203. classNames = value.match(rnotwhite) || [];
  7204.  
  7205. while ((className = classNames[i++]))
  7206. {
  7207. // check each className given, space separated list
  7208. if (self.hasClass(className))
  7209. {
  7210. self.removeClass(className);
  7211. } else
  7212. {
  7213. self.addClass(className);
  7214. }
  7215. }
  7216.  
  7217. // Toggle whole class name
  7218. } else if (type === strundefined || type === "boolean")
  7219. {
  7220. if (this.className)
  7221. {
  7222. // store className if set
  7223. data_priv.set(this, "__className__", this.className);
  7224. }
  7225.  
  7226. // If the element has a class name or if we're passed "false",
  7227. // then remove the whole classname (if there was one, the above saved it).
  7228. // Otherwise bring back whatever was previously saved (if anything),
  7229. // falling back to the empty string if nothing was stored.
  7230. this.className = this.className || value === false ? "" : data_priv.get(this, "__className__") || "";
  7231. }
  7232. });
  7233. },
  7234.  
  7235. hasClass: function(selector)
  7236. {
  7237. var className = " " + selector + " ",
  7238. i = 0,
  7239. l = this.length;
  7240. for (; i < l; i++)
  7241. {
  7242. if (this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf(className) >= 0)
  7243. {
  7244. return true;
  7245. }
  7246. }
  7247.  
  7248. return false;
  7249. }
  7250. });
  7251.  
  7252.  
  7253.  
  7254.  
  7255. var rreturn = /\r/g;
  7256.  
  7257. jQuery.fn.extend({
  7258. val: function(value)
  7259. {
  7260. var hooks, ret, isFunction,
  7261. elem = this[0];
  7262.  
  7263. if (!arguments.length)
  7264. {
  7265. if (elem)
  7266. {
  7267. hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()];
  7268.  
  7269. if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined)
  7270. {
  7271. return ret;
  7272. }
  7273.  
  7274. ret = elem.value;
  7275.  
  7276. return typeof ret === "string" ?
  7277. // handle most common string cases
  7278. ret.replace(rreturn, "") :
  7279. // handle cases where value is null/undef or number
  7280. ret == null ? "" : ret;
  7281. }
  7282.  
  7283. return;
  7284. }
  7285.  
  7286. isFunction = jQuery.isFunction(value);
  7287.  
  7288. return this.each(function(i)
  7289. {
  7290. var val;
  7291.  
  7292. if (this.nodeType !== 1)
  7293. {
  7294. return;
  7295. }
  7296.  
  7297. if (isFunction)
  7298. {
  7299. val = value.call(this, i, jQuery(this).val());
  7300. } else
  7301. {
  7302. val = value;
  7303. }
  7304.  
  7305. // Treat null/undefined as ""; convert numbers to string
  7306. if (val == null)
  7307. {
  7308. val = "";
  7309. } else if (typeof val === "number")
  7310. {
  7311. val += "";
  7312. } else if (jQuery.isArray(val))
  7313. {
  7314. val = jQuery.map(val, function(value)
  7315. {
  7316. return value == null ? "" : value + "";
  7317. });
  7318. }
  7319.  
  7320. hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()];
  7321.  
  7322. // If set returns undefined, fall back to normal setting
  7323. if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined)
  7324. {
  7325. this.value = val;
  7326. }
  7327. });
  7328. }
  7329. });
  7330.  
  7331. jQuery.extend({
  7332. valHooks: {
  7333. option: {
  7334. get: function(elem)
  7335. {
  7336. var val = jQuery.find.attr(elem, "value");
  7337. return val != null ?
  7338. val :
  7339. // Support: IE10-11+
  7340. // option.text throws exceptions (#14686, #14858)
  7341. jQuery.trim(jQuery.text(elem));
  7342. }
  7343. },
  7344. select: {
  7345. get: function(elem)
  7346. {
  7347. var value, option,
  7348. options = elem.options,
  7349. index = elem.selectedIndex,
  7350. one = elem.type === "select-one" || index < 0,
  7351. values = one ? null : [],
  7352. max = one ? index + 1 : options.length,
  7353. i = index < 0 ?
  7354. max :
  7355. one ? index : 0;
  7356.  
  7357. // Loop through all the selected options
  7358. for (; i < max; i++)
  7359. {
  7360. option = options[i];
  7361.  
  7362. // IE6-9 doesn't update selected after form reset (#2551)
  7363. if ((option.selected || i === index) &&
  7364. // Don't return options that are disabled or in a disabled optgroup
  7365. (support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
  7366. (!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, "optgroup")))
  7367. {
  7368. // Get the specific value for the option
  7369. value = jQuery(option).val();
  7370.  
  7371. // We don't need an array for one selects
  7372. if (one)
  7373. {
  7374. return value;
  7375. }
  7376.  
  7377. // Multi-Selects return an array
  7378. values.push(value);
  7379. }
  7380. }
  7381.  
  7382. return values;
  7383. },
  7384.  
  7385. set: function(elem, value)
  7386. {
  7387. var optionSet, option,
  7388. options = elem.options,
  7389. values = jQuery.makeArray(value),
  7390. i = options.length;
  7391.  
  7392. while (i--)
  7393. {
  7394. option = options[i];
  7395. if ((option.selected = jQuery.inArray(option.value, values) >= 0))
  7396. {
  7397. optionSet = true;
  7398. }
  7399. }
  7400.  
  7401. // force browsers to behave consistently when non-matching value is set
  7402. if (!optionSet)
  7403. {
  7404. elem.selectedIndex = -1;
  7405. }
  7406. return values;
  7407. }
  7408. }
  7409. }
  7410. });
  7411.  
  7412. // Radios and checkboxes getter/setter
  7413. jQuery.each(["radio", "checkbox"], function()
  7414. {
  7415. jQuery.valHooks[this] = {
  7416. set: function(elem, value)
  7417. {
  7418. if (jQuery.isArray(value))
  7419. {
  7420. return (elem.checked = jQuery.inArray(jQuery(elem).val(), value) >= 0);
  7421. }
  7422. }
  7423. };
  7424. if (!support.checkOn)
  7425. {
  7426. jQuery.valHooks[this].get = function(elem)
  7427. {
  7428. // Support: Webkit
  7429. // "" is returned instead of "on" if a value isn't specified
  7430. return elem.getAttribute("value") === null ? "on" : elem.value;
  7431. };
  7432. }
  7433. });
  7434.  
  7435.  
  7436.  
  7437.  
  7438. // Return jQuery for attributes-only inclusion
  7439.  
  7440.  
  7441. jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick " +
  7442. "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
  7443. "change select submit keydown keypress keyup error contextmenu").split(" "), function(i, name)
  7444. {
  7445. // Handle event binding
  7446. jQuery.fn[name] = function(data, fn)
  7447. {
  7448. return arguments.length > 0 ?
  7449. this.on(name, null, data, fn) :
  7450. this.trigger(name);
  7451. };
  7452. });
  7453.  
  7454. jQuery.fn.extend({
  7455. hover: function(fnOver, fnOut)
  7456. {
  7457. return this.mouseenter(fnOver).mouseleave(fnOut || fnOver);
  7458. },
  7459.  
  7460. bind: function(types, data, fn)
  7461. {
  7462. return this.on(types, null, data, fn);
  7463. },
  7464. unbind: function(types, fn)
  7465. {
  7466. return this.off(types, null, fn);
  7467. },
  7468.  
  7469. delegate: function(selector, types, data, fn)
  7470. {
  7471. return this.on(types, selector, data, fn);
  7472. },
  7473. undelegate: function(selector, types, fn)
  7474. {
  7475. // ( namespace ) or ( selector, types [, fn] )
  7476. return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
  7477. }
  7478. });
  7479.  
  7480.  
  7481. var nonce = jQuery.now();
  7482.  
  7483. var rquery = (/\?/);
  7484.  
  7485.  
  7486.  
  7487. var
  7488. // Document location
  7489. ajaxLocParts,
  7490. ajaxLocation,
  7491.  
  7492. rhash = /#.*$/,
  7493. rts = /([?&])_=[^&]*/,
  7494. rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  7495. // #7653, #8125, #8152: local protocol detection
  7496. rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  7497. rnoContent = /^(?:GET|HEAD)$/,
  7498. rprotocol = /^\/\//,
  7499. rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
  7500.  
  7501. /* Prefilters
  7502. * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  7503. * 2) These are called:
  7504. * - BEFORE asking for a transport
  7505. * - AFTER param serialization (s.data is a string if s.processData is true)
  7506. * 3) key is the dataType
  7507. * 4) the catchall symbol "*" can be used
  7508. * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  7509. */
  7510. prefilters = {},
  7511.  
  7512. /* Transports bindings
  7513. * 1) key is the dataType
  7514. * 2) the catchall symbol "*" can be used
  7515. * 3) selection will start with transport dataType and THEN go to "*" if needed
  7516. */
  7517. transports = {},
  7518.  
  7519. // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  7520. allTypes = "*/".concat("*");
  7521.  
  7522. // #8138, IE may throw an exception when accessing
  7523. // a field from window.location if document.domain has been set
  7524. try
  7525. {
  7526. ajaxLocation = location.href;
  7527. } catch (e)
  7528. {
  7529. // Use the href attribute of an A element
  7530. // since IE will modify it given document.location
  7531. ajaxLocation = document.createElement("a");
  7532. ajaxLocation.href = "";
  7533. ajaxLocation = ajaxLocation.href;
  7534. }
  7535.  
  7536. // Segment location into parts
  7537. ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [];
  7538.  
  7539. // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  7540. function addToPrefiltersOrTransports(structure)
  7541. {
  7542. // dataTypeExpression is optional and defaults to "*"
  7543. return function(dataTypeExpression, func)
  7544. {
  7545. if (typeof dataTypeExpression !== "string")
  7546. {
  7547. func = dataTypeExpression;
  7548. dataTypeExpression = "*";
  7549. }
  7550.  
  7551. var dataType,
  7552. i = 0,
  7553. dataTypes = dataTypeExpression.toLowerCase().match(rnotwhite) || [];
  7554.  
  7555. if (jQuery.isFunction(func))
  7556. {
  7557. // For each dataType in the dataTypeExpression
  7558. while ((dataType = dataTypes[i++]))
  7559. {
  7560. // Prepend if requested
  7561. if (dataType[0] === "+")
  7562. {
  7563. dataType = dataType.slice(1) || "*";
  7564. (structure[dataType] = structure[dataType] || []).unshift(func);
  7565.  
  7566. // Otherwise append
  7567. } else
  7568. {
  7569. (structure[dataType] = structure[dataType] || []).push(func);
  7570. }
  7571. }
  7572. }
  7573. };
  7574. }
  7575.  
  7576. // Base inspection function for prefilters and transports
  7577. function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR)
  7578. {
  7579. var inspected = {},
  7580. seekingTransport = (structure === transports);
  7581.  
  7582. function inspect(dataType)
  7583. {
  7584. var selected;
  7585. inspected[dataType] = true;
  7586. jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory)
  7587. {
  7588. var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);
  7589. if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport])
  7590. {
  7591. options.dataTypes.unshift(dataTypeOrTransport);
  7592. inspect(dataTypeOrTransport);
  7593. return false;
  7594. } else if (seekingTransport)
  7595. {
  7596. return !(selected = dataTypeOrTransport);
  7597. }
  7598. });
  7599. return selected;
  7600. }
  7601.  
  7602. return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");
  7603. }
  7604.  
  7605. // A special extend for ajax options
  7606. // that takes "flat" options (not to be deep extended)
  7607. // Fixes #9887
  7608. function ajaxExtend(target, src)
  7609. {
  7610. var key, deep,
  7611. flatOptions = jQuery.ajaxSettings.flatOptions || {};
  7612.  
  7613. for (key in src)
  7614. {
  7615. if (src[key] !== undefined)
  7616. {
  7617. (flatOptions[key] ? target : (deep || (deep = {})))[key] = src[key];
  7618. }
  7619. }
  7620. if (deep)
  7621. {
  7622. jQuery.extend(true, target, deep);
  7623. }
  7624.  
  7625. return target;
  7626. }
  7627.  
  7628. /* Handles responses to an ajax request:
  7629. * - finds the right dataType (mediates between content-type and expected dataType)
  7630. * - returns the corresponding response
  7631. */
  7632. function ajaxHandleResponses(s, jqXHR, responses)
  7633. {
  7634. var ct, type, finalDataType, firstDataType,
  7635. contents = s.contents,
  7636. dataTypes = s.dataTypes;
  7637.  
  7638. // Remove auto dataType and get content-type in the process
  7639. while (dataTypes[0] === "*")
  7640. {
  7641. dataTypes.shift();
  7642. if (ct === undefined)
  7643. {
  7644. ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
  7645. }
  7646. }
  7647.  
  7648. // Check if we're dealing with a known content-type
  7649. if (ct)
  7650. {
  7651. for (type in contents)
  7652. {
  7653. if (contents[type] && contents[type].test(ct))
  7654. {
  7655. dataTypes.unshift(type);
  7656. break;
  7657. }
  7658. }
  7659. }
  7660.  
  7661. // Check to see if we have a response for the expected dataType
  7662. if (dataTypes[0] in responses)
  7663. {
  7664. finalDataType = dataTypes[0];
  7665. } else
  7666. {
  7667. // Try convertible dataTypes
  7668. for (type in responses)
  7669. {
  7670. if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]])
  7671. {
  7672. finalDataType = type;
  7673. break;
  7674. }
  7675. if (!firstDataType)
  7676. {
  7677. firstDataType = type;
  7678. }
  7679. }
  7680. // Or just use first one
  7681. finalDataType = finalDataType || firstDataType;
  7682. }
  7683.  
  7684. // If we found a dataType
  7685. // We add the dataType to the list if needed
  7686. // and return the corresponding response
  7687. if (finalDataType)
  7688. {
  7689. if (finalDataType !== dataTypes[0])
  7690. {
  7691. dataTypes.unshift(finalDataType);
  7692. }
  7693. return responses[finalDataType];
  7694. }
  7695. }
  7696.  
  7697. /* Chain conversions given the request and the original response
  7698. * Also sets the responseXXX fields on the jqXHR instance
  7699. */
  7700. function ajaxConvert(s, response, jqXHR, isSuccess)
  7701. {
  7702. var conv2, current, conv, tmp, prev,
  7703. converters = {},
  7704. // Work with a copy of dataTypes in case we need to modify it for conversion
  7705. dataTypes = s.dataTypes.slice();
  7706.  
  7707. // Create converters map with lowercased keys
  7708. if (dataTypes[1])
  7709. {
  7710. for (conv in s.converters)
  7711. {
  7712. converters[conv.toLowerCase()] = s.converters[conv];
  7713. }
  7714. }
  7715.  
  7716. current = dataTypes.shift();
  7717.  
  7718. // Convert to each sequential dataType
  7719. while (current)
  7720. {
  7721. if (s.responseFields[current])
  7722. {
  7723. jqXHR[s.responseFields[current]] = response;
  7724. }
  7725.  
  7726. // Apply the dataFilter if provided
  7727. if (!prev && isSuccess && s.dataFilter)
  7728. {
  7729. response = s.dataFilter(response, s.dataType);
  7730. }
  7731.  
  7732. prev = current;
  7733. current = dataTypes.shift();
  7734.  
  7735. if (current)
  7736. {
  7737. // There's only work to do if current dataType is non-auto
  7738. if (current === "*")
  7739. {
  7740. current = prev;
  7741.  
  7742. // Convert response if prev dataType is non-auto and differs from current
  7743. } else if (prev !== "*" && prev !== current)
  7744. {
  7745. // Seek a direct converter
  7746. conv = converters[prev + " " + current] || converters["* " + current];
  7747.  
  7748. // If none found, seek a pair
  7749. if (!conv)
  7750. {
  7751. for (conv2 in converters)
  7752. {
  7753. // If conv2 outputs current
  7754. tmp = conv2.split(" ");
  7755. if (tmp[1] === current)
  7756. {
  7757. // If prev can be converted to accepted input
  7758. conv = converters[prev + " " + tmp[0]] ||
  7759. converters["* " + tmp[0]];
  7760. if (conv)
  7761. {
  7762. // Condense equivalence converters
  7763. if (conv === true)
  7764. {
  7765. conv = converters[conv2];
  7766.  
  7767. // Otherwise, insert the intermediate dataType
  7768. } else if (converters[conv2] !== true)
  7769. {
  7770. current = tmp[0];
  7771. dataTypes.unshift(tmp[1]);
  7772. }
  7773. break;
  7774. }
  7775. }
  7776. }
  7777. }
  7778.  
  7779. // Apply converter (if not an equivalence)
  7780. if (conv !== true)
  7781. {
  7782. // Unless errors are allowed to bubble, catch and return them
  7783. if (conv && s["throws"])
  7784. {
  7785. response = conv(response);
  7786. } else
  7787. {
  7788. try
  7789. {
  7790. response = conv(response);
  7791. } catch (e)
  7792. {
  7793. return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
  7794. }
  7795. }
  7796. }
  7797. }
  7798. }
  7799. }
  7800.  
  7801. return { state: "success", data: response };
  7802. }
  7803.  
  7804. jQuery.extend({
  7805. // Counter for holding the number of active queries
  7806. active: 0,
  7807.  
  7808. // Last-Modified header cache for next request
  7809. lastModified: {},
  7810. etag: {},
  7811.  
  7812. ajaxSettings: {
  7813. url: ajaxLocation,
  7814. type: "GET",
  7815. isLocal: rlocalProtocol.test(ajaxLocParts[1]),
  7816. global: true,
  7817. processData: true,
  7818. async: true,
  7819. contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  7820. /*
  7821. timeout: 0,
  7822. data: null,
  7823. dataType: null,
  7824. uzername: null,
  7825. pazzwurd: null,
  7826. cache: null,
  7827. throws: false,
  7828. traditional: false,
  7829. headers: {},
  7830. */
  7831.  
  7832. accepts: {
  7833. "*": allTypes,
  7834. text: "text/plain",
  7835. html: "text/html",
  7836. xml: "application/xml, text/xml",
  7837. json: "application/json, text/javascript"
  7838. },
  7839.  
  7840. contents: {
  7841. xml: /xml/,
  7842. html: /html/,
  7843. json: /json/
  7844. },
  7845.  
  7846. responseFields: {
  7847. xml: "responseXML",
  7848. text: "responseText",
  7849. json: "responseJSON"
  7850. },
  7851.  
  7852. // Data converters
  7853. // Keys separate source (or catchall "*") and destination types with a single space
  7854. converters: {
  7855. // Convert anything to text
  7856. "* text": String,
  7857.  
  7858. // Text to html (true = no transformation)
  7859. "text html": true,
  7860.  
  7861. // Evaluate text as a json expression
  7862. "text json": jQuery.parseJSON,
  7863.  
  7864. // Parse text as xml
  7865. "text xml": jQuery.parseXML
  7866. },
  7867.  
  7868. // For options that shouldn't be deep extended:
  7869. // you can add your own custom options here if
  7870. // and when you create one that shouldn't be
  7871. // deep extended (see ajaxExtend)
  7872. flatOptions: {
  7873. url: true,
  7874. context: true
  7875. }
  7876. },
  7877.  
  7878. // Creates a full fledged settings object into target
  7879. // with both ajaxSettings and settings fields.
  7880. // If target is omitted, writes into ajaxSettings.
  7881. ajaxSetup: function(target, settings)
  7882. {
  7883. return settings ?
  7884.  
  7885. // Building a settings object
  7886. ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) :
  7887.  
  7888. // Extending ajaxSettings
  7889. ajaxExtend(jQuery.ajaxSettings, target);
  7890. },
  7891.  
  7892. ajaxPrefilter: addToPrefiltersOrTransports(prefilters),
  7893. ajaxTransport: addToPrefiltersOrTransports(transports),
  7894.  
  7895. // Main method
  7896. ajax: function(url, options)
  7897. {
  7898. // If url is an object, simulate pre-1.5 signature
  7899. if (typeof url === "object")
  7900. {
  7901. options = url;
  7902. url = undefined;
  7903. }
  7904.  
  7905. // Force options to be an object
  7906. options = options || {};
  7907.  
  7908. var transport,
  7909. // URL without anti-cache param
  7910. cacheURL,
  7911. // Response headers
  7912. responseHeadersString,
  7913. responseHeaders,
  7914. // timeout handle
  7915. timeoutTimer,
  7916. // Cross-domain detection vars
  7917. parts,
  7918. // To know if global events are to be dispatched
  7919. fireGlobals,
  7920. // Loop variable
  7921. i,
  7922. // Create the final options object
  7923. s = jQuery.ajaxSetup({}, options),
  7924. // Callbacks context
  7925. callbackContext = s.context || s,
  7926. // Context for global events is callbackContext if it is a DOM node or jQuery collection
  7927. globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ?
  7928. jQuery(callbackContext) :
  7929. jQuery.event,
  7930. // Deferreds
  7931. deferred = jQuery.Deferred(),
  7932. completeDeferred = jQuery.Callbacks("once memory"),
  7933. // Status-dependent callbacks
  7934. statusCode = s.statusCode || {},
  7935. // Headers (they are sent all at once)
  7936. requestHeaders = {},
  7937. requestHeadersNames = {},
  7938. // The jqXHR state
  7939. state = 0,
  7940. // Default abort message
  7941. strAbort = "canceled",
  7942. // Fake xhr
  7943. jqXHR = {
  7944. readyState: 0,
  7945.  
  7946. // Builds headers hashtable if needed
  7947. getResponseHeader: function(key)
  7948. {
  7949. var match;
  7950. if (state === 2)
  7951. {
  7952. if (!responseHeaders)
  7953. {
  7954. responseHeaders = {};
  7955. while ((match = rheaders.exec(responseHeadersString)))
  7956. {
  7957. responseHeaders[match[1].toLowerCase()] = match[2];
  7958. }
  7959. }
  7960. match = responseHeaders[key.toLowerCase()];
  7961. }
  7962. return match == null ? null : match;
  7963. },
  7964.  
  7965. // Raw string
  7966. getAllResponseHeaders: function()
  7967. {
  7968. return state === 2 ? responseHeadersString : null;
  7969. },
  7970.  
  7971. // Caches the header
  7972. setRequestHeader: function(name, value)
  7973. {
  7974. var lname = name.toLowerCase();
  7975. if (!state)
  7976. {
  7977. name = requestHeadersNames[lname] = requestHeadersNames[lname] || name;
  7978. requestHeaders[name] = value;
  7979. }
  7980. return this;
  7981. },
  7982.  
  7983. // Overrides response content-type header
  7984. overrideMimeType: function(type)
  7985. {
  7986. if (!state)
  7987. {
  7988. s.mimeType = type;
  7989. }
  7990. return this;
  7991. },
  7992.  
  7993. // Status-dependent callbacks
  7994. statusCode: function(map)
  7995. {
  7996. var code;
  7997. if (map)
  7998. {
  7999. if (state < 2)
  8000. {
  8001. for (code in map)
  8002. {
  8003. // Lazy-add the new callback in a way that preserves old ones
  8004. statusCode[code] = [statusCode[code], map[code]];
  8005. }
  8006. } else
  8007. {
  8008. // Execute the appropriate callbacks
  8009. jqXHR.always(map[jqXHR.status]);
  8010. }
  8011. }
  8012. return this;
  8013. },
  8014.  
  8015. // Cancel the request
  8016. abort: function(statusText)
  8017. {
  8018. var finalText = statusText || strAbort;
  8019. if (transport)
  8020. {
  8021. transport.abort(finalText);
  8022. }
  8023. done(0, finalText);
  8024. return this;
  8025. }
  8026. };
  8027.  
  8028. // Attach deferreds
  8029. deferred.promise(jqXHR).complete = completeDeferred.add;
  8030. jqXHR.success = jqXHR.done;
  8031. jqXHR.error = jqXHR.fail;
  8032.  
  8033. // Remove hash character (#7531: and string promotion)
  8034. // Add protocol if not provided (prefilters might expect it)
  8035. // Handle falsy url in the settings object (#10093: consistency with old signature)
  8036. // We also use the url parameter if available
  8037. s.url = ((url || s.url || ajaxLocation) + "").replace(rhash, "")
  8038. .replace(rprotocol, ajaxLocParts[1] + "//");
  8039.  
  8040. // Alias method option to type as per ticket #12004
  8041. s.type = options.method || options.type || s.method || s.type;
  8042.  
  8043. // Extract dataTypes list
  8044. s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().match(rnotwhite) || [""];
  8045.  
  8046. // A cross-domain request is in order when we have a protocol:host:port mismatch
  8047. if (s.crossDomain == null)
  8048. {
  8049. parts = rurl.exec(s.url.toLowerCase());
  8050. s.crossDomain = !!(parts &&
  8051. (parts[1] !== ajaxLocParts[1] || parts[2] !== ajaxLocParts[2] ||
  8052. (parts[3] || (parts[1] === "http:" ? "80" : "443")) !==
  8053. (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? "80" : "443")))
  8054. );
  8055. }
  8056.  
  8057. // Convert data if not already a string
  8058. if (s.data && s.processData && typeof s.data !== "string")
  8059. {
  8060. s.data = jQuery.param(s.data, s.traditional);
  8061. }
  8062.  
  8063. // Apply prefilters
  8064. inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);
  8065.  
  8066. // If request was aborted inside a prefilter, stop there
  8067. if (state === 2)
  8068. {
  8069. return jqXHR;
  8070. }
  8071.  
  8072. // We can fire global events as of now if asked to
  8073. fireGlobals = s.global;
  8074.  
  8075. // Watch for a new set of requests
  8076. if (fireGlobals && jQuery.active++ === 0)
  8077. {
  8078. jQuery.event.trigger("ajaxStart");
  8079. }
  8080.  
  8081. // Uppercase the type
  8082. s.type = s.type.toUpperCase();
  8083.  
  8084. // Determine if request has content
  8085. s.hasContent = !rnoContent.test(s.type);
  8086.  
  8087. // Save the URL in case we're toying with the If-Modified-Since
  8088. // and/or If-None-Match header later on
  8089. cacheURL = s.url;
  8090.  
  8091. // More options handling for requests with no content
  8092. if (!s.hasContent)
  8093. {
  8094. // If data is available, append data to url
  8095. if (s.data)
  8096. {
  8097. cacheURL = (s.url += (rquery.test(cacheURL) ? "&" : "?") + s.data);
  8098. // #9682: remove data so that it's not used in an eventual retry
  8099. delete s.data;
  8100. }
  8101.  
  8102. // Add anti-cache in url if needed
  8103. if (s.cache === false)
  8104. {
  8105. s.url = rts.test(cacheURL) ?
  8106.  
  8107. // If there is already a '_' parameter, set its value
  8108. cacheURL.replace(rts, "$1_=" + nonce++) :
  8109.  
  8110. // Otherwise add one to the end
  8111. cacheURL + (rquery.test(cacheURL) ? "&" : "?") + "_=" + nonce++;
  8112. }
  8113. }
  8114.  
  8115. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  8116. if (s.ifModified)
  8117. {
  8118. if (jQuery.lastModified[cacheURL])
  8119. {
  8120. jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[cacheURL]);
  8121. }
  8122. if (jQuery.etag[cacheURL])
  8123. {
  8124. jqXHR.setRequestHeader("If-None-Match", jQuery.etag[cacheURL]);
  8125. }
  8126. }
  8127.  
  8128. // Set the correct header, if data is being sent
  8129. if (s.data && s.hasContent && s.contentType !== false || options.contentType)
  8130. {
  8131. jqXHR.setRequestHeader("Content-Type", s.contentType);
  8132. }
  8133.  
  8134. // Set the Accepts header for the server, depending on the dataType
  8135. jqXHR.setRequestHeader(
  8136. "Accept",
  8137. s.dataTypes[0] && s.accepts[s.dataTypes[0]] ?
  8138. s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") :
  8139. s.accepts["*"]
  8140. );
  8141.  
  8142. // Check for headers option
  8143. for (i in s.headers)
  8144. {
  8145. jqXHR.setRequestHeader(i, s.headers[i]);
  8146. }
  8147.  
  8148. // Allow custom headers/mimetypes and early abort
  8149. if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2))
  8150. {
  8151. // Abort if not done already and return
  8152. return jqXHR.abort();
  8153. }
  8154.  
  8155. // aborting is no longer a cancellation
  8156. strAbort = "abort";
  8157.  
  8158. // Install callbacks on deferreds
  8159. for (i in { success: 1, error: 1, complete: 1 })
  8160. {
  8161. jqXHR[i](s[i]);
  8162. }
  8163.  
  8164. // Get transport
  8165. transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
  8166.  
  8167. // If no transport, we auto-abort
  8168. if (!transport)
  8169. {
  8170. done(-1, "No Transport");
  8171. } else
  8172. {
  8173. jqXHR.readyState = 1;
  8174.  
  8175. // Send global event
  8176. if (fireGlobals)
  8177. {
  8178. globalEventContext.trigger("ajaxSend", [jqXHR, s]);
  8179. }
  8180. // Timeout
  8181. if (s.async && s.timeout > 0)
  8182. {
  8183. timeoutTimer = setTimeout(function()
  8184. {
  8185. jqXHR.abort("timeout");
  8186. }, s.timeout);
  8187. }
  8188.  
  8189. try
  8190. {
  8191. state = 1;
  8192. transport.send(requestHeaders, done);
  8193. } catch (e)
  8194. {
  8195. // Propagate exception as error if not done
  8196. if (state < 2)
  8197. {
  8198. done(-1, e);
  8199. // Simply rethrow otherwise
  8200. } else
  8201. {
  8202. throw e;
  8203. }
  8204. }
  8205. }
  8206.  
  8207. // Callback for when everything is done
  8208. function done(status, nativeStatusText, responses, headers)
  8209. {
  8210. var isSuccess, success, error, response, modified,
  8211. statusText = nativeStatusText;
  8212.  
  8213. // Called once
  8214. if (state === 2)
  8215. {
  8216. return;
  8217. }
  8218.  
  8219. // State is "done" now
  8220. state = 2;
  8221.  
  8222. // Clear timeout if it exists
  8223. if (timeoutTimer)
  8224. {
  8225. clearTimeout(timeoutTimer);
  8226. }
  8227.  
  8228. // Dereference transport for early garbage collection
  8229. // (no matter how long the jqXHR object will be used)
  8230. transport = undefined;
  8231.  
  8232. // Cache response headers
  8233. responseHeadersString = headers || "";
  8234.  
  8235. // Set readyState
  8236. jqXHR.readyState = status > 0 ? 4 : 0;
  8237.  
  8238. // Determine if successful
  8239. isSuccess = status >= 200 && status < 300 || status === 304;
  8240.  
  8241. // Get response data
  8242. if (responses)
  8243. {
  8244. response = ajaxHandleResponses(s, jqXHR, responses);
  8245. }
  8246.  
  8247. // Convert no matter what (that way responseXXX fields are always set)
  8248. response = ajaxConvert(s, response, jqXHR, isSuccess);
  8249.  
  8250. // If successful, handle type chaining
  8251. if (isSuccess)
  8252. {
  8253. // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  8254. if (s.ifModified)
  8255. {
  8256. modified = jqXHR.getResponseHeader("Last-Modified");
  8257. if (modified)
  8258. {
  8259. jQuery.lastModified[cacheURL] = modified;
  8260. }
  8261. modified = jqXHR.getResponseHeader("etag");
  8262. if (modified)
  8263. {
  8264. jQuery.etag[cacheURL] = modified;
  8265. }
  8266. }
  8267.  
  8268. // if no content
  8269. if (status === 204 || s.type === "HEAD")
  8270. {
  8271. statusText = "nocontent";
  8272.  
  8273. // if not modified
  8274. } else if (status === 304)
  8275. {
  8276. statusText = "notmodified";
  8277.  
  8278. // If we have data, let's convert it
  8279. } else
  8280. {
  8281. statusText = response.state;
  8282. success = response.data;
  8283. error = response.error;
  8284. isSuccess = !error;
  8285. }
  8286. } else
  8287. {
  8288. // We extract error from statusText
  8289. // then normalize statusText and status for non-aborts
  8290. error = statusText;
  8291. if (status || !statusText)
  8292. {
  8293. statusText = "error";
  8294. if (status < 0)
  8295. {
  8296. status = 0;
  8297. }
  8298. }
  8299. }
  8300.  
  8301. // Set data for the fake xhr object
  8302. jqXHR.status = status;
  8303. jqXHR.statusText = (nativeStatusText || statusText) + "";
  8304.  
  8305. // Success/Error
  8306. if (isSuccess)
  8307. {
  8308. deferred.resolveWith(callbackContext, [success, statusText, jqXHR]);
  8309. } else
  8310. {
  8311. deferred.rejectWith(callbackContext, [jqXHR, statusText, error]);
  8312. }
  8313.  
  8314. // Status-dependent callbacks
  8315. jqXHR.statusCode(statusCode);
  8316. statusCode = undefined;
  8317.  
  8318. if (fireGlobals)
  8319. {
  8320. globalEventContext.trigger(isSuccess ? "ajaxSuccess" : "ajaxError",
  8321. [jqXHR, s, isSuccess ? success : error]);
  8322. }
  8323.  
  8324. // Complete
  8325. completeDeferred.fireWith(callbackContext, [jqXHR, statusText]);
  8326.  
  8327. if (fireGlobals)
  8328. {
  8329. globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
  8330. // Handle the global AJAX counter
  8331. if (!(--jQuery.active))
  8332. {
  8333. jQuery.event.trigger("ajaxStop");
  8334. }
  8335. }
  8336. }
  8337.  
  8338. return jqXHR;
  8339. },
  8340.  
  8341. getJSON: function(url, data, callback)
  8342. {
  8343. return jQuery.get(url, data, callback, "json");
  8344. },
  8345.  
  8346. getScript: function(url, callback)
  8347. {
  8348. return jQuery.get(url, undefined, callback, "script");
  8349. }
  8350. });
  8351.  
  8352. jQuery.each(["get", "post"], function(i, method)
  8353. {
  8354. jQuery[method] = function(url, data, callback, type)
  8355. {
  8356. // shift arguments if data argument was omitted
  8357. if (jQuery.isFunction(data))
  8358. {
  8359. type = type || callback;
  8360. callback = data;
  8361. data = undefined;
  8362. }
  8363.  
  8364. return jQuery.ajax({
  8365. url: url,
  8366. type: method,
  8367. dataType: type,
  8368. data: data,
  8369. success: callback
  8370. });
  8371. };
  8372. });
  8373.  
  8374. // Attach a bunch of functions for handling common AJAX events
  8375. jQuery.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function(i, type)
  8376. {
  8377. jQuery.fn[type] = function(fn)
  8378. {
  8379. return this.on(type, fn);
  8380. };
  8381. });
  8382.  
  8383.  
  8384. jQuery._evalUrl = function(url)
  8385. {
  8386. return jQuery.ajax({
  8387. url: url,
  8388. type: "GET",
  8389. dataType: "script",
  8390. async: false,
  8391. global: false,
  8392. "throws": true
  8393. });
  8394. };
  8395.  
  8396.  
  8397. jQuery.expr.filters.hidden = function(elem)
  8398. {
  8399. // Support: Opera <= 12.12
  8400. // Opera reports offsetWidths and offsetHeights less than zero on some elements
  8401. return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
  8402. };
  8403. jQuery.expr.filters.visible = function(elem)
  8404. {
  8405. return !jQuery.expr.filters.hidden(elem);
  8406. };
  8407.  
  8408.  
  8409.  
  8410.  
  8411. var r20 = /%20/g,
  8412. rbracket = /\[\]$/,
  8413. rCRLF = /\r?\n/g,
  8414. rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
  8415. rsubmittable = /^(?:input|select|textarea|keygen)/i;
  8416.  
  8417. function buildParams(prefix, obj, traditional, add)
  8418. {
  8419. var name;
  8420.  
  8421. if (jQuery.isArray(obj))
  8422. {
  8423. // Serialize array item.
  8424. jQuery.each(obj, function(i, v)
  8425. {
  8426. if (traditional || rbracket.test(prefix))
  8427. {
  8428. // Treat each array item as a scalar.
  8429. add(prefix, v);
  8430. } else
  8431. {
  8432. // Item is non-scalar (array or object), encode its numeric index.
  8433. buildParams(prefix + "[" + (typeof v === "object" ? i : "") + "]", v, traditional, add);
  8434. }
  8435. });
  8436. } else if (!traditional && jQuery.type(obj) === "object")
  8437. {
  8438. // Serialize object item.
  8439. for (name in obj)
  8440. {
  8441. buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
  8442. }
  8443. } else
  8444. {
  8445. // Serialize scalar item.
  8446. add(prefix, obj);
  8447. }
  8448. }
  8449.  
  8450. // Serialize an array of form elements or a set of
  8451. // key/values into a query string
  8452. jQuery.param = function(a, traditional)
  8453. {
  8454. var prefix,
  8455. s = [],
  8456. add = function(key, value)
  8457. {
  8458. // If value is a function, invoke it and return its value
  8459. value = jQuery.isFunction(value) ? value() : (value == null ? "" : value);
  8460. s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
  8461. };
  8462.  
  8463. // Set traditional to true for jQuery <= 1.3.2 behavior.
  8464. if (traditional === undefined)
  8465. {
  8466. traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
  8467. }
  8468.  
  8469. // If an array was passed in, assume that it is an array of form elements.
  8470. if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a)))
  8471. {
  8472. // Serialize the form elements
  8473. jQuery.each(a, function()
  8474. {
  8475. add(this.name, this.value);
  8476. });
  8477. } else
  8478. {
  8479. // If traditional, encode the "old" way (the way 1.3.2 or older
  8480. // did it), otherwise encode params recursively.
  8481. for (prefix in a)
  8482. {
  8483. buildParams(prefix, a[prefix], traditional, add);
  8484. }
  8485. }
  8486.  
  8487. // Return the resulting serialization
  8488. return s.join("&").replace(r20, "+");
  8489. };
  8490.  
  8491. jQuery.fn.extend({
  8492. serialize: function()
  8493. {
  8494. return jQuery.param(this.serializeArray());
  8495. },
  8496. serializeArray: function()
  8497. {
  8498. return this.map(function()
  8499. {
  8500. // Can add propHook for "elements" to filter or add form elements
  8501. var elements = jQuery.prop(this, "elements");
  8502. return elements ? jQuery.makeArray(elements) : this;
  8503. })
  8504. .filter(function()
  8505. {
  8506. var type = this.type;
  8507.  
  8508. // Use .is( ":disabled" ) so that fieldset[disabled] works
  8509. return this.name && !jQuery(this).is(":disabled") &&
  8510. rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) &&
  8511. (this.checked || !rcheckableType.test(type));
  8512. })
  8513. .map(function(i, elem)
  8514. {
  8515. var val = jQuery(this).val();
  8516.  
  8517. return val == null ?
  8518. null :
  8519. jQuery.isArray(val) ?
  8520. jQuery.map(val, function(val)
  8521. {
  8522. return { name: elem.name, value: val.replace(rCRLF, "\r\n") };
  8523. }) :
  8524. { name: elem.name, value: val.replace(rCRLF, "\r\n") };
  8525. }).get();
  8526. }
  8527. });
  8528.  
  8529.  
  8530. jQuery.ajaxSettings.xhr = function()
  8531. {
  8532. try
  8533. {
  8534. return new XMLHttpRequest();
  8535. } catch (e) { }
  8536. };
  8537.  
  8538. var xhrId = 0,
  8539. xhrCallbacks = {},
  8540. xhrSuccessStatus = {
  8541. // file protocol always yields status code 0, assume 200
  8542. 0: 200,
  8543. // Support: IE9
  8544. // #1450: sometimes IE returns 1223 when it should be 204
  8545. 1223: 204
  8546. },
  8547. xhrSupported = jQuery.ajaxSettings.xhr();
  8548.  
  8549. // Support: IE9
  8550. // Open requests must be manually aborted on unload (#5280)
  8551. if (window.ActiveXObject)
  8552. {
  8553. jQuery(window).on("unload", function()
  8554. {
  8555. for (var key in xhrCallbacks)
  8556. {
  8557. xhrCallbacks[key]();
  8558. }
  8559. });
  8560. }
  8561.  
  8562. support.cors = !!xhrSupported && ("withCredentials" in xhrSupported);
  8563. support.ajax = xhrSupported = !!xhrSupported;
  8564.  
  8565. jQuery.ajaxTransport(function(options)
  8566. {
  8567. var callback;
  8568.  
  8569. // Cross domain only allowed if supported through XMLHttpRequest
  8570. if (support.cors || xhrSupported && !options.crossDomain)
  8571. {
  8572. return {
  8573. send: function(headers, complete)
  8574. {
  8575. var i,
  8576. xhr = options.xhr(),
  8577. id = ++xhrId;
  8578.  
  8579. xhr.open(options.type, options.url, options.async, options.uzername, options.pazzwurd);
  8580.  
  8581. // Apply custom fields if provided
  8582. if (options.xhrFields)
  8583. {
  8584. for (i in options.xhrFields)
  8585. {
  8586. xhr[i] = options.xhrFields[i];
  8587. }
  8588. }
  8589.  
  8590. // Override mime type if needed
  8591. if (options.mimeType && xhr.overrideMimeType)
  8592. {
  8593. xhr.overrideMimeType(options.mimeType);
  8594. }
  8595.  
  8596. // X-Requested-With header
  8597. // For cross-domain requests, seeing as conditions for a preflight are
  8598. // akin to a jigsaw puzzle, we simply never set it to be sure.
  8599. // (it can always be set on a per-request basis or even using ajaxSetup)
  8600. // For same-domain requests, won't change header if already provided.
  8601. if (!options.crossDomain && !headers["X-Requested-With"])
  8602. {
  8603. headers["X-Requested-With"] = "XMLHttpRequest";
  8604. }
  8605.  
  8606. // Set headers
  8607. for (i in headers)
  8608. {
  8609. xhr.setRequestHeader(i, headers[i]);
  8610. }
  8611.  
  8612. // Callback
  8613. callback = function(type)
  8614. {
  8615. return function()
  8616. {
  8617. if (callback)
  8618. {
  8619. delete xhrCallbacks[id];
  8620. callback = xhr.onload = xhr.onerror = null;
  8621.  
  8622. if (type === "abort")
  8623. {
  8624. xhr.abort();
  8625. } else if (type === "error")
  8626. {
  8627. complete(
  8628. // file: protocol always yields status 0; see #8605, #14207
  8629. xhr.status,
  8630. xhr.statusText
  8631. );
  8632. } else
  8633. {
  8634. complete(
  8635. xhrSuccessStatus[xhr.status] || xhr.status,
  8636. xhr.statusText,
  8637. // Support: IE9
  8638. // Accessing binary-data responseText throws an exception
  8639. // (#11426)
  8640. typeof xhr.responseText === "string" ? {
  8641. text: xhr.responseText
  8642. } : undefined,
  8643. xhr.getAllResponseHeaders()
  8644. );
  8645. }
  8646. }
  8647. };
  8648. };
  8649.  
  8650. // Listen to events
  8651. xhr.onload = callback();
  8652. xhr.onerror = callback("error");
  8653.  
  8654. // Create the abort callback
  8655. callback = xhrCallbacks[id] = callback("abort");
  8656.  
  8657. try
  8658. {
  8659. // Do send the request (this may raise an exception)
  8660. xhr.send(options.hasContent && options.data || null);
  8661. } catch (e)
  8662. {
  8663. // #14683: Only rethrow if this hasn't been notified as an error yet
  8664. if (callback)
  8665. {
  8666. throw e;
  8667. }
  8668. }
  8669. },
  8670.  
  8671. abort: function()
  8672. {
  8673. if (callback)
  8674. {
  8675. callback();
  8676. }
  8677. }
  8678. };
  8679. }
  8680. });
  8681.  
  8682.  
  8683.  
  8684.  
  8685. // data: string of html
  8686. // context (optional): If specified, the fragment will be created in this context, defaults to document
  8687. // keepScripts (optional): If true, will include scripts passed in the html string
  8688. jQuery.parseHTML = function(data, context, keepScripts)
  8689. {
  8690. if (!data || typeof data !== "string")
  8691. {
  8692. return null;
  8693. }
  8694. if (typeof context === "boolean")
  8695. {
  8696. keepScripts = context;
  8697. context = false;
  8698. }
  8699. context = context || document;
  8700.  
  8701. var parsed = rsingleTag.exec(data),
  8702. scripts = !keepScripts && [];
  8703.  
  8704. // Single tag
  8705. if (parsed)
  8706. {
  8707. return [context.createElement(parsed[1])];
  8708. }
  8709.  
  8710. parsed = jQuery.buildFragment([data], context, scripts);
  8711.  
  8712. if (scripts && scripts.length)
  8713. {
  8714. jQuery(scripts).remove();
  8715. }
  8716.  
  8717. return jQuery.merge([], parsed.childNodes);
  8718. };
  8719.  
  8720.  
  8721. var docElem = window.document.documentElement;
  8722.  
  8723. /**
  8724. * Gets a window from an element
  8725. */
  8726. function getWindow(elem)
  8727. {
  8728. return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
  8729. }
  8730.  
  8731. jQuery.offset = {
  8732. setOffset: function(elem, options, i)
  8733. {
  8734. var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
  8735. position = jQuery.css(elem, "position"),
  8736. curElem = jQuery(elem),
  8737. props = {};
  8738.  
  8739. // Set position first, in-case top/left are set even on static elem
  8740. if (position === "static")
  8741. {
  8742. elem.style.position = "relative";
  8743. }
  8744.  
  8745. curOffset = curElem.offset();
  8746. curCSSTop = jQuery.css(elem, "top");
  8747. curCSSLeft = jQuery.css(elem, "left");
  8748. calculatePosition = (position === "absolute" || position === "fixed") &&
  8749. (curCSSTop + curCSSLeft).indexOf("auto") > -1;
  8750.  
  8751. // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
  8752. if (calculatePosition)
  8753. {
  8754. curPosition = curElem.position();
  8755. curTop = curPosition.top;
  8756. curLeft = curPosition.left;
  8757. } else
  8758. {
  8759. curTop = parseFloat(curCSSTop) || 0;
  8760. curLeft = parseFloat(curCSSLeft) || 0;
  8761. }
  8762.  
  8763. if (jQuery.isFunction(options))
  8764. {
  8765. options = options.call(elem, i, curOffset);
  8766. }
  8767.  
  8768. if (options.top != null)
  8769. {
  8770. props.top = (options.top - curOffset.top) + curTop;
  8771. }
  8772. if (options.left != null)
  8773. {
  8774. props.left = (options.left - curOffset.left) + curLeft;
  8775. }
  8776.  
  8777. if ("using" in options)
  8778. {
  8779. options.using.call(elem, props);
  8780. } else
  8781. {
  8782. curElem.css(props);
  8783. }
  8784. }
  8785. };
  8786.  
  8787. jQuery.fn.extend({
  8788. offset: function(options)
  8789. {
  8790. if (arguments.length)
  8791. {
  8792. return options === undefined ?
  8793. this :
  8794. this.each(function(i)
  8795. {
  8796. jQuery.offset.setOffset(this, options, i);
  8797. });
  8798. }
  8799.  
  8800. var docElem, win,
  8801. elem = this[0],
  8802. box = { top: 0, left: 0 },
  8803. doc = elem && elem.ownerDocument;
  8804.  
  8805. if (!doc)
  8806. {
  8807. return;
  8808. }
  8809.  
  8810. docElem = doc.documentElement;
  8811.  
  8812. // Make sure it's not a disconnected DOM node
  8813. if (!jQuery.contains(docElem, elem))
  8814. {
  8815. return box;
  8816. }
  8817.  
  8818. // If we don't have gBCR, just use 0,0 rather than error
  8819. // BlackBerry 5, iOS 3 (original iPhone)
  8820. if (typeof elem.getBoundingClientRect !== strundefined)
  8821. {
  8822. box = elem.getBoundingClientRect();
  8823. }
  8824. win = getWindow(doc);
  8825. return {
  8826. top: box.top + win.pageYOffset - docElem.clientTop,
  8827. left: box.left + win.pageXOffset - docElem.clientLeft
  8828. };
  8829. },
  8830.  
  8831. position: function()
  8832. {
  8833. if (!this[0])
  8834. {
  8835. return;
  8836. }
  8837.  
  8838. var offsetParent, offset,
  8839. elem = this[0],
  8840. parentOffset = { top: 0, left: 0 };
  8841.  
  8842. // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
  8843. if (jQuery.css(elem, "position") === "fixed")
  8844. {
  8845. // We assume that getBoundingClientRect is available when computed position is fixed
  8846. offset = elem.getBoundingClientRect();
  8847. } else
  8848. {
  8849. // Get *real* offsetParent
  8850. offsetParent = this.offsetParent();
  8851.  
  8852. // Get correct offsets
  8853. offset = this.offset();
  8854. if (!jQuery.nodeName(offsetParent[0], "html"))
  8855. {
  8856. parentOffset = offsetParent.offset();
  8857. }
  8858.  
  8859. // Add offsetParent borders
  8860. parentOffset.top += jQuery.css(offsetParent[0], "borderTopWidth", true);
  8861. parentOffset.left += jQuery.css(offsetParent[0], "borderLeftWidth", true);
  8862. }
  8863.  
  8864. // Subtract parent offsets and element margins
  8865. return {
  8866. top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true),
  8867. left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true)
  8868. };
  8869. },
  8870.  
  8871. offsetParent: function()
  8872. {
  8873. return this.map(function()
  8874. {
  8875. var offsetParent = this.offsetParent || docElem;
  8876.  
  8877. while (offsetParent && (!jQuery.nodeName(offsetParent, "html") && jQuery.css(offsetParent, "position") === "static"))
  8878. {
  8879. offsetParent = offsetParent.offsetParent;
  8880. }
  8881.  
  8882. return offsetParent || docElem;
  8883. });
  8884. }
  8885. });
  8886.  
  8887. // Create scrollLeft and scrollTop methods
  8888. jQuery.each({ scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function(method, prop)
  8889. {
  8890. var top = "pageYOffset" === prop;
  8891.  
  8892. jQuery.fn[method] = function(val)
  8893. {
  8894. return access(this, function(elem, method, val)
  8895. {
  8896. var win = getWindow(elem);
  8897.  
  8898. if (val === undefined)
  8899. {
  8900. return win ? win[prop] : elem[method];
  8901. }
  8902.  
  8903. if (win)
  8904. {
  8905. win.scrollTo(
  8906. !top ? val : window.pageXOffset,
  8907. top ? val : window.pageYOffset
  8908. );
  8909. } else
  8910. {
  8911. elem[method] = val;
  8912. }
  8913. }, method, val, arguments.length, null);
  8914. };
  8915. });
  8916.  
  8917. // Add the top/left cssHooks using jQuery.fn.position
  8918. // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  8919. // getComputedStyle returns percent when specified for top/left/bottom/right
  8920. // rather than make the css module depend on the offset module, we just check for it here
  8921. jQuery.each(["top", "left"], function(i, prop)
  8922. {
  8923. jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition,
  8924. function(elem, computed)
  8925. {
  8926. if (computed)
  8927. {
  8928. computed = curCSS(elem, prop);
  8929. // if curCSS returns percentage, fallback to offset
  8930. return rnumnonpx.test(computed) ?
  8931. jQuery(elem).position()[prop] + "px" :
  8932. computed;
  8933. }
  8934. }
  8935. );
  8936. });
  8937.  
  8938.  
  8939. // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  8940. jQuery.each({ Height: "height", Width: "width" }, function(name, type)
  8941. {
  8942. jQuery.each({ padding: "inner" + name, content: type, "": "outer" + name }, function(defaultExtra, funcName)
  8943. {
  8944. // margin is only for outerHeight, outerWidth
  8945. jQuery.fn[funcName] = function(margin, value)
  8946. {
  8947. var chainable = arguments.length && (defaultExtra || typeof margin !== "boolean"),
  8948. extra = defaultExtra || (margin === true || value === true ? "margin" : "border");
  8949.  
  8950. return access(this, function(elem, type, value)
  8951. {
  8952. var doc;
  8953.  
  8954. if (jQuery.isWindow(elem))
  8955. {
  8956. // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
  8957. // isn't a whole lot we can do. See pull request at this URL for discussion:
  8958. // https://github.com/jquery/jquery/pull/764
  8959. return elem.document.documentElement["client" + name];
  8960. }
  8961.  
  8962. // Get document width or height
  8963. if (elem.nodeType === 9)
  8964. {
  8965. doc = elem.documentElement;
  8966.  
  8967. // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
  8968. // whichever is greatest
  8969. return Math.max(
  8970. elem.body["scroll" + name], doc["scroll" + name],
  8971. elem.body["offset" + name], doc["offset" + name],
  8972. doc["client" + name]
  8973. );
  8974. }
  8975.  
  8976. return value === undefined ?
  8977. // Get width or height on the element, requesting but not forcing parseFloat
  8978. jQuery.css(elem, type, extra) :
  8979.  
  8980. // Set width or height on the element
  8981. jQuery.style(elem, type, value, extra);
  8982. }, type, chainable ? margin : undefined, chainable, null);
  8983. };
  8984. });
  8985. });
  8986.  
  8987. jQuery.noConflict = function() { };
  8988.  
  8989.  
  8990.  
  8991. return jQuery;
  8992. }));
  8993.  
  8994. /*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
  8995. * Licensed under the MIT License (LICENSE.txt).
  8996. *
  8997. * Version: 3.1.11
  8998. *
  8999. * Requires: jQuery 1.2.2+
  9000. */
  9001.  
  9002. (function($)
  9003. {
  9004. var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
  9005. toBind = ('onwheel' in document || document.documentMode >= 9) ?
  9006. ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
  9007. slice = Array.prototype.slice,
  9008. nullLowestDeltaTimeout, lowestDelta;
  9009.  
  9010. if ($.event.fixHooks)
  9011. {
  9012. for (var i = toFix.length; i;)
  9013. {
  9014. $.event.fixHooks[toFix[--i]] = $.event.mouseHooks;
  9015. }
  9016. }
  9017.  
  9018. var special = $.event.special.mousewheel = {
  9019. version: '3.1.11',
  9020.  
  9021. setup: function()
  9022. {
  9023. if (this.addEventListener)
  9024. {
  9025. for (var i = toBind.length; i;)
  9026. {
  9027. this.addEventListener(toBind[--i], handler, false);
  9028. }
  9029. } else
  9030. {
  9031. this.onmousewheel = handler;
  9032. }
  9033. // Store the line height and page height for this particular element
  9034. $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
  9035. $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
  9036. },
  9037.  
  9038. teardown: function()
  9039. {
  9040. if (this.removeEventListener)
  9041. {
  9042. for (var i = toBind.length; i;)
  9043. {
  9044. this.removeEventListener(toBind[--i], handler, false);
  9045. }
  9046. } else
  9047. {
  9048. this.onmousewheel = null;
  9049. }
  9050. // Clean up the data we added to the element
  9051. $.removeData(this, 'mousewheel-line-height');
  9052. $.removeData(this, 'mousewheel-page-height');
  9053. },
  9054.  
  9055. getLineHeight: function(elem)
  9056. {
  9057. var $parent = $(elem)['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
  9058. if (!$parent.length)
  9059. {
  9060. $parent = $('body');
  9061. }
  9062. return parseInt($parent.css('fontSize'), 10);
  9063. },
  9064.  
  9065. getPageHeight: function(elem)
  9066. {
  9067. return $(elem).height();
  9068. },
  9069.  
  9070. settings: {
  9071. adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
  9072. normalizeOffset: true // calls getBoundingClientRect for each event
  9073. }
  9074. };
  9075.  
  9076. $.fn.extend({
  9077. mousewheel: function(fn)
  9078. {
  9079. return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
  9080. },
  9081.  
  9082. unmousewheel: function(fn)
  9083. {
  9084. return this.unbind('mousewheel', fn);
  9085. }
  9086. });
  9087.  
  9088.  
  9089. function handler(event)
  9090. {
  9091. var orgEvent = event || window.event,
  9092. args = slice.call(arguments, 1),
  9093. delta = 0,
  9094. deltaX = 0,
  9095. deltaY = 0,
  9096. absDelta = 0,
  9097. offsetX = 0,
  9098. offsetY = 0;
  9099. event = $.event.fix(orgEvent);
  9100. event.type = 'mousewheel';
  9101.  
  9102. // Old school scrollwheel delta
  9103. if ('detail' in orgEvent) { deltaY = orgEvent.detail * -1; }
  9104. if ('wheelDelta' in orgEvent) { deltaY = orgEvent.wheelDelta; }
  9105. if ('wheelDeltaY' in orgEvent) { deltaY = orgEvent.wheelDeltaY; }
  9106. if ('wheelDeltaX' in orgEvent) { deltaX = orgEvent.wheelDeltaX * -1; }
  9107.  
  9108. // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
  9109. if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS)
  9110. {
  9111. deltaX = deltaY * -1;
  9112. deltaY = 0;
  9113. }
  9114.  
  9115. // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
  9116. delta = deltaY === 0 ? deltaX : deltaY;
  9117.  
  9118. // New school wheel delta (wheel event)
  9119. if ('deltaY' in orgEvent)
  9120. {
  9121. deltaY = orgEvent.deltaY * -1;
  9122. delta = deltaY;
  9123. }
  9124. if ('deltaX' in orgEvent)
  9125. {
  9126. deltaX = orgEvent.deltaX;
  9127. if (deltaY === 0) { delta = deltaX * -1; }
  9128. }
  9129.  
  9130. // No change actually happened, no reason to go any further
  9131. if (deltaY === 0 && deltaX === 0) { return; }
  9132.  
  9133. // Need to convert lines and pages to pixels if we aren't already in pixels
  9134. // There are three delta modes:
  9135. // * deltaMode 0 is by pixels, nothing to do
  9136. // * deltaMode 1 is by lines
  9137. // * deltaMode 2 is by pages
  9138. if (orgEvent.deltaMode === 1)
  9139. {
  9140. var lineHeight = $.data(this, 'mousewheel-line-height');
  9141. delta *= lineHeight;
  9142. deltaY *= lineHeight;
  9143. deltaX *= lineHeight;
  9144. } else if (orgEvent.deltaMode === 2)
  9145. {
  9146. var pageHeight = $.data(this, 'mousewheel-page-height');
  9147. delta *= pageHeight;
  9148. deltaY *= pageHeight;
  9149. deltaX *= pageHeight;
  9150. }
  9151.  
  9152. // Store lowest absolute delta to normalize the delta values
  9153. absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));
  9154.  
  9155. if (!lowestDelta || absDelta < lowestDelta)
  9156. {
  9157. lowestDelta = absDelta;
  9158.  
  9159. // Adjust older deltas if necessary
  9160. if (shouldAdjustOldDeltas(orgEvent, absDelta))
  9161. {
  9162. lowestDelta /= 40;
  9163. }
  9164. }
  9165.  
  9166. // Adjust older deltas if necessary
  9167. if (shouldAdjustOldDeltas(orgEvent, absDelta))
  9168. {
  9169. // Divide all the things by 40!
  9170. delta /= 40;
  9171. deltaX /= 40;
  9172. deltaY /= 40;
  9173. }
  9174.  
  9175. // Get a whole, normalized value for the deltas
  9176. delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);
  9177. deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);
  9178. deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);
  9179.  
  9180. // Normalise offsetX and offsetY properties
  9181. if (special.settings.normalizeOffset && this.getBoundingClientRect)
  9182. {
  9183. var boundingRect = this.getBoundingClientRect();
  9184. offsetX = event.clientX - boundingRect.left;
  9185. offsetY = event.clientY - boundingRect.top;
  9186. }
  9187.  
  9188. // Add information to the event object
  9189. event.deltaX = deltaX;
  9190. event.deltaY = deltaY;
  9191. event.deltaFactor = lowestDelta;
  9192. event.offsetX = offsetX;
  9193. event.offsetY = offsetY;
  9194. // Go ahead and set deltaMode to 0 since we converted to pixels
  9195. // Although this is a little odd since we overwrite the deltaX/Y
  9196. // properties with normalized deltas.
  9197. event.deltaMode = 0;
  9198.  
  9199. // Add event and delta to the front of the arguments
  9200. args.unshift(event, delta, deltaX, deltaY);
  9201.  
  9202. // Clearout lowestDelta after sometime to better
  9203. // handle multiple device types that give different
  9204. // a different lowestDelta
  9205. // Ex: trackpad = 3 and mouse wheel = 120
  9206. if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
  9207. nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
  9208.  
  9209. return ($.event.dispatch || $.event.handle).apply(this, args);
  9210. }
  9211.  
  9212. function nullLowestDelta()
  9213. {
  9214. lowestDelta = null;
  9215. }
  9216.  
  9217. function shouldAdjustOldDeltas(orgEvent, absDelta)
  9218. {
  9219. // If this is an older event and the delta is divisable by 120,
  9220. // then we are assuming that the browser is treating this as an
  9221. // older mouse wheel event and that we should divide the deltas
  9222. // by 40 to try and get a more usable deltaFactor.
  9223. // Side note, this actually impacts the reported scroll distance
  9224. // in older browsers and can cause scrolling to be slower than native.
  9225. // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
  9226. return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
  9227. }
  9228. })($);
  9229.  
  9230. var resourceStorage = "https://bitbucket.org/TheDarkKRONOS/dead-frontier-enhanced-ui/downloads/";
  9231.  
  9232. // interface
  9233. var armorData = resourceStorage + "armor.png";
  9234. var centeredData = resourceStorage + "centered.png";
  9235. var chatData = resourceStorage + "chat.png";
  9236. var chatInNewWindowData = resourceStorage + "chatInNewWindow.png";
  9237. var checkData = resourceStorage + "check.png";
  9238. var clearData = resourceStorage + "clear.png";
  9239. var clearAllData = resourceStorage + "clearAll.png";
  9240. var downData = resourceStorage + "down.png";
  9241. var downLeftData = resourceStorage + "downLeft.png";
  9242. var downRightData = resourceStorage + "downRight.png";
  9243. var healthData = resourceStorage + "health.png";
  9244. var hungerData = resourceStorage + "satiety.png";
  9245. var inventoryData = resourceStorage + "inventory.png";
  9246. var leftData = resourceStorage + "left.png";
  9247. var legendData = resourceStorage + "legend.png";
  9248. var messageData = resourceStorage + "message.png";
  9249. var outpostData = resourceStorage + "outpost.png";
  9250. var refreshData = resourceStorage + "refresh.png";
  9251. var rightData = resourceStorage + "right.png";
  9252. var settingsData = resourceStorage + "settings.png";
  9253. var upData = resourceStorage + "up.png";
  9254. var upLeftData = resourceStorage + "upLeft.png";
  9255. var upRightData = resourceStorage + "upRight.png";
  9256.  
  9257. // new style
  9258. var newLegendData = resourceStorage + "newLegend.png";
  9259. var newMapData = resourceStorage + "newMap.png";
  9260.  
  9261. // old style
  9262. var oldLegendData = resourceStorage + "oldLegend.png";
  9263. var oldMapData = resourceStorage + "oldMap.png";
  9264.  
  9265. var Parameters = function (message)
  9266. {
  9267. this.data = {};
  9268.  
  9269. var startIndex = message.indexOf('?') + 1;
  9270. message = message.substring(startIndex);
  9271.  
  9272. var args = message.split('&');
  9273. for (var i = 0; i < args.length; i++)
  9274. {
  9275. var parts = args[i].split('=');
  9276. this.data[parts[0].toLowerCase()] = parts[1];
  9277. }
  9278. };
  9279.  
  9280. Parameters.prototype.get = function (name, defaultValue)
  9281. {
  9282. var key = name.toLowerCase();
  9283. if (!this.data.hasOwnProperty(key)) return defaultValue;
  9284.  
  9285. var value = this.data[key];
  9286. if (value === '') return defaultValue;
  9287.  
  9288. return value;
  9289. };
  9290.  
  9291. var main = new function()
  9292. {
  9293. var main = this;
  9294.  
  9295. main.isNotLoaded = true;
  9296. main.isNotGameScreen = !/^http:\/\/(?:fairview.deadfrontier.com\/onlinezombiemmo\/index\.php\?page=21|localhost)/i.test(document.location.href);
  9297.  
  9298. main.resetPosition = function()
  9299. {
  9300. var controlList = [];
  9301.  
  9302. function resetPositionRecursive(parent)
  9303. {
  9304. /// <param name="parent" type="Control"></param>
  9305.  
  9306. for (var i = 0; i < parent.childs.length; i++)
  9307. {
  9308. /// <var type="Control"></var>
  9309. var control = parent.childs[i];
  9310.  
  9311. controlList.push(control);
  9312. resetPositionRecursive(control);
  9313. }
  9314. }
  9315.  
  9316. resetPositionRecursive(container);
  9317.  
  9318. for (var i = 0; i < controlList.length; i++) controlList[i].resetPosition();
  9319. }
  9320.  
  9321. //#region Control
  9322.  
  9323. var switchingManualControlList = [], switchingAutomaticControlList = [];
  9324.  
  9325. main.addSwitchingManualControlHandler = function(handler)
  9326. {
  9327. switchingManualControlList.push(handler);
  9328. };
  9329.  
  9330. main.addSwitchingAutomaticControlHandler = function(handler)
  9331. {
  9332. switchingAutomaticControlList.push(handler);
  9333. };
  9334.  
  9335. main.manualControl = true;
  9336.  
  9337. main.manual = function()
  9338. {
  9339. for (var i = 0; i < switchingManualControlList.length; i++) switchingManualControlList[i]();
  9340.  
  9341. main.manualControl = true;
  9342. };
  9343.  
  9344. main.automatic = function()
  9345. {
  9346. for (var i = 0; i < switchingAutomaticControlList.length; i++) switchingAutomaticControlList[i]();
  9347.  
  9348. main.manualControl = false;
  9349. };
  9350.  
  9351. main.toggleControl = function()
  9352. {
  9353. if (main.manualControl)
  9354. {
  9355. main.automatic();
  9356. }
  9357. else
  9358. {
  9359. main.manual();
  9360. }
  9361. }
  9362.  
  9363. //#endregion
  9364.  
  9365. //#region Save/load parameters
  9366.  
  9367. var saveList = [], loadList = [];
  9368.  
  9369. main.save = function(key, value)
  9370. {
  9371. try
  9372. {
  9373. localStorage.setItem(key, value);
  9374. }
  9375. catch (e) { }
  9376. };
  9377.  
  9378. main.loadString = function(key, defaultValue)
  9379. {
  9380. try
  9381. {
  9382. var value = localStorage.getItem(key);
  9383. if (value == null) return defaultValue;
  9384.  
  9385. return localStorage.getItem(key);
  9386. }
  9387. catch (e)
  9388. {
  9389. return defaultValue;
  9390. }
  9391. };
  9392.  
  9393. main.loadNumber = function(key, defaultValue)
  9394. {
  9395. try
  9396. {
  9397. var value = localStorage.getItem(key);
  9398. if (value == null) return defaultValue;
  9399.  
  9400. value = Number(value);
  9401. if (isNaN(value)) return defaultValue;
  9402.  
  9403. return value;
  9404. }
  9405. catch (e)
  9406. {
  9407. return defaultValue;
  9408. }
  9409. };
  9410.  
  9411. main.loadBoolean = function(key, defaultValue)
  9412. {
  9413. try
  9414. {
  9415. var value = localStorage.getItem(key);
  9416. if (value == null) return defaultValue;
  9417.  
  9418. return (value == 'true');
  9419. }
  9420. catch (e)
  9421. {
  9422. return defaultValue;
  9423. }
  9424. };
  9425.  
  9426. main.addSaveHandler = function(handler)
  9427. {
  9428. saveList.push(handler);
  9429. };
  9430.  
  9431. main.addLoadHandler = function(handler)
  9432. {
  9433. loadList.push(handler);
  9434. };
  9435.  
  9436. main.saveAll = function()
  9437. {
  9438. for (var i = 0; i < saveList.length; i++) saveList[i]();
  9439. };
  9440.  
  9441. main.loadAll = function()
  9442. {
  9443. for (var i = 0; i < loadList.length; i++) loadList[i]();
  9444. };
  9445.  
  9446. //#endregion
  9447.  
  9448. main.addSaveHandler(function()
  9449. {
  9450. main.save('mainMode', main.manualControl);
  9451. });
  9452.  
  9453. main.addLoadHandler(function()
  9454. {
  9455. if (main.loadBoolean('mainMode', false))
  9456. {
  9457. main.manual();
  9458. }
  9459. else
  9460. {
  9461. main.automatic();
  9462. }
  9463. });
  9464. };
  9465.  
  9466. function Player()
  9467. {
  9468. this.id = 0;
  9469. this.x = 1;
  9470. this.y = 20;
  9471.  
  9472. this.health = 0;
  9473. this.maxHealth = 0;
  9474. this.armor = 0;
  9475. this.maxArmor = 0;
  9476. this.hunger = 0;
  9477. this.maxHunger = 0;
  9478. this.usedInventoryCells = 0;
  9479. this.freeInventoryCells = 0;
  9480. this.maxInventoryCells = 0;
  9481.  
  9482. this.newMessageCount = 0;
  9483.  
  9484. this.disabled = true;
  9485. this.timerId = 0;
  9486. this.requestIsSend = false;
  9487.  
  9488. /// <field type="Array" elementType="Function"></field>
  9489. this.updateHandlerList = [];
  9490. /// <field type="Array" elementType="Function"></field>
  9491. this.updatePositionHandlerList = [];
  9492.  
  9493. var player = this;
  9494.  
  9495. main.addSwitchingAutomaticControlHandler(function()
  9496. {
  9497. player.enable();
  9498. });
  9499.  
  9500. main.addSwitchingManualControlHandler(function()
  9501. {
  9502. player.disable();
  9503. });
  9504.  
  9505. main.addSaveHandler(function()
  9506. {
  9507. main.save('player_id', player.id);
  9508. main.save('player_x', player.x);
  9509. main.save('player_y', player.y);
  9510. main.save('player_newMessageCount', player.newMessageCount);
  9511. main.save('player_health', player.health);
  9512. main.save('player_maxHealth', player.maxHealth);
  9513. main.save('player_armor', player.armor);
  9514. main.save('player_maxArmor', player.maxArmor);
  9515. main.save('player_hunger', player.hunger);
  9516. main.save('player_maxHunger', player.maxHunger);
  9517. main.save('player_maxInventoryCells', player.maxInventoryCells);
  9518. main.save('player_usedInventoryCells', player.usedInventoryCells);
  9519. });
  9520.  
  9521. main.addLoadHandler(function()
  9522. {
  9523. player.id = main.loadNumber('player_id', 0);
  9524. if (player.id == 0) return;
  9525.  
  9526. player.x = main.loadNumber('player_x', -1);
  9527. player.y = main.loadNumber('player_y', -1);
  9528.  
  9529. if (player.x < 0 || player.y < 0)
  9530. {
  9531. player.x = map.outposts.NastyasHoldout.x;
  9532. player.y = map.outposts.NastyasHoldout.y;
  9533. }
  9534.  
  9535. player.newMessageCount = main.loadNumber('player_newMessageCount', 0);
  9536. player.health = main.loadNumber('player_health', 0);
  9537. player.maxHealth = main.loadNumber('player_maxHealth', 0);
  9538. player.armor = main.loadNumber('player_armor', 0);
  9539. player.maxArmor = main.loadNumber('player_maxArmor', 0);
  9540. player.hunger = main.loadNumber('player_hunger', 0);
  9541. player.maxHunger = main.loadNumber('player_maxHunger', 0);
  9542. player.maxInventoryCells = main.loadNumber('player_maxInventoryCells', 0);
  9543. player.usedInventoryCells = main.loadNumber('player_usedInventoryCells', 0);
  9544.  
  9545. player.freeInventoryCells = player.maxInventoryCells - player.usedInventoryCells;
  9546.  
  9547. player.updatePosition();
  9548.  
  9549. if (player.maxHealth == 0 && player.maxArmor == 0) return;
  9550.  
  9551. player.update();
  9552. });
  9553.  
  9554. player.update();
  9555. };
  9556.  
  9557. //#region Enabled
  9558.  
  9559. Player.prototype.enable = function()
  9560. {
  9561. var player = this;
  9562. if (this.timerId != 0) this.disable();
  9563.  
  9564. this.disabled = false;
  9565. this.timerId = setInterval(function() { player.refresh(); }, 10000);
  9566. }
  9567.  
  9568. Player.prototype.disable = function()
  9569. {
  9570. this.disabled = true;
  9571. clearInterval(this.timerId);
  9572. this.timerId = 0;
  9573. }
  9574.  
  9575. Player.prototype.toggle = function()
  9576. {
  9577. if (this.disabled)
  9578. {
  9579. this.enable();
  9580. }
  9581. else
  9582. {
  9583. this.disable();
  9584. }
  9585. }
  9586.  
  9587. //#endregion
  9588.  
  9589. //#region Position
  9590.  
  9591. Player.prototype.move = function(x, y)
  9592. {
  9593. this.x = x;
  9594. this.y = y;
  9595.  
  9596. this.updatePosition();
  9597. };
  9598.  
  9599. Player.prototype.add = function(offsetX, offsetY)
  9600. {
  9601. this.x += offsetX;
  9602. this.y += offsetY;
  9603.  
  9604. this.updatePosition();
  9605. };
  9606.  
  9607. //#endregion
  9608.  
  9609. //#region Refresh
  9610.  
  9611. Player.prototype.addUpdateHandler = function(handler)
  9612. {
  9613. /// <param name="handler" type="Function"></param>
  9614.  
  9615. this.updateHandlerList.push(handler);
  9616. };
  9617.  
  9618. Player.prototype.addUpdatePositionHandler = function(handler)
  9619. {
  9620. /// <param name="handler" type="Function"></param>
  9621.  
  9622. this.updatePositionHandlerList.push(handler);
  9623. };
  9624.  
  9625. Player.prototype.updatePosition = function()
  9626. {
  9627. for (var i = 0; i < this.updatePositionHandlerList.length; i++) this.updatePositionHandlerList[i]();
  9628. };
  9629.  
  9630. Player.prototype.update = function()
  9631. {
  9632. for (var i = 0; i < this.updateHandlerList.length; i++) this.updateHandlerList[i]();
  9633. };
  9634.  
  9635. Player.prototype.refresh = function()
  9636. {
  9637. var player = this;
  9638.  
  9639. if (player.id <= 0) return;
  9640.  
  9641. var antiCache = Math.random() + new Date().getUTCMilliseconds();
  9642. var url = 'http://fairview.deadfrontier.com/onlinezombiemmo/get_values.php?/userID=' + player.id + '&t=' + antiCache;
  9643.  
  9644. $.ajax({
  9645. url: url,
  9646. cache: false,
  9647. dataType: 'text',
  9648. success: function(result)
  9649. {
  9650. var data = new Parameters(result);
  9651. player.newMessageCount = data.get('newpms', 0);
  9652.  
  9653. player.health = data.get('df_hpcurrent', 0);
  9654. player.maxHealth = data.get('df_hpmax', 0);
  9655.  
  9656. player.armor = data.get('df_armourhp', 0);
  9657. player.maxArmor = data.get('df_armourhpmax', 0);
  9658.  
  9659. player.hunger = data.get('df_hungerhp', 0);
  9660. player.maxHunger = 100;
  9661.  
  9662. player.maxInventoryCells = data.get('df_invslots', 0);
  9663. player.usedInventoryCells = 0;
  9664.  
  9665. for (var i = 1; i <= player.maxInventoryCells; i++)
  9666. if (data.get('df_inv' + i + '_type', '') != '') player.usedInventoryCells += 1;
  9667.  
  9668. player.freeInventoryCells = player.maxInventoryCells - player.usedInventoryCells;
  9669.  
  9670. var x = data.get('df_positionx', player.x + 998) - 998;
  9671. var y = data.get('df_positiony', player.y + 980) - 980;
  9672.  
  9673. if (player.x != x || player.y != y) player.move(x, y);
  9674.  
  9675. player.update();
  9676. player.requestIsSend = false;
  9677. },
  9678. error: function()
  9679. {
  9680. player.requestIsSend = false;
  9681. }
  9682. });
  9683.  
  9684. player.requestIsSend = true;
  9685. };
  9686.  
  9687. //#endregion
  9688.  
  9689. var language = new function()
  9690. {
  9691. var language = this;
  9692.  
  9693. language.list = {};
  9694. language.current = null;
  9695.  
  9696. language.setCurrent = function(value)
  9697. {
  9698. language.current = value;
  9699.  
  9700. function updateRecursive(parent)
  9701. {
  9702. /// <param name="parent" type="Control"></param>
  9703.  
  9704. for (var i = 0; i < parent.childs.length; i++)
  9705. {
  9706. /// <var type="Control"></var>
  9707. var control = parent.childs[i];
  9708.  
  9709. control.update();
  9710. updateRecursive(control);
  9711. }
  9712. }
  9713.  
  9714. updateRecursive(container);
  9715. };
  9716.  
  9717. main.addSaveHandler(function()
  9718. {
  9719. main.save('language_current', language.current.id);
  9720. });
  9721.  
  9722. main.addLoadHandler(function()
  9723. {
  9724. var current = main.loadString('language_current', '');
  9725.  
  9726. if (current != '')
  9727. {
  9728. language.current = language.list[current];
  9729.  
  9730. if (language.current != null) language.setCurrent(language.current);
  9731. }
  9732. });
  9733. };
  9734.  
  9735. // buttonName: "text"
  9736. //
  9737. // For description of elements in legend can use line1 и line2 to place text on separate lines:
  9738. //
  9739. // labelName:
  9740. // {
  9741. // line1: "text on 1 line",
  9742. // line2: "text on 2 line"
  9743. // },
  9744.  
  9745. language.list.en =
  9746. {
  9747. id: 'en',
  9748. text: "English",
  9749.  
  9750. left: "x: ",
  9751. top: "y: ",
  9752. width: "w: ",
  9753. height: "h: ",
  9754.  
  9755. // settings
  9756.  
  9757. optionsButton: "Settings",
  9758.  
  9759. developers: "Developers Haonik & TheDarkKRONOS",
  9760. site: "Go to the website of project",
  9761.  
  9762. on: "yes",
  9763. off: "no",
  9764.  
  9765. hide: "Hide",
  9766. opacity:
  9767. {
  9768. text: "Opacity",
  9769. unit: "%"
  9770. },
  9771. background: "Show background",
  9772. borders: "Show borders",
  9773.  
  9774. fitGameScreen: "Fit game screen",
  9775.  
  9776. customize: "Customization interface",
  9777. exitCustomize: "Сomplete сustomization",
  9778. resetCustomize: "Reset element's position",
  9779.  
  9780. customizeHelp: "To select an element, you must set mouse cursor to it.<br/><br/>" +
  9781. "Click on selected element - show/hide settings.<br/>" +
  9782. "To change sizes selected element, need, hold right button, move mouse.<br/>" +
  9783. "To move selected element, need, hold left button, move mouse.<br/><br/>" +
  9784. "During the move if bring any element of the border to another (They will be highlighted in red),<br/>" +
  9785. "items will be bound. To bind element to center of another,<br/>" +
  9786. "hover the mouse on the horizontal or vertical yellow line (Highlighted in red).<br/><br/>" +
  9787. "Click on setting button to hide menu and you can move elements.<br/><br/>" +
  9788. "Click here to hide this hint.<br/>" +
  9789. "You can open hint again by going to Settings -> Help.",
  9790. customizeHelpOption: "Help",
  9791.  
  9792. languageSelect: "Language",
  9793.  
  9794. modeAutomatic: "automatic",
  9795. modeManual: "manual",
  9796. modeButton: "Mode",
  9797.  
  9798. playerIdLabel: "Your player ID:",
  9799. playerIdIsInvalid: "Player ID invalid!",
  9800. playerIdReset: "Auto determine Player ID",
  9801.  
  9802. gameWindow: "Game window",
  9803.  
  9804. // themes
  9805.  
  9806. themeSelect: "Theme",
  9807. themeFontSize: "Font size",
  9808. themeFontSpacing: "Font spacing",
  9809.  
  9810. themeSite: "Style of the site",
  9811. themeLight: "Light",
  9812. themeStandart: "Standart",
  9813.  
  9814. // map
  9815.  
  9816. map: "Click right mouse button or Ctrl + left mouse button on cell for set or remove mark on map",
  9817. mapOption: "Show map",
  9818.  
  9819. mapScale: "Scale",
  9820.  
  9821. mapStyle: "Style",
  9822. mapNewStyle: "new",
  9823. mapOldStyle: "old",
  9824.  
  9825. playerControlButtonsToggleOption: "Show map controls",
  9826.  
  9827. outpostSelect: "View outpost in automatic mode / fast roaming in manual mode",
  9828. outpostSelectOption: "Show outpost's list",
  9829.  
  9830. checkButton: "Set mark on selected cell of map.",
  9831. checkButtonOption: 'Button "Set mark"',
  9832. clearButton: "Remove mark on selected cell of map",
  9833. clearButtonOption: 'Button "Remove mark"',
  9834. clearAllButton: "Remove all marks from map",
  9835. clearAllButtonOption: 'Button "Remove all marks"',
  9836.  
  9837. centeredOnPlayerButton: "Show player position on map",
  9838. centeredOnPlayerButtonOption: "Show centering button",
  9839.  
  9840. // manipulating elements in manual mode
  9841.  
  9842. upButton: "Go up",
  9843. downButton: "Go down",
  9844. leftButton: "Go left",
  9845. rightButton: "Go right",
  9846. leftUpButton: "Go left-up",
  9847. leftDownButton: "Go left-down",
  9848. rightUpButton: "Go rigth-up",
  9849. rightDownButton: "Go rigth-down",
  9850. directionButtonOption: "Show direction buttons",
  9851.  
  9852. // manipulating elements in automatic mode
  9853.  
  9854. refreshButton: "Update player's information",
  9855. refreshButtonOption: "Show update button",
  9856.  
  9857. healthLabel: "Health",
  9858. healthLabelOption: "Show health",
  9859.  
  9860. armorLabel: "Armor",
  9861. armorLabelOption: "Show armor",
  9862.  
  9863. hungerLabel: "satiety",
  9864. hungerLabelOption: "Show satiety",
  9865.  
  9866. inventoryLabel: "Count of free cells in inventory",
  9867. inventoryLabelOption: "Show count free cells",
  9868.  
  9869. messageLabel: "Count of new messages",
  9870. messageLabelOption: "Show count of new messages",
  9871.  
  9872. // map legend
  9873.  
  9874. legend: "Click for close map legend",
  9875.  
  9876. legendButton: "Map legend",
  9877. legendButtonOption: "Show map legend button",
  9878.  
  9879. legendDescriptionOutpost: "Outpost",
  9880. legendDescriptionWarehouse: "Warehouse",
  9881. legendDescriptionHouse: "House",
  9882. legendDescriptionApartment:
  9883. {
  9884. line1: "Apartment",
  9885. line2: "home"
  9886. },
  9887. legendDescriptionPoliceStation:
  9888. {
  9889. line1: "Police station",
  9890. line2: "Weapon's shop"
  9891. },
  9892. legendDescriptionClothingStore: "Clothing store",
  9893. legendDescriptionSuperMarket: "Supermarket",
  9894. legendDescriptionShop: "Shop",
  9895. legendDescriptionRowShops: "Row shops",
  9896. legendDescriptionHospital: "Hospital",
  9897. legendDescriptionSchool: "School",
  9898. legendDescriptionSportField: "Sport field",
  9899. legendDescriptionHotel: "Hotel",
  9900. legendDescriptionJunkyard: "Junkyard",
  9901. legendDescriptionOfficeBuilding: "Office building",
  9902. legendDescriptionBlinds: "Blinds",
  9903. legendDescriptionGreenArea: "Green area",
  9904. legendDescriptionBigGreenArea: "Big green area",
  9905. legendDescriptionDoorBarricade:
  9906. {
  9907. line1: "In building 1 door",
  9908. line2: "is blocked"
  9909. },
  9910. legendDescriptionCyanRoute:
  9911. {
  9912. line1: "Blue route.",
  9913. line2: "From outpost to outpost."
  9914. },
  9915. legendDescriptionGreenRoute:
  9916. {
  9917. line1: "Green route.",
  9918. line2: "Loot, low risk."
  9919. },
  9920. legendDescriptionYellowRoute:
  9921. {
  9922. line1: "Yellow route.",
  9923. line2: "Loot, mid risk."
  9924. },
  9925. legendDescriptionOrangeRoute:
  9926. {
  9927. line1: "Light-red route.",
  9928. line2: "Loot, high risk."
  9929. },
  9930. legendDescriptionRedRoute:
  9931. {
  9932. line1: "Dark-red route.",
  9933. line2: "Loot, extreme risk."
  9934. },
  9935. legendDescriptionBlueZone:
  9936. {
  9937. line1: "Blue zone.",
  9938. line2: "Low risk."
  9939. },
  9940. legendDescriptionGreenZone:
  9941. {
  9942. line1: "Green zone.",
  9943. line2: "Mid-low risk."
  9944. },
  9945. legendDescriptionYellowZone:
  9946. {
  9947. line1: "Yellow zone.",
  9948. line2: "Mid risk."
  9949. },
  9950. legendDescriptionOrangeZone:
  9951. {
  9952. line1: "Orange zone.",
  9953. line2: "Mid-high risk."
  9954. },
  9955. legendDescriptionRedZone:
  9956. {
  9957. line1: "Dark-red zone.",
  9958. line2: "High risk."
  9959. },
  9960. legendDescriptionDarkZone:
  9961. {
  9962. line1: "Dark zone.",
  9963. line2: "Very high risk."
  9964. },
  9965. legendDescriptionNightmareZone:
  9966. {
  9967. line1: "Nightmare zone.",
  9968. line2: "Nightmare risk."
  9969. },
  9970.  
  9971. // chat
  9972.  
  9973. chatOption: "Show chat",
  9974.  
  9975. toggleChatButton: "Show/hide chat",
  9976. toggleChatButtonOption: 'Button "Show/Hide chat"',
  9977.  
  9978. openChatButton: "Open chat in new window",
  9979. openChatButtonOption: 'Button "Chat in new window"',
  9980.  
  9981. // messages
  9982.  
  9983. message_isIntersectsWithGameWindow: "Setting's button don't stay on top of game window!"
  9984. };
  9985.  
  9986. // названиеКнопки: "текст"
  9987. //
  9988. // Для описания элементов карты в легенде можно использовать line1 и line2, чтобы разместить текст на разных строках:
  9989. //
  9990. // названиеПоля:
  9991. // {
  9992. // line1: "текст на 1 строке",
  9993. // line2: "текст на 2 строке"
  9994. // },
  9995.  
  9996. language.list.ru =
  9997. {
  9998. id: 'ru',
  9999. text: "Русский",
  10000.  
  10001. left: "x: ",
  10002. top: "y: ",
  10003. width: "ш: ",
  10004. height: "в: ",
  10005.  
  10006. // настройки
  10007.  
  10008. optionsButton: "Настройки",
  10009.  
  10010. developers: "Разработчики Haonik и TheDarkKRONOS",
  10011. site: "Перейти на сайт проекта",
  10012.  
  10013. on: "да",
  10014. off: "нет",
  10015.  
  10016. hide: "Скрыть",
  10017. opacity:
  10018. {
  10019. text: "Непрозрачность",
  10020. unit: "%"
  10021. },
  10022. background: "Показать фон",
  10023. borders: "Показать рамки",
  10024.  
  10025. fitGameScreen: "Развернуть игровое окно",
  10026.  
  10027. customize: "Настроить расположение",
  10028. exitCustomize: "Завершить настройку",
  10029. resetCustomize: "Сбросить расположение элементов",
  10030.  
  10031. customizeHelp: "Чтобы выделить элемент, нужно навести на него мышку.<br/><br/>" +
  10032. "У каждого элемента есть настройки, чтобы их показать, нужно его выделить и щёлкнуть по нему любой кнопкой мыши.<br/>" +
  10033. "Чтобы изменить размеры выделенного элемента, нужно, удерживая правую кнопку (Либо ctrl и левую кнопку), двигать мышь.<br/>" +
  10034. "Чтобы переместить выделенный элемент, нужно нажать левую кнопку, и удерживая её, двигать мышь.<br/><br/>" +
  10035. "Во время перемещения, если подвести элемент любой из границ к другому (Они выделятся красным),<br/>" +
  10036. "элементы будут связаны. Чтобы привязать элемент к центру другого,<br/>" +
  10037. "нужно навести мышкой на горизонтальную или вертикальную жёлтую линию (Выделится красным).<br/><br/>" +
  10038. "Щёлкните на кнопке настроек, чтобы скрыть меню, и можно было перемещать элементы.<br/><br/>" +
  10039. "Щелкните здесь, чтобы скрыть эту подсказку.<br/>" +
  10040. "Её снова можно открыть, зайдя в Настройки -> Помощь.",
  10041. customizeHelpOption: "Помощь",
  10042.  
  10043. languageSelect: "Язык",
  10044.  
  10045. modeAutomatic: "автоматический",
  10046. modeManual: "ручной",
  10047. modeButton: "Режим",
  10048.  
  10049. playerIdLabel: "Ваш игровой номер:",
  10050. playerIdIsInvalid: "Неправильно задан номер игрока!",
  10051. playerIdReset: "Определить номер автоматически",
  10052.  
  10053. gameWindow: "Окно игры",
  10054.  
  10055. // темы
  10056.  
  10057. themeSelect: "Тема",
  10058. themeFontSize: "Размер шрифта",
  10059. themeFontSpacing: "Расстояние между буквами",
  10060.  
  10061. themeSite: "Стиль сайта",
  10062. themeLight: "Светлая",
  10063. themeStandart: "Обычная",
  10064.  
  10065. // карта
  10066.  
  10067. map: "Щёлкните правой кнопкой мыши или ctrl + левая кнопка мыши на клетке, чтобы поставить или убрать метку",
  10068. mapOption: "Карта",
  10069.  
  10070. mapScale: "Масштаб",
  10071.  
  10072. mapStyle: "Стиль",
  10073. mapNewStyle: "новый",
  10074. mapOldStyle: "старый",
  10075.  
  10076. playerControlButtonsToggleOption: "Элементы управления для карты",
  10077.  
  10078. outpostSelect: "Просмотр аванпоста в автоматическом режиме / быстрое перемещение в ручном",
  10079. outpostSelectOption: "Список аванпостов",
  10080.  
  10081. checkButton: "Поставить метку на выделенной клетке карты",
  10082. checkButtonOption: 'Кнопка "поставить метку"',
  10083. clearButton: "Убрать метку на выделенной клетке карты",
  10084. clearButtonOption: 'Кнопка "убрать метку"',
  10085. clearAllButton: "Убрать все метки на карте",
  10086. clearAllButtonOption: 'Кнопка "убрать все метки"',
  10087.  
  10088. centeredOnPlayerButton: "Показать игрока на карте",
  10089. centeredOnPlayerButtonOption: 'Кнопка "центрирования на игроке"',
  10090.  
  10091. // элементы управления в ручном режиме
  10092.  
  10093. upButton: "Пойти вверх",
  10094. downButton: "Пойти вниз",
  10095. leftButton: "Пойти влево",
  10096. rightButton: "Пойти вправо",
  10097. leftUpButton: "Пойти влево-вверх",
  10098. leftDownButton: "Пойти влево-вниз",
  10099. rightUpButton: "Пойти вправо-вверх",
  10100. rightDownButton: "Пойти вправо-вниз",
  10101. directionButtonOption: "Показать кнопки движения",
  10102.  
  10103. // элементы управления в автоматическом режиме
  10104.  
  10105. refreshButton: "Обновить информацию об игроке",
  10106. refreshButtonOption: 'Кнопка "обновить информацию"',
  10107.  
  10108. healthLabel: "Здоровье персонажа",
  10109. healthLabelOption: "Показать здоровье",
  10110.  
  10111. armorLabel: "Броня персонажа",
  10112. armorLabelOption: "Показать броню",
  10113.  
  10114. hungerLabel: "Сытость персонажа",
  10115. hungerLabelOption: "Показать сытость",
  10116.  
  10117. inventoryLabel: "Количество свободных ячеек в инвентаре",
  10118. inventoryLabelOption: "Показать место в инвентаре",
  10119.  
  10120. messageLabel: "Количество новых сообщений",
  10121. messageLabelOption: "Количество новых сообщений",
  10122.  
  10123. // легенда карты
  10124.  
  10125. legend: "Щёлкните, чтобы закрыть легенду карты",
  10126.  
  10127. legendButton: "Легенда карты",
  10128. legendButtonOption: 'Кнопка "легенда карты"',
  10129.  
  10130. legendDescriptionOutpost: "Аванпост",
  10131. legendDescriptionWarehouse: "Склад",
  10132. legendDescriptionHouse: "Дом",
  10133. legendDescriptionApartment:
  10134. {
  10135. line1: "Многоквартирный",
  10136. line2: "дом"
  10137. },
  10138. legendDescriptionPoliceStation:
  10139. {
  10140. line1: "Полицеский участок",
  10141. line2: "Оружейный магазин"
  10142. },
  10143. legendDescriptionClothingStore: "Магазин одежды",
  10144. legendDescriptionSuperMarket: "Универмаг",
  10145. legendDescriptionShop: "Магазин",
  10146. legendDescriptionRowShops: "Торговый ряд",
  10147. legendDescriptionHospital: "Больница",
  10148. legendDescriptionSchool: "Школа",
  10149. legendDescriptionSportField: "Спортплощадка",
  10150. legendDescriptionHotel: "Гостиница",
  10151. legendDescriptionJunkyard: "Свалка",
  10152. legendDescriptionOfficeBuilding: "Офисное здание",
  10153. legendDescriptionBlinds: "Деревья",
  10154. legendDescriptionGreenArea: "Парк",
  10155. legendDescriptionBigGreenArea: "Большой парк",
  10156. legendDescriptionDoorBarricade:
  10157. {
  10158. line1: "В здании 1 дверь",
  10159. line2: "заблокирована"
  10160. },
  10161. legendDescriptionCyanRoute:
  10162. {
  10163. line1: "Путь от аванпоста",
  10164. line2: "к аванпосту"
  10165. },
  10166. legendDescriptionGreenRoute:
  10167. {
  10168. line1: "Путь с наименьшим",
  10169. line2: "риском"
  10170. },
  10171. legendDescriptionYellowRoute:
  10172. {
  10173. line1: "Путь со средним",
  10174. line2: "риском"
  10175. },
  10176. legendDescriptionOrangeRoute:
  10177. {
  10178. line1: "Путь с высоким",
  10179. line2: "риском"
  10180. },
  10181. legendDescriptionRedRoute:
  10182. {
  10183. line1: "Путь с наибольшим",
  10184. line2: "риском"
  10185. },
  10186. legendDescriptionBlueZone:
  10187. {
  10188. line1: "Зона наименьшей",
  10189. line2: "опасности"
  10190. },
  10191. legendDescriptionGreenZone:
  10192. {
  10193. line1: "Зона низкой-",
  10194. line2: "средней опасности"
  10195. },
  10196. legendDescriptionYellowZone:
  10197. {
  10198. line1: "Зона средней",
  10199. line2: "опасности"
  10200. },
  10201. legendDescriptionOrangeZone:
  10202. {
  10203. line1: "Зона средней-",
  10204. line2: "высокой опасности"
  10205. },
  10206. legendDescriptionRedZone:
  10207. {
  10208. line1: "Зона высокой",
  10209. line2: "опасности"
  10210. },
  10211. legendDescriptionDarkZone:
  10212. {
  10213. line1: "Зона очень",
  10214. line2: "высокой опасности"
  10215. },
  10216. legendDescriptionNightmareZone:
  10217. {
  10218. line1: "Зона наибольшей",
  10219. line2: "опасности"
  10220. },
  10221.  
  10222. // чат
  10223.  
  10224. chatOption: "Показать чат",
  10225.  
  10226. toggleChatButton: "Показать/Скрыть чат",
  10227. toggleChatButtonOption: 'Кнопка "показать/Скрыть чат"',
  10228.  
  10229. openChatButton: "Открыть чат в новом окне",
  10230. openChatButtonOption: 'Кнопка "чат в новом окне"',
  10231.  
  10232. // сообщения
  10233.  
  10234. message_isIntersectsWithGameWindow: "Кнопка настроек не должна находиться поверх игрового окна!"
  10235. };
  10236.  
  10237. language.current = language.list.en;
  10238.  
  10239. var theme = new function()
  10240. {
  10241. var theme = this;
  10242.  
  10243. //#region Classes
  10244.  
  10245. theme.className = 'dfeui';
  10246.  
  10247. theme.classControl = theme.className + 'Control';
  10248. theme.classDiv = theme.className + 'Div';
  10249. theme.classButton = theme.className + 'Button';
  10250. theme.classLabel = theme.className + 'Label';
  10251. theme.classInput = theme.className + 'Input';
  10252. theme.classSelect = theme.className + 'Select';
  10253. theme.classOption = theme.className + 'Option';
  10254. theme.classImage = theme.className + 'Image';
  10255. theme.classLink = theme.className + 'Link';
  10256. theme.classDelimiter = theme.className + 'Delimiter';
  10257. theme.classImageButton = theme.className + 'ImageButton';
  10258. theme.classCanvas = theme.className + 'Canvas';
  10259.  
  10260. theme.classBackground = theme.className + 'Background';
  10261. theme.classTrack = theme.className + 'Track';
  10262. theme.classText = theme.className + 'Text';
  10263.  
  10264. theme.classNoBorders = theme.className + 'NoBorders';
  10265.  
  10266. theme.classDock = theme.className + 'Dock';
  10267. theme.classFixed = theme.className + 'Fixed';
  10268. theme.classCustomizationOn = theme.className + 'CustomizationOn';
  10269.  
  10270. theme.classOn = theme.className + 'On';
  10271. theme.classOff = theme.className + 'Off';
  10272.  
  10273. theme.classMore75 = theme.className + 'More75';
  10274. theme.classMore50 = theme.className + 'More50';
  10275. theme.classMore25 = theme.className + 'More25';
  10276. theme.classMore0 = theme.className + 'More0';
  10277.  
  10278. //#endregion
  10279.  
  10280. theme.list = {};
  10281. theme.current = null;
  10282.  
  10283. theme.fontSize = 12;
  10284. theme.elementHeight = theme.fontSize + 4;
  10285. theme.fontSpacing = 1;
  10286. theme.controlsBordersSize = 0;
  10287. theme.controlsBordersSize2 = 0;
  10288. theme.padding = 10;
  10289. theme.padding2 = 20;
  10290.  
  10291. theme.element = document.createElement('style');
  10292. theme.element.type = 'text/css';
  10293. document.head.appendChild(theme.element);
  10294.  
  10295. function replaceCode(value)
  10296. {
  10297. return value
  10298. .replace(/\-c\-/g, theme.className)
  10299. .replace(/\-s\-/g, theme.fontSize)
  10300. .replace(/\-p\-/g, theme.fontSpacing);
  10301. };
  10302.  
  10303. theme.setCurrent = function(value)
  10304. {
  10305. theme.current = value;
  10306. theme.controlsBordersSize = theme.current.controlsBordersSize;
  10307. theme.controlsBordersSize2 = theme.controlsBordersSize + theme.controlsBordersSize;
  10308.  
  10309. theme.element.innerHTML =
  10310. 'html, body { margin: 0 !important; padding: 0 !important; width: 100% !important; height: 100% !important; } ' +
  10311. '.' + theme.className + ' { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } ' +
  10312. replaceCode(theme.current.styles);
  10313. };
  10314.  
  10315. theme.update = function()
  10316. {
  10317. for (var item in theme.list)
  10318. {
  10319. if (!theme.list.hasOwnProperty(item)) continue;
  10320.  
  10321. theme.list[item].update();
  10322. }
  10323. };
  10324.  
  10325. main.addSaveHandler(function()
  10326. {
  10327. main.save('theme_current', theme.current.id);
  10328. main.save('theme_fontSize', theme.fontSize);
  10329. main.save('theme_fontSpacing', theme.fontSpacing);
  10330. });
  10331.  
  10332. main.addLoadHandler(function()
  10333. {
  10334. theme.fontSize = main.loadNumber('theme_fontSize', 12);
  10335. theme.elementHeight = theme.fontSize + 4;
  10336.  
  10337. theme.fontSpacing = main.loadNumber('theme_fontSpacing', 1);
  10338.  
  10339. var current = main.loadString('theme_current', '');
  10340.  
  10341. if (current != '')
  10342. {
  10343. theme.current = theme.list[current];
  10344.  
  10345. if (theme.current != null) theme.setCurrent(theme.current);
  10346. }
  10347. });
  10348. };
  10349.  
  10350. theme.list.standart =
  10351. {
  10352. id: 'standart',
  10353. text: language.current.themeStandart,
  10354.  
  10355. controlsBordersSize: 1,
  10356.  
  10357. styles: '.-c-,.-c-gameWindowTd{letter-spacing:-p-px!important;font-size:-s-px!important;font-family:"Times New Roman",Arial!important}.-c-Control{background:#303030;border:1px solid #707070}.-c-Canvas,.-c-gameWindowTable{border:1px solid #909090!important}.-c-Div,.-c-Button,.-c-Label,.-c-Input,.-c-Select,.-c-Option,.-c-Link,.-c-gameWindowTd{background:#303030;border:none;color:#fff!important;text-align:center!important;vertical-align:middle!important}.-c-gameWindowBlack{background:#000!important}.-c-Option{background:#606060}.-c-informationPopup{color:#f7fe57!important}.-c-settingWindow .-c-Div,.-c-settingWindow .-c-Button,.-c-settingWindow .-c-Label,.-c-settingWindow .-c-Input,.-c-settingWindow .-c-Select,.-c-settingWindow .-c-Link{background:#606060;border:1px solid #909090}.-c-Delimiter{background:#cacaca;border:none}.-c-Button:hover,.-c-Link:hover,.-c-Background:hover .-c-Track{background:#909090!important;border:1px solid #f7fe57!important}.-c-Button:active,.-c-Link:active,.-c-Background:active .-c-Track{background:#303030!important;border:1px solid #505050!important}.-c-Control .-c-ImageButton{background-color:transparent;background-position:left 0 top 0}.-c-Control:hover .-c-ImageButton{background-color:transparent;background-position:left 0 top -18px}.-c-Control:active .-c-ImageButton{background-color:transparent;background-position:left 0 top -36px}.-c-NoBorders,.-c-container{border:1px solid transparent}.-c-customization{background:none;border:1px solid #ffc677}.-c-Dock{border:1px solid #f7fe57}.-c-Fixed{border:1px solid #ef1919}.-c-CustomizationOn{border:1px solid #a0fa2c}.-c-Track{background:#82742f!important}.-c-Text{background:none!important;border:none!important}.-c-On{background:#41562c!important}.-c-Off{background:#5f2b2b!important}.-c-More75{color:#8fd846!important}.-c-More50{color:#eaeb34!important}.-c-More25{color:#e69b14!important}.-c-More0{color:#f53939!important}',
  10358.  
  10359. update: function()
  10360. {
  10361. this.text = language.current.themeStandart;
  10362. }
  10363. };
  10364.  
  10365. theme.list.site =
  10366. {
  10367. id: 'site',
  10368. text: language.current.themeSite,
  10369.  
  10370. controlsBordersSize: 1,
  10371.  
  10372. styles: '.-c-,.-c-gameWindowTd{letter-spacing:-p-px!important;font-size:-s-px!important}.-c-Control{background:#58554a;border-top:#232323 1px solid;border-bottom:#898988 1px solid;border-left:#232323 1px solid;border-right:#898988 1px solid;color:#af9b6d!important}.-c-gameWindowBlack{background:#000!important}.-c-Div{background-image:url(images/HD/textbg.gif);background-repeat:repeat-x;background-color:#373737;color:#af9b6d!important}.-c-Link:link,.-c-Link:visited{text-decoration:none;color:#fdfdfd}.-c-Link:hover{text-decoration:none;color:#af9b6d}.-c-Track,.-c-Background,.-c-Canvas,.-c-settingWindow .-c-Div,.-c-settingWindow .-c-Button,.-c-settingWindow .-c-Label,.-c-settingWindow .-c-Input,.-c-settingWindow .-c-Select,.-c-settingWindow .-c-Link,.-c-gameWindowTd,.-c-gameWindowTable{background-image:url(images/HD/input.gif);background-repeat:repeat-x;background-color:#373737;border-top:#232323 1px solid;border-bottom:#898988 1px solid;border-left:#232323 1px solid;border-right:#898988 1px solid;color:#af9b6d!important}.-c-Option{background-color:#373737}.-c-Delimiter{background:#404040;border:none}.-c-NoBorders,.-c-container{border:1px solid transparent}.-c-customization{background:none;border:1px solid #c43c02}.-c-Dock{border:1px solid #ffd700}.-c-Fixed{border:1px solid #c00}.-c-CustomizationOn{border:1px solid #a0fa2c}.-c-Background:hover .-c-Track{background:#505050!important;border:1px solid #af9b6d!important}.-c-Background:active .-c-Track{background:#4d4d4d!important;border:1px solid #505050!important}.-c-Text,.-c-Image,.-c-ImageButton{background:none;border:none!important}.-c-Control .-c-ImageButton{background-color:transparent;background-position:left 0 top 0}.-c-Control:hover .-c-ImageButton{background-color:transparent;background-position:left 0 top -18px}.-c-Control:active .-c-ImageButton{background-color:transparent;background-position:left 0 top -36px}.-c-On{background:#382a1c!important}.-c-Off{background:#373737!important}.-c-More75{color:#090!important}.-c-More50{color:#ffd700!important}.-c-More25{color:#c43c02!important}.-c-More0{color:#c00!important}',
  10373.  
  10374. update: function()
  10375. {
  10376. this.text = language.current.themeSite;
  10377. }
  10378. };
  10379.  
  10380. theme.list.light =
  10381. {
  10382. id: 'light',
  10383. text: language.current.themeLight,
  10384.  
  10385. controlsBordersSize: 1,
  10386.  
  10387. styles: '.-c-,.-c-gameWindowTd{letter-spacing:-p-px!important;font-size:-s-px!important;font-family:"Times New Roman",Arial!important;background:none;border:1px solid transparent;color:#fff!important;text-align:center!important;vertical-align:middle!important}.-c-Control{background:#707070;border:1px solid #404040}.-c-gameWindowBlack{background:#000!important}.-c-Canvas,.-c-gameWindowTable{border:1px solid #606060!important}.-c-Delimiter{background:#cfcfcf}.-c-Track{background:#8c8c80!important;border:1px solid gray!important}.-c-Button,.-c-Link{background:#8c8c80}.-c-Background,.-c-Select,.-c-Option{background:gray}.-c-Button:hover,.-c-Link:hover,.-c-Background:hover .-c-Track{border:1px solid #cfcfcf!important}.-c-Button:active,.-c-Link:active,.-c-Background:active .-c-Track{border:1px solid #505050!important}.-c-Control .-c-ImageButton{background-color:transparent;background-position:left 0 top 0}.-c-Control:hover .-c-ImageButton{background-color:transparent;background-position:left 0 top -18px}.-c-Control:active .-c-ImageButton{background-color:transparent;background-position:left 0 top -36px}.-c-NoBorders,.-c-container{border:1px solid transparent!important}.-c-customization{border:1px solid #fece8d}.-c-Dock{border:1px solid #faff84}.-c-Fixed{border:1px solid #e44040}.-c-CustomizationOn{border:1px solid #a0fa2c!important}.-c-On{background:#748761!important}.-c-Off{background:#9a6f6f!important}.-c-More75{color:#8fd846!important}.-c-More50{color:#eaeb34!important}.-c-More25{color:#e69b14!important}.-c-More0{color:#f27676!important}',
  10388.  
  10389. update: function()
  10390. {
  10391. this.text = language.current.themeLight;
  10392. }
  10393. };
  10394.  
  10395. function Control(name, order, minWidth, minHeight, isDiv, disableSavePosition)
  10396. {
  10397. /// <param name="name" type="String"></param>
  10398. /// <param name="order" type="Integer"></param>
  10399. /// <param name="minWidth" type="Integer"></param>
  10400. /// <param name="minHeight" type="Integer"></param>
  10401. /// <param name="isDiv" type="Boolean"></param>
  10402. /// <param name="disableSavePosition" type="Boolean"></param>
  10403.  
  10404. this.name = name;
  10405. this.className = theme.className + name;
  10406.  
  10407. controls.list[name] = this;
  10408.  
  10409. if (isDiv)
  10410. {
  10411. this.element = document.createElement('div');
  10412. }
  10413. else
  10414. {
  10415. this.element = document.createElement('button');
  10416. this.element.type = 'button';
  10417. }
  10418.  
  10419. this.element.className = theme.className + ' ' + theme.classControl + ' ' + this.className;
  10420. this.elementStyle = this.element.style;
  10421. this.elementStyle.cssText = 'position: absolute; overflow: hidden; margin: 0; padding: 0; z-index: ' + (order || 0);
  10422.  
  10423. this.visible = true;
  10424. this.opacity = 1;
  10425. this.order = order || 0;
  10426. this.changeWidthIsDisabled = false;
  10427. this.changeHeightIsDisabled = false;
  10428. this.savePositionIsDisabled = disableSavePosition || false;
  10429.  
  10430. container.element.append(this.element);
  10431. this.element = $(this.element);
  10432.  
  10433. /// <field type="Array" elementType="Control"></field>
  10434. this.childs = [];
  10435. this.minWidth = minWidth || 16;
  10436. this.minHeight = minHeight || 16;
  10437. /// <field type="Control"></field>
  10438. this.parent = null;
  10439.  
  10440. this.calculatePadding();
  10441. this.resetPosition();
  10442. this.resize();
  10443.  
  10444. var control = this;
  10445.  
  10446. this.toggle = function()
  10447. {
  10448. if (control.visible)
  10449. {
  10450. return control.hide();
  10451. }
  10452. else
  10453. {
  10454. return control.show();
  10455. }
  10456. };
  10457.  
  10458. //#region Saving settings
  10459.  
  10460. if (name == '' || this.savePositionIsDisabled) return;
  10461.  
  10462. main.addSaveHandler(function()
  10463. {
  10464. var prefix = 'control_' + name + '_';
  10465.  
  10466. main.save(prefix + 'parent', control.parent.name);
  10467.  
  10468. main.save(prefix + 'dockLeft', control.dockLeft);
  10469. main.save(prefix + 'dockTop', control.dockTop);
  10470. main.save(prefix + 'dockRight', control.dockRight);
  10471. main.save(prefix + 'dockBottom', control.dockBottom);
  10472. main.save(prefix + 'dockOuterHorizontal', control.dockOuterHorizontal);
  10473. main.save(prefix + 'dockOuterVertical', control.dockOuterVertical);
  10474.  
  10475. main.save(prefix + 'offsetLeft', control.offsetLeft);
  10476. main.save(prefix + 'offsetTop', control.offsetTop);
  10477. main.save(prefix + 'offsetWidth', control.offsetWidth);
  10478. main.save(prefix + 'offsetHeight', control.offsetHeight);
  10479.  
  10480. main.save(prefix + 'visible', control.visible);
  10481. main.save(prefix + 'opacity', control.opacity);
  10482. main.save(prefix + 'background', control.element[0].style.background != 'none');
  10483. main.save(prefix + 'borders', !control.element.hasClass(theme.classNoBorders));
  10484. });
  10485.  
  10486. main.addLoadHandler(function()
  10487. {
  10488. var prefix = 'control_' + name + '_';
  10489.  
  10490. var parentName = main.loadString(prefix + 'parent', '');
  10491. if (parentName == '') return;
  10492.  
  10493. /// <var type="Control"></var>
  10494. var parent = controls.list[parentName];
  10495. if (parent == null) parent = container;
  10496.  
  10497. control.setParent(parent);
  10498.  
  10499. var dockLeft = main.loadBoolean(prefix + 'dockLeft', false);
  10500. var dockTop = main.loadBoolean(prefix + 'dockTop', false);
  10501. var dockRight = main.loadBoolean(prefix + 'dockRight', false);
  10502. var dockBottom = main.loadBoolean(prefix + 'dockBottom', false);
  10503. var dockOuterHorizontal = main.loadBoolean(prefix + 'dockOuterHorizontal', false);
  10504. var dockOuterVertical = main.loadBoolean(prefix + 'dockOuterVertical', false);
  10505.  
  10506. control.dock(dockLeft, dockTop, dockRight, dockBottom, dockOuterHorizontal, dockOuterVertical);
  10507.  
  10508. var left = main.loadNumber(prefix + 'offsetLeft', 0);
  10509. var top = main.loadNumber(prefix + 'offsetTop', 0);
  10510. var width = main.loadNumber(prefix + 'offsetWidth', 0);
  10511. var height = main.loadNumber(prefix + 'offsetHeight', 0);
  10512.  
  10513. control.locate(left, top, width, height);
  10514.  
  10515. if (!main.loadBoolean(prefix + 'visible', true)) control.hide();
  10516.  
  10517. control.setOpacity(main.loadNumber(prefix + 'opacity', 1));
  10518.  
  10519. var background = main.loadBoolean(prefix + 'background', true);
  10520. control.element[0].style.background = (background ? '' : 'none');
  10521.  
  10522. var borders = main.loadBoolean(prefix + 'borders', true);
  10523. if (!borders) control.element.addClass(theme.classNoBorders);
  10524. });
  10525.  
  10526. //#endregion
  10527. }
  10528.  
  10529. Control.prototype.addSettings = function()
  10530. {
  10531. settingWindow.addSharedElements(this, true, true, true, false);
  10532. };
  10533.  
  10534. Control.prototype.update = function() { };
  10535.  
  10536. Control.prototype.resetPosition = function()
  10537. {
  10538. this.locate().dock().setParent();
  10539. };
  10540.  
  10541. //#region Position
  10542.  
  10543. Control.prototype.locate = function(left, top, width, height)
  10544. {
  10545. /// <param name="left" type="Float"></param>
  10546. /// <param name="top" type="Float"></param>
  10547. /// <param name="width" type="Float"></param>
  10548. /// <param name="height" type="Float"></param>
  10549.  
  10550. this.offsetLeft = left || 0;
  10551. this.offsetTop = top || 0;
  10552. this.offsetWidth = width || 0;
  10553. this.offsetHeight = height || 0;
  10554.  
  10555. if (this.offsetWidth < this.minWidth) this.offsetWidth = this.minWidth;
  10556. if (this.offsetHeight < this.minHeight) this.offsetHeight = this.minHeight;
  10557.  
  10558. return this;
  10559. };
  10560.  
  10561. Control.prototype.calculatePosition = function()
  10562. {
  10563. var offsetLeft = this.offsetLeft;
  10564. var offsetTop = this.offsetTop;
  10565.  
  10566. if (this.dockNone)
  10567. {
  10568. this.width = this.offsetWidth;
  10569. this.height = this.offsetHeight;
  10570. }
  10571. else if (this.dockFill)
  10572. {
  10573. offsetLeft = this.parent.paddingLeft + theme.padding;
  10574. offsetTop = this.parent.paddingTop + theme.padding;
  10575. this.width = this.parent.width - this.parent.paddingLeft - this.parent.paddingRight - theme.padding2;
  10576. this.height = this.parent.height - this.parent.paddingTop - this.parent.paddingBottom - theme.padding2;
  10577. }
  10578. else
  10579. {
  10580. this.width = this.offsetWidth;
  10581. this.height = this.offsetHeight;
  10582.  
  10583. if (this.dockLeft && this.dockRight)
  10584. {
  10585. offsetLeft = this.parent.width / 2 - this.offsetWidth / 2;
  10586. }
  10587. else if (this.dockRight)
  10588. {
  10589. var padding = (this.dockOuterVertical ? 0 : theme.padding);
  10590. offsetLeft = this.parent.width + (this.dockOuterHorizontal ? theme.padding : -this.offsetWidth - padding);
  10591. }
  10592. else if (this.dockLeft)
  10593. {
  10594. var padding = (this.dockOuterVertical ? 0 : theme.padding);
  10595. offsetLeft = (this.dockOuterHorizontal ? -this.offsetWidth - theme.padding : padding);
  10596. }
  10597.  
  10598. if (this.dockTop && this.dockBottom)
  10599. {
  10600. offsetTop = this.parent.height / 2 - this.offsetHeight / 2;
  10601. }
  10602. else if (this.dockBottom)
  10603. {
  10604. var padding = (this.dockOuterHorizontal ? 0 : theme.padding);
  10605. offsetTop = this.parent.height + (this.dockOuterVertical ? theme.padding : -this.offsetHeight - padding);
  10606. }
  10607. else if (this.dockTop)
  10608. {
  10609. var padding = (this.dockOuterHorizontal ? 0 : theme.padding);
  10610. offsetTop = (this.dockOuterVertical ? -this.offsetHeight - theme.padding : padding);
  10611. }
  10612. }
  10613.  
  10614. this.left = this.parent.left + offsetLeft;
  10615. this.top = this.parent.top + offsetTop;
  10616.  
  10617. if (this.dockLeft == false && this.dockRight == false)
  10618. {
  10619. if (offsetLeft + this.width > this.parent.width)
  10620. {
  10621. this.left = this.parent.left + this.parent.width - this.width;
  10622. }
  10623. else if (this.left < this.parent.left)
  10624. {
  10625. this.left = this.parent.left;
  10626. }
  10627. }
  10628.  
  10629. if (this.dockTop == false && this.dockBottom == false)
  10630. {
  10631. if (offsetTop + this.height > this.parent.height)
  10632. {
  10633. this.top = this.parent.top + this.parent.height - this.height;
  10634. }
  10635. else if (this.top < this.parent.top)
  10636. {
  10637. this.top = this.parent.top;
  10638. }
  10639. }
  10640.  
  10641. if (this.left + this.width > container.width)
  10642. {
  10643. this.left = container.left + container.width - this.width;
  10644. }
  10645. else if (this.left < container.left)
  10646. {
  10647. this.left = container.left;
  10648. }
  10649.  
  10650. if (this.top + this.height > container.height)
  10651. {
  10652. this.top = container.top + container.height - this.height;
  10653. }
  10654. else if (this.top < container.top)
  10655. {
  10656. this.top = container.top;
  10657. }
  10658.  
  10659. this.clientWidth = this.width - theme.controlsBordersSize2;
  10660. this.clientHeight = this.height - theme.controlsBordersSize2;
  10661.  
  10662. return this;
  10663. };
  10664.  
  10665. Control.prototype.resize = Control.prototype.baseResize = function()
  10666. {
  10667. if (main.isNotLoaded) return;
  10668.  
  10669. this.calculatePosition();
  10670.  
  10671. this.elementStyle.left = Math.floor(this.left) + 'px';
  10672. this.elementStyle.top = Math.floor(this.top) + 'px';
  10673. this.elementStyle.width = Math.floor(this.width) + 'px';
  10674. this.elementStyle.height = Math.floor(this.height) + 'px';
  10675.  
  10676. for (var i = 0; i < this.childs.length; i++)
  10677. if (this.childs[i].visible || controls.notIgnoreHiddenOnResize) this.childs[i].resize();
  10678.  
  10679. return this;
  10680. };
  10681.  
  10682. //#endregion
  10683.  
  10684. //#region Dock
  10685.  
  10686. Control.prototype.setParent = function(parent)
  10687. {
  10688. /// <param name="parent" type="Control"></param>
  10689.  
  10690. parent = parent || container;
  10691.  
  10692. if (this.parent != null && this.parent == parent) return this;
  10693.  
  10694. if (this.parent != null)
  10695. {
  10696. for (var i = 0; i < this.parent.childs.length; i++)
  10697. {
  10698. if (this.parent.childs[i] != this) continue;
  10699.  
  10700. this.parent.childs.splice(i, 1);
  10701. this.parent.calculatePadding();
  10702.  
  10703. break;
  10704. }
  10705. }
  10706.  
  10707. this.parent = parent;
  10708.  
  10709. for (var i = 0; i < parent.childs.length; i++)
  10710. if (this.order >= parent.childs[i].order) break;
  10711.  
  10712. parent.childs.splice(i, 0, this);
  10713. this.checkPadding();
  10714.  
  10715. return this;
  10716. }
  10717.  
  10718. Control.prototype.dock = function(dockLeft, dockTop, dockRight, dockBottom, outerHorizontal, outerVertical)
  10719. {
  10720. /// <signature>
  10721. /// <param name="dockFill" type="Boolean"></param>
  10722. /// </signature>
  10723. /// <signature>
  10724. /// <param name="dockLeft" type="Boolean"></param>
  10725. /// <param name="dockTop" type="Boolean"></param>
  10726. /// <param name="dockRight" type="Boolean"></param>
  10727. /// <param name="dockBottom" type="Boolean"></param>
  10728. /// <param name="outerHorizontal" type="Boolean"></param>
  10729. /// <param name="outerVertical" type="Boolean"></param>
  10730. /// </signature>
  10731.  
  10732. dockLeft = dockLeft || false;
  10733.  
  10734. if (dockTop == null && dockRight == null && dockBottom == null && outerHorizontal == null && outerVertical == null)
  10735. {
  10736. this.dockLeft = dockLeft;
  10737. this.dockTop = dockLeft;
  10738. this.dockRight = dockLeft;
  10739. this.dockBottom = dockLeft;
  10740. }
  10741. else
  10742. {
  10743. this.dockLeft = dockLeft;
  10744. this.dockTop = dockTop || false;
  10745. this.dockRight = dockRight || false;
  10746. this.dockBottom = dockBottom || false;
  10747. }
  10748.  
  10749. this.dockNone = !(this.dockLeft || this.dockRight || this.dockTop || this.dockBottom);
  10750. this.dockFill = this.dockLeft && this.dockRight && this.dockTop && this.dockBottom;
  10751. this.dockOuterHorizontal = outerHorizontal || false;
  10752. this.dockOuterVertical = outerVertical || false;
  10753.  
  10754. if (this.parent != null) this.parent.calculatePadding();
  10755.  
  10756. return this;
  10757. }
  10758.  
  10759. Control.prototype.checkPadding = function()
  10760. {
  10761. var update = false;
  10762.  
  10763. if (this.dockFill || this.dockNone) return false;
  10764.  
  10765. if (!this.dockOuterVertical && this.dockTop != this.dockBottom)
  10766. {
  10767. if (this.dockTop && this.offsetHeight + theme.padding > this.parent.paddingTop)
  10768. {
  10769. this.parent.paddingTop = this.offsetHeight + theme.padding;
  10770. update = true;
  10771. }
  10772.  
  10773. if (this.dockBottom && this.offsetHeight + theme.padding > this.parent.paddingBottom)
  10774. {
  10775. this.parent.paddingBottom = this.offsetHeight + theme.padding;
  10776. update = true;
  10777. }
  10778. }
  10779.  
  10780. if (!(this.dockOuterHorizontal || this.dockTop != this.dockBottom) && this.dockLeft != this.dockRight)
  10781. {
  10782. if (this.dockLeft && this.offsetWidth + theme.padding > this.parent.paddingLeft)
  10783. {
  10784. this.parent.paddingLeft = this.offsetWidth + theme.padding;
  10785. update = true;
  10786. }
  10787.  
  10788. if (this.dockRight && this.offsetWidth + theme.padding > this.parent.paddingRight)
  10789. {
  10790. this.parent.paddingRight = this.offsetWidth + theme.padding;
  10791. update = true;
  10792. }
  10793. }
  10794.  
  10795. return update;
  10796. }
  10797.  
  10798. Control.prototype.calculatePadding = function()
  10799. {
  10800. this.paddingLeft = 0;
  10801. this.paddingTop = 0;
  10802. this.paddingRight = 0;
  10803. this.paddingBottom = 0;
  10804.  
  10805. for (var i = 0; i < this.childs.length; i++)
  10806. {
  10807. if (!this.childs[i].visible) continue;
  10808.  
  10809. this.childs[i].checkPadding();
  10810. }
  10811.  
  10812. return this;
  10813. };
  10814.  
  10815. //#endregion
  10816.  
  10817. //#region Visible
  10818.  
  10819. Control.prototype.setOpacity = function(opacity)
  10820. {
  10821. /// <param name="opacity" type="Float"></param>
  10822.  
  10823. this.opacity = opacity;
  10824. this.element.css('opacity', opacity);
  10825.  
  10826. return this;
  10827. }
  10828.  
  10829. Control.prototype.show = Control.prototype.baseShow = function()
  10830. {
  10831. this.visible = true;
  10832. this.element[0].style.display = 'block';
  10833.  
  10834. this.resize();
  10835.  
  10836. if (this.checkPadding()) this.parent.resize();
  10837.  
  10838. return this;
  10839. };
  10840.  
  10841. Control.prototype.hide = function()
  10842. {
  10843. this.visible = false;
  10844. this.element[0].style.display = 'none';
  10845.  
  10846. this.parent.calculatePadding();
  10847. this.parent.resize();
  10848.  
  10849. return this;
  10850. };
  10851.  
  10852. //#endregion
  10853.  
  10854. var controls = new function()
  10855. {
  10856. var controls = this;
  10857.  
  10858. controls.notIgnoreHiddenOnResize = true;
  10859.  
  10860. controls.getText = function(text)
  10861. {
  10862. if (text == null) text = '';
  10863.  
  10864. return text.text || text;
  10865. }
  10866.  
  10867. controls.getClassName = function(currentValue, maxValue)
  10868. {
  10869. var percent = (maxValue == 0 ? 0 : 100 / maxValue * currentValue);
  10870.  
  10871. if (percent > 75) return theme.classMore75;
  10872. if (percent > 50) return theme.classMore50;
  10873. if (percent > 25) return theme.classMore25;
  10874. return theme.classMore0;
  10875. }
  10876.  
  10877. controls.makeButton = function createButton(control, icon, clickHandler)
  10878. {
  10879. if (clickHandler != null) control.element.mouseup(clickHandler);
  10880.  
  10881. var image = controls.createDiv(control, 'ImageButton');
  10882. image.style.cssText = 'background-image: url(' + icon + '); position: absolute; width: 17px; height: 17px';
  10883.  
  10884. control.resize = function()
  10885. {
  10886. control.baseResize();
  10887.  
  10888. image.style.left = Math.floor((control.width - 17) / 2) + 'px';
  10889. image.style.top = Math.floor((control.height - 17) / 2) + 'px';
  10890. };
  10891. }
  10892.  
  10893. controls.list = {};
  10894.  
  10895. //#region Elements
  10896.  
  10897. controls.createDiv = function(control, className)
  10898. {
  10899. className = className || '';
  10900. if (className != '') className = ' ' + theme.className + className;
  10901.  
  10902. var element = document.createElement('div');
  10903. element.style.position = 'absolute';
  10904. element.className = theme.className + ' ' + theme.classDiv + ' ' + control.className + className;
  10905.  
  10906. control.element.append(element);
  10907.  
  10908. return element;
  10909. };
  10910.  
  10911. controls.createSelect = function(control, changeHandler)
  10912. {
  10913. /// <param name="control" type="Control"></param>
  10914.  
  10915. var element = document.createElement('select');
  10916. element.style.position = 'absolute';
  10917. element.className = theme.className + ' ' + theme.classSelect + ' ' + control.className;
  10918.  
  10919. control.element.append(element);
  10920.  
  10921. $(element).change(function()
  10922. {
  10923. changeHandler(element.value);
  10924. });
  10925.  
  10926. return element;
  10927. };
  10928.  
  10929. controls.updateSelect = function(control, element, data, value)
  10930. {
  10931. /// <param name="control" type="Control"></param>
  10932. /// <param name="element" type="HTMLSelectElement"></param>
  10933. /// <param name="data" type="Array" elementType="DataList"></param>
  10934. /// <param name="value" type="String"></param>
  10935.  
  10936. element.innerHTML = '';
  10937.  
  10938. for (var item in data)
  10939. {
  10940. if (!data.hasOwnProperty(item)) continue;
  10941.  
  10942. var option = document.createElement('option');
  10943. option.innerHTML = controls.getText(data[item].text);
  10944. option.value = data[item].id;
  10945. option.className = theme.className + ' ' + theme.classOption + ' ' + control.className;
  10946.  
  10947. if (data[item].hidden != null)
  10948. {
  10949. option.style.display = 'none';
  10950. option.style.visibility = 'hidden';
  10951. }
  10952.  
  10953. element.appendChild(option);
  10954. }
  10955.  
  10956. element.value = value;
  10957. };
  10958.  
  10959. //#endregion
  10960. };
  10961.  
  10962. var container = (function()
  10963. {
  10964. function Container()
  10965. {
  10966. this.name = 'container';
  10967. controls.list.container = this;
  10968.  
  10969. this.element = document.createElement('div');
  10970. this.element.className = theme.className + ' ' + theme.className + 'container';
  10971. this.elementStyle = this.element.style;
  10972. this.elementStyle.cssText =
  10973. 'position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; ' +
  10974. 'background: black; overflow: hidden; margin: 0; padding: 0;';
  10975. document.body.appendChild(this.element);
  10976. this.element = $(this.element);
  10977.  
  10978. this.childs = [];
  10979.  
  10980. this.left = 0;
  10981. this.top = 0;
  10982.  
  10983. this.calculatePadding();
  10984. this.locate();
  10985.  
  10986. this.resize = function()
  10987. {
  10988. if (main.isNotLoaded) return;
  10989.  
  10990. this.width = this.element.width();
  10991. this.height = this.element.height();
  10992.  
  10993. for (var i = 0; i < this.childs.length; i++)
  10994. if (this.childs[i].visible || controls.notIgnoreHiddenOnResize) this.childs[i].resize();
  10995.  
  10996. if (customization.visible || controls.notIgnoreHiddenOnResize) customization.resize();
  10997. };
  10998.  
  10999. this.resize();
  11000. };
  11001.  
  11002. Container.prototype = Control.prototype;
  11003.  
  11004. var container = new Container(), mode = false;
  11005.  
  11006. $(window).resize(function()
  11007. {
  11008. if (mode) return;
  11009.  
  11010. mode = true;
  11011.  
  11012. setTimeout(function()
  11013. {
  11014. container.resize();
  11015. mode = false;
  11016. }, 20);
  11017. });
  11018.  
  11019. return container;
  11020. })();
  11021.  
  11022. var settingWindow = new Control('settingWindow', 100, 32, 32, true, true).hide();
  11023.  
  11024. (function()
  11025. {
  11026. settingWindow.elementStyle.overflow = 'auto';
  11027. settingWindow.elementStyle.padding = '0';
  11028. settingWindow.changeWidthIsDisabled = true;
  11029. settingWindow.changeHeightIsDisabled = true;
  11030. settingWindow.baseShowFunction = settingWindow.show;
  11031.  
  11032. var top = theme.padding;
  11033. var labelWidth = 250;
  11034. var elementWidth = 200;
  11035. var elementHeight = 20;
  11036. var firstColumn = theme.padding;
  11037. var secondColumn = labelWidth + theme.padding + theme.padding;
  11038.  
  11039. var elementsContainer = document.createElement('div');
  11040. elementsContainer.style.cssText = 'position: static; overflow: hidden; display: block; background none; border: none;';
  11041. elementsContainer.style.margin = theme.padding + 'px';
  11042. elementsContainer.className = theme.className + ' ' + theme.className + settingWindow.name;
  11043.  
  11044. settingWindow.element.append(elementsContainer);
  11045.  
  11046. //#region Elements
  11047.  
  11048. function nextRow()
  11049. {
  11050. top += theme.padding + elementHeight;
  11051. }
  11052.  
  11053. function addLabel(text)
  11054. {
  11055. var element = document.createElement('div');
  11056. element.className = theme.className + ' ' + theme.classDiv + settingWindow.className;
  11057. element.innerHTML = controls.getText(text);
  11058. element.style.cssText =
  11059. 'position: absolute; left: ' + firstColumn + 'px; top: ' + top + 'px; width: ' + (labelWidth - 10) + 'px; height: 20px;' +
  11060. 'line-height: 20px; overflow: hidden; padding: 0px 5px';
  11061.  
  11062. elementsContainer.appendChild(element);
  11063. }
  11064.  
  11065. settingWindow.addInscription = function(text)
  11066. {
  11067. var element = document.createElement('div');
  11068. element.className = theme.className + ' ' + theme.classDiv + settingWindow.className;
  11069. element.innerHTML = controls.getText(text);
  11070. element.style.cssText =
  11071. 'position: absolute; background: none; border: none; left: ' + firstColumn + 'px; top: ' + top + 'px; height: 20px;' +
  11072. 'line-height: 20px; overflow: hidden; padding: 0px 5px';
  11073. element.style.width = (labelWidth + elementWidth + theme.padding - 10) + 'px';
  11074.  
  11075. elementsContainer.appendChild(element);
  11076. nextRow();
  11077.  
  11078. return element;
  11079. };
  11080.  
  11081. settingWindow.addLink = function(text, url)
  11082. {
  11083. var element = document.createElement('a');
  11084. element.target = '_newBlank';
  11085. element.href = url;
  11086. element.innerHTML = controls.getText(text);
  11087. element.className = theme.className + ' ' + theme.classLink + settingWindow.className;
  11088. element.style.cssText = 'position: absolute; left: ' + firstColumn + 'px; top: ' + top + 'px; height: 20px; line-height: 20px;';
  11089. element.style.width = (labelWidth + elementWidth + theme.padding) + 'px';
  11090.  
  11091. elementsContainer.appendChild(element);
  11092. nextRow();
  11093.  
  11094. return element;
  11095. };
  11096.  
  11097. settingWindow.addButton = function(text, clickHandler)
  11098. {
  11099. var element = document.createElement('input');
  11100. element.type = 'button';
  11101. element.className = theme.className + ' ' + theme.classButton + settingWindow.className;
  11102. element.style.cssText = 'position: absolute; left: ' + firstColumn + 'px; top: ' + top + 'px; height: 20px;';
  11103. element.style.width = (labelWidth + elementWidth + theme.padding) + 'px';
  11104. element.value = controls.getText(text);
  11105.  
  11106. elementsContainer.appendChild(element);
  11107. nextRow();
  11108.  
  11109. $(element).mouseup(clickHandler);
  11110.  
  11111. return element;
  11112. };
  11113.  
  11114. settingWindow.addSelect = function(text, data, value, changeHandler)
  11115. {
  11116. addLabel(text);
  11117.  
  11118. var element = document.createElement('select');
  11119. element.className = theme.className + ' ' + theme.classSelect + settingWindow.className;
  11120. element.style.cssText = 'position: absolute; left: ' + secondColumn + 'px; top: ' + top + 'px; width: ' + elementWidth + 'px; height: 20px;';
  11121.  
  11122. for (var item in data)
  11123. {
  11124. if (!data.hasOwnProperty(item)) continue;
  11125.  
  11126. var option = document.createElement('option');
  11127. option.innerHTML = controls.getText(data[item].text);
  11128. option.value = data[item].id;
  11129. option.className = theme.classOption + settingWindow.className;
  11130.  
  11131. element.appendChild(option);
  11132. }
  11133.  
  11134. element.value = value;
  11135.  
  11136. $(element).change(function() { changeHandler(element.value); });
  11137.  
  11138. elementsContainer.appendChild(element);
  11139. nextRow();
  11140.  
  11141. return element;
  11142. };
  11143.  
  11144. settingWindow.addInput = function(text, value, changeHandler)
  11145. {
  11146. addLabel(text);
  11147.  
  11148. var element = document.createElement('input');
  11149. element.type = 'text';
  11150. element.className = theme.className + ' ' + theme.classInput + settingWindow.className;
  11151. element.value = value;
  11152. element.style.cssText = 'position: absolute; left: ' + secondColumn + 'px; top: ' + top + 'px; width: ' + elementWidth + 'px; height: 20px;';
  11153.  
  11154. $(element)
  11155. .keyup(function(e)
  11156. {
  11157. if (e.which == 13) changeHandler(element.value);
  11158. })
  11159. .focusout(function()
  11160. {
  11161. changeHandler(element.value);
  11162. });
  11163.  
  11164. elementsContainer.appendChild(element);
  11165. nextRow();
  11166.  
  11167. return element;
  11168. };
  11169.  
  11170. settingWindow.addDelimiter = function()
  11171. {
  11172. var element = document.createElement('div');
  11173. element.className = theme.className + ' ' + theme.classDelimiter + settingWindow.className;
  11174. element.style.cssText = 'position: absolute; left: ' + firstColumn + 'px; top: ' + top + 'px; height: 1px;';
  11175. element.style.width = (labelWidth + elementWidth + theme.padding) + 'px';
  11176.  
  11177. elementsContainer.appendChild(element);
  11178. top += theme.padding;
  11179.  
  11180. return element;
  11181. };
  11182.  
  11183. //#region Slider
  11184.  
  11185. var notActive = true;
  11186.  
  11187. function activate()
  11188. {
  11189. notActive = false;
  11190. }
  11191.  
  11192. function deactivate()
  11193. {
  11194. notActive = true;
  11195. }
  11196.  
  11197. function addSlider(text, minValue, maxValue, step, value, data, changeHandler)
  11198. {
  11199. addLabel(text);
  11200.  
  11201. var background = document.createElement('div');
  11202. background.className = theme.className + ' ' + theme.classDiv + ' ' + theme.classBackground + settingWindow.className;
  11203. background.style.cssText =
  11204. '-webkit-touch-callout: none; -moz-user-select: none; -ms-user-select: none; -webkit-user-select: none; -khtml-user-select: none; user-select: none;' +
  11205. 'position: absolute; left: ' + secondColumn + 'px; top: ' + top + 'px; width: ' + elementWidth + 'px; height: 20px;';
  11206.  
  11207. var track = document.createElement('div');
  11208. track.className = theme.className + ' ' + theme.classDiv + ' ' + theme.classTrack + settingWindow.className;
  11209. track.style.cssText = 'position: absolute; height: 20px;';
  11210. background.appendChild(track);
  11211.  
  11212. var label = document.createElement('div');
  11213. label.className = theme.className + ' ' + theme.classDiv + ' ' + theme.classText + settingWindow.className;
  11214. label.innerHTML = (data != null ? data[value] : value) + (text.unit || '');
  11215. label.style.cssText =
  11216. 'position: absolute; left: 0px; top: 0px; width: ' + elementWidth + 'px; height: 20px; z-index: 1;' +
  11217. 'line-height: 20px; overflow: hidden; text-align: center; vertical-align: middle';
  11218. background.appendChild(label);
  11219.  
  11220. elementsContainer.appendChild(background);
  11221. background = $(background);
  11222.  
  11223. var prevValue = value;
  11224. var trackLeft = (background.outerWidth() - elementWidth) / 2;
  11225. var stepWidth = (elementWidth + theme.controlsBordersSize + trackLeft) / (maxValue - minValue + 1);
  11226. var trackWidth = 0;
  11227.  
  11228. if (stepWidth < 20)
  11229. {
  11230. trackWidth = 20;
  11231. stepWidth = (elementWidth + theme.controlsBordersSize + trackLeft - trackWidth) / (maxValue - minValue);
  11232. track.style.width = trackWidth + 'px';
  11233. }
  11234. else
  11235. {
  11236. track.style.width = Math.floor(stepWidth) + 'px';
  11237. }
  11238.  
  11239. track.style.left = Math.floor((value - minValue) * stepWidth - trackLeft - theme.controlsBordersSize) + 'px';
  11240. track.style.top = ((20 - background.outerHeight()) / 2 - theme.controlsBordersSize) + 'px';
  11241.  
  11242. background
  11243. .mousedown(activate)
  11244. .mousemove(function(e)
  11245. {
  11246. if (notActive) return;
  11247.  
  11248. var x = e.pageX - background.offset().left - trackWidth / 2;
  11249.  
  11250. value = Math.floor((x / stepWidth + minValue) / step) * step;
  11251.  
  11252. if (value < minValue)
  11253. {
  11254. value = minValue;
  11255. }
  11256. else if (value > maxValue)
  11257. {
  11258. value = maxValue;
  11259. }
  11260.  
  11261. if (value == prevValue) return;
  11262.  
  11263. prevValue = value;
  11264. var totalValue = (data != null ? data[value] : value);
  11265.  
  11266. track.style.left = Math.floor((value - minValue) * stepWidth - trackLeft - theme.controlsBordersSize) + 'px';
  11267.  
  11268. label.innerHTML = totalValue + (text.unit || '');
  11269. changeHandler(totalValue);
  11270. });
  11271.  
  11272. nextRow();
  11273.  
  11274. return label;
  11275. }
  11276.  
  11277. settingWindow.addTrackBar = function(text, data, value, changeHandler)
  11278. {
  11279. return addSlider(text, 0, data.length, 1, data.indexOf(value), data, changeHandler);
  11280. };
  11281.  
  11282. settingWindow.addSlider = function(text, minValue, maxValue, step, value, changeHandler)
  11283. {
  11284. return addSlider(text, minValue, maxValue, step, value, null, changeHandler);
  11285. };
  11286.  
  11287. //#endregion
  11288.  
  11289. //#region Check
  11290.  
  11291. function setCheckStyle(element, value)
  11292. {
  11293. if (value)
  11294. {
  11295. element[0].value = controls.getText(language.current.on);
  11296. element.removeClass(theme.classOff);
  11297. element.addClass(theme.classOn);
  11298. }
  11299. else
  11300. {
  11301. element[0].value = controls.getText(language.current.off);
  11302. element.removeClass(theme.classOn);
  11303. element.addClass(theme.classOff);
  11304. }
  11305. }
  11306.  
  11307. settingWindow.addCheck = function(text, value, changeHandler, valueReplace)
  11308. {
  11309. addLabel(text);
  11310.  
  11311. var element = document.createElement('input');
  11312. element.type = 'button';
  11313. element.className = theme.className + ' ' + theme.classButton + settingWindow.className;
  11314. element.style.cssText = 'position: absolute; left: ' + secondColumn + 'px; top: ' + top + 'px; width: ' + elementWidth + 'px; height: 20px;';
  11315.  
  11316. elementsContainer.appendChild(element);
  11317. element = $(element);
  11318.  
  11319. setCheckStyle(element, value);
  11320. if (valueReplace != null) element[0].value = controls.getText(valueReplace);
  11321.  
  11322. element
  11323. .mouseup(function()
  11324. {
  11325. value = !value;
  11326. setCheckStyle(element, value);
  11327.  
  11328. var result = changeHandler(value);
  11329. if (typeof result != 'string') return;
  11330.  
  11331. element[0].value = controls.getText(result);
  11332. });
  11333.  
  11334. nextRow();
  11335.  
  11336. return element[0];
  11337. };
  11338.  
  11339. //#endregion
  11340.  
  11341. settingWindow.addSharedElements = function(control, changeVisibility, changeOpacity, changeBackgroundAndBorders, showDelimiter)
  11342. {
  11343. if (changeVisibility == null || changeVisibility)
  11344. {
  11345. settingWindow.addButton(language.current.hide, function()
  11346. {
  11347. control.hide();
  11348. customization.hide();
  11349. });
  11350. }
  11351.  
  11352. if (changeOpacity == null || changeOpacity)
  11353. {
  11354. settingWindow.addSlider(language.current.opacity, 10, 100, 1, Math.floor((control.opacity || 1) * 100), function(value)
  11355. {
  11356. control.setOpacity(value / 100);
  11357. });
  11358. }
  11359.  
  11360. if (changeBackgroundAndBorders == null || changeBackgroundAndBorders)
  11361. {
  11362. settingWindow.addCheck(language.current.background, (control.element[0].style.background != 'none'), function(value)
  11363. {
  11364. control.element[0].style.background = (value ? '' : 'none');
  11365. });
  11366.  
  11367. settingWindow.addCheck(language.current.borders, !control.element.hasClass(theme.classNoBorders), function(value)
  11368. {
  11369. if (value)
  11370. {
  11371. control.element.removeClass(theme.classNoBorders);
  11372. }
  11373. else
  11374. {
  11375. control.element.addClass(theme.classNoBorders);
  11376. }
  11377. });
  11378. }
  11379.  
  11380. if (showDelimiter == null || showDelimiter) settingWindow.addDelimiter();
  11381. }
  11382.  
  11383. //#endregion
  11384.  
  11385. settingWindow.element
  11386. .mouseleave(deactivate)
  11387. .mouseup(deactivate)
  11388.  
  11389. settingWindow.show = function(control)
  11390. {
  11391. /// <param name="control" type="Control"></param>
  11392.  
  11393. if (control == null) return;
  11394.  
  11395. $(elementsContainer).empty();
  11396. top = theme.padding;
  11397.  
  11398. control.addSettings();
  11399.  
  11400. if (top == theme.padding) return;
  11401.  
  11402. var style = settingWindow.element[0].style;
  11403. var containerWidth = secondColumn + elementWidth;
  11404. var containerHeight = top;
  11405.  
  11406. elementsContainer.style.width = (containerWidth - theme.padding2) + 'px';
  11407. elementsContainer.style.height = (containerHeight - theme.padding2) + 'px';
  11408.  
  11409. if (containerHeight > 600)
  11410. {
  11411. containerHeight = 600;
  11412. containerWidth += 20;
  11413. }
  11414.  
  11415. settingWindow.offsetWidth = containerWidth + theme.padding;
  11416. settingWindow.offsetHeight = containerHeight + theme.current.controlsBordersSize + theme.current.controlsBordersSize;
  11417.  
  11418. function checkPosition(position)
  11419. {
  11420. return (position.left >= container.left &&
  11421. position.left + containerWidth <= container.width &&
  11422. position.top >= container.top &&
  11423. position.top + containerHeight <= container.height);
  11424. }
  11425.  
  11426. function findPosition()
  11427. {
  11428. var controlWidth = control.width;
  11429. var controlHeight = control.height;
  11430.  
  11431. // bottom
  11432. var position =
  11433. {
  11434. left: control.left,
  11435. top: control.top + controlHeight
  11436. };
  11437.  
  11438. if (position.left + containerWidth > container.width) position.left = control.left + controlWidth - containerWidth;
  11439. if (checkPosition(position)) return position;
  11440.  
  11441. // right
  11442. position.left = control.left + controlWidth;
  11443. position.top = control.top;
  11444.  
  11445. if (position.top + containerHeight > container.height) position.top = control.top + controlHeight - containerHeight;
  11446. if (checkPosition(position)) return position;
  11447.  
  11448. // top
  11449. position.left = control.left;
  11450. position.top = control.top - containerHeight;
  11451.  
  11452. if (position.left + containerWidth > container.width) position.left = control.left + controlWidth - containerWidth;
  11453. if (checkPosition(position)) return position;
  11454.  
  11455. // left
  11456. position.left = control.left - containerWidth;
  11457. position.top = control.top;
  11458.  
  11459. if (position.top + containerHeight > container.height) position.top = control.top + controlHeight - containerHeight;
  11460. if (checkPosition(position)) return position;
  11461.  
  11462. // inner
  11463. position.left = control.left + theme.padding;
  11464. position.top = control.top + theme.padding;
  11465.  
  11466. return position;
  11467. }
  11468.  
  11469. settingWindow.resize = function()
  11470. {
  11471. var position = findPosition();
  11472.  
  11473. settingWindow.offsetLeft = position.left - container.left;
  11474. settingWindow.offsetTop = position.top - container.top;
  11475.  
  11476. settingWindow.baseResize();
  11477. };
  11478.  
  11479. settingWindow.update = function()
  11480. {
  11481. settingWindow.hide();
  11482. settingWindow.show(control);
  11483. };
  11484.  
  11485. settingWindow.baseShowFunction();
  11486. };
  11487.  
  11488. settingWindow.hide = function()
  11489. {
  11490. this.visible = false;
  11491. this.element[0].style.display = 'none';
  11492.  
  11493. return this;
  11494. };
  11495. })();
  11496.  
  11497. var customization = new function()
  11498. {
  11499. function offEvent() { return false; }
  11500.  
  11501. var customization = this;
  11502. customization.name = 'customization';
  11503. customization.visible = false;
  11504. customization.resize = function() { };
  11505.  
  11506. /// <var type="Control"></var>
  11507. var selectedControl = null;
  11508. var fixedSelect = false;
  11509. var notFirstOpen = false;
  11510.  
  11511. var element = document.createElement('div');
  11512. element.style.cssText = 'position: absolute; overflow: hidden; display: none; z-index: 99;';
  11513. element.className = theme.className + ' ' + theme.className + customization.name;
  11514.  
  11515. var horizontalDockMarker = document.createElement('div');
  11516. horizontalDockMarker.style.cssText = 'position: absolute; display: none; background: red; border: none; left: 0px; width: 100%; top: 50%; height: 1px; z-index: 99;';
  11517. horizontalDockMarker.className = theme.className + ' ' + theme.className + customization.name;
  11518. element.appendChild(horizontalDockMarker);
  11519.  
  11520. var verticalDockMarker = document.createElement('div');
  11521. verticalDockMarker.style.cssText = 'position: absolute; display: none; background: red; border: none; left: 50%; width: 1px; top: 0px; height: 100%; z-index: 99;';
  11522. verticalDockMarker.className = theme.className + ' ' + theme.className + customization.name;
  11523. element.appendChild(verticalDockMarker);
  11524.  
  11525. var background = document.createElement('div');
  11526. background.style.cssText = 'position: absolute; border: none; padding: 0; margin: 0; left: 0px; top: 0px; width: 100%; height: 100%; overflow: hidden; display: none; z-index: 99; display: none; background: rgba(0, 0, 0, 0.30);';
  11527. background.className = theme.className + ' ' + theme.className + customization.name;
  11528.  
  11529. container.element.append(element);
  11530. container.element.append(background);
  11531.  
  11532. function showPositionInfoPopup()
  11533. {
  11534. if (selectedControl == null) return;
  11535.  
  11536. var message = '&nbsp;' +
  11537. language.current.left + (Math.floor(selectedControl.left / 8) * 8) + '; ' +
  11538. language.current.top + (Math.floor(selectedControl.top / 8) * 8) + '; ' +
  11539. language.current.width + (Math.floor(selectedControl.width / 8) * 8) + '; ' +
  11540. language.current.height + (Math.floor(selectedControl.height / 8) * 8) + '&nbsp;';
  11541.  
  11542. informationPopup.show(message, selectedControl);
  11543. }
  11544.  
  11545. customization.showHelp = function()
  11546. {
  11547. informationPopup.show(language.current.customizeHelp, -1, -1, 30);
  11548. };
  11549.  
  11550. function autoShowHelp()
  11551. {
  11552. if (notFirstOpen) return
  11553.  
  11554. settingWindowDockControl = selectedControl = options;
  11555. fixedSelect = true;
  11556. settingWindow.show(options);
  11557. backgroundShow();
  11558. customization.showHelp();
  11559. notFirstOpen = true;
  11560. }
  11561.  
  11562. //#region Background
  11563.  
  11564. function backgroundShow()
  11565. {
  11566. background.style.display = 'block';
  11567. background.appendChild(element);
  11568. }
  11569.  
  11570. function backgroundHide()
  11571. {
  11572. container.element.append(element);
  11573. background.style.display = 'none';
  11574. }
  11575.  
  11576. //#endregion
  11577.  
  11578. //#region Dock controls
  11579.  
  11580. var dockSize = 16;
  11581. /// <var type="Control"></var>
  11582. var dockControl = null;
  11583.  
  11584. var horizontalControlDockMarker = document.createElement('div');
  11585. horizontalControlDockMarker.style.cssText = 'position: absolute; display: block; background: #a7ac3b; border: none; left: 0px; width: 100%; top: 50%; height: 1px; z-index: 99;';
  11586. horizontalControlDockMarker.className = theme.className + customization.name;
  11587.  
  11588. var verticalControlDockMarker = document.createElement('div');
  11589. verticalControlDockMarker.style.cssText = 'position: absolute; display: block; background: #a7ac3b; border: none; left: 50%; width: 1px; top: 0px; height: 100%; z-index: 99;';
  11590. verticalControlDockMarker.className = theme.className + customization.name;
  11591.  
  11592. function clearDockData(control)
  11593. {
  11594. /// <param name="control" type="Control"></param>
  11595.  
  11596. horizontalControlDockMarker.style.background = '#a7ac3b';
  11597. verticalControlDockMarker.style.background = '#a7ac3b';
  11598. horizontalDockMarker.style.display = 'none';
  11599. verticalDockMarker.style.display = 'none';
  11600. element.style.border = '';
  11601. control.elementStyle.border = '';
  11602. }
  11603.  
  11604. function showDockControl(control)
  11605. {
  11606. /// <param name="control" type="Control"></param>
  11607.  
  11608. if (dockControl == control) return true;
  11609. if (dockControl != null) hideDockControl();
  11610.  
  11611. dockControl = control;
  11612.  
  11613. control.element.addClass(theme.classDock);
  11614. control.element.append(horizontalControlDockMarker);
  11615. control.element.append(verticalControlDockMarker);
  11616.  
  11617. horizontalControlDockMarker.style.display = 'block';
  11618. verticalControlDockMarker.style.display = 'block';
  11619. }
  11620.  
  11621. function hideDockControl()
  11622. {
  11623. if (dockControl == null) return;
  11624.  
  11625. clearDockData(dockControl);
  11626.  
  11627. horizontalControlDockMarker.style.display = 'none';
  11628. verticalControlDockMarker.style.display = 'none';
  11629.  
  11630. dockControl.element.removeClass(theme.classDock);
  11631. dockControl = null;
  11632. }
  11633.  
  11634. function checkHorizontalDockForControl(control, e)
  11635. {
  11636. /// <param name="control" type="Control"></param>
  11637. /// <param name="e" type="MouseEvent"></param>
  11638.  
  11639. var selectedControlRight = selectedControl.left + selectedControl.width;
  11640. var controlCenter = control.left + control.width / 2;
  11641. var controlRight = control.left + control.width;
  11642.  
  11643. if (selectedControl.left >= control.left && selectedControl.left < control.left + dockSize)
  11644. {
  11645. element.style.borderLeft = 'solid 1px red';
  11646. control.elementStyle.borderLeft = 'solid 1px red';
  11647. selectedControl.dockLeft = true;
  11648. }
  11649. else if (selectedControlRight > controlRight - dockSize && selectedControlRight <= controlRight)
  11650. {
  11651. element.style.borderRight = 'solid 1px red';
  11652. control.elementStyle.borderRight = 'solid 1px red';
  11653. selectedControl.dockRight = true;
  11654. }
  11655. else if (e.pageX > controlCenter - dockSize && e.pageX < controlCenter + dockSize)
  11656. {
  11657. verticalDockMarker.style.display = 'block';
  11658. verticalControlDockMarker.style.background = 'red';
  11659. selectedControl.dockLeft = true;
  11660. selectedControl.dockRight = true;
  11661. }
  11662. else if (selectedControl.left > controlRight && selectedControl.left < controlRight + dockSize)
  11663. {
  11664. element.style.borderLeft = 'solid 1px red';
  11665. control.elementStyle.borderRight = 'solid 1px red';
  11666. selectedControl.dockRight = true;
  11667. selectedControl.dockOuterHorizontal = true;
  11668. }
  11669. else if (selectedControlRight > control.left - dockSize && selectedControlRight < control.left)
  11670. {
  11671. element.style.borderRight = 'solid 1px red';
  11672. control.elementStyle.borderLeft = 'solid 1px red';
  11673. selectedControl.dockLeft = true;
  11674. selectedControl.dockOuterHorizontal = true;
  11675. }
  11676. }
  11677.  
  11678. function checkVerticalDockForControl(control, e)
  11679. {
  11680. /// <param name="control" type="Control"></param>
  11681. /// <param name="e" type="MouseEvent"></param>
  11682.  
  11683. var selectedControlBottom = selectedControl.top + selectedControl.height;
  11684. var controlMiddle = control.top + control.height / 2;
  11685. var controlBottom = control.top + control.height;
  11686.  
  11687. if (selectedControl.top >= control.top && selectedControl.top < control.top + dockSize)
  11688. {
  11689. element.style.borderTop = 'solid 1px red';
  11690. control.elementStyle.borderTop = 'solid 1px red';
  11691. selectedControl.dockTop = true;
  11692. }
  11693. else if (selectedControlBottom > controlBottom - dockSize && selectedControlBottom <= controlBottom)
  11694. {
  11695. element.style.borderBottom = 'solid 1px red';
  11696. control.elementStyle.borderBottom = 'solid 1px red';
  11697. selectedControl.dockBottom = true;
  11698. }
  11699. else if (e.pageY > controlMiddle - dockSize && e.pageY < controlMiddle + dockSize)
  11700. {
  11701. horizontalDockMarker.style.display = 'block';
  11702. horizontalControlDockMarker.style.background = 'red';
  11703. selectedControl.dockTop = true;
  11704. selectedControl.dockBottom = true;
  11705. }
  11706. else if (selectedControl.top > controlBottom && selectedControl.top < controlBottom + dockSize)
  11707. {
  11708. element.style.borderTop = 'solid 1px red';
  11709. control.elementStyle.borderBottom = 'solid 1px red';
  11710. selectedControl.dockBottom = true;
  11711. selectedControl.dockOuterVertical = true;
  11712. }
  11713. else if (selectedControlBottom > control.top - dockSize && selectedControlBottom < control.top)
  11714. {
  11715. element.style.borderBottom = 'solid 1px red';
  11716. control.elementStyle.borderTop = 'solid 1px red';
  11717. selectedControl.dockTop = true;
  11718. selectedControl.dockOuterVertical = true;
  11719. }
  11720. }
  11721.  
  11722. function checkHorizontalDockForSmallControls(control, e)
  11723. {
  11724. /// <param name="control" type="Control"></param>
  11725. /// <param name="e" type="MouseEvent"></param>
  11726.  
  11727. var selectedControlRight = selectedControl.left + selectedControl.width;
  11728. var controlCenter = control.left + control.width / 2;
  11729. var controlRight = control.left + control.width;
  11730. var dockSizeHalf = dockSize / 2;
  11731.  
  11732. if (e.pageX >= controlCenter - dockSizeHalf && e.pageX <= controlCenter + dockSizeHalf)
  11733. {
  11734. verticalDockMarker.style.display = 'block';
  11735. verticalControlDockMarker.style.background = 'red';
  11736. selectedControl.dockLeft = true;
  11737. selectedControl.dockRight = true;
  11738. }
  11739. else if (selectedControl.left >= controlCenter - dockSizeHalf && selectedControl.left < controlRight + dockSize)
  11740. {
  11741. element.style.borderLeft = 'solid 1px red';
  11742. control.elementStyle.borderRight = 'solid 1px red';
  11743. selectedControl.dockRight = true;
  11744. selectedControl.dockOuterHorizontal = true;
  11745. }
  11746. else if (selectedControlRight > control.left - dockSize && selectedControlRight <= controlCenter + dockSizeHalf)
  11747. {
  11748. element.style.borderRight = 'solid 1px red';
  11749. control.elementStyle.borderLeft = 'solid 1px red';
  11750. selectedControl.dockLeft = true;
  11751. selectedControl.dockOuterHorizontal = true;
  11752. }
  11753. }
  11754.  
  11755. function checkVerticalDockForSmallControls(control, e)
  11756. {
  11757. /// <param name="control" type="Control"></param>
  11758. /// <param name="e" type="MouseEvent"></param>
  11759.  
  11760. var selectedControlBottom = selectedControl.top + selectedControl.height;
  11761. var controlMiddle = control.top + control.height / 2;
  11762. var controlBottom = control.top + control.height;
  11763. var dockSizeHalf = dockSize / 2;
  11764.  
  11765. if (e.pageY >= controlMiddle - dockSizeHalf && e.pageY <= controlMiddle + dockSizeHalf)
  11766. {
  11767. horizontalDockMarker.style.display = 'block';
  11768. horizontalControlDockMarker.style.background = 'red';
  11769. selectedControl.dockTop = true;
  11770. selectedControl.dockBottom = true;
  11771. }
  11772. else if (selectedControl.top >= controlMiddle - dockSizeHalf && selectedControl.top < controlBottom + dockSize)
  11773. {
  11774. element.style.borderTop = 'solid 1px red';
  11775. control.elementStyle.borderBottom = 'solid 1px red';
  11776. selectedControl.dockBottom = true;
  11777. selectedControl.dockOuterVertical = true;
  11778. }
  11779. else if (selectedControlBottom > control.top - dockSize && selectedControlBottom <= controlMiddle + dockSizeHalf)
  11780. {
  11781. element.style.borderBottom = 'solid 1px red';
  11782. control.elementStyle.borderTop = 'solid 1px red';
  11783. selectedControl.dockTop = true;
  11784. selectedControl.dockOuterVertical = true;
  11785. }
  11786. }
  11787.  
  11788. function checkDock(control, e)
  11789. {
  11790. /// <param name="control" type="Control"></param>
  11791. /// <param name="e" type="MouseEvent"></param>
  11792.  
  11793. clearDockData(control);
  11794.  
  11795. checkHorizontalDockForControl(control, e);
  11796. checkVerticalDockForControl(control, e);
  11797.  
  11798. if (selectedControl.dockOuterVertical || selectedControl.dockOuterHorizontal) return;
  11799.  
  11800. if (control.width <= 32) checkHorizontalDockForSmallControls(control, e);
  11801. if (control.height <= 32) checkVerticalDockForSmallControls(control, e);
  11802.  
  11803. if (!(selectedControl.dockBottom && selectedControl.dockTop || selectedControl.dockLeft && selectedControl.dockRight)) return;
  11804.  
  11805. if (selectedControl.changeWidthIsDisabled || selectedControl.changeHeightIsDisabled || control.width <= 32 || control.height <= 32)
  11806. {
  11807. horizontalDockMarker.style.display = 'none';
  11808. horizontalControlDockMarker.style.background = '#a7ac3b';
  11809. element.style.borderTop = 'solid 1px red';
  11810. control.elementStyle.borderTop = 'solid 1px red';
  11811. element.style.borderBottom = '';
  11812. control.elementStyle.borderBottom = '';
  11813.  
  11814. selectedControl.dockTop = true;
  11815. selectedControl.dockLeft = true;
  11816. selectedControl.dockRight = true;
  11817. selectedControl.dockBottom = false;
  11818. selectedControl.dockOuterHorizontal = false;
  11819. selectedControl.dockOuterVertical = true;
  11820. }
  11821. }
  11822.  
  11823. function findDropControl(parent, e)
  11824. {
  11825. /// <param name="parent" type="Control"></param>
  11826. /// <param name="e" type="MouseEvent"></param>
  11827.  
  11828. for (var i = 0; i < parent.childs.length; i++)
  11829. {
  11830. /// <var type="Control"></var>
  11831. var control = parent.childs[i];
  11832.  
  11833. if (control == selectedControl ||
  11834. control == customization ||
  11835. control == settingWindow ||
  11836. control == informationPopup ||
  11837. !control.visible) continue;
  11838.  
  11839. if (findDropControl(control, e)) return true;
  11840. }
  11841.  
  11842. var selectedControlRight = selectedControl.left + selectedControl.width;
  11843. var selectedControlBottom = selectedControl.top + selectedControl.height;
  11844. var parentRight = parent.left + parent.width;
  11845. var parentBottom = parent.top + parent.height;
  11846.  
  11847. if (selectedControl.left >= parentRight + dockSize ||
  11848. selectedControl.top >= parentBottom + dockSize ||
  11849. selectedControlRight <= parent.left - dockSize ||
  11850. selectedControlBottom <= parent.top - dockSize) return false;
  11851.  
  11852. showDockControl(parent);
  11853. checkDock(parent, e);
  11854.  
  11855. return true;
  11856. }
  11857.  
  11858. //#endregion
  11859.  
  11860. //#region Move/resize controls
  11861.  
  11862. /// <var type="Control"></var>
  11863. var settingWindowDockControl = null;
  11864.  
  11865. var data =
  11866. {
  11867. resizeMode: false,
  11868. moved: false,
  11869. mouseX: 0,
  11870. mouseY: 0,
  11871. mode: false
  11872. };;
  11873.  
  11874. $(element).mousedown(function(e)
  11875. {
  11876. if (selectedControl == null) return;
  11877.  
  11878. fixedSelect = true;
  11879.  
  11880. data =
  11881. {
  11882. resizeMode: (e.which == 3 || e.ctrlKey),
  11883. moved: false,
  11884. mouseX: e.pageX,
  11885. mouseY: e.pageY,
  11886. mode: false
  11887. };
  11888.  
  11889. container.element.on({ mousemove: mousemove, mouseup: mouseup, mouseleave: customization.hide });
  11890. });
  11891.  
  11892. function undock(e)
  11893. {
  11894. if (selectedControl.parent == container && selectControl.dockNone) return;
  11895.  
  11896. selectedControl.setParent().dock();
  11897.  
  11898. if (data.mouseX > selectedControl.offsetLeft + selectedControl.offsetWidth)
  11899. {
  11900. selectedControl.offsetLeft = e.pageX - selectedControl.offsetWidth / 2;
  11901. }
  11902.  
  11903. if (data.mouseY > selectedControl.offsetTop + selectedControl.offsetHeight)
  11904. {
  11905. selectedControl.offsetTop = e.pageY - selectedControl.offsetHeight / 2;
  11906. }
  11907. }
  11908.  
  11909. function move(e)
  11910. {
  11911. var offsetLeft = Math.floor(e.pageX - data.mouseX);
  11912. var offsetTop = Math.floor(e.pageY - data.mouseY);
  11913.  
  11914. selectedControl.offsetLeft += offsetLeft;
  11915. selectedControl.offsetTop += offsetTop;
  11916.  
  11917. selectedControl.calculatePosition();
  11918.  
  11919. offsetLeft = selectedControl.offsetLeft - selectedControl.left;
  11920. offsetTop = selectedControl.offsetTop - selectedControl.top;
  11921.  
  11922. if (selectedControl.left - offsetLeft < container.left)
  11923. {
  11924. selectedControl.offsetLeft = container.left - offsetLeft;
  11925. }
  11926. else if (selectedControl.left + offsetLeft + selectedControl.width > container.width)
  11927. {
  11928. selectedControl.offsetLeft = container.width - selectedControl.width;
  11929. }
  11930.  
  11931. if (selectedControl.top - offsetTop < container.top)
  11932. {
  11933. selectedControl.offsetTop = container.top - offsetTop;
  11934. }
  11935. else if (selectedControl.top + offsetTop + selectedControl.height > container.height)
  11936. {
  11937. selectedControl.offsetTop = container.height - selectedControl.height;
  11938. }
  11939. }
  11940.  
  11941. function resizeWidth(e)
  11942. {
  11943. if (selectedControl.changeWidthIsDisabled) return;
  11944.  
  11945. selectedControl.offsetWidth += Math.floor(e.pageX - data.mouseX);
  11946.  
  11947. if (selectedControl.offsetWidth < selectedControl.minWidth)
  11948. {
  11949. selectedControl.offsetWidth = selectedControl.minWidth;
  11950. }
  11951.  
  11952. selectedControl.calculatePosition();
  11953.  
  11954. if (selectedControl.left + selectedControl.width < container.width) return;
  11955.  
  11956. selectedControl.offsetWidth = container.width - (selectedControl.width - selectedControl.offsetWidth) - selectedControl.left;
  11957. }
  11958.  
  11959. function resizeHeight(e)
  11960. {
  11961. if (selectedControl.changeHeightIsDisabled) return;
  11962.  
  11963. selectedControl.offsetHeight += Math.floor(e.pageY - data.mouseY);
  11964.  
  11965. if (selectedControl.offsetHeight < selectedControl.minHeight)
  11966. {
  11967. selectedControl.offsetHeight = selectedControl.minHeight;
  11968. }
  11969.  
  11970. selectedControl.calculatePosition();
  11971.  
  11972. if (selectedControl.top + selectedControl.height < container.height) return;
  11973.  
  11974. selectedControl.offsetHeight = container.height - (selectedControl.height - selectedControl.offsetHeight) - selectedControl.top;
  11975. }
  11976.  
  11977. function mousemove(e)
  11978. {
  11979. if (data.mode || Math.abs(data.mouseX - e.pageX) + Math.abs(data.mouseY - e.pageY) < 4) return;
  11980.  
  11981. data.mode = true;
  11982.  
  11983. setTimeout(function()
  11984. {
  11985. if (selectedControl == null) return;
  11986.  
  11987. if (settingWindow.visible)
  11988. {
  11989. backgroundHide();
  11990. settingWindow.hide();
  11991. }
  11992.  
  11993. if (data.resizeMode)
  11994. {
  11995. resizeWidth(e);
  11996. resizeHeight(e);
  11997. }
  11998. else
  11999. {
  12000. undock(e);
  12001. move(e);
  12002.  
  12003. if (selectedControl.left <= 0 ||
  12004. selectedControl.top <= 0 ||
  12005. selectedControl.left + selectedControl.width >= container.width ||
  12006. selectedControl.top + selectedControl.height >= container.height)
  12007. {
  12008. showDockControl(container);
  12009. checkDock(container, e);
  12010. }
  12011. else if (!findDropControl(container, e))
  12012. {
  12013. hideDockControl();
  12014. }
  12015. }
  12016.  
  12017. customization.resize();
  12018.  
  12019. showPositionInfoPopup();
  12020.  
  12021. data.mouseX = e.pageX;
  12022. data.mouseY = e.pageY;
  12023. data.moved = true;
  12024. data.mode = false;
  12025. }, 20);
  12026. }
  12027.  
  12028. function mouseup()
  12029. {
  12030. container.element.off({ mousemove: mousemove, mouseup: mouseup, mouseleave: customization.hide });
  12031.  
  12032. setTimeout(function()
  12033. {
  12034. selectedControl.offsetLeft = Math.floor(selectedControl.offsetLeft / 8) * 8;
  12035. selectedControl.offsetTop = Math.floor(selectedControl.offsetTop / 8) * 8;
  12036. selectedControl.offsetWidth = Math.floor(selectedControl.offsetWidth / 8) * 8;
  12037. selectedControl.offsetHeight = Math.floor(selectedControl.offsetHeight / 8) * 8;
  12038.  
  12039. if (dockControl != null)
  12040. {
  12041. if (selectedControl.dockLeft || selectedControl.dockRight) selectedControl.offsetLeft = 0;
  12042. if (selectedControl.dockTop || selectedControl.dockBottom) selectedControl.offsetTop = 0;
  12043.  
  12044. selectedControl.setParent(dockControl).dock
  12045. (
  12046. selectedControl.dockLeft,
  12047. selectedControl.dockTop,
  12048. selectedControl.dockRight,
  12049. selectedControl.dockBottom,
  12050. selectedControl.dockOuterHorizontal,
  12051. selectedControl.dockOuterVertical
  12052. );
  12053.  
  12054. selectedControl.offsetLeft -= selectedControl.parent.left;
  12055. selectedControl.offsetTop -= selectedControl.parent.top;
  12056.  
  12057. customization.resize();
  12058.  
  12059. hideDockControl();
  12060. }
  12061.  
  12062. if (dockControl != null || data.moved)
  12063. {
  12064. selectedControl.parent.calculatePadding();
  12065. container.resize();
  12066. }
  12067.  
  12068. if (data.moved == false)
  12069. {
  12070. if (settingWindowDockControl != selectedControl || !settingWindow.visible)
  12071. {
  12072. settingWindowDockControl = selectedControl;
  12073. backgroundShow();
  12074. settingWindow.show(selectedControl);
  12075.  
  12076. return;
  12077. }
  12078. else if (settingWindow.visible)
  12079. {
  12080. backgroundHide();
  12081. settingWindow.hide();
  12082. settingWindowDockControl = null;
  12083. }
  12084. }
  12085.  
  12086. showPositionInfoPopup();
  12087.  
  12088. fixedSelect = false;
  12089. }, 20);
  12090. }
  12091.  
  12092. //#endregion
  12093.  
  12094. //#region Selection
  12095.  
  12096. function selectControl(e)
  12097. {
  12098. /// <param name="e" type="MouseEvent"></param>
  12099.  
  12100. if (fixedSelect) return;
  12101.  
  12102. findSelectedControl(container, e);
  12103. }
  12104.  
  12105. function findSelectedControl(parent, e)
  12106. {
  12107. /// <param name="parent" type="Control"></param>
  12108. /// <param name="e" type="MouseEvent"></param>
  12109.  
  12110. for (var i = 0; i < parent.childs.length; i++)
  12111. {
  12112. /// <var type="Control"></var>
  12113. var control = parent.childs[i];
  12114.  
  12115. if (control == customization || control == informationPopup) continue;
  12116.  
  12117. if (findSelectedControl(control, e)) return true;
  12118.  
  12119. if (!control.visible) continue;
  12120.  
  12121. if (e.pageX > control.left + control.width ||
  12122. e.pageY > control.top + control.height ||
  12123. e.pageX < control.left ||
  12124. e.pageY < control.top) continue;
  12125.  
  12126. if (control != selectedControl && control != settingWindow) customization.show(control);
  12127.  
  12128. return true;
  12129. }
  12130.  
  12131. return false;
  12132. }
  12133.  
  12134. //#endregion
  12135.  
  12136. //#region Controls
  12137.  
  12138. customization.show = function(control)
  12139. {
  12140. /// <param name="control" type="Control"></param>
  12141.  
  12142. if (selectedControl == control) return;
  12143. if (selectedControl != null) customization.hide();
  12144.  
  12145. element.style.display = 'block';
  12146. customization.visible = true;
  12147. selectedControl = control;
  12148.  
  12149. showPositionInfoPopup();
  12150.  
  12151. customization.resize = function()
  12152. {
  12153. control.resize();
  12154.  
  12155. element.style.left = control.elementStyle.left;
  12156. element.style.top = control.elementStyle.top;
  12157. element.style.width = control.elementStyle.width;
  12158. element.style.height = control.elementStyle.height;
  12159. };
  12160.  
  12161. customization.resize();
  12162. };
  12163.  
  12164. customization.hide = function()
  12165. {
  12166. if (selectedControl == null) return;
  12167.  
  12168. backgroundHide();
  12169. settingWindow.hide();
  12170. hideDockControl();
  12171.  
  12172. container.element.off({ mousemove: mousemove, mouseup: mouseup, mouseleave: customization.hide });
  12173. customization.visible = false;
  12174. element.style.display = 'none';
  12175.  
  12176. selectedControl = null;
  12177. fixedSelect = false;
  12178. };
  12179.  
  12180. //#endregion
  12181.  
  12182. //#region Enabled
  12183.  
  12184. customization.disabled = true;
  12185.  
  12186. customization.enable = function(control)
  12187. {
  12188. customization.disabled = false;
  12189.  
  12190. container.element.addClass(theme.classCustomizationOn);
  12191. document.body.style.cssText = '-webkit-touch-callout: none; -moz-user-select: none; -ms-user-select: none; -webkit-user-select: none; -khtml-user-select: none; user-select: none;';
  12192. container.element.on({ mousemove: selectControl, contextmenu: offEvent });
  12193.  
  12194. if (typeof control != 'undefined') customization.show(control);
  12195.  
  12196. autoShowHelp();
  12197. }
  12198.  
  12199. customization.disable = function()
  12200. {
  12201. container.element.removeClass(theme.classCustomizationOn);
  12202. document.body.style.cssText = '';
  12203. container.element.off({ mousemove: selectControl, contextmenu: offEvent });
  12204.  
  12205. customization.disabled = true;
  12206. customization.hide();
  12207. backgroundHide();
  12208. }
  12209.  
  12210. customization.toggleEnabled = function()
  12211. {
  12212. if (customization.disabled)
  12213. {
  12214. customization.enable();
  12215. }
  12216. else
  12217. {
  12218. customization.disable();
  12219. }
  12220. }
  12221.  
  12222. //#endregion
  12223.  
  12224. //#region Saving settings
  12225.  
  12226. main.addSaveHandler(function()
  12227. {
  12228. main.save('customization_notFirstOpen', notFirstOpen);
  12229. });
  12230.  
  12231. main.addLoadHandler(function()
  12232. {
  12233. notFirstOpen = main.loadBoolean('customization_notFirstOpen', false);
  12234. });
  12235.  
  12236. //#endregion
  12237. };
  12238.  
  12239. var gameWindow = new Control('gameWindow', 0, 100, 100, true);
  12240. (function()
  12241. {
  12242. var unityPlayer = document.getElementById('unityPlayer');
  12243. var inventoryControl = $('#DFLightBox').parent();
  12244.  
  12245. gameWindow.resetPosition = function()
  12246. {
  12247. gameWindow.setParent().dock(true).locate();
  12248. };
  12249.  
  12250. gameWindow.addSettings = function()
  12251. {
  12252. settingWindow.addSharedElements(gameWindow, false, false);
  12253.  
  12254. settingWindow.addCheck(language.current.fitGameScreen, gameWindow.fitToScreen, gameWindow.setFitToScreen);
  12255. };
  12256.  
  12257. //#region Replace old interface
  12258.  
  12259. if (main.isNotGameScreen)
  12260. {
  12261. gameWindow.elementStyle.overflow = 'auto';
  12262. gameWindow.element.addClass(gameWindow.className + 'Black');
  12263.  
  12264. $(document.body.childNodes)
  12265. .not(container.element)
  12266. .appendTo(gameWindow.element);
  12267. }
  12268. else
  12269. {
  12270. gameWindow.elementStyle.overflow = 'hidden';
  12271.  
  12272. gameWindow.element.append(unityPlayer);
  12273. unityPlayer.className = theme.classCanvas;
  12274. unityPlayer.style.position = 'absolute';
  12275. unityPlayer.style.left = '0px';
  12276. unityPlayer.style.top = '0px';
  12277. unityPlayer.style.width = '100%';
  12278. unityPlayer.style.height = '100%';
  12279. unityPlayer.style.border = 'none';
  12280.  
  12281. var object = $(unityPlayer).children()[0];
  12282. object.style.width = '100%';
  12283. object.style.height = '100%';
  12284.  
  12285. var label = $('<table class="' + gameWindow.className + 'Table"><tr class="' + gameWindow.className + 'Tr"><td class="' + gameWindow.className + 'Td"></td></tr></table>');
  12286. label.find('td')
  12287. .css('cssText', 'width: 100%; height: 100%; vertical-align: middle; text-align: center;')
  12288. .html(language.current.gameWindow);
  12289.  
  12290. var hiddenContainer = document.createElement('div');
  12291. hiddenContainer.style.display = 'none';
  12292.  
  12293. $('table').appendTo(hiddenContainer);
  12294. gameWindow.element.append(inventoryControl);
  12295. gameWindow.element.append(label);
  12296. document.body.appendChild(hiddenContainer);
  12297. }
  12298.  
  12299. loadingScreen.resetPosition();
  12300. document.body.appendChild(container.element[0]);
  12301.  
  12302. //#endregion
  12303.  
  12304. //#region Unity player
  12305.  
  12306. gameWindow.hideUnityPlayer = function()
  12307. {
  12308. if (unityPlayer == null) return;
  12309.  
  12310. unityPlayer.style.visibility = 'hidden';
  12311. label.css('display', 'table');
  12312. }
  12313.  
  12314. gameWindow.showUnityPlayer = function()
  12315. {
  12316. if (unityPlayer == null) return;
  12317.  
  12318. unityPlayer.style.visibility = 'visible';
  12319. label.css('display', 'none');
  12320. }
  12321.  
  12322. //#endregion
  12323.  
  12324. gameWindow.update = function()
  12325. {
  12326. if (main.isNotGameScreen) return;
  12327.  
  12328. label.find('td').html(language.current.gameWindow);
  12329. };
  12330.  
  12331. //#region Fit to screen
  12332.  
  12333. gameWindow.fitToScreen = true;
  12334.  
  12335. gameWindow.setFitToScreen = function(value)
  12336. {
  12337. gameWindow.fitToScreen = value;
  12338. gameWindow.resize();
  12339. };
  12340.  
  12341. gameWindow.toogleFitToScreen = function()
  12342. {
  12343. gameWindow.setFitToScreen(!gameWindow.fitToScreen);
  12344. };
  12345.  
  12346. function fitToScreen()
  12347. {
  12348. if (main.isNotGameScreen) return;
  12349.  
  12350. setTimeout(function()
  12351. {
  12352. var containerWidth = gameWindow.clientWidth - theme.padding2 - theme.controlsBordersSize2;
  12353. var containerHeight = gameWindow.clientHeight - theme.padding2 - theme.controlsBordersSize2;
  12354.  
  12355. if (gameWindow.fitToScreen)
  12356. {
  12357. unityPlayer.style.left = '0px';
  12358. unityPlayer.style.top = '0px';
  12359. unityPlayer.style.width = '100%';
  12360. unityPlayer.style.height = '100%';
  12361. unityPlayer.style.border = 'none';
  12362.  
  12363. label.css('cssText', 'position: absolute; left: 0px; top: 0px; width: 100%; height: 100%; border: none; z-index: -1');
  12364. }
  12365. else
  12366. {
  12367. var width = 1024, height = 600;
  12368.  
  12369. if (width != containerWidth)
  12370. {
  12371. height *= (containerWidth / width);
  12372. width = containerWidth;
  12373. }
  12374.  
  12375. if (height > containerHeight)
  12376. {
  12377. width *= (containerHeight / height);
  12378. height = containerHeight;
  12379. }
  12380.  
  12381. var left = (containerWidth - width) / 2 + theme.padding;
  12382. var top = (containerHeight - height) / 2 + theme.padding;
  12383.  
  12384. unityPlayer.style.left = Math.floor(left) + 'px';
  12385. unityPlayer.style.top = Math.floor(top) + 'px';
  12386. unityPlayer.style.width = Math.floor(width) + 'px';
  12387. unityPlayer.style.height = Math.floor(height) + 'px';
  12388. unityPlayer.style.border = '';
  12389.  
  12390. label.css(
  12391. {
  12392. position: 'absolute',
  12393. left: Math.floor(left) + 'px',
  12394. top: Math.floor(top) + 'px',
  12395. width: Math.floor(width) + 'px',
  12396. height: Math.floor(height) + 'px',
  12397. border: '',
  12398. zIndex: -1
  12399. });
  12400. }
  12401. }, 20);
  12402. }
  12403.  
  12404. //#endregion
  12405.  
  12406. gameWindow.resize = function()
  12407. {
  12408. if (main.isNotLoaded) return;
  12409.  
  12410. gameWindow.baseResize();
  12411.  
  12412. fitToScreen();
  12413. };
  12414.  
  12415. //#region Saving settings
  12416.  
  12417. main.addSaveHandler(function()
  12418. {
  12419. main.save('gameWindow_fitToScreen', gameWindow.fitToScreen);
  12420. });
  12421.  
  12422. main.addLoadHandler(function()
  12423. {
  12424. gameWindow.setFitToScreen(main.loadBoolean('gameWindow_fitToScreen', true));
  12425. });
  12426.  
  12427. //#endregion
  12428. })();
  12429.  
  12430. var options = new Control('options', 90, 32, 32);
  12431. (function()
  12432. {
  12433. var visibleWindow = false;
  12434.  
  12435. function isIntersectsWithGameWindow()
  12436. {
  12437. return !(options.left + options.width < gameWindow.left ||
  12438. options.top + options.height < gameWindow.top ||
  12439. options.left > gameWindow.left + gameWindow.width ||
  12440. options.top > gameWindow.top + gameWindow.height);
  12441. }
  12442.  
  12443. function inGameModeMenu()
  12444. {
  12445. settingWindow.addButton(language.current.customize, function()
  12446. {
  12447. settingWindow.hide();
  12448. customization.enable(options);
  12449. });
  12450.  
  12451. settingWindow.addDelimiter();
  12452.  
  12453. settingWindow.addSelect(language.current.languageSelect, language.list, language.current.id, function(value)
  12454. {
  12455. language.setCurrent(language.list[value]);
  12456. });
  12457.  
  12458. settingWindow.addCheck(language.current.modeButton, main.manualControl, function()
  12459. {
  12460. main.toggleControl();
  12461.  
  12462. return (main.manualControl ? language.current.modeManual : language.current.modeAutomatic);
  12463. }, (main.manualControl ? language.current.modeManual : language.current.modeAutomatic));
  12464.  
  12465. settingWindow.addDelimiter();
  12466.  
  12467. theme.update();
  12468. settingWindow.addSelect(language.current.themeSelect, theme.list, theme.current.id, function(value)
  12469. {
  12470. theme.setCurrent(theme.list[value]);
  12471. });
  12472.  
  12473. settingWindow.addSlider(language.current.themeFontSize, 8, 16, 1, theme.fontSize, function(value)
  12474. {
  12475. theme.fontSize = value;
  12476. theme.elementHeight = theme.fontSize + 4;
  12477. theme.setCurrent(theme.current);
  12478. container.resize();
  12479. });
  12480.  
  12481. settingWindow.addSlider(language.current.themeFontSpacing, 0, 2, 1, theme.fontSpacing, function(value)
  12482. {
  12483. theme.fontSpacing = value;
  12484. theme.setCurrent(theme.current);
  12485. });
  12486.  
  12487. settingWindow.addDelimiter();
  12488.  
  12489. settingWindow.addLink(language.current.site, 'https://bitbucket.org/TheDarkKRONOS/dead-frontier-enhanced-ui/overview');
  12490. settingWindow.addInscription(language.current.developers);
  12491. }
  12492.  
  12493. //#region inSettingModeMenu
  12494.  
  12495. var sharedSettingsList = [], manualSettingsList = [], automaticSettingsList = [];
  12496.  
  12497. options.addSharedSettingHandler = function(handler)
  12498. {
  12499. sharedSettingsList.push(handler);
  12500. };
  12501.  
  12502. options.addManualSettingHandler = function(handler)
  12503. {
  12504. manualSettingsList.push(handler);
  12505. };
  12506.  
  12507. options.addAutomaticSettingHandler = function(handler)
  12508. {
  12509. automaticSettingsList.push(handler);
  12510. };
  12511.  
  12512. function inSettingModeMenu()
  12513. {
  12514. settingWindow.addButton(language.current.exitCustomize, function()
  12515. {
  12516. if (isIntersectsWithGameWindow())
  12517. {
  12518. alert(language.current.message_isIntersectsWithGameWindow);
  12519. return;
  12520. }
  12521.  
  12522. gameWindow.showUnityPlayer();
  12523. customization.disable();
  12524. visibleWindow = false;
  12525. });
  12526.  
  12527. settingWindow.addButton(language.current.customizeHelpOption, customization.showHelp);
  12528.  
  12529. settingWindow.addButton(language.current.resetCustomize, function()
  12530. {
  12531. main.resetPosition();
  12532. container.resize();
  12533. settingWindow.update();
  12534. });
  12535.  
  12536. settingWindow.addDelimiter();
  12537.  
  12538. settingWindow.addSharedElements(options, false, true, true, false);
  12539.  
  12540. if (sharedSettingsList.length > 0)
  12541. {
  12542. settingWindow.addDelimiter();
  12543.  
  12544. for (var i = 0; i < sharedSettingsList.length; i++) sharedSettingsList[i]();
  12545. }
  12546.  
  12547. if (manualSettingsList.length > 0)
  12548. {
  12549. settingWindow.addDelimiter();
  12550.  
  12551. for (var i = 0; i < manualSettingsList.length; i++) manualSettingsList[i]();
  12552. }
  12553.  
  12554. if (automaticSettingsList.length > 0)
  12555. {
  12556. settingWindow.addDelimiter();
  12557.  
  12558. for (var i = 0; i < automaticSettingsList.length; i++) automaticSettingsList[i]();
  12559. }
  12560. }
  12561.  
  12562. //#endregion
  12563.  
  12564. controls.makeButton(options, settingsData, function()
  12565. {
  12566. if (!customization.disabled) return;
  12567.  
  12568. if (visibleWindow)
  12569. {
  12570. gameWindow.showUnityPlayer();
  12571. visibleWindow = false;
  12572. settingWindow.hide();
  12573. }
  12574. else
  12575. {
  12576. gameWindow.hideUnityPlayer();
  12577. visibleWindow = true;
  12578. settingWindow.show(options);
  12579. }
  12580. });
  12581.  
  12582. options.resetPosition = function()
  12583. {
  12584. options.setParent().dock(true, true).locate();
  12585. };
  12586.  
  12587. options.update = function()
  12588. {
  12589. options.element[0].title = controls.getText(language.current.optionsButton);
  12590. settingWindow.update();
  12591. };
  12592.  
  12593. options.addSettings = function()
  12594. {
  12595. if (customization.disabled)
  12596. {
  12597. inGameModeMenu();
  12598. }
  12599. else
  12600. {
  12601. inSettingModeMenu();
  12602. }
  12603. };
  12604. })();
  12605.  
  12606. var informationPopup = new Control('informationPopup', 101, 100, 20, false, true).hide();
  12607. (function()
  12608. {
  12609. informationPopup.showTime = 0;
  12610.  
  12611. informationPopup.element.mouseup(function()
  12612. {
  12613. informationPopup.showTime = 0;
  12614. informationPopup.hide();
  12615. });
  12616.  
  12617. informationPopup.show = function(message, left, top, time)
  12618. {
  12619. /// <signature>
  12620. /// <param name="message" type="String"></param>
  12621. /// <param name="control" type="Control"></param>
  12622. /// <param name="time" type="Integer"></param>
  12623. /// </signature>
  12624. /// <signature>
  12625. /// <param name="message" type="String"></param>
  12626. /// <param name="left" type="Integer"></param>
  12627. /// <param name="top" type="Integer"></param>
  12628. /// <param name="time" type="Integer"></param>
  12629. /// </signature>
  12630.  
  12631. informationPopup.element.html(message);
  12632.  
  12633. var containerWidth = informationPopup.element.width();
  12634. var containerHeight = informationPopup.element.height();
  12635.  
  12636. if (typeof left == 'number')
  12637. {
  12638. time = time || 2;
  12639.  
  12640. informationPopup.offsetLeft = Math.floor(left < 0 ? (container.width - containerWidth) / 2 : left);
  12641. informationPopup.offsetTop = Math.floor(top < 0 ? (container.height - containerHeight) / 2 : top);
  12642.  
  12643. informationPopup.resize = function()
  12644. {
  12645. informationPopup.baseResize();
  12646. informationPopup.elementStyle.width = '';
  12647. informationPopup.elementStyle.height = '';
  12648. };
  12649. }
  12650. else
  12651. {
  12652. time = top || 2;
  12653.  
  12654. function checkPosition(position)
  12655. {
  12656. return (position.left >= container.left &&
  12657. position.left + containerWidth <= container.width &&
  12658. position.top >= container.top &&
  12659. position.top + containerHeight <= container.height);
  12660. }
  12661.  
  12662. function findPosition(control)
  12663. {
  12664. var controlWidth = control.width;
  12665. var controlHeight = control.height;
  12666.  
  12667. // bottom
  12668. var position =
  12669. {
  12670. left: control.left,
  12671. top: control.top + controlHeight + theme.padding
  12672. };
  12673.  
  12674. if (position.left + containerWidth > container.width) position.left = control.left + controlWidth - containerWidth;
  12675. if (checkPosition(position)) return position;
  12676.  
  12677. // right
  12678. position.left = control.left + controlWidth + theme.padding;
  12679. position.top = control.top;
  12680.  
  12681. if (position.top + containerHeight > container.height) position.top = control.top + controlHeight - containerHeight;
  12682. if (checkPosition(position)) return position;
  12683.  
  12684. // top
  12685. position.left = control.left;
  12686. position.top = control.top - containerHeight - theme.padding;
  12687.  
  12688. if (position.left + containerWidth > container.width) position.left = control.left + controlWidth - containerWidth;
  12689. if (checkPosition(position)) return position;
  12690.  
  12691. // left
  12692. position.left = control.left - containerWidth - theme.padding;
  12693. position.top = control.top;
  12694.  
  12695. if (position.top + containerHeight > container.height) position.top = control.top + controlHeight - containerHeight;
  12696. if (checkPosition(position)) return position;
  12697.  
  12698. // inner
  12699. position.left = control.left + theme.padding;
  12700. position.top = control.top + theme.padding;
  12701.  
  12702. return position;
  12703. }
  12704.  
  12705. informationPopup.resize = function()
  12706. {
  12707. var position = findPosition(left);
  12708.  
  12709. informationPopup.offsetLeft = position.left - container.left;
  12710. informationPopup.offsetTop = position.top - container.top;
  12711.  
  12712. informationPopup.baseResize();
  12713.  
  12714. informationPopup.elementStyle.width = '';
  12715. informationPopup.elementStyle.height = '';
  12716. };
  12717. }
  12718.  
  12719. informationPopup.showTime = time;
  12720. informationPopup.baseShow();
  12721. };
  12722.  
  12723. setInterval(function()
  12724. {
  12725. if (informationPopup.showTime <= 0) return;
  12726.  
  12727. informationPopup.showTime -= 1;
  12728.  
  12729. if (informationPopup.showTime == 0) informationPopup.hide();
  12730. }, 1000);
  12731. })();
  12732.  
  12733. var player = new Player();
  12734.  
  12735. player.findUserId = function()
  12736. {
  12737. var elements = document.getElementsByTagName('script');
  12738. var userIdRegex = /"SendUserID",\s"(\d+)"/i;
  12739.  
  12740. if (main.isNotGameScreen)
  12741. {
  12742. elements = document.getElementsByTagName('param');
  12743. userIdRegex = /userID=(\d+)&/i;
  12744. }
  12745.  
  12746. for (var i = 0; i < elements.length; i++)
  12747. {
  12748. var data = userIdRegex.exec(main.isNotGameScreen ? elements[i].value : elements[i].innerHTML);
  12749. if (data == null) continue;
  12750.  
  12751. player.id = parseInt(data[1]);
  12752.  
  12753. break;
  12754. }
  12755. };
  12756.  
  12757. var refreshButton = new Control('refreshButton', 25, 32, 32);
  12758. var healthLabel = new Control('healthLabel', 24, 96, 32);
  12759. var armorLabel = new Control('armorLabel', 23, 96, 32);
  12760. var hungerLabel = new Control('hungerLabel', 22, 96, 32);
  12761. var inventoryLabel = new Control('inventoryLabel', 21, 96, 32);
  12762. var messageLabel = new Control('messageLabel', 20, 64, 32);
  12763.  
  12764. (function()
  12765. {
  12766. function playerSetting()
  12767. {
  12768. settingWindow.addInput(language.current.playerIdLabel, player.id, function(value)
  12769. {
  12770. var newId = parseInt(value);
  12771.  
  12772. if (isNaN(newId))
  12773. {
  12774. alert(controls.getText(language.current.playerIdIsInvalid));
  12775. }
  12776. else
  12777. {
  12778. player.id = newId;
  12779. }
  12780. });
  12781.  
  12782. settingWindow.addButton(language.current.playerIdReset, function()
  12783. {
  12784. player.findUserId();
  12785.  
  12786. settingWindow.update();
  12787. });
  12788. };
  12789.  
  12790. controls.makeButton(refreshButton, refreshData, function()
  12791. {
  12792. if (player.requestIsSend) return;
  12793.  
  12794. player.refresh();
  12795. });
  12796.  
  12797. refreshButton.addSettings = function()
  12798. {
  12799. settingWindow.addSharedElements(refreshButton);
  12800.  
  12801. playerSetting();
  12802. };
  12803.  
  12804. refreshButton.resetPosition = function()
  12805. {
  12806. refreshButton.setParent(gameWindow).dock(false, true, true, false, false, true).locate();
  12807. };
  12808.  
  12809. refreshButton.update = function()
  12810. {
  12811. refreshButton.element[0].title = controls.getText(language.current.refreshButton);
  12812. };
  12813.  
  12814. options.addAutomaticSettingHandler(function()
  12815. {
  12816. settingWindow.addCheck(language.current.refreshButtonOption, refreshButton.visible, refreshButton.toggle);
  12817. });
  12818.  
  12819. var a = refreshButton.offsetLeft;
  12820. })();
  12821.  
  12822. (function()
  12823. {
  12824. function createLabel(control, icon, valueName, maxValueName, resetHandler, updateHandler)
  12825. {
  12826. /// <param name="control" type="Control"></param>
  12827. /// <param name="icon" type="String"></param>
  12828. /// <param name="valueName" type="String"></param>
  12829. /// <param name="maxValueName" type="String"></param>
  12830. /// <param name="resetHandler" type="Function"></param>
  12831. /// <param name="updateHandler" type="Function"></param>
  12832.  
  12833. control.changeHeightIsDisabled = true;
  12834. control.resetPosition = resetHandler;
  12835. control.update = updateHandler;
  12836.  
  12837. var image = controls.createDiv(control, 'ImageButton');
  12838. image.style.cssText =
  12839. 'background-image: url(' + icon + ');' +
  12840. 'position: absolute; left: 6px; width: 17px; height: 17px';
  12841.  
  12842. control.label = controls.createDiv(control, 'Text');
  12843. control.label.style.cssText = 'position: absolute; left: 40px; text-align: left';
  12844.  
  12845. var labelStandartClasses = control.label.className;
  12846.  
  12847. control.resize = function()
  12848. {
  12849. control.baseResize();
  12850.  
  12851. image.style.top = Math.floor((control.clientHeight - 17) / 2) + 'px';
  12852.  
  12853. control.label.style.top = Math.floor((control.clientHeight - theme.elementHeight) / 2 + theme.controlsBordersSize) + 'px';
  12854. control.label.style.width = (control.clientWidth - 46) + 'px';
  12855. control.label.style.height = theme.elementHeight + 'px';
  12856. };
  12857.  
  12858. function updateData()
  12859. {
  12860. control.label.innerHTML = player[valueName] + '/' + player[maxValueName];
  12861. control.label.className = labelStandartClasses + ' ' + controls.getClassName(player[valueName], player[maxValueName]);
  12862. }
  12863.  
  12864. player.addUpdateHandler(updateData);
  12865. }
  12866.  
  12867. createLabel(healthLabel, healthData, 'health', 'maxHealth', function()
  12868. {
  12869. healthLabel.setParent(gameWindow).dock(true, true, false, false, false, true).locate();
  12870. }, function()
  12871. {
  12872. healthLabel.element[0].title = controls.getText(language.current.healthLabel);
  12873. });
  12874. options.addAutomaticSettingHandler(function()
  12875. {
  12876. settingWindow.addCheck(language.current.healthLabelOption, healthLabel.visible, healthLabel.toggle);
  12877. });
  12878.  
  12879. createLabel(armorLabel, armorData, 'armor', 'maxArmor', function()
  12880. {
  12881. armorLabel.setParent(healthLabel).dock(false, true, true, false, true).locate();
  12882. }, function()
  12883. {
  12884. armorLabel.element[0].title = controls.getText(language.current.armorLabel);
  12885. });
  12886. options.addAutomaticSettingHandler(function()
  12887. {
  12888. settingWindow.addCheck(language.current.armorLabelOption, armorLabel.visible, armorLabel.toggle);
  12889. });
  12890.  
  12891. createLabel(hungerLabel, hungerData, 'hunger', 'maxHunger', function()
  12892. {
  12893. hungerLabel.setParent(armorLabel).dock(false, true, true, false, true).locate();
  12894. }, function()
  12895. {
  12896. hungerLabel.element[0].title = controls.getText(language.current.hungerLabel);
  12897. });
  12898. options.addAutomaticSettingHandler(function()
  12899. {
  12900. settingWindow.addCheck(language.current.hungerLabelOption, hungerLabel.visible, hungerLabel.toggle);
  12901. });
  12902.  
  12903. createLabel(inventoryLabel, inventoryData, 'freeInventoryCells', 'maxInventoryCells', function()
  12904. {
  12905. inventoryLabel.setParent(hungerLabel).dock(false, true, true, false, true).locate();
  12906. }, function()
  12907. {
  12908. inventoryLabel.element[0].title = controls.getText(language.current.inventoryLabel);
  12909. });
  12910. options.addAutomaticSettingHandler(function()
  12911. {
  12912. settingWindow.addCheck(language.current.inventoryLabelOption, inventoryLabel.visible, inventoryLabel.toggle);
  12913. });
  12914. })();
  12915.  
  12916. (function()
  12917. {
  12918. messageLabel.changeWidthIsDisabled = true;
  12919. messageLabel.changeHeightIsDisabled = true;
  12920.  
  12921. messageLabel.resetPosition = function()
  12922. {
  12923. messageLabel.setParent(refreshButton).dock(true, true, false, false, true).locate();
  12924. };
  12925.  
  12926. messageLabel.update = function()
  12927. {
  12928. messageLabel.element[0].title = controls.getText(language.current.messageLabel);
  12929. };
  12930.  
  12931. var image = controls.createDiv(messageLabel, 'ImageButton');
  12932. image.style.cssText =
  12933. 'background-image: url(' + messageData + ');' +
  12934. 'position: absolute; left: 6px; width: 17px; height: 17px';
  12935.  
  12936. var label = controls.createDiv(messageLabel, 'Text');
  12937. label.style.cssText = 'position: absolute; left: 40px; text-align: left';
  12938.  
  12939. var labelStandartClasses = label.className;
  12940.  
  12941. messageLabel.resize = function()
  12942. {
  12943. messageLabel.baseResize();
  12944.  
  12945. image.style.top = Math.floor((messageLabel.clientHeight - 17) / 2) + 'px';
  12946.  
  12947. label.style.top = Math.floor((messageLabel.clientHeight - theme.elementHeight) / 2 + theme.controlsBordersSize) + 'px';
  12948. label.style.width = (messageLabel.width - 46) + 'px';
  12949. label.style.height = theme.elementHeight + 'px';
  12950. };
  12951.  
  12952. function update()
  12953. {
  12954. label.innerHTML = player.newMessageCount;
  12955. label.className = labelStandartClasses + ' ' + (player.newMessageCount > 0 ? theme.classMore0 : theme.classMore75);
  12956. }
  12957.  
  12958. player.addUpdateHandler(update);
  12959.  
  12960. options.addAutomaticSettingHandler(function()
  12961. {
  12962. settingWindow.addCheck(language.current.messageLabelOption, messageLabel.visible, messageLabel.toggle);
  12963. });
  12964. })();
  12965.  
  12966. var map = new Control('map', 10, 100, 100, true);
  12967. (function()
  12968. {
  12969. function offEvent() { return false; }
  12970.  
  12971. map.scaledGridSize = 50;
  12972. map.halfScaledGridSize = 25;
  12973. map.gridSize = 50;
  12974.  
  12975. map.offsetX = 0;
  12976. map.offsetY = 0;
  12977. map.halfWidth = 0;
  12978. map.halfHeight = 0;
  12979.  
  12980. var element = document.createElement('canvas');
  12981. element.className = theme.className + ' ' + theme.classCanvas;
  12982. element.style.cssText = 'position: absolute; left: ' + theme.padding + 'px; top: ' + theme.padding + 'px;';
  12983. element.style.border = '';
  12984. element.style.backgroundColor = 'black';
  12985. map.element.append(element);
  12986.  
  12987. var ctx = element.getContext('2d');
  12988.  
  12989. var image = new Image();
  12990. image.onload = function()
  12991. {
  12992. map.imageWidth = image.width / map.gridSize;
  12993. map.imageHeight = image.height / map.gridSize;
  12994. };
  12995. image.src = newMapData;
  12996.  
  12997. map.resetPosition = function()
  12998. {
  12999. map.setParent().dock(true, true, false, true).locate(0, 0, 300, 300);
  13000. };
  13001.  
  13002. function changeMapScale(value)
  13003. {
  13004. map.scaledGridSize = value;
  13005.  
  13006. ctx.clearRect(0, 0, element.width, element.height);
  13007. map.draw();
  13008. }
  13009.  
  13010. $(element).mousewheel(function(e)
  13011. {
  13012. if (e.deltaY < 0 && map.scaledGridSize > 10)
  13013. {
  13014. map.scaledGridSize -= 5;
  13015. }
  13016. else if (e.deltaY > 0 && map.scaledGridSize < 100)
  13017. {
  13018. map.scaledGridSize += 5;
  13019. }
  13020.  
  13021. changeMapScale(map.scaledGridSize);
  13022. informationPopup.show(language.current.mapScale + ' ' + map.scaledGridSize, map.left + 60, map.top + 60);
  13023. });
  13024.  
  13025. map.addSettings = function()
  13026. {
  13027. settingWindow.addSharedElements(map);
  13028.  
  13029. settingWindow.addSlider(language.current.mapScale, 10, 100, 5, map.scaledGridSize, changeMapScale);
  13030.  
  13031. settingWindow.addCheck(language.current.mapStyle, map.newStyle, function(value)
  13032. {
  13033. map.setStyle(value);
  13034.  
  13035. return (map.newStyle ? language.current.mapNewStyle : language.current.mapOldStyle);
  13036. }, map.newStyle ? language.current.mapNewStyle : language.current.mapOldStyle);
  13037. };
  13038.  
  13039. map.update = function()
  13040. {
  13041. map.element[0].title = controls.getText(language.current.map);
  13042. };
  13043.  
  13044. map.resize = function()
  13045. {
  13046. map.baseResize();
  13047.  
  13048. element.width = map.clientWidth - theme.controlsBordersSize2 - theme.padding2;
  13049. element.height = map.clientHeight - theme.controlsBordersSize2 - theme.padding2;
  13050. element.style.width = element.width + 'px';
  13051. element.style.height = element.height + 'px';
  13052.  
  13053. map.halfWidth = map.width / 2;
  13054. map.halfHeight = map.height / 2;
  13055.  
  13056. map.draw();
  13057. };
  13058.  
  13059. //#region Style
  13060.  
  13061. var styleChangeHandler = [];
  13062.  
  13063. map.newStyle = true;
  13064.  
  13065. map.setStyle = function(value)
  13066. {
  13067. map.newStyle = value;
  13068. image.src = (map.newStyle ? newMapData : oldMapData);
  13069. map.draw();
  13070.  
  13071. for (var i = 0; i < styleChangeHandler.length; i++) styleChangeHandler[i](value);
  13072. }
  13073.  
  13074. map.addStyleChangeHandler = function(handler)
  13075. {
  13076. styleChangeHandler.push(handler);
  13077. };
  13078.  
  13079. //#endregion
  13080.  
  13081. //#region Map view
  13082.  
  13083. var mapControls =
  13084. {
  13085. enable: false,
  13086. left: 1,
  13087. top: 1,
  13088. right: 1,
  13089. down: 1
  13090. };
  13091.  
  13092. var data =
  13093. {
  13094. mouseX: 0,
  13095. mouseY: 0,
  13096. userMoveTimer: 0,
  13097. smoothMoveTimer: 0,
  13098. userMovingIsDisable: false
  13099. };
  13100.  
  13101. map.element
  13102. .on('contextmenu selectstart', offEvent)
  13103. .on({
  13104. mousedown: function(e)
  13105. {
  13106. var position = map.element.position();
  13107.  
  13108. data.mouseX = e.pageX;
  13109. data.mouseY = e.pageY;
  13110.  
  13111. if (data.userMovingIsDisable || !customization.disabled) return;
  13112. if (e.which == 3 || e.ctrlKey) return toggleMark(data.mouseX - position.left, data.mouseY - position.top);
  13113. if (data.userMoveTimer != 0) clearInterval(data.userMoveTimer);
  13114.  
  13115. data.userMoveTimer = setInterval(function()
  13116. {
  13117. var horizontalMoveDisabled = map.imageWidth * map.scaledGridSize < map.width;
  13118. var varticalMoveDisabled = map.imageHeight * map.scaledGridSize < map.height;
  13119. var offsetX = (horizontalMoveDisabled ? 0 : 0.5 / map.halfWidth * (data.mouseX - position.left - map.halfWidth));
  13120. var offsetY = (varticalMoveDisabled ? 0 : 0.5 / map.halfHeight * (data.mouseY - position.top - map.halfHeight));
  13121.  
  13122. map.move(offsetX, offsetY);
  13123. map.draw();
  13124. }, 20);
  13125. },
  13126. mousemove: function(e)
  13127. {
  13128. data.mouseX = e.pageX;
  13129. data.mouseY = e.pageY;
  13130.  
  13131. if (!mapControls.enable)
  13132. {
  13133. mapControls.enable = true;
  13134. map.draw();
  13135. }
  13136. },
  13137. mouseup: function()
  13138. {
  13139. clearInterval(data.userMoveTimer);
  13140. data.userMoveTimer = 0;
  13141. resetControls();
  13142. },
  13143. mouseout: function()
  13144. {
  13145. clearInterval(data.userMoveTimer);
  13146. data.userMoveTimer = 0;
  13147. mapControls.enable = false;
  13148. resetControls();
  13149. }
  13150. });
  13151.  
  13152. function resetControls()
  13153. {
  13154. mapControls.left = 1;
  13155. mapControls.right = 1;
  13156. mapControls.top = 1;
  13157. mapControls.down = 1;
  13158.  
  13159. map.draw();
  13160. }
  13161.  
  13162. function activateControls(offsetX, offsetY)
  13163. {
  13164. mapControls.left = 1;
  13165. mapControls.right = 1;
  13166. mapControls.top = 1;
  13167. mapControls.down = 1;
  13168.  
  13169. if (offsetX < -0.05)
  13170. {
  13171. mapControls.left = 2;
  13172. }
  13173. else if (offsetX > 0.05)
  13174. {
  13175. mapControls.right = 2;
  13176. }
  13177.  
  13178. if (offsetY < -0.05)
  13179. {
  13180. mapControls.top = 2;
  13181. }
  13182. else if (offsetY > 0.05)
  13183. {
  13184. mapControls.down = 2;
  13185. }
  13186. }
  13187.  
  13188. function checkBorders(newPosition)
  13189. {
  13190. var position =
  13191. {
  13192. left: (newPosition.offsetX + 0.5) * map.scaledGridSize - map.halfWidth,
  13193. top: (newPosition.offsetY + 0.5) * map.scaledGridSize - map.halfHeight,
  13194. width: map.imageWidth * map.scaledGridSize,
  13195. height: map.imageHeight * map.scaledGridSize
  13196. };
  13197.  
  13198. if (position.width < map.width)
  13199. {
  13200. position.left = (position.width - map.width) / 2 + map.scaledGridSize;
  13201. newPosition.offsetX = (position.left + map.halfWidth) / map.scaledGridSize - 0.5;
  13202. mapControls.left = 0;
  13203. mapControls.right = 0;
  13204. }
  13205. else if (position.left < 0)
  13206. {
  13207. position.left = 0;
  13208. newPosition.offsetX = map.halfWidth / map.scaledGridSize - 0.5;
  13209. mapControls.left = 0;
  13210. }
  13211. else if (position.left > position.width + map.halfScaledGridSize - map.width)
  13212. {
  13213. position.left = position.width + map.halfScaledGridSize - map.width;
  13214. newPosition.offsetX = (position.left + map.halfWidth) / map.scaledGridSize - 0.5;
  13215. mapControls.right = 0;
  13216. }
  13217.  
  13218. if (position.height < map.height)
  13219. {
  13220. position.top = (position.height - map.height) / 2 + map.scaledGridSize;
  13221. newPosition.offsetY = (position.top + map.halfHeight) / map.scaledGridSize - 0.5;
  13222. mapControls.top = 0;
  13223. mapControls.down = 0;
  13224. }
  13225. else if (position.top < 0)
  13226. {
  13227. position.top = 0;
  13228. newPosition.offsetY = map.halfHeight / map.scaledGridSize - 0.5;
  13229. mapControls.top = 0;
  13230. }
  13231. else if (position.top > position.height + map.halfScaledGridSize - map.height)
  13232. {
  13233. position.top = position.height + map.halfScaledGridSize - map.height;
  13234. newPosition.offsetY = (position.top + map.halfHeight) / map.scaledGridSize - 0.5;
  13235. mapControls.down = 0;
  13236. }
  13237.  
  13238. return position;
  13239. }
  13240.  
  13241. map.smoothMove = function(x, y)
  13242. {
  13243. var speed = 15;
  13244. var minSpeed = 0.02;
  13245. var position = { offsetX: x, offsetY: y };
  13246.  
  13247. checkBorders(position);
  13248.  
  13249. if (data.userMovingIsDisable) clearInterval(data.smoothMoveTimer);
  13250.  
  13251. data.userMovingIsDisable = true;
  13252.  
  13253. data.smoothMoveTimer = setInterval(function()
  13254. {
  13255. var isEnd = true;
  13256. var prevOffsetX = map.offsetX;
  13257. var prevOffsetY = map.offsetY;
  13258. var distanceX = position.offsetX - map.offsetX;
  13259. var distanceY = position.offsetY - map.offsetY;
  13260.  
  13261. if (Math.abs(distanceX) > minSpeed)
  13262. {
  13263. distanceX /= speed;
  13264. if (Math.abs(distanceX) < minSpeed) distanceX = distanceX / Math.abs(distanceX) * minSpeed;
  13265. isEnd = false;
  13266. }
  13267.  
  13268. if (Math.abs(distanceY) > minSpeed)
  13269. {
  13270. distanceY /= speed;
  13271. if (Math.abs(distanceY) < minSpeed) distanceY = distanceY / Math.abs(distanceY) * minSpeed;
  13272. isEnd = false;
  13273. }
  13274.  
  13275. map.move(distanceX, distanceY);
  13276. map.draw();
  13277.  
  13278. if (isEnd || (prevOffsetX == map.offsetX && prevOffsetY == map.offsetY))
  13279. {
  13280. clearInterval(data.smoothMoveTimer);
  13281. resetControls();
  13282. data.userMovingIsDisable = false;
  13283. }
  13284. }, 20);
  13285. }
  13286.  
  13287. map.move = function(offsetX, offsetY)
  13288. {
  13289. map.offsetX += offsetX;
  13290. map.offsetY += offsetY;
  13291.  
  13292. activateControls(offsetX, offsetY);
  13293. };
  13294.  
  13295. player.addUpdatePositionHandler(function()
  13296. {
  13297. map.smoothMove(player.x, player.y);
  13298. });
  13299.  
  13300. //#endregion
  13301.  
  13302. //#region Render
  13303.  
  13304. function setControlColor2(state1, state2, x1, y1, x2, y2, lenght)
  13305. {
  13306. if (state1 == 0 || state2 == 0) return;
  13307.  
  13308. drawArrowShadow(x1, y1, x2, y2, lenght);
  13309.  
  13310. if (state1 == 2 && state2 == 2)
  13311. {
  13312. ctx.fillStyle = 'red';
  13313. ctx.strokeStyle = 'red';
  13314. }
  13315. else
  13316. {
  13317. ctx.fillStyle = 'white';
  13318. ctx.strokeStyle = 'white';
  13319. }
  13320.  
  13321. drawArrow(x1, y1, x2, y2, lenght);
  13322. }
  13323.  
  13324. function setControlColor3(state1, state2, state3, x1, y1, x2, y2, lenght)
  13325. {
  13326. if (state1 == 0) return;
  13327.  
  13328. drawArrowShadow(x1, y1, x2, y2, lenght);
  13329.  
  13330. if (state1 == 2 && state2 != 2 && state3 != 2)
  13331. {
  13332. ctx.fillStyle = 'red';
  13333. ctx.strokeStyle = 'red';
  13334. }
  13335. else
  13336. {
  13337. ctx.fillStyle = 'white';
  13338. ctx.strokeStyle = 'white';
  13339. }
  13340.  
  13341. drawArrow(x1, y1, x2, y2, lenght);
  13342. }
  13343.  
  13344. function drawControls()
  13345. {
  13346. if (!mapControls.enable) return;
  13347.  
  13348. ctx.save();
  13349.  
  13350. var gridSize = Math.floor(Math.min(element.width, element.height) / 19);
  13351. var lenght = gridSize;
  13352. var near = gridSize;
  13353. var near2 = gridSize * 2;
  13354. var center = gridSize * 10;
  13355. var far = gridSize * 18;
  13356. var far2 = gridSize * 19;
  13357.  
  13358. ctx.lineWidth = 2;
  13359.  
  13360. if (element.width < element.height)
  13361. {
  13362. ctx.translate(0, (element.height - element.width) / 2);
  13363. }
  13364. else
  13365. {
  13366. ctx.translate((element.width - element.height) / 2, 0);
  13367. }
  13368.  
  13369. setControlColor2(mapControls.left, mapControls.top, near2, near2, near, near, lenght);
  13370. setControlColor2(mapControls.right, mapControls.down, far, far, far2, far2, lenght);
  13371. setControlColor2(mapControls.left, mapControls.down, near2, far, near, far2, lenght);
  13372. setControlColor2(mapControls.right, mapControls.top, far, near2, far2, near, lenght);
  13373.  
  13374. setControlColor3(mapControls.left, mapControls.top, mapControls.down, near2, center, near, center, lenght);
  13375. setControlColor3(mapControls.right, mapControls.top, mapControls.down, far, center, far2, center, lenght);
  13376. setControlColor3(mapControls.top, mapControls.left, mapControls.right, center, near2, center, near, lenght);
  13377. setControlColor3(mapControls.down, mapControls.left, mapControls.right, center, far, center, far2, lenght);
  13378.  
  13379. ctx.restore();
  13380. }
  13381.  
  13382. function drawArrowShadow(x1, y1, x2, y2, lenght)
  13383. {
  13384. ctx.fillStyle = 'black';
  13385. ctx.strokeStyle = 'black';
  13386. drawArrow(x1 + 1, y1 + 1, x2 + 1, y2 + 1, lenght);
  13387. }
  13388.  
  13389. function drawArrow(x1, y1, x2, y2, lenght)
  13390. {
  13391. var angle = Math.PI / 8;
  13392.  
  13393. ctx.beginPath();
  13394. ctx.moveTo(x1, y1);
  13395. ctx.lineTo(x2, y2);
  13396. ctx.closePath();
  13397.  
  13398. var lineangle = Math.atan2(y2 - y1, x2 - x1);
  13399. var h = Math.abs(lenght / Math.cos(angle));
  13400.  
  13401. var angle1 = lineangle + Math.PI + angle;
  13402. var topx = x2 + Math.cos(angle1) * h;
  13403. var topy = y2 + Math.sin(angle1) * h;
  13404. var angle2 = lineangle + Math.PI - angle;
  13405. var botx = x2 + Math.cos(angle2) * h;
  13406. var boty = y2 + Math.sin(angle2) * h;
  13407.  
  13408. var radius = 3;
  13409. var twoPI = 2 * Math.PI;
  13410.  
  13411. ctx.beginPath();
  13412. ctx.moveTo(topx, topy);
  13413. ctx.lineTo(x2, y2);
  13414. ctx.lineTo(botx, boty);
  13415.  
  13416. var cp1x, cp1y, cp2x, cp2y, backdist;
  13417. var shiftamt = 5;
  13418. if (botx == topx)
  13419. {
  13420. backdist = boty - topy;
  13421. cp1x = (x2 + topx) / 2;
  13422. cp2x = (x2 + topx) / 2;
  13423. cp1y = y2 + backdist / shiftamt;
  13424. cp2y = y2 - backdist / shiftamt;
  13425. }
  13426. else
  13427. {
  13428. backdist = Math.sqrt(((botx - topx) * (botx - topx)) + ((boty - topy) * (boty - topy)));
  13429. var xback = (topx + botx) / 2;
  13430. var yback = (topy + boty) / 2;
  13431. var xmid = (xback + x2) / 2;
  13432. var ymid = (yback + y2) / 2;
  13433.  
  13434. var m = (boty - topy) / (botx - topx);
  13435. var dx = (backdist / (2 * Math.sqrt(m * m + 1))) / shiftamt;
  13436. var dy = m * dx;
  13437. cp1x = xmid - dx;
  13438. cp1y = ymid - dy;
  13439. cp2x = xmid + dx;
  13440. cp2y = ymid + dy;
  13441. }
  13442.  
  13443. ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, topx, topy);
  13444. ctx.fill();
  13445. }
  13446.  
  13447. function drawCross(x, y, color)
  13448. {
  13449. ctx.strokeStyle = color;
  13450. ctx.lineWidth = 2;
  13451. ctx.beginPath();
  13452. ctx.moveTo(x, y);
  13453. ctx.lineTo(x + map.scaledGridSize, y + map.scaledGridSize);
  13454. ctx.closePath();
  13455. ctx.moveTo(x + map.scaledGridSize, y);
  13456. ctx.lineTo(x, y + map.scaledGridSize);
  13457. ctx.closePath();
  13458. ctx.stroke();
  13459. }
  13460.  
  13461. function drawPlayer(position, x, y)
  13462. {
  13463. x = Math.floor(x * map.scaledGridSize - position.left);
  13464. y = Math.floor(y * map.scaledGridSize - position.top);
  13465.  
  13466. ctx.strokeStyle = 'red';
  13467. ctx.lineWidth = 4;
  13468. ctx.strokeRect(x, y, map.scaledGridSize, map.scaledGridSize);
  13469.  
  13470. ctx.strokeStyle = 'white';
  13471. ctx.lineWidth = 2;
  13472. ctx.strokeRect(x, y, map.scaledGridSize, map.scaledGridSize);
  13473. }
  13474.  
  13475. function drawMark(position, x, y)
  13476. {
  13477. x = Math.floor(x * map.scaledGridSize - position.left);
  13478. y = Math.floor(y * map.scaledGridSize - position.top);
  13479.  
  13480. drawCross(x, y, 'yellow');
  13481. }
  13482.  
  13483. map.draw = function()
  13484. {
  13485. var position = checkBorders(map);
  13486.  
  13487. ctx.drawImage(image, -Math.floor(position.left), -Math.floor(position.top), Math.floor(position.width), Math.floor(position.height));
  13488. drawControls();
  13489.  
  13490. for (var i = 0; i < marks.length; i++)
  13491. if (marks[i].visible) drawMark(position, marks[i].x, marks[i].y);
  13492.  
  13493. drawPlayer(position, player.x, player.y);
  13494. }
  13495.  
  13496. //#endregion
  13497.  
  13498. //#region Marks
  13499.  
  13500. function MapMark(x, y, visible)
  13501. {
  13502. this.x = x;
  13503. this.y = y;
  13504. this.visible = visible;
  13505. }
  13506.  
  13507. /// <var type="Array" elementType="MapMark"></var>
  13508. var marks = [];
  13509.  
  13510. function setMark(x, y, visible)
  13511. {
  13512. var newMark = new MapMark(x, y, visible);
  13513.  
  13514. for (var i = 0; i < marks.length; i++)
  13515. {
  13516. if (marks[i].x == x && marks[i].y == y)
  13517. {
  13518. marks[i] = newMark;
  13519. return;
  13520. }
  13521. }
  13522.  
  13523. marks.push(newMark);
  13524. }
  13525.  
  13526. function toggleMark(mouseX, mouseY)
  13527. {
  13528. var position = checkBorders(map);
  13529. var x = Math.floor((mouseX + theme.padding - map.halfWidth) / map.scaledGridSize + map.offsetX);
  13530. var y = Math.floor((mouseY + theme.padding - map.halfHeight) / map.scaledGridSize + map.offsetY);
  13531.  
  13532. for (var i = 0; i < marks.length; i++)
  13533. {
  13534. if (marks[i].x == x && marks[i].y == y)
  13535. {
  13536. marks[i].visible = !marks[i].visible;
  13537. return;
  13538. }
  13539. }
  13540.  
  13541. setMark(x, y, true);
  13542. }
  13543.  
  13544. map.clearMarks = function()
  13545. {
  13546. marks = [];
  13547. map.draw();
  13548. }
  13549.  
  13550. map.removeMark = function(x, y)
  13551. {
  13552. setMark(x, y, false);
  13553. map.draw();
  13554. }
  13555.  
  13556. map.setMark = function(x, y)
  13557. {
  13558. setMark(x, y, true);
  13559. map.draw();
  13560. }
  13561.  
  13562. //#endregion
  13563.  
  13564. options.addSharedSettingHandler(function()
  13565. {
  13566. settingWindow.addCheck(language.current.mapOption, map.visible, map.toggle);
  13567. });
  13568.  
  13569. //#region Saving settings
  13570.  
  13571. main.addSaveHandler(function()
  13572. {
  13573. var count = 0;
  13574.  
  13575. for (var i = 0; i < marks.length; i++)
  13576. {
  13577. if (!marks[i].visible) continue;
  13578.  
  13579. main.save('map_marks_' + i + '_x', marks[i].x);
  13580. main.save('map_marks_' + i + '_y', marks[i].y);
  13581.  
  13582. count += 1;
  13583. }
  13584.  
  13585. main.save('map_marks_count', count);
  13586. main.save('map_newStyle', map.newStyle);
  13587. });
  13588.  
  13589. main.addLoadHandler(function()
  13590. {
  13591. map.setStyle(main.loadBoolean('map_newStyle', true));
  13592.  
  13593. var count = main.loadNumber('map_marks_count', 0);
  13594.  
  13595. for (var i = 0; i < count; i++)
  13596. {
  13597. var x = main.loadNumber('map_marks_' + i + '_x', -1);
  13598. var y = main.loadNumber('map_marks_' + i + '_y', -1);
  13599.  
  13600. if (x < 0 || y < 0) continue;
  13601.  
  13602. setMark(x, y, true);
  13603. }
  13604.  
  13605. map.draw();
  13606. });
  13607.  
  13608. //#endregion
  13609. })();
  13610.  
  13611. var legend = new Control('legend', 60, 200, 100, true).hide();
  13612.  
  13613. (function()
  13614. {
  13615. legend.elementStyle.overflow = 'auto';
  13616. legend.elementStyle.padding = theme.padding + 'px';
  13617.  
  13618. var element = document.createElement('canvas');
  13619. element.className = theme.className + ' ' + theme.classCanvas;
  13620. element.style.cssText = 'position: static; left: 0px; top: 0px;';
  13621. element.style.border = '';
  13622. element.style.backgroundColor = '#404040';
  13623. legend.element.append(element);
  13624.  
  13625. var ctx = element.getContext('2d');
  13626.  
  13627. var imageWidth = 0;
  13628. var imageHeight = 0;
  13629. var image = new Image();
  13630. image.onload = function()
  13631. {
  13632. imageWidth = image.width;
  13633. imageHeight = image.height;
  13634. };
  13635. image.src = newLegendData;
  13636.  
  13637. $(legend.element).mouseup(function()
  13638. {
  13639. legend.hide();
  13640. });
  13641.  
  13642. //#region Style
  13643.  
  13644. legend.newStyle = true;
  13645.  
  13646. legend.setStyle = function(value)
  13647. {
  13648. legend.newStyle = value;
  13649. image.src = (legend.newStyle ? newLegendData : oldLegendData);
  13650. legend.draw();
  13651. }
  13652.  
  13653. //#endregion
  13654.  
  13655. map.addStyleChangeHandler(legend.setStyle);
  13656.  
  13657. legend.resetPosition = function()
  13658. {
  13659. legend.setParent().dock(true, true, false, true).locate(theme.padding, 0, 300, 900);
  13660. };
  13661.  
  13662. legend.update = function()
  13663. {
  13664. legend.element[0].title = controls.getText(language.current.legend);
  13665. };
  13666.  
  13667. legend.resize = function()
  13668. {
  13669. legend.baseResize();
  13670.  
  13671. element.width = legend.element.width() - theme.controlsBordersSize2 - theme.padding2;
  13672. element.height = imageHeight;
  13673. element.style.width = element.width + 'px';
  13674. element.style.height = imageHeight + 'px';
  13675.  
  13676. legend.draw();
  13677. };
  13678.  
  13679. function drawText(text, lineNumber)
  13680. {
  13681. var left = imageWidth + theme.padding;
  13682. var top = lineNumber * 50;
  13683.  
  13684. if (text != null) ctx.fillText(text.line1 || text, left, top);
  13685. if (text.line2 != null) ctx.fillText(text.line2, left, top + 25);
  13686.  
  13687. top += 51;
  13688.  
  13689. ctx.beginPath();
  13690. ctx.moveTo(imageWidth, top);
  13691. ctx.lineTo(element.width, top);
  13692. ctx.stroke();
  13693. }
  13694.  
  13695. legend.draw = function()
  13696. {
  13697. ctx.lineWidth = 2;
  13698. ctx.strokeStyle = 'black';
  13699.  
  13700. ctx.clearRect(0, 0, element.width, element.height);
  13701.  
  13702. ctx.strokeRect(1, 1, element.width - 2, element.height - 2);
  13703. ctx.drawImage(image, 0, 0, imageWidth, imageHeight);
  13704.  
  13705. ctx.font = '20px "Times New Roman"';
  13706. ctx.textBaseline = 'top';
  13707. ctx.fillStyle = 'white';
  13708.  
  13709. drawText(language.current.legendDescriptionOutpost, 0);
  13710. drawText(language.current.legendDescriptionWarehouse, 1);
  13711. drawText(language.current.legendDescriptionHouse, 2);
  13712. drawText(language.current.legendDescriptionApartment, 3);
  13713. drawText(language.current.legendDescriptionPoliceStation, 4);
  13714. drawText(language.current.legendDescriptionClothingStore, 5);
  13715. drawText(language.current.legendDescriptionSuperMarket, 6);
  13716. drawText(language.current.legendDescriptionShop, 7);
  13717. drawText(language.current.legendDescriptionRowShops, 8);
  13718. drawText(language.current.legendDescriptionHospital, 9);
  13719. drawText(language.current.legendDescriptionSchool, 10);
  13720. drawText(language.current.legendDescriptionSportField, 11);
  13721. drawText(language.current.legendDescriptionHotel, 12);
  13722. drawText(language.current.legendDescriptionJunkyard, 13);
  13723. drawText(language.current.legendDescriptionOfficeBuilding, 14);
  13724. drawText(language.current.legendDescriptionBlinds, 15);
  13725. drawText(language.current.legendDescriptionGreenArea, 16);
  13726. drawText(language.current.legendDescriptionBigGreenArea, 17);
  13727. drawText(language.current.legendDescriptionDoorBarricade, 18);
  13728. drawText(language.current.legendDescriptionCyanRoute, 19);
  13729. drawText(language.current.legendDescriptionGreenRoute, 20);
  13730. drawText(language.current.legendDescriptionYellowRoute, 21);
  13731. drawText(language.current.legendDescriptionOrangeRoute, 22);
  13732. drawText(language.current.legendDescriptionRedRoute, 23);
  13733. drawText(language.current.legendDescriptionBlueZone, 24);
  13734. drawText(language.current.legendDescriptionGreenZone, 25);
  13735. drawText(language.current.legendDescriptionYellowZone, 26);
  13736. drawText(language.current.legendDescriptionOrangeZone, 27);
  13737. drawText(language.current.legendDescriptionRedZone, 28);
  13738. drawText(language.current.legendDescriptionDarkZone, 29);
  13739. drawText(language.current.legendDescriptionNightmareZone, 30);
  13740. }
  13741. })();
  13742.  
  13743. function visibleOnlyManualControl(control)
  13744. {
  13745. /// <param name="control" type="Control"></param>
  13746.  
  13747. main.addSwitchingManualControlHandler(function()
  13748. {
  13749. control.show();
  13750. });
  13751.  
  13752. main.addSwitchingAutomaticControlHandler(function()
  13753. {
  13754. control.hide();
  13755. });
  13756. }
  13757.  
  13758. var legendButton = new Control('legendButton', 45, 32, 32);
  13759. controls.makeButton(legendButton, legendData, legend.toggle);
  13760. legendButton.resetPosition = function()
  13761. {
  13762. legendButton.setParent(map).dock(true, true, false, false, false, true).locate();
  13763. };
  13764. legendButton.update = function()
  13765. {
  13766. legendButton.element[0].title = controls.getText(language.current.legendButton);
  13767. };
  13768. options.addSharedSettingHandler(function()
  13769. {
  13770. settingWindow.addCheck(language.current.legendButtonOption, legendButton.visible, legendButton.toggle);
  13771. });
  13772.  
  13773. var centeredOnPlayerButton = new Control('centeredOnPlayerButton', 42, 32, 32);
  13774. controls.makeButton(centeredOnPlayerButton, centeredData, function()
  13775. {
  13776. map.smoothMove(player.x, player.y);
  13777. });
  13778. centeredOnPlayerButton.resetPosition = function()
  13779. {
  13780. centeredOnPlayerButton.setParent(upButton).dock(false, false, true, true, false, true).locate();
  13781. };
  13782. centeredOnPlayerButton.update = function()
  13783. {
  13784. centeredOnPlayerButton.element[0].title = controls.getText(language.current.centeredOnPlayerButton);
  13785. };
  13786. options.addSharedSettingHandler(function()
  13787. {
  13788. settingWindow.addCheck(language.current.centeredOnPlayerButtonOption, centeredOnPlayerButton.visible, centeredOnPlayerButton.toggle);
  13789. });
  13790.  
  13791. var upButton = new Control('upButton', 40, 32, 32);
  13792. controls.makeButton(upButton, upData, function()
  13793. {
  13794. if (player.y > 0) player.add(0, -1);
  13795. });
  13796. upButton.resetPosition = function()
  13797. {
  13798. upButton.setParent(rightUpButton).dock(true, true, false, false, true, false).locate();
  13799. };
  13800. upButton.update = function()
  13801. {
  13802. upButton.element[0].title = controls.getText(language.current.upButton);
  13803. };
  13804. visibleOnlyManualControl(upButton);
  13805.  
  13806. var downButton = new Control('downButton', 40, 32, 32);
  13807. controls.makeButton(downButton, downData, function()
  13808. {
  13809. if (player.y < Math.floor(map.imageHeight - 1)) player.add(0, 1);
  13810. });
  13811. downButton.resetPosition = function()
  13812. {
  13813. downButton.setParent(centeredOnPlayerButton).dock(false, false, true, true, false, true);
  13814. };
  13815. downButton.update = function()
  13816. {
  13817. downButton.element[0].title = controls.getText(language.current.downButton);
  13818. };
  13819. visibleOnlyManualControl(downButton);
  13820.  
  13821. var leftUpButton = new Control('leftUpButton', 40, 32, 32);
  13822. controls.makeButton(leftUpButton, upLeftData, function()
  13823. {
  13824. if (player.x > 0) player.add(-1, 0);
  13825. if (player.y > 0) player.add(0, -1);
  13826. });
  13827. leftUpButton.resetPosition = function()
  13828. {
  13829. leftUpButton.setParent(upButton).dock(true, true, false, false, true, false).locate();
  13830. };
  13831. leftUpButton.update = function()
  13832. {
  13833. leftUpButton.element[0].title = controls.getText(language.current.leftUpButton);
  13834. };
  13835. visibleOnlyManualControl(leftUpButton);
  13836.  
  13837. var leftButton = new Control('leftButton', 40, 32, 32);
  13838. controls.makeButton(leftButton, leftData, function()
  13839. {
  13840. if (player.x > 0) player.add(-1, 0);
  13841. });
  13842. leftButton.resetPosition = function()
  13843. {
  13844. leftButton.setParent(centeredOnPlayerButton).dock(true, true, false, false, true, false).locate();
  13845. };
  13846. leftButton.update = function()
  13847. {
  13848. leftButton.element[0].title = controls.getText(language.current.leftButton);
  13849. };
  13850. visibleOnlyManualControl(leftButton);
  13851.  
  13852. var leftDownButton = new Control('leftDownButton', 40, 32, 32);
  13853. controls.makeButton(leftDownButton, downLeftData, function()
  13854. {
  13855. if (player.x > 0) player.add(-1, 0);
  13856. if (player.y < Math.floor(map.imageHeight - 1)) player.add(0, 1);
  13857. });
  13858. leftDownButton.resetPosition = function()
  13859. {
  13860. leftDownButton.setParent(downButton).dock(true, false, false, true, true, false).locate();
  13861. };
  13862. leftDownButton.update = function()
  13863. {
  13864. leftDownButton.element[0].title = controls.getText(language.current.leftDownButton);
  13865. };
  13866. visibleOnlyManualControl(leftDownButton);
  13867.  
  13868. var rightUpButton = new Control('rightUpButton', 40, 32, 32);
  13869. controls.makeButton(rightUpButton, upRightData, function()
  13870. {
  13871. if (player.x < Math.floor(map.imageWidth - 1)) player.add(1, 0);
  13872. if (player.y > 0) player.add(0, -1);
  13873. });
  13874. rightUpButton.resetPosition = function()
  13875. {
  13876. rightUpButton.setParent(map).dock(false, false, true, true, false, true).locate();
  13877. };
  13878. rightUpButton.update = function()
  13879. {
  13880. rightUpButton.element[0].title = controls.getText(language.current.rightUpButton);
  13881. };
  13882. visibleOnlyManualControl(rightUpButton);
  13883.  
  13884. var rightButton = new Control('rightButton', 40, 32, 32);
  13885. controls.makeButton(rightButton, rightData, function()
  13886. {
  13887. if (player.x < Math.floor(map.imageWidth - 1)) player.add(1, 0);
  13888. });
  13889. rightButton.resetPosition = function()
  13890. {
  13891. rightButton.setParent(centeredOnPlayerButton).dock(false, true, true, false, true, false).locate();
  13892. };
  13893. rightButton.update = function()
  13894. {
  13895. rightButton.element[0].title = controls.getText(language.current.rightButton);
  13896. };
  13897. visibleOnlyManualControl(rightButton);
  13898.  
  13899. var rightDownButton = new Control('rightDownButton', 40, 32, 32);
  13900. controls.makeButton(rightDownButton, downRightData, function()
  13901. {
  13902. if (player.x < Math.floor(map.imageWidth - 1)) player.add(1, 0);
  13903. if (player.y < Math.floor(map.imageHeight - 1)) player.add(0, 1);
  13904. });
  13905. rightDownButton.resetPosition = function()
  13906. {
  13907. rightDownButton.setParent(downButton).dock(false, false, true, true, true, false).locate();
  13908. };
  13909. rightDownButton.update = function()
  13910. {
  13911. rightDownButton.element[0].title = controls.getText(language.current.rightDownButton);
  13912. };
  13913. visibleOnlyManualControl(rightDownButton);
  13914.  
  13915. var checkedButton = new Control('checkedButton', 41, 32, 32);
  13916. controls.makeButton(checkedButton, checkData, function()
  13917. {
  13918. map.setMark(player.x, player.y);
  13919. });
  13920. checkedButton.resetPosition = function()
  13921. {
  13922. checkedButton.setParent(map).dock(true, false, false, true, false, true).locate();
  13923. };
  13924. checkedButton.update = function()
  13925. {
  13926. checkedButton.element[0].title = controls.getText(language.current.checkButton);
  13927. };
  13928. options.addSharedSettingHandler(function()
  13929. {
  13930. settingWindow.addCheck(language.current.checkButtonOption, checkedButton.visible, checkedButton.toggle);
  13931. });
  13932.  
  13933. var clearButton = new Control('clearButton', 41, 32, 32);
  13934. controls.makeButton(clearButton, clearData, function()
  13935. {
  13936. map.removeMark(player.x, player.y);
  13937. });
  13938. clearButton.resetPosition = function()
  13939. {
  13940. clearButton.setParent(checkedButton).dock(true, false, false, true, false, true).locate();
  13941. };
  13942. clearButton.update = function()
  13943. {
  13944. clearButton.element[0].title = controls.getText(language.current.clearButton);
  13945. };
  13946. options.addSharedSettingHandler(function()
  13947. {
  13948. settingWindow.addCheck(language.current.clearButtonOption, clearButton.visible, clearButton.toggle);
  13949. });
  13950.  
  13951. var clearAllButton = new Control('clearAllButton', 41, 32, 32);
  13952. controls.makeButton(clearAllButton, clearAllData, map.clearMarks);
  13953. clearAllButton.resetPosition = function()
  13954. {
  13955. clearAllButton.setParent(clearButton).dock(true, false, false, true, false, true).locate();
  13956. };
  13957. clearAllButton.update = function()
  13958. {
  13959. clearAllButton.element[0].title = controls.getText(language.current.clearAllButton);
  13960. };
  13961. options.addSharedSettingHandler(function()
  13962. {
  13963. settingWindow.addCheck(language.current.clearAllButtonOption, clearAllButton.visible, clearAllButton.toggle);
  13964. });
  13965.  
  13966. function playerControlButtonsToggle()
  13967. {
  13968. upButton.toggle();
  13969. downButton.toggle();
  13970. leftButton.toggle();
  13971. rightButton.toggle();
  13972. leftUpButton.toggle();
  13973. leftDownButton.toggle();
  13974. rightUpButton.toggle();
  13975. rightDownButton.toggle();
  13976. }
  13977.  
  13978. options.addManualSettingHandler(function()
  13979. {
  13980. settingWindow.addCheck(language.current.playerControlButtonsToggleOption, upButton.visible, playerControlButtonsToggle);
  13981. });
  13982.  
  13983. map.outposts =
  13984. {
  13985. Street: { id: 'Street', text: "Street", x: -1, y: -1, hidden: true },
  13986. FortPastor: { id: 'FortPastor', text: "Fort Pastor", x: 31, y: 23 },
  13987. NastyasHoldout: { id: 'NastyasHoldout', text: "Nastya's Holdout", x: 1, y: 20 },
  13988. DoggsStockage: { id: 'DoggsStockage', text: "Dogg's Stockage", x: 7, y: 5 },
  13989. Precint13: { id: 'Precint13', text: "Precint 13", x: 14, y: 39 }
  13990. };
  13991.  
  13992. map.outpost = map.outposts.NastyasHoldout;
  13993.  
  13994. var outpostSelect = new Control('outpostSelect', 30, 96, 32, true);
  13995. (function()
  13996. {
  13997. outpostSelect.changeHeightIsDisabled = true;
  13998.  
  13999. outpostSelect.resetPosition = function()
  14000. {
  14001. outpostSelect.setParent(map).dock(false, true, true, false, false, true).locate(0, 0, 160);
  14002. };
  14003.  
  14004. outpostSelect.update = function()
  14005. {
  14006. outpostSelect.element[0].title = controls.getText(language.current.outpostSelect);
  14007. };
  14008.  
  14009. var image = controls.createDiv(outpostSelect, 'ImageButton');
  14010. image.style.cssText =
  14011. 'background-image: url(' + outpostData + ');' +
  14012. 'position: absolute; left: 6px; width: 17px; height: 17px';
  14013.  
  14014. var select = controls.createSelect(outpostSelect, function(value)
  14015. {
  14016. if (value == map.outposts.Street.id)
  14017. {
  14018. select.value = map.outpost.id;
  14019.  
  14020. return;
  14021. }
  14022.  
  14023. map.outpost = map.outposts[value];
  14024.  
  14025. if (main.manualControl)
  14026. {
  14027. player.move(map.outpost.x, map.outpost.y);
  14028. }
  14029. else
  14030. {
  14031. map.smoothMove(map.outpost.x, map.outpost.y);
  14032. }
  14033. });
  14034. select.style.cssText = 'position: absolute; left: 40px; text-align: left';
  14035. controls.updateSelect(outpostSelect, select, map.outposts, map.outposts.Street.id);
  14036.  
  14037. outpostSelect.resize = function()
  14038. {
  14039. outpostSelect.baseResize();
  14040.  
  14041. image.style.top = Math.floor((outpostSelect.clientHeight - 17) / 2) + 'px';
  14042.  
  14043. select.style.top = Math.floor((outpostSelect.clientHeight - theme.elementHeight) / 2 + theme.controlsBordersSize) + 'px';
  14044. select.style.width = (outpostSelect.clientWidth - 46) + 'px';
  14045. select.style.height = theme.elementHeight + 'px';
  14046. };
  14047.  
  14048. function updatePosition()
  14049. {
  14050. for (var item in map.outposts)
  14051. {
  14052. if (!map.outposts.hasOwnProperty(item) || player.x != map.outposts[item].x || player.y != map.outposts[item].y) continue;
  14053.  
  14054. select.value = map.outposts[item].id;
  14055. return;
  14056. }
  14057.  
  14058. select.value = map.outposts.Street.id;
  14059. }
  14060.  
  14061. player.addUpdatePositionHandler(updatePosition);
  14062. options.addSharedSettingHandler(function()
  14063. {
  14064. settingWindow.addCheck(language.current.outpostSelectOption, outpostSelect.visible, outpostSelect.toggle);
  14065. });
  14066.  
  14067. updatePosition();
  14068. })();
  14069.  
  14070. var chat = new Control('chat', 15, 100, 100);
  14071.  
  14072. (function()
  14073. {
  14074. chat.url = "";
  14075. chat.openInNewWindowCommand = "";
  14076. chat.elementStyle.padding = theme.padding + 'px';
  14077.  
  14078. var element = document.createElement('iframe');
  14079. element.className = theme.className + ' ' + theme.classCanvas;
  14080. element.style.cssText = 'position: static; margin: 0; left: 0%; top: 0%; width: 100%; height: 100%';
  14081. element.style.backgroundColor = 'black';
  14082. chat.element.append(element);
  14083.  
  14084. //#region Find chat url
  14085.  
  14086. var tags = document.getElementsByTagName(main.isNotGameScreen ? 'img' : 'a');
  14087.  
  14088. for (var i = 0; i < tags.length; i++)
  14089. {
  14090. try
  14091. {
  14092. var data = tags[i].getAttribute('onclick');
  14093.  
  14094. var startUrlIndex = data.indexOf("window.open('http://chat.deadfrontier.com");
  14095. if (startUrlIndex < 0) continue;
  14096. startUrlIndex += 13;
  14097.  
  14098. var endUrlIndex = data.indexOf("'", startUrlIndex);
  14099. if (endUrlIndex < 0) continue;
  14100.  
  14101. chat.openInNewWindowCommand = data;
  14102. chat.url = data.substring(startUrlIndex, endUrlIndex);
  14103.  
  14104. break;
  14105. }
  14106. catch (e) { }
  14107. }
  14108.  
  14109. element.src = chat.url;
  14110.  
  14111. //#endregion
  14112.  
  14113. chat.show = function()
  14114. {
  14115. element.src = chat.url;
  14116. chat.baseShow();
  14117. };
  14118.  
  14119. chat.resetPosition = function()
  14120. {
  14121. chat.setParent().dock(false, true, true, true).locate(0, 0, 600, 800);
  14122. };
  14123.  
  14124. options.addSharedSettingHandler(function()
  14125. {
  14126. settingWindow.addCheck(language.current.chatOption, chat.visible, chat.toggle);
  14127. });
  14128. })();
  14129.  
  14130. var openChatInNewWindowButton = new Control('openChatInNewWindowButton', 45, 32, 32);
  14131. controls.makeButton(openChatInNewWindowButton, chatInNewWindowData, function()
  14132. {
  14133. setTimeout(chat.openInNewWindowCommand, 0);
  14134. chat.hide();
  14135. });
  14136. openChatInNewWindowButton.resetPosition = function()
  14137. {
  14138. openChatInNewWindowButton.setParent(options).dock(false, true, true, false, true, false).locate();
  14139. };
  14140. openChatInNewWindowButton.update = function()
  14141. {
  14142. openChatInNewWindowButton.element[0].title = controls.getText(language.current.openChatButton);
  14143. };
  14144. options.addSharedSettingHandler(function()
  14145. {
  14146. settingWindow.addCheck(language.current.openChatButtonOption, openChatInNewWindowButton.visible, openChatInNewWindowButton.toggle);
  14147. });
  14148.  
  14149. var openChatButton = new Control('openChatButton', 45, 32, 32);
  14150. controls.makeButton(openChatButton, chatData, chat.toggle);
  14151. openChatButton.resetPosition = function()
  14152. {
  14153. openChatButton.setParent(openChatInNewWindowButton).dock(false, true, true, false, true, false).locate();
  14154. };
  14155. openChatButton.update = function()
  14156. {
  14157. openChatButton.element[0].title = controls.getText(language.current.openChatButton);
  14158. };
  14159. options.addSharedSettingHandler(function()
  14160. {
  14161. settingWindow.addCheck(language.current.toggleChatButtonOption, openChatButton.visible, openChatButton.toggle);
  14162. });
  14163.  
  14164. $(function()
  14165. {
  14166. main.resetPosition();
  14167. main.loadAll();
  14168.  
  14169. if (language.current == null) language.setCurrent(language.list.en);
  14170. if (theme.current == null) theme.setCurrent(theme.list.standart);
  14171. if (player.id == 0) player.findUserId();
  14172. map.smoothMove(player.x, player.y);
  14173.  
  14174. main.isNotLoaded = false;
  14175. container.resize();
  14176. controls.notIgnoreHiddenOnResize = false;
  14177.  
  14178. loadingScreen.hide();
  14179. });
  14180.  
  14181. $(window).unload(main.saveAll);
  14182.  
  14183. })(window, window.document);