PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/files/treesaver/0.10.0/treesaver.debug.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 1596 lines | 674 code | 204 blank | 718 comment | 198 complexity | 6abb6f1c120868bd9342eca020521e45 MD5 | raw file
  1. /*
  2. mustache.js — Logic-less templates in JavaScript
  3. See http://mustache.github.com/ for more info.
  4. */
  5. var Mustache = function() {
  6. var Renderer = function() {};
  7. Renderer.prototype = {
  8. otag: "{{",
  9. ctag: "}}",
  10. pragmas: {},
  11. buffer: [],
  12. pragmas_implemented: {
  13. "IMPLICIT-ITERATOR": true
  14. },
  15. context: {},
  16. render: function(template, context, partials, in_recursion) {
  17. // reset buffer & set context
  18. if(!in_recursion) {
  19. this.context = context;
  20. this.buffer = []; // TODO: make this non-lazy
  21. }
  22. // fail fast
  23. if(!this.includes("", template)) {
  24. if(in_recursion) {
  25. return template;
  26. } else {
  27. this.send(template);
  28. return;
  29. }
  30. }
  31. template = this.render_pragmas(template);
  32. var html = this.render_section(template, context, partials);
  33. if(in_recursion) {
  34. return this.render_tags(html, context, partials, in_recursion);
  35. }
  36. this.render_tags(html, context, partials, in_recursion);
  37. },
  38. /*
  39. Sends parsed lines
  40. */
  41. send: function(line) {
  42. if(line !== "") {
  43. this.buffer.push(line);
  44. }
  45. },
  46. /*
  47. Looks for %PRAGMAS
  48. */
  49. render_pragmas: function(template) {
  50. // no pragmas
  51. if(!this.includes("%", template)) {
  52. return template;
  53. }
  54. var that = this;
  55. var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
  56. this.ctag, "g");
  57. return template.replace(regex, function(match, pragma, options) {
  58. if(!that.pragmas_implemented[pragma]) {
  59. throw({message:
  60. "This implementation of mustache doesn't understand the '" +
  61. pragma + "' pragma"});
  62. }
  63. that.pragmas[pragma] = {};
  64. if(options) {
  65. var opts = options.split("=");
  66. that.pragmas[pragma][opts[0]] = opts[1];
  67. }
  68. return "";
  69. // ignore unknown pragmas silently
  70. });
  71. },
  72. /*
  73. Tries to find a partial in the curent scope and render it
  74. */
  75. render_partial: function(name, context, partials) {
  76. name = this.trim(name);
  77. if(!partials || partials[name] === undefined) {
  78. throw({message: "unknown_partial '" + name + "'"});
  79. }
  80. if(typeof(context[name]) != "object") {
  81. return this.render(partials[name], context, partials, true);
  82. }
  83. return this.render(partials[name], context[name], partials, true);
  84. },
  85. /*
  86. Renders inverted (^) and normal (#) sections
  87. */
  88. render_section: function(template, context, partials) {
  89. if(!this.includes("#", template) && !this.includes("^", template)) {
  90. return template;
  91. }
  92. var that = this;
  93. // CSW - Added "+?" so it finds the tighest bound, not the widest
  94. var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
  95. "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
  96. "\\s*", "mg");
  97. // for each {{#foo}}{{/foo}} section do...
  98. return template.replace(regex, function(match, type, name, content) {
  99. var value = that.find(name, context);
  100. if(type == "^") { // inverted section
  101. if(!value || that.is_array(value) && value.length === 0) {
  102. // false or empty list, render it
  103. return that.render(content, context, partials, true);
  104. } else {
  105. return "";
  106. }
  107. } else if(type == "#") { // normal section
  108. if(that.is_array(value)) { // Enumerable, Let's loop!
  109. return that.map(value, function(row) {
  110. return that.render(content, that.create_context(row),
  111. partials, true);
  112. }).join("");
  113. } else if(that.is_object(value)) { // Object, Use it as subcontext!
  114. return that.render(content, that.create_context(value),
  115. partials, true);
  116. } else if(typeof value === "function") {
  117. // higher order section
  118. return value.call(context, content, function(text) {
  119. return that.render(text, context, partials, true);
  120. });
  121. } else if(value) { // boolean section
  122. return that.render(content, context, partials, true);
  123. } else {
  124. return "";
  125. }
  126. }
  127. });
  128. },
  129. /*
  130. Replace {{foo}} and friends with values from our view
  131. */
  132. render_tags: function(template, context, partials, in_recursion) {
  133. // tit for tat
  134. var that = this;
  135. var new_regex = function() {
  136. return new RegExp(that.otag + "(=|!|>|\\{|%|\\$)?([^\\/#\\^]+?)\\1?" +
  137. that.ctag + "+", "g");
  138. };
  139. var regex = new_regex();
  140. var tag_replace_callback = function(match, operator, name) {
  141. switch(operator) {
  142. case "!": // ignore comments
  143. return "";
  144. case "=": // set new delimiters, rebuild the replace regexp
  145. that.set_delimiters(name);
  146. regex = new_regex();
  147. return "";
  148. case ">": // render partial
  149. return that.render_partial(name, context, partials);
  150. case "{": // the triple mustache is unescaped
  151. return that.find(name, context);
  152. case "$":
  153. return encodeURIComponent(that.find(name, context));
  154. default: // escape the value
  155. return that.escape(that.find(name, context));
  156. }
  157. };
  158. var lines = template.split("\n");
  159. for(var i = 0; i < lines.length; i++) {
  160. lines[i] = lines[i].replace(regex, tag_replace_callback, this);
  161. if(!in_recursion) {
  162. this.send(lines[i]);
  163. }
  164. }
  165. if(in_recursion) {
  166. return lines.join("\n");
  167. }
  168. },
  169. set_delimiters: function(delimiters) {
  170. var dels = delimiters.split(" ");
  171. this.otag = this.escape_regex(dels[0]);
  172. this.ctag = this.escape_regex(dels[1]);
  173. },
  174. escape_regex: function(text) {
  175. // thank you Simon Willison
  176. if(!arguments.callee.sRE) {
  177. var specials = [
  178. '/', '.', '*', '+', '?', '|',
  179. '(', ')', '[', ']', '{', '}', '\\'
  180. ];
  181. arguments.callee.sRE = new RegExp(
  182. '(\\' + specials.join('|\\') + ')', 'g'
  183. );
  184. }
  185. return text.replace(arguments.callee.sRE, '\\$1');
  186. },
  187. /*
  188. find `name` in current `context`. That is find me a value
  189. from the view object
  190. */
  191. find: function(name, context) {
  192. name = this.trim(name);
  193. // Checks whether a value is thruthy or false or 0
  194. function is_kinda_truthy(bool) {
  195. return bool === false || bool === 0 || bool;
  196. }
  197. var value;
  198. if(is_kinda_truthy(context[name])) {
  199. value = context[name];
  200. } else if(is_kinda_truthy(this.context[name])) {
  201. value = this.context[name];
  202. }
  203. if(typeof value === "function") {
  204. return value.apply(context);
  205. }
  206. if(value !== undefined) {
  207. return value;
  208. }
  209. // silently ignore unkown variables
  210. return "";
  211. },
  212. // Utility methods
  213. /* includes tag */
  214. includes: function(needle, haystack) {
  215. return haystack.indexOf(this.otag + needle) != -1;
  216. },
  217. /*
  218. Does away with nasty characters
  219. */
  220. escape: function(s) {
  221. s = String(s === null ? "" : s);
  222. return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
  223. switch(s) {
  224. case "&": return "&amp;";
  225. case "\\": return "\\\\";
  226. case '"': return '&quot;';
  227. case "'": return '&#39;';
  228. case "<": return "&lt;";
  229. case ">": return "&gt;";
  230. default: return s;
  231. }
  232. });
  233. },
  234. // by @langalex, support for arrays of strings
  235. create_context: function(_context) {
  236. if(this.is_object(_context)) {
  237. return _context;
  238. } else {
  239. var iterator = ".";
  240. if(this.pragmas["IMPLICIT-ITERATOR"]) {
  241. iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
  242. }
  243. var ctx = {};
  244. ctx[iterator] = _context;
  245. return ctx;
  246. }
  247. },
  248. is_object: function(a) {
  249. return a && typeof a == "object";
  250. },
  251. is_array: function(a) {
  252. return Object.prototype.toString.call(a) === '[object Array]';
  253. },
  254. /*
  255. Gets rid of leading and trailing whitespace
  256. */
  257. trim: function(s) {
  258. return s.replace(/^\s*|\s*$/g, "");
  259. },
  260. /*
  261. Why, why, why? Because IE. Cry, cry cry.
  262. */
  263. map: function(array, fn) {
  264. if (typeof array.map == "function") {
  265. return array.map(fn);
  266. } else {
  267. var r = [];
  268. var l = array.length;
  269. for(var i = 0; i < l; i++) {
  270. r.push(fn(array[i]));
  271. }
  272. return r;
  273. }
  274. }
  275. };
  276. return({
  277. name: "mustache.js",
  278. version: "0.3.1-dev",
  279. /*
  280. Turns a template and view into HTML
  281. */
  282. to_html: function(template, view, partials, send_fun) {
  283. var renderer = new Renderer();
  284. if(send_fun) {
  285. renderer.send = send_fun;
  286. }
  287. renderer.render(template, view, partials);
  288. if(!send_fun) {
  289. return renderer.buffer.join("\n");
  290. }
  291. }
  292. });
  293. }();
  294. // Input 0
  295. window.CLOSURE_NO_DEPS = true;
  296. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  297. //
  298. // Licensed under the Apache License, Version 2.0 (the "License");
  299. // you may not use this file except in compliance with the License.
  300. // You may obtain a copy of the License at
  301. //
  302. // http://www.apache.org/licenses/LICENSE-2.0
  303. //
  304. // Unless required by applicable law or agreed to in writing, software
  305. // distributed under the License is distributed on an "AS-IS" BASIS,
  306. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  307. // See the License for the specific language governing permissions and
  308. // limitations under the License.
  309. /**
  310. * @fileoverview Bootstrap for the Google JS Library (Closure).
  311. *
  312. * In uncompiled mode base.js will write out Closure's deps file, unless the
  313. * global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects to
  314. * include their own deps file(s) from different locations.
  315. *
  316. */
  317. /**
  318. * @define {boolean} Overridden to true by the compiler when --closure_pass
  319. * or --mark_as_compiled is specified.
  320. */
  321. var COMPILED = true;
  322. /**
  323. * Base namespace for the Closure library. Checks to see goog is
  324. * already defined in the current scope before assigning to prevent
  325. * clobbering if base.js is loaded more than once.
  326. *
  327. * @const
  328. */
  329. var goog = goog || {}; // Identifies this file as the Closure base.
  330. /**
  331. * Reference to the global context. In most cases this will be 'window'.
  332. */
  333. goog.global = this;
  334. /**
  335. * @define {boolean} DEBUG is provided as a convenience so that debugging code
  336. * that should not be included in a production js_binary can be easily stripped
  337. * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
  338. * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
  339. * because they are generally used for debugging purposes and it is difficult
  340. * for the JSCompiler to statically determine whether they are used.
  341. */
  342. goog.DEBUG = true;
  343. /**
  344. * @define {string} LOCALE defines the locale being used for compilation. It is
  345. * used to select locale specific data to be compiled in js binary. BUILD rule
  346. * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
  347. * option.
  348. *
  349. * Take into account that the locale code format is important. You should use
  350. * the canonical Unicode format with hyphen as a delimiter. Language must be
  351. * lowercase, Language Script - Capitalized, Region - UPPERCASE.
  352. * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
  353. *
  354. * See more info about locale codes here:
  355. * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
  356. *
  357. * For language codes you should use values defined by ISO 693-1. See it here
  358. * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
  359. * this rule: the Hebrew language. For legacy reasons the old code (iw) should
  360. * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
  361. */
  362. goog.LOCALE = 'en'; // default to en
  363. /**
  364. * Creates object stubs for a namespace. The presence of one or more
  365. * goog.provide() calls indicate that the file defines the given
  366. * objects/namespaces. Build tools also scan for provide/require statements
  367. * to discern dependencies, build dependency files (see deps.js), etc.
  368. * @see goog.require
  369. * @param {string} name Namespace provided by this file in the form
  370. * "goog.package.part".
  371. */
  372. goog.provide = function(name) {
  373. if (!COMPILED) {
  374. // Ensure that the same namespace isn't provided twice. This is intended
  375. // to teach new developers that 'goog.provide' is effectively a variable
  376. // declaration. And when JSCompiler transforms goog.provide into a real
  377. // variable declaration, the compiled JS should work the same as the raw
  378. // JS--even when the raw JS uses goog.provide incorrectly.
  379. if (goog.isProvided_(name)) {
  380. throw Error('Namespace "' + name + '" already declared.');
  381. }
  382. delete goog.implicitNamespaces_[name];
  383. var namespace = name;
  384. while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
  385. if (goog.getObjectByName(namespace)) {
  386. break;
  387. }
  388. goog.implicitNamespaces_[namespace] = true;
  389. }
  390. }
  391. goog.exportPath_(name);
  392. };
  393. /**
  394. * Marks that the current file should only be used for testing, and never for
  395. * live code in production.
  396. * @param {string=} opt_message Optional message to add to the error that's
  397. * raised when used in production code.
  398. */
  399. goog.setTestOnly = function(opt_message) {
  400. if (COMPILED && !goog.DEBUG) {
  401. opt_message = opt_message || '';
  402. throw Error('Importing test-only code into non-debug environment' +
  403. opt_message ? ': ' + opt_message : '.');
  404. }
  405. };
  406. if (!COMPILED) {
  407. /**
  408. * Check if the given name has been goog.provided. This will return false for
  409. * names that are available only as implicit namespaces.
  410. * @param {string} name name of the object to look for.
  411. * @return {boolean} Whether the name has been provided.
  412. * @private
  413. */
  414. goog.isProvided_ = function(name) {
  415. return !goog.implicitNamespaces_[name] && !!goog.getObjectByName(name);
  416. };
  417. /**
  418. * Namespaces implicitly defined by goog.provide. For example,
  419. * goog.provide('goog.events.Event') implicitly declares
  420. * that 'goog' and 'goog.events' must be namespaces.
  421. *
  422. * @type {Object}
  423. * @private
  424. */
  425. goog.implicitNamespaces_ = {};
  426. }
  427. /**
  428. * Builds an object structure for the provided namespace path,
  429. * ensuring that names that already exist are not overwritten. For
  430. * example:
  431. * "a.b.c" -> a = {};a.b={};a.b.c={};
  432. * Used by goog.provide and goog.exportSymbol.
  433. * @param {string} name name of the object that this file defines.
  434. * @param {*=} opt_object the object to expose at the end of the path.
  435. * @param {Object=} opt_objectToExportTo The object to add the path to; default
  436. * is |goog.global|.
  437. * @private
  438. */
  439. goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
  440. var parts = name.split('.');
  441. var cur = opt_objectToExportTo || goog.global;
  442. // Internet Explorer exhibits strange behavior when throwing errors from
  443. // methods externed in this manner. See the testExportSymbolExceptions in
  444. // base_test.html for an example.
  445. if (!(parts[0] in cur) && cur.execScript) {
  446. cur.execScript('var ' + parts[0]);
  447. }
  448. // Certain browsers cannot parse code in the form for((a in b); c;);
  449. // This pattern is produced by the JSCompiler when it collapses the
  450. // statement above into the conditional loop below. To prevent this from
  451. // happening, use a for-loop and reserve the init logic as below.
  452. // Parentheses added to eliminate strict JS warning in Firefox.
  453. for (var part; parts.length && (part = parts.shift());) {
  454. if (!parts.length && goog.isDef(opt_object)) {
  455. // last part and we have an object; use it
  456. cur[part] = opt_object;
  457. } else if (cur[part]) {
  458. cur = cur[part];
  459. } else {
  460. cur = cur[part] = {};
  461. }
  462. }
  463. };
  464. /**
  465. * Returns an object based on its fully qualified external name. If you are
  466. * using a compilation pass that renames property names beware that using this
  467. * function will not find renamed properties.
  468. *
  469. * @param {string} name The fully qualified name.
  470. * @param {Object=} opt_obj The object within which to look; default is
  471. * |goog.global|.
  472. * @return {Object} The object or, if not found, null.
  473. */
  474. goog.getObjectByName = function(name, opt_obj) {
  475. var parts = name.split('.');
  476. var cur = opt_obj || goog.global;
  477. for (var part; part = parts.shift(); ) {
  478. if (goog.isDefAndNotNull(cur[part])) {
  479. cur = cur[part];
  480. } else {
  481. return null;
  482. }
  483. }
  484. return cur;
  485. };
  486. /**
  487. * Globalizes a whole namespace, such as goog or goog.lang.
  488. *
  489. * @param {Object} obj The namespace to globalize.
  490. * @param {Object=} opt_global The object to add the properties to.
  491. * @deprecated Properties may be explicitly exported to the global scope, but
  492. * this should no longer be done in bulk.
  493. */
  494. goog.globalize = function(obj, opt_global) {
  495. var global = opt_global || goog.global;
  496. for (var x in obj) {
  497. global[x] = obj[x];
  498. }
  499. };
  500. /**
  501. * Adds a dependency from a file to the files it requires.
  502. * @param {string} relPath The path to the js file.
  503. * @param {Array} provides An array of strings with the names of the objects
  504. * this file provides.
  505. * @param {Array} requires An array of strings with the names of the objects
  506. * this file requires.
  507. */
  508. goog.addDependency = function(relPath, provides, requires) {
  509. if (!COMPILED) {
  510. var provide, require;
  511. var path = relPath.replace(/\\/g, '/');
  512. var deps = goog.dependencies_;
  513. for (var i = 0; provide = provides[i]; i++) {
  514. deps.nameToPath[provide] = path;
  515. if (!(path in deps.pathToNames)) {
  516. deps.pathToNames[path] = {};
  517. }
  518. deps.pathToNames[path][provide] = true;
  519. }
  520. for (var j = 0; require = requires[j]; j++) {
  521. if (!(path in deps.requires)) {
  522. deps.requires[path] = {};
  523. }
  524. deps.requires[path][require] = true;
  525. }
  526. }
  527. };
  528. // NOTE(user): The debug DOM loader was included in base.js as an orignal
  529. // way to do "debug-mode" development. The dependency system can sometimes
  530. // be confusing, as can the debug DOM loader's asyncronous nature.
  531. //
  532. // With the DOM loader, a call to goog.require() is not blocking -- the
  533. // script will not load until some point after the current script. If a
  534. // namespace is needed at runtime, it needs to be defined in a previous
  535. // script, or loaded via require() with its registered dependencies.
  536. // User-defined namespaces may need their own deps file. See http://go/js_deps,
  537. // http://go/genjsdeps, or, externally, DepsWriter.
  538. // http://code.google.com/closure/library/docs/depswriter.html
  539. //
  540. // Because of legacy clients, the DOM loader can't be easily removed from
  541. // base.js. Work is being done to make it disableable or replaceable for
  542. // different environments (DOM-less JavaScript interpreters like Rhino or V8,
  543. // for example). See bootstrap/ for more information.
  544. /**
  545. * @define {boolean} Whether to enable the debug loader.
  546. *
  547. * If enabled, a call to goog.require() will attempt to load the namespace by
  548. * appending a script tag to the DOM (if the namespace has been registered).
  549. *
  550. * If disabled, goog.require() will simply assert that the namespace has been
  551. * provided (and depend on the fact that some outside tool correctly ordered
  552. * the script).
  553. */
  554. goog.ENABLE_DEBUG_LOADER = true;
  555. /**
  556. * Implements a system for the dynamic resolution of dependencies
  557. * that works in parallel with the BUILD system. Note that all calls
  558. * to goog.require will be stripped by the JSCompiler when the
  559. * --closure_pass option is used.
  560. * @see goog.provide
  561. * @param {string} name Namespace to include (as was given in goog.provide())
  562. * in the form "goog.package.part".
  563. */
  564. goog.require = function(name) {
  565. // if the object already exists we do not need do do anything
  566. // TODO(user): If we start to support require based on file name this has
  567. // to change
  568. // TODO(user): If we allow goog.foo.* this has to change
  569. // TODO(user): If we implement dynamic load after page load we should probably
  570. // not remove this code for the compiled output
  571. if (!COMPILED) {
  572. if (goog.isProvided_(name)) {
  573. return;
  574. }
  575. if (goog.ENABLE_DEBUG_LOADER) {
  576. var path = goog.getPathFromDeps_(name);
  577. if (path) {
  578. goog.included_[path] = true;
  579. goog.writeScripts_();
  580. return;
  581. }
  582. }
  583. var errorMessage = 'goog.require could not find: ' + name;
  584. if (goog.global.console) {
  585. goog.global.console['error'](errorMessage);
  586. }
  587. throw Error(errorMessage);
  588. }
  589. };
  590. /**
  591. * Path for included scripts
  592. * @type {string}
  593. */
  594. goog.basePath = '';
  595. /**
  596. * A hook for overriding the base path.
  597. * @type {string|undefined}
  598. */
  599. goog.global.CLOSURE_BASE_PATH;
  600. /**
  601. * Whether to write out Closure's deps file. By default,
  602. * the deps are written.
  603. * @type {boolean|undefined}
  604. */
  605. goog.global.CLOSURE_NO_DEPS;
  606. /**
  607. * A function to import a single script. This is meant to be overridden when
  608. * Closure is being run in non-HTML contexts, such as web workers. It's defined
  609. * in the global scope so that it can be set before base.js is loaded, which
  610. * allows deps.js to be imported properly.
  611. *
  612. * The function is passed the script source, which is a relative URI. It should
  613. * return true if the script was imported, false otherwise.
  614. */
  615. goog.global.CLOSURE_IMPORT_SCRIPT;
  616. /**
  617. * Null function used for default values of callbacks, etc.
  618. * @return {void} Nothing.
  619. */
  620. goog.nullFunction = function() {};
  621. /**
  622. * The identity function. Returns its first argument.
  623. *
  624. * @param {...*} var_args The arguments of the function.
  625. * @return {*} The first argument.
  626. * @deprecated Use goog.functions.identity instead.
  627. */
  628. goog.identityFunction = function(var_args) {
  629. return arguments[0];
  630. };
  631. /**
  632. * When defining a class Foo with an abstract method bar(), you can do:
  633. *
  634. * Foo.prototype.bar = goog.abstractMethod
  635. *
  636. * Now if a subclass of Foo fails to override bar(), an error
  637. * will be thrown when bar() is invoked.
  638. *
  639. * Note: This does not take the name of the function to override as
  640. * an argument because that would make it more difficult to obfuscate
  641. * our JavaScript code.
  642. *
  643. * @type {!Function}
  644. * @throws {Error} when invoked to indicate the method should be
  645. * overridden.
  646. */
  647. goog.abstractMethod = function() {
  648. throw Error('unimplemented abstract method');
  649. };
  650. /**
  651. * Adds a {@code getInstance} static method that always return the same instance
  652. * object.
  653. * @param {!Function} ctor The constructor for the class to add the static
  654. * method to.
  655. */
  656. goog.addSingletonGetter = function(ctor) {
  657. ctor.getInstance = function() {
  658. return ctor.instance_ || (ctor.instance_ = new ctor());
  659. };
  660. };
  661. if (!COMPILED && goog.ENABLE_DEBUG_LOADER) {
  662. /**
  663. * Object used to keep track of urls that have already been added. This
  664. * record allows the prevention of circular dependencies.
  665. * @type {Object}
  666. * @private
  667. */
  668. goog.included_ = {};
  669. /**
  670. * This object is used to keep track of dependencies and other data that is
  671. * used for loading scripts
  672. * @private
  673. * @type {Object}
  674. */
  675. goog.dependencies_ = {
  676. pathToNames: {}, // 1 to many
  677. nameToPath: {}, // 1 to 1
  678. requires: {}, // 1 to many
  679. // used when resolving dependencies to prevent us from
  680. // visiting the file twice
  681. visited: {},
  682. written: {} // used to keep track of script files we have written
  683. };
  684. /**
  685. * Tries to detect whether is in the context of an HTML document.
  686. * @return {boolean} True if it looks like HTML document.
  687. * @private
  688. */
  689. goog.inHtmlDocument_ = function() {
  690. var doc = goog.global.document;
  691. return typeof doc != 'undefined' &&
  692. 'write' in doc; // XULDocument misses write.
  693. };
  694. /**
  695. * Tries to detect the base path of the base.js script that bootstraps Closure
  696. * @private
  697. */
  698. goog.findBasePath_ = function() {
  699. if (goog.global.CLOSURE_BASE_PATH) {
  700. goog.basePath = goog.global.CLOSURE_BASE_PATH;
  701. return;
  702. } else if (!goog.inHtmlDocument_()) {
  703. return;
  704. }
  705. var doc = goog.global.document;
  706. var scripts = doc.getElementsByTagName('script');
  707. // Search backwards since the current script is in almost all cases the one
  708. // that has base.js.
  709. for (var i = scripts.length - 1; i >= 0; --i) {
  710. var src = scripts[i].src;
  711. var qmark = src.lastIndexOf('?');
  712. var l = qmark == -1 ? src.length : qmark;
  713. if (src.substr(l - 7, 7) == 'base.js') {
  714. goog.basePath = src.substr(0, l - 7);
  715. return;
  716. }
  717. }
  718. };
  719. /**
  720. * Imports a script if, and only if, that script hasn't already been imported.
  721. * (Must be called at execution time)
  722. * @param {string} src Script source.
  723. * @private
  724. */
  725. goog.importScript_ = function(src) {
  726. var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
  727. goog.writeScriptTag_;
  728. if (!goog.dependencies_.written[src] && importScript(src)) {
  729. goog.dependencies_.written[src] = true;
  730. }
  731. };
  732. /**
  733. * The default implementation of the import function. Writes a script tag to
  734. * import the script.
  735. *
  736. * @param {string} src The script source.
  737. * @return {boolean} True if the script was imported, false otherwise.
  738. * @private
  739. */
  740. goog.writeScriptTag_ = function(src) {
  741. if (goog.inHtmlDocument_()) {
  742. var doc = goog.global.document;
  743. doc.write(
  744. '<script type="text/javascript" src="' + src + '"></' + 'script>');
  745. return true;
  746. } else {
  747. return false;
  748. }
  749. };
  750. /**
  751. * Resolves dependencies based on the dependencies added using addDependency
  752. * and calls importScript_ in the correct order.
  753. * @private
  754. */
  755. goog.writeScripts_ = function() {
  756. // the scripts we need to write this time
  757. var scripts = [];
  758. var seenScript = {};
  759. var deps = goog.dependencies_;
  760. function visitNode(path) {
  761. if (path in deps.written) {
  762. return;
  763. }
  764. // we have already visited this one. We can get here if we have cyclic
  765. // dependencies
  766. if (path in deps.visited) {
  767. if (!(path in seenScript)) {
  768. seenScript[path] = true;
  769. scripts.push(path);
  770. }
  771. return;
  772. }
  773. deps.visited[path] = true;
  774. if (path in deps.requires) {
  775. for (var requireName in deps.requires[path]) {
  776. // If the required name is defined, we assume that it was already
  777. // bootstrapped by other means.
  778. if (!goog.isProvided_(requireName)) {
  779. if (requireName in deps.nameToPath) {
  780. visitNode(deps.nameToPath[requireName]);
  781. } else {
  782. throw Error('Undefined nameToPath for ' + requireName);
  783. }
  784. }
  785. }
  786. }
  787. if (!(path in seenScript)) {
  788. seenScript[path] = true;
  789. scripts.push(path);
  790. }
  791. }
  792. for (var path in goog.included_) {
  793. if (!deps.written[path]) {
  794. visitNode(path);
  795. }
  796. }
  797. for (var i = 0; i < scripts.length; i++) {
  798. if (scripts[i]) {
  799. goog.importScript_(goog.basePath + scripts[i]);
  800. } else {
  801. throw Error('Undefined script input');
  802. }
  803. }
  804. };
  805. /**
  806. * Looks at the dependency rules and tries to determine the script file that
  807. * fulfills a particular rule.
  808. * @param {string} rule In the form goog.namespace.Class or project.script.
  809. * @return {?string} Url corresponding to the rule, or null.
  810. * @private
  811. */
  812. goog.getPathFromDeps_ = function(rule) {
  813. if (rule in goog.dependencies_.nameToPath) {
  814. return goog.dependencies_.nameToPath[rule];
  815. } else {
  816. return null;
  817. }
  818. };
  819. goog.findBasePath_();
  820. // Allow projects to manage the deps files themselves.
  821. if (!goog.global.CLOSURE_NO_DEPS) {
  822. goog.importScript_(goog.basePath + 'deps.js');
  823. }
  824. }
  825. //==============================================================================
  826. // Language Enhancements
  827. //==============================================================================
  828. /**
  829. * This is a "fixed" version of the typeof operator. It differs from the typeof
  830. * operator in such a way that null returns 'null' and arrays return 'array'.
  831. * @param {*} value The value to get the type of.
  832. * @return {string} The name of the type.
  833. */
  834. goog.typeOf = function(value) {
  835. var s = typeof value;
  836. if (s == 'object') {
  837. if (value) {
  838. // Check these first, so we can avoid calling Object.prototype.toString if
  839. // possible.
  840. //
  841. // IE improperly marshals tyepof across execution contexts, but a
  842. // cross-context object will still return false for "instanceof Object".
  843. if (value instanceof Array) {
  844. return 'array';
  845. } else if (value instanceof Object) {
  846. return s;
  847. }
  848. // HACK: In order to use an Object prototype method on the arbitrary
  849. // value, the compiler requires the value be cast to type Object,
  850. // even though the ECMA spec explicitly allows it.
  851. var className = Object.prototype.toString.call(
  852. /** @type {Object} */ (value));
  853. // In Firefox 3.6, attempting to access iframe window objects' length
  854. // property throws an NS_ERROR_FAILURE, so we need to special-case it
  855. // here.
  856. if (className == '[object Window]') {
  857. return 'object';
  858. }
  859. // We cannot always use constructor == Array or instanceof Array because
  860. // different frames have different Array objects. In IE6, if the iframe
  861. // where the array was created is destroyed, the array loses its
  862. // prototype. Then dereferencing val.splice here throws an exception, so
  863. // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
  864. // so that will work. In this case, this function will return false and
  865. // most array functions will still work because the array is still
  866. // array-like (supports length and []) even though it has lost its
  867. // prototype.
  868. // Mark Miller noticed that Object.prototype.toString
  869. // allows access to the unforgeable [[Class]] property.
  870. // 15.2.4.2 Object.prototype.toString ( )
  871. // When the toString method is called, the following steps are taken:
  872. // 1. Get the [[Class]] property of this object.
  873. // 2. Compute a string value by concatenating the three strings
  874. // "[object ", Result(1), and "]".
  875. // 3. Return Result(2).
  876. // and this behavior survives the destruction of the execution context.
  877. if ((className == '[object Array]' ||
  878. // In IE all non value types are wrapped as objects across window
  879. // boundaries (not iframe though) so we have to do object detection
  880. // for this edge case
  881. typeof value.length == 'number' &&
  882. typeof value.splice != 'undefined' &&
  883. typeof value.propertyIsEnumerable != 'undefined' &&
  884. !value.propertyIsEnumerable('splice')
  885. )) {
  886. return 'array';
  887. }
  888. // HACK: There is still an array case that fails.
  889. // function ArrayImpostor() {}
  890. // ArrayImpostor.prototype = [];
  891. // var impostor = new ArrayImpostor;
  892. // this can be fixed by getting rid of the fast path
  893. // (value instanceof Array) and solely relying on
  894. // (value && Object.prototype.toString.vall(value) === '[object Array]')
  895. // but that would require many more function calls and is not warranted
  896. // unless closure code is receiving objects from untrusted sources.
  897. // IE in cross-window calls does not correctly marshal the function type
  898. // (it appears just as an object) so we cannot use just typeof val ==
  899. // 'function'. However, if the object has a call property, it is a
  900. // function.
  901. if ((className == '[object Function]' ||
  902. typeof value.call != 'undefined' &&
  903. typeof value.propertyIsEnumerable != 'undefined' &&
  904. !value.propertyIsEnumerable('call'))) {
  905. return 'function';
  906. }
  907. } else {
  908. return 'null';
  909. }
  910. } else if (s == 'function' && typeof value.call == 'undefined') {
  911. // In Safari typeof nodeList returns 'function', and on Firefox
  912. // typeof behaves similarly for HTML{Applet,Embed,Object}Elements
  913. // and RegExps. We would like to return object for those and we can
  914. // detect an invalid function by making sure that the function
  915. // object has a call method.
  916. return 'object';
  917. }
  918. return s;
  919. };
  920. /**
  921. * Safe way to test whether a property is enumarable. It allows testing
  922. * for enumerable on objects where 'propertyIsEnumerable' is overridden or
  923. * does not exist (like DOM nodes in IE). Does not use browser native
  924. * Object.propertyIsEnumerable.
  925. * @param {Object} object The object to test if the property is enumerable.
  926. * @param {string} propName The property name to check for.
  927. * @return {boolean} True if the property is enumarable.
  928. * @private
  929. */
  930. goog.propertyIsEnumerableCustom_ = function(object, propName) {
  931. // KJS in Safari 2 is not ECMAScript compatible and lacks crucial methods
  932. // such as propertyIsEnumerable. We therefore use a workaround.
  933. // Does anyone know a more efficient work around?
  934. if (propName in object) {
  935. for (var key in object) {
  936. if (key == propName &&
  937. Object.prototype.hasOwnProperty.call(object, propName)) {
  938. return true;
  939. }
  940. }
  941. }
  942. return false;
  943. };
  944. /**
  945. * Safe way to test whether a property is enumarable. It allows testing
  946. * for enumerable on objects where 'propertyIsEnumerable' is overridden or
  947. * does not exist (like DOM nodes in IE).
  948. * @param {Object} object The object to test if the property is enumerable.
  949. * @param {string} propName The property name to check for.
  950. * @return {boolean} True if the property is enumarable.
  951. * @private
  952. */
  953. goog.propertyIsEnumerable_ = function(object, propName) {
  954. // In IE if object is from another window, cannot use propertyIsEnumerable
  955. // from this window's Object. Will raise a 'JScript object expected' error.
  956. if (object instanceof Object) {
  957. return Object.prototype.propertyIsEnumerable.call(object, propName);
  958. } else {
  959. return goog.propertyIsEnumerableCustom_(object, propName);
  960. }
  961. };
  962. /**
  963. * Returns true if the specified value is not |undefined|.
  964. * WARNING: Do not use this to test if an object has a property. Use the in
  965. * operator instead. Additionally, this function assumes that the global
  966. * undefined variable has not been redefined.
  967. * @param {*} val Variable to test.
  968. * @return {boolean} Whether variable is defined.
  969. */
  970. goog.isDef = function(val) {
  971. return val !== undefined;
  972. };
  973. /**
  974. * Returns true if the specified value is |null|
  975. * @param {*} val Variable to test.
  976. * @return {boolean} Whether variable is null.
  977. */
  978. goog.isNull = function(val) {
  979. return val === null;
  980. };
  981. /**
  982. * Returns true if the specified value is defined and not null
  983. * @param {*} val Variable to test.
  984. * @return {boolean} Whether variable is defined and not null.
  985. */
  986. goog.isDefAndNotNull = function(val) {
  987. // Note that undefined == null.
  988. return val != null;
  989. };
  990. /**
  991. * Returns true if the specified value is an array
  992. * @param {*} val Variable to test.
  993. * @return {boolean} Whether variable is an array.
  994. */
  995. goog.isArray = function(val) {
  996. return goog.typeOf(val) == 'array';
  997. };
  998. /**
  999. * Returns true if the object looks like an array. To qualify as array like
  1000. * the value needs to be either a NodeList or an object with a Number length
  1001. * property.
  1002. * @param {*} val Variable to test.
  1003. * @return {boolean} Whether variable is an array.
  1004. */
  1005. goog.isArrayLike = function(val) {
  1006. var type = goog.typeOf(val);
  1007. return type == 'array' || type == 'object' && typeof val.length == 'number';
  1008. };
  1009. /**
  1010. * Returns true if the object looks like a Date. To qualify as Date-like
  1011. * the value needs to be an object and have a getFullYear() function.
  1012. * @param {*} val Variable to test.
  1013. * @return {boolean} Whether variable is a like a Date.
  1014. */
  1015. goog.isDateLike = function(val) {
  1016. return goog.isObject(val) && typeof val.getFullYear == 'function';
  1017. };
  1018. /**
  1019. * Returns true if the specified value is a string
  1020. * @param {*} val Variable to test.
  1021. * @return {boolean} Whether variable is a string.
  1022. */
  1023. goog.isString = function(val) {
  1024. return typeof val == 'string';
  1025. };
  1026. /**
  1027. * Returns true if the specified value is a boolean
  1028. * @param {*} val Variable to test.
  1029. * @return {boolean} Whether variable is boolean.
  1030. */
  1031. goog.isBoolean = function(val) {
  1032. return typeof val == 'boolean';
  1033. };
  1034. /**
  1035. * Returns true if the specified value is a number
  1036. * @param {*} val Variable to test.
  1037. * @return {boolean} Whether variable is a number.
  1038. */
  1039. goog.isNumber = function(val) {
  1040. return typeof val == 'number';
  1041. };
  1042. /**
  1043. * Returns true if the specified value is a function
  1044. * @param {*} val Variable to test.
  1045. * @return {boolean} Whether variable is a function.
  1046. */
  1047. goog.isFunction = function(val) {
  1048. return goog.typeOf(val) == 'function';
  1049. };
  1050. /**
  1051. * Returns true if the specified value is an object. This includes arrays
  1052. * and functions.
  1053. * @param {*} val Variable to test.
  1054. * @return {boolean} Whether variable is an object.
  1055. */
  1056. goog.isObject = function(val) {
  1057. var type = goog.typeOf(val);
  1058. return type == 'object' || type == 'array' || type == 'function';
  1059. };
  1060. /**
  1061. * Gets a unique ID for an object. This mutates the object so that further
  1062. * calls with the same object as a parameter returns the same value. The unique
  1063. * ID is guaranteed to be unique across the current session amongst objects that
  1064. * are passed into {@code getUid}. There is no guarantee that the ID is unique
  1065. * or consistent across sessions. It is unsafe to generate unique ID for
  1066. * function prototypes.
  1067. *
  1068. * @param {Object} obj The object to get the unique ID for.
  1069. * @return {number} The unique ID for the object.
  1070. */
  1071. goog.getUid = function(obj) {
  1072. // TODO(user): Make the type stricter, do not accept null.
  1073. // In Opera window.hasOwnProperty exists but always returns false so we avoid
  1074. // using it. As a consequence the unique ID generated for BaseClass.prototype
  1075. // and SubClass.prototype will be the same.
  1076. return obj[goog.UID_PROPERTY_] ||
  1077. (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
  1078. };
  1079. /**
  1080. * Removes the unique ID from an object. This is useful if the object was
  1081. * previously mutated using {@code goog.getUid} in which case the mutation is
  1082. * undone.
  1083. * @param {Object} obj The object to remove the unique ID field from.
  1084. */
  1085. goog.removeUid = function(obj) {
  1086. // TODO(user): Make the type stricter, do not accept null.
  1087. // DOM nodes in IE are not instance of Object and throws exception
  1088. // for delete. Instead we try to use removeAttribute
  1089. if ('removeAttribute' in obj) {
  1090. obj.removeAttribute(goog.UID_PROPERTY_);
  1091. }
  1092. /** @preserveTry */
  1093. try {
  1094. delete obj[goog.UID_PROPERTY_];
  1095. } catch (ex) {
  1096. }
  1097. };
  1098. /**
  1099. * Name for unique ID property. Initialized in a way to help avoid collisions
  1100. * with other closure javascript on the same page.
  1101. * @type {string}
  1102. * @private
  1103. */
  1104. goog.UID_PROPERTY_ = 'closure_uid_' +
  1105. Math.floor(Math.random() * 2147483648).toString(36);
  1106. /**
  1107. * Counter for UID.
  1108. * @type {number}
  1109. * @private
  1110. */
  1111. goog.uidCounter_ = 0;
  1112. /**
  1113. * Adds a hash code field to an object. The hash code is unique for the
  1114. * given object.
  1115. * @param {Object} obj The object to get the hash code for.
  1116. * @return {number} The hash code for the object.
  1117. * @deprecated Use goog.getUid instead.
  1118. */
  1119. goog.getHashCode = goog.getUid;
  1120. /**
  1121. * Removes the hash code field from an object.
  1122. * @param {Object} obj The object to remove the field from.
  1123. * @deprecated Use goog.removeUid instead.
  1124. */
  1125. goog.removeHashCode = goog.removeUid;
  1126. /**
  1127. * Clones a value. The input may be an Object, Array, or basic type. Objects and
  1128. * arrays will be cloned recursively.
  1129. *
  1130. * WARNINGS:
  1131. * <code>goog.cloneObject</code> does not detect reference loops. Objects that
  1132. * refer to themselves will cause infinite recursion.
  1133. *
  1134. * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
  1135. * UIDs created by <code>getUid</code> into cloned results.
  1136. *
  1137. * @param {*} obj The value to clone.
  1138. * @return {*} A clone of the input value.
  1139. * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
  1140. */
  1141. goog.cloneObject = function(obj) {
  1142. var type = goog.typeOf(obj);
  1143. if (type == 'object' || type == 'array') {
  1144. if (obj.clone) {
  1145. return obj.clone();
  1146. }
  1147. var clone = type == 'array' ? [] : {};
  1148. for (var key in obj) {
  1149. clone[key] = goog.cloneObject(obj[key]);
  1150. }
  1151. return clone;
  1152. }
  1153. return obj;
  1154. };
  1155. /**
  1156. * Forward declaration for the clone method. This is necessary until the
  1157. * compiler can better support duck-typing constructs as used in
  1158. * goog.cloneObject.
  1159. *
  1160. * TODO(user): Remove once the JSCompiler can infer that the check for
  1161. * proto.clone is safe in goog.cloneObject.
  1162. *
  1163. * @type {Function}
  1164. */
  1165. Object.prototype.clone;
  1166. /**
  1167. * A native implementation of goog.bind.
  1168. * @param {Function} fn A function to partially apply.
  1169. * @param {Object|undefined} selfObj Specifies the object which |this| should
  1170. * point to when the function is run.
  1171. * @param {...*} var_args Additional arguments that are partially
  1172. * applied to the function.
  1173. * @return {!Function} A partially-applied form of the function bind() was
  1174. * invoked as a method of.
  1175. * @private
  1176. * @suppress {deprecated} The compiler thinks that Function.prototype.bind
  1177. * is deprecated because some people have declared a pure-JS version.
  1178. * Only the pure-JS version is truly deprecated.
  1179. */
  1180. goog.bindNative_ = function(fn, selfObj, var_args) {
  1181. return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
  1182. };
  1183. /**
  1184. * A pure-JS implementation of goog.bind.
  1185. * @param {Function} fn A function to partially apply.
  1186. * @param {Object|undefined} selfObj Specifies the object which |this| should
  1187. * point to when the function is run.
  1188. * @param {...*} var_args Additional arguments that are partially
  1189. * applied to the function.
  1190. * @return {!Function} A partially-applied form of the function bind() was
  1191. * invoked as a method of.
  1192. * @private
  1193. */
  1194. goog.bindJs_ = function(fn, selfObj, var_args) {
  1195. if (!fn) {
  1196. throw new Error();
  1197. }
  1198. if (arguments.length > 2) {
  1199. var boundArgs = Array.prototype.slice.call(arguments, 2);
  1200. return function() {
  1201. // Prepend the bound arguments to the current arguments.
  1202. var newArgs = Array.prototype.slice.call(arguments);
  1203. Array.prototype.unshift.apply(newArgs, boundArgs);
  1204. return fn.apply(selfObj, newArgs);
  1205. };
  1206. } else {
  1207. return function() {
  1208. return fn.apply(selfObj, arguments);
  1209. };
  1210. }
  1211. };
  1212. /**
  1213. * Partially applies this function to a particular 'this object' and zero or
  1214. * more arguments. The result is a new function with some arguments of the first
  1215. * function pre-filled and the value of |this| 'pre-specified'.<br><br>
  1216. *
  1217. * Remaining arguments specified at call-time are appended to the pre-
  1218. * specified ones.<br><br>
  1219. *
  1220. * Also see: {@link #partial}.<br><br>
  1221. *
  1222. * Usage:
  1223. * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
  1224. * barMethBound('arg3', 'arg4');</pre>
  1225. *
  1226. * @param {Function} fn A function to partially apply.
  1227. * @param {Object|undefined} selfObj Specifies the object which |this| should
  1228. * point to when the function is run.
  1229. * @param {...*} var_args Additional arguments that are partially
  1230. * applied to the function.
  1231. * @return {!Function} A partially-applied form of the function bind() was
  1232. * invoked as a method of.
  1233. * @suppress {deprecated} See above.
  1234. */
  1235. goog.bind = function(fn, selfObj, var_args) {
  1236. // TODO(nicksantos): narrow the type signature.
  1237. if (Function.prototype.bind &&
  1238. // NOTE(nicksantos): Somebody pulled base.js into the default
  1239. // Chrome extension environment. This means that for Chrome extensions,
  1240. // they get the implementation of Function.prototype.bind that
  1241. // calls goog.bind instead of the native one. Even worse, we don't want
  1242. // to introduce a circular dependency between goog.bind and
  1243. // Function.prototype.bind, so we have to hack this to make sure it
  1244. // works correctly.
  1245. Function.prototype.bind.toString().indexOf('native code') != -1) {
  1246. goog.bind = goog.bindNative_;
  1247. } else {
  1248. goog.bind = goog.bindJs_;
  1249. }
  1250. return goog.bind.apply(null, arguments);
  1251. };
  1252. /**
  1253. * Like bind(), except that a 'this object' is not required. Useful when the
  1254. * target function is already bound.
  1255. *
  1256. * Usage:
  1257. * var g = partial(f, arg1, arg2);
  1258. * g(arg3, arg4);
  1259. *
  1260. * @param {Function} fn A function to partially apply.
  1261. * @param {...*} var_args Additional arguments that are partially
  1262. * applied to fn.
  1263. * @return {!Function} A partially-applied form of the function bind() was
  1264. * invoked as a method of.
  1265. */
  1266. goog.partial = function(fn, var_args) {
  1267. var args = Array.prototype.slice.call(arguments, 1);
  1268. return function() {
  1269. // Prepend the bound arguments to the current arguments.
  1270. var newArgs = Array.prototype.slice.call(arguments);
  1271. newArgs.unshift.apply(newArgs, args);
  1272. return fn.apply(this, newArgs);
  1273. };
  1274. };
  1275. /**
  1276. * Copies all the members of a source object to a target object. This method
  1277. * does not work on all browsers for all objects that contain keys such as
  1278. * toString or hasOwnProperty. Use goog.object.extend for this purpose.
  1279. * @param {Object} target Target.
  1280. * @param {Object} source Source.
  1281. */
  1282. goog.mixin = function(target, source) {
  1283. for (var x in source) {
  1284. target[x] = source[x];
  1285. }
  1286. // For IE7 or lower, the for-in-loop does not contain any properties that are
  1287. // not enumerable on the prototype object (for example, isPrototypeOf from
  1288. // Object.prototype) but also it will not include 'replace' on objects that
  1289. // extend String and change 'replace' (not that it is common for anyone to
  1290. // extend anything except Object).
  1291. };
  1292. /**
  1293. * @return {number} An integer value representing the number of milliseconds
  1294. * between midnight, January 1, 1970 and the current time.
  1295. */
  1296. goog.now = Date.now || (function() {
  1297. // Unary plus operator converts its operand to a number which in the case of
  1298. // a date is done by calling getTime().
  1299. return +new Date();
  1300. });
  1301. /**
  1302. * Evals javascript in the global scope. In IE this uses execScript, other
  1303. * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
  1304. * global scope (for example, in Safari), appends a script tag instead.
  1305. * Throws an exception if neither execScript or eval is defined.
  1306. * @param {string} script JavaScript string.
  1307. */
  1308. goog.globalEval = function(script) {
  1309. if (goog.global.execScript) {
  1310. goog.global.execScript(script, 'JavaScript');
  1311. } else if (goog.global.eval) {
  1312. // Test to see if eval works
  1313. if (goog.evalWorksForGlobals_ == null) {
  1314. goog.global.eval('var _et_ = 1;');
  1315. if (typeof goog.global['_et_'] != 'undefined') {
  1316. delete goog.global['_et_'];
  1317. goog.evalWorksForGlobals_ = true;
  1318. } else {
  1319. goog.evalWorksForGlobals_ = false;
  1320. }
  1321. }
  1322. if (goog.evalWorksForGlobals_) {
  1323. goog.global.eval(script);
  1324. } else {
  1325. var doc = goog.global.document;
  1326. var scriptElt = doc.createElement('script');
  1327. scriptElt.type = 'text/javascript';
  1328. scriptElt.defer = false;
  1329. // Note(user): can't use .innerHTML since "t('<test>')" will fail and
  1330. // .text doesn't work in Safari 2. Therefore we append a text node.
  1331. scriptElt.appendChild(doc.createTextNode(script));
  1332. doc.body.appendChild(scriptElt);
  1333. doc.body.removeChild(scriptElt);
  1334. }
  1335. } else {
  1336. throw Error('goog.globalEval not available');
  1337. }
  1338. };
  1339. /**
  1340. * Indicates whether or not we can call 'eval' directly to eval code in the
  1341. * global scope. Set to a Boolean by the first call to goog.globalEval (which
  1342. * empirically tests whether eval works for globals). @see goog.globalEval
  1343. * @type {?boolean}
  1344. * @private
  1345. */
  1346. goog.evalWorksForGlobals_ = null;
  1347. /**
  1348. * Optional map of CSS class names to obfuscated names used with
  1349. * goog.getCssName().
  1350. * @type {Object|undefined}
  1351. * @private
  1352. * @see goog.setCssNameMapping
  1353. */
  1354. goog.cssNameMapping_;
  1355. /**
  1356. * Optional obfuscation style for CSS class names. Should be set to either
  1357. * 'BY_WHOLE' or 'BY_PART' if defined.
  1358. * @type {string|undefined}
  1359. * @private
  1360. * @see goog.setCssNameMapping
  1361. */
  1362. goog.cssNameMappingStyle_;
  1363. /**
  1364. * Handles strings that are intended to be used as CSS class names.
  1365. *
  1366. * This function works in tandem with @see goog.setCssNameMapping.
  1367. *
  1368. * Without any mapping set, the arguments are simple joined with a
  1369. * hyphen and passed through unaltered.
  1370. *
  1371. * When there is a mapping, there are two possible styles in which
  1372. * these mappings are used. In the BY_PART style, each part (i.e. in
  1373. * between hyphens) of the passed in css name is rewritten according
  1374. * to the map. In the BY_WHOLE style, the full css name is looked up in
  1375. * the map directly. If a rewrite is not specified by the map, the
  1376. * compiler will output a warning.
  1377. *
  1378. * When the mapping is passed to the compiler, it will replace calls
  1379. * to goog.getCssName with the strings from the mapping, e.g.
  1380. * var x = goog.getCssName('foo');
  1381. * var y = goog.getCssName(this.baseClass, 'active');
  1382. * becomes:
  1383. * var x= 'foo';
  1384. * var y = this.baseClass + '-active';
  1385. *
  1386. * If one argument is passed it will be processed, if two are passed
  1387. * only the modifier will be processed, as it is assumed the first
  1388. * argument was generated as a result of calling goog.getCssName.
  1389. *
  1390. * @param {string} className The class name.
  1391. * @param {string=} opt_modifier A modifier to be appended to the class name.