| OLD | NEW |
| (Empty) |
| 1 // Copyright 2006 Google Inc. | |
| 2 // All Rights Reserved. | |
| 3 // | |
| 4 // Redistribution and use in source and binary forms, with or without | |
| 5 // modification, are permitted provided that the following conditions | |
| 6 // are met: | |
| 7 // | |
| 8 // * Redistributions of source code must retain the above copyright | |
| 9 // notice, this list of conditions and the following disclaimer. | |
| 10 // * Redistributions in binary form must reproduce the above copyright | |
| 11 // notice, this list of conditions and the following disclaimer in | |
| 12 // the documentation and/or other materials provided with the | |
| 13 // distribution. | |
| 14 // | |
| 15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 18 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 19 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 21 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 25 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 26 // POSSIBILITY OF SUCH DAMAGE. | |
| 27 | |
| 28 // NOTE: This file has been changed from the one on doctype. The following | |
| 29 // changes were made: | |
| 30 // - Removed goog.globalEval because it calls eval() which is not allowed from | |
| 31 // inside v8 extensions. If we ever need to use globalEval, we will need to | |
| 32 // find a way to work around this problem. | |
| 33 // - Remove Function.prototype.apply() emulation for the same reason. This one | |
| 34 // is useless anyway because V8 supports apply() natively. | |
| 35 | |
| 36 /** | |
| 37 * @fileoverview Bootstrap for the Google JS Library | |
| 38 */ | |
| 39 | |
| 40 /** | |
| 41 * @define {boolean} Overridden to true by the compiler when | |
| 42 * --mark_as_compiled is specified. | |
| 43 */ | |
| 44 var COMPILED = true; | |
| 45 | |
| 46 | |
| 47 /** | |
| 48 * Base namespace for the Google JS library. Checks to see goog is | |
| 49 * already defined in the current scope before assigning to prevent | |
| 50 * clobbering if base.js is loaded more than once. | |
| 51 */ | |
| 52 var goog = {}; // Check to see if already defined in current scope | |
| 53 | |
| 54 | |
| 55 /** | |
| 56 * Reference to the global context. In most cases this will be 'window'. | |
| 57 */ | |
| 58 goog.global = this; | |
| 59 | |
| 60 | |
| 61 /** | |
| 62 * Indicates whether or not we can call 'eval' directly to eval code in the | |
| 63 * global scope. Set to a Boolean by the first call to goog.globalEval (which | |
| 64 * empirically tests whether eval works for globals). @see goog.globalEval | |
| 65 * @type {boolean?} | |
| 66 * @private | |
| 67 */ | |
| 68 goog.evalWorksForGlobals_ = null; | |
| 69 | |
| 70 | |
| 71 /** | |
| 72 * Creates object stubs for a namespace. When present in a file, goog.provide | |
| 73 * also indicates that the file defines the indicated object. | |
| 74 * @param {string} name name of the object that this file defines. | |
| 75 */ | |
| 76 goog.provide = function(name) { | |
| 77 if (!COMPILED) { | |
| 78 // Ensure that the same namespace isn't provided twice. This is intended | |
| 79 // to teach new developers that 'goog.provide' is effectively a variable | |
| 80 // declaration. And when JSCompiler transforms goog.provide into a real | |
| 81 // variable declaration, the compiled JS should work the same as the raw | |
| 82 // JS--even when the raw JS uses goog.provide incorrectly. | |
| 83 if (goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) { | |
| 84 throw 'Namespace "' + name + '" already declared.'; | |
| 85 } | |
| 86 | |
| 87 var namespace = name; | |
| 88 while ((namespace = namespace.substr(0, namespace.lastIndexOf('.')))) { | |
| 89 goog.implicitNamespaces_[namespace] = true; | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 goog.exportPath_(name); | |
| 94 }; | |
| 95 | |
| 96 | |
| 97 if (!COMPILED) { | |
| 98 /** | |
| 99 * Namespaces implicitly defined by goog.provide. For example, | |
| 100 * goog.provide('goog.events.Event') implicitly declares | |
| 101 * that 'goog' and 'goog.events' must be namespaces. | |
| 102 * | |
| 103 * @type {Object} | |
| 104 * @private | |
| 105 */ | |
| 106 goog.implicitNamespaces_ = {}; | |
| 107 } | |
| 108 | |
| 109 | |
| 110 /** | |
| 111 * Builds an object structure for the provided namespace path, | |
| 112 * ensuring that names that already exist are not overwritten. For | |
| 113 * example: | |
| 114 * "a.b.c" -> a = {};a.b={};a.b.c={}; | |
| 115 * Used by goog.provide and goog.exportSymbol. | |
| 116 * @param {string} name name of the object that this file defines. | |
| 117 * @param {Object} opt_object the object to expose at the end of the path. | |
| 118 * @private | |
| 119 */ | |
| 120 goog.exportPath_ = function(name, opt_object) { | |
| 121 var parts = name.split('.'); | |
| 122 var cur = goog.global; | |
| 123 var part; | |
| 124 | |
| 125 // Internet Explorer exhibits strange behavior when throwing errors from | |
| 126 // methods externed in this manner. See the testExportSymbolExceptions in | |
| 127 // base_test.html for an example. | |
| 128 if (!(parts[0] in cur) && cur.execScript) { | |
| 129 cur.execScript('var ' + parts[0]); | |
| 130 } | |
| 131 | |
| 132 // Parentheses added to eliminate strict JS warning in Firefox. | |
| 133 while ((part = parts.shift())) { | |
| 134 if (!parts.length && goog.isDef(opt_object)) { | |
| 135 // last part and we have an object; use it | |
| 136 cur[part] = opt_object; | |
| 137 } else if (cur[part]) { | |
| 138 cur = cur[part]; | |
| 139 } else { | |
| 140 cur = cur[part] = {}; | |
| 141 } | |
| 142 } | |
| 143 }; | |
| 144 | |
| 145 | |
| 146 /** | |
| 147 * Returns an object based on its fully qualified name | |
| 148 * @param {string} name The fully qualified name. | |
| 149 * @return {Object?} The object or, if not found, null. | |
| 150 */ | |
| 151 goog.getObjectByName = function(name) { | |
| 152 var parts = name.split('.'); | |
| 153 var cur = goog.global; | |
| 154 for (var part; part = parts.shift(); ) { | |
| 155 if (cur[part]) { | |
| 156 cur = cur[part]; | |
| 157 } else { | |
| 158 return null; | |
| 159 } | |
| 160 } | |
| 161 return cur; | |
| 162 }; | |
| 163 | |
| 164 | |
| 165 /** | |
| 166 * Globalizes a whole namespace, such as goog or goog.lang. | |
| 167 * | |
| 168 * @param {Object} obj The namespace to globalize. | |
| 169 * @param {Object} opt_global The object to add the properties to. | |
| 170 * @deprecated Properties may be explicitly exported to the global scope, but | |
| 171 * this should no longer be done in bulk. | |
| 172 */ | |
| 173 goog.globalize = function(obj, opt_global) { | |
| 174 var global = opt_global || goog.global; | |
| 175 for (var x in obj) { | |
| 176 global[x] = obj[x]; | |
| 177 } | |
| 178 }; | |
| 179 | |
| 180 | |
| 181 /** | |
| 182 * Adds a dependency from a file to the files it requires. | |
| 183 * @param {string} relPath The path to the js file. | |
| 184 * @param {Array} provides An array of strings with the names of the objects | |
| 185 * this file provides. | |
| 186 * @param {Array} requires An array of strings with the names of the objects | |
| 187 * this file requires. | |
| 188 */ | |
| 189 goog.addDependency = function(relPath, provides, requires) { | |
| 190 if (!COMPILED) { | |
| 191 var provide, require; | |
| 192 var path = relPath.replace(/\\/g, '/'); | |
| 193 var deps = goog.dependencies_; | |
| 194 for (var i = 0; provide = provides[i]; i++) { | |
| 195 deps.nameToPath[provide] = path; | |
| 196 if (!(path in deps.pathToNames)) { | |
| 197 deps.pathToNames[path] = {}; | |
| 198 } | |
| 199 deps.pathToNames[path][provide] = true; | |
| 200 } | |
| 201 for (var j = 0; require = requires[j]; j++) { | |
| 202 if (!(path in deps.requires)) { | |
| 203 deps.requires[path] = {}; | |
| 204 } | |
| 205 deps.requires[path][require] = true; | |
| 206 } | |
| 207 } | |
| 208 }; | |
| 209 | |
| 210 | |
| 211 /** | |
| 212 * Implements a system for the dynamic resolution of dependencies | |
| 213 * that works in parallel with the BUILD system. | |
| 214 * @param {string} rule Rule to include, in the form goog.package.part. | |
| 215 */ | |
| 216 goog.require = function(rule) { | |
| 217 | |
| 218 // if the object already exists we do not need do do anything | |
| 219 if (!COMPILED) { | |
| 220 if (goog.getObjectByName(rule)) { | |
| 221 return; | |
| 222 } | |
| 223 var path = goog.getPathFromDeps_(rule); | |
| 224 if (path) { | |
| 225 goog.included_[path] = true; | |
| 226 goog.writeScripts_(); | |
| 227 } else { | |
| 228 // NOTE(nicksantos): We could throw an error, but this would break | |
| 229 // legacy users that depended on this failing silently. Instead, the | |
| 230 // compiler should warn us when there are invalid goog.require calls. | |
| 231 } | |
| 232 } | |
| 233 }; | |
| 234 | |
| 235 | |
| 236 /** | |
| 237 * Path for included scripts | |
| 238 * @type {string} | |
| 239 */ | |
| 240 goog.basePath = ''; | |
| 241 | |
| 242 | |
| 243 /** | |
| 244 * Null function used for default values of callbacks, etc. | |
| 245 * @type {Function} | |
| 246 */ | |
| 247 goog.nullFunction = function() {}; | |
| 248 | |
| 249 | |
| 250 /** | |
| 251 * When defining a class Foo with an abstract method bar(), you can do: | |
| 252 * | |
| 253 * Foo.prototype.bar = goog.abstractMethod | |
| 254 * | |
| 255 * Now if a subclass of Foo fails to override bar(), an error | |
| 256 * will be thrown when bar() is invoked. | |
| 257 * | |
| 258 * Note: This does not take the name of the function to override as | |
| 259 * an argument because that would make it more difficult to obfuscate | |
| 260 * our JavaScript code. | |
| 261 * | |
| 262 * @throws {Error} when invoked to indicate the method should be | |
| 263 * overridden. | |
| 264 */ | |
| 265 goog.abstractMethod = function() { | |
| 266 throw Error('unimplemented abstract method'); | |
| 267 }; | |
| 268 | |
| 269 | |
| 270 if (!COMPILED) { | |
| 271 /** | |
| 272 * Object used to keep track of urls that have already been added. This | |
| 273 * record allows the prevention of circular dependencies. | |
| 274 * @type {Object} | |
| 275 * @private | |
| 276 */ | |
| 277 goog.included_ = {}; | |
| 278 | |
| 279 | |
| 280 /** | |
| 281 * This object is used to keep track of dependencies and other data that is | |
| 282 * used for loading scripts | |
| 283 * @private | |
| 284 * @type {Object} | |
| 285 */ | |
| 286 goog.dependencies_ = { | |
| 287 pathToNames: {}, // 1 to many | |
| 288 nameToPath: {}, // 1 to 1 | |
| 289 requires: {}, // 1 to many | |
| 290 visited: {}, // used when resolving dependencies to prevent us from | |
| 291 // visiting the file twice | |
| 292 written: {} // used to keep track of script files we have written | |
| 293 }; | |
| 294 | |
| 295 | |
| 296 /** | |
| 297 * Tries to detect the base path of the base.js script that bootstraps | |
| 298 * Google JS Library | |
| 299 * @private | |
| 300 */ | |
| 301 goog.findBasePath_ = function() { | |
| 302 var doc = goog.global.document; | |
| 303 if (typeof doc == 'undefined') { | |
| 304 return; | |
| 305 } | |
| 306 if (goog.global.GOOG_BASE_PATH) { | |
| 307 goog.basePath = goog.global.GOOG_BASE_PATH; | |
| 308 return; | |
| 309 } else { | |
| 310 goog.global.GOOG_BASE_PATH = null; | |
| 311 } | |
| 312 var scripts = doc.getElementsByTagName('script'); | |
| 313 for (var script, i = 0; script = scripts[i]; i++) { | |
| 314 var src = script.src; | |
| 315 var l = src.length; | |
| 316 if (src.substr(l - 7) == 'base.js') { | |
| 317 goog.basePath = src.substr(0, l - 7); | |
| 318 return; | |
| 319 } | |
| 320 } | |
| 321 }; | |
| 322 | |
| 323 | |
| 324 /** | |
| 325 * Writes a script tag if, and only if, that script hasn't already been added | |
| 326 * to the document. (Must be called at execution time) | |
| 327 * @param {string} src Script source. | |
| 328 * @private | |
| 329 */ | |
| 330 goog.writeScriptTag_ = function(src) { | |
| 331 var doc = goog.global.document; | |
| 332 if (typeof doc != 'undefined' && | |
| 333 !goog.dependencies_.written[src]) { | |
| 334 goog.dependencies_.written[src] = true; | |
| 335 doc.write('<script type="text/javascript" src="' + | |
| 336 src + '"></' + 'script>'); | |
| 337 } | |
| 338 }; | |
| 339 | |
| 340 | |
| 341 /** | |
| 342 * Resolves dependencies based on the dependencies added using addDependency | |
| 343 * and calls writeScriptTag_ in the correct order. | |
| 344 * @private | |
| 345 */ | |
| 346 goog.writeScripts_ = function() { | |
| 347 // the scripts we need to write this time | |
| 348 var scripts = []; | |
| 349 var seenScript = {}; | |
| 350 var deps = goog.dependencies_; | |
| 351 | |
| 352 function visitNode(path) { | |
| 353 if (path in deps.written) { | |
| 354 return; | |
| 355 } | |
| 356 | |
| 357 // we have already visited this one. We can get here if we have cyclic | |
| 358 // dependencies | |
| 359 if (path in deps.visited) { | |
| 360 if (!(path in seenScript)) { | |
| 361 seenScript[path] = true; | |
| 362 scripts.push(path); | |
| 363 } | |
| 364 return; | |
| 365 } | |
| 366 | |
| 367 deps.visited[path] = true; | |
| 368 | |
| 369 if (path in deps.requires) { | |
| 370 for (var requireName in deps.requires[path]) { | |
| 371 visitNode(deps.nameToPath[requireName]); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 if (!(path in seenScript)) { | |
| 376 seenScript[path] = true; | |
| 377 scripts.push(path); | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 for (var path in goog.included_) { | |
| 382 if (!deps.written[path]) { | |
| 383 visitNode(path); | |
| 384 } | |
| 385 } | |
| 386 | |
| 387 for (var i = 0; i < scripts.length; i++) { | |
| 388 if (scripts[i]) { | |
| 389 goog.writeScriptTag_(goog.basePath + scripts[i]); | |
| 390 } else { | |
| 391 throw Error('Undefined script input'); | |
| 392 } | |
| 393 } | |
| 394 }; | |
| 395 | |
| 396 | |
| 397 /** | |
| 398 * Looks at the dependency rules and tries to determine the script file that | |
| 399 * fulfills a particular rule. | |
| 400 * @param {string} rule In the form goog.namespace.Class or project.script. | |
| 401 * @return {string?} Url corresponding to the rule, or null. | |
| 402 * @private | |
| 403 */ | |
| 404 goog.getPathFromDeps_ = function(rule) { | |
| 405 if (rule in goog.dependencies_.nameToPath) { | |
| 406 return goog.dependencies_.nameToPath[rule]; | |
| 407 } else { | |
| 408 return null; | |
| 409 } | |
| 410 }; | |
| 411 | |
| 412 goog.findBasePath_(); | |
| 413 goog.writeScriptTag_(goog.basePath + 'deps.js'); | |
| 414 } | |
| 415 | |
| 416 | |
| 417 | |
| 418 //============================================================================== | |
| 419 // Language Enhancements | |
| 420 //============================================================================== | |
| 421 | |
| 422 | |
| 423 /** | |
| 424 * This is a "fixed" version of the typeof operator. It differs from the typeof | |
| 425 * operator in such a way that null returns 'null' and arrays return 'array'. | |
| 426 * @param {*} value The value to get the type of. | |
| 427 * @return {string} The name of the type. | |
| 428 */ | |
| 429 goog.typeOf = function(value) { | |
| 430 var s = typeof value; | |
| 431 if (s == 'object') { | |
| 432 if (value) { | |
| 433 // We cannot use constructor == Array or instanceof Array because | |
| 434 // different frames have different Array objects. In IE6, if the iframe | |
| 435 // where the array was created is destroyed, the array loses its | |
| 436 // prototype. Then dereferencing val.splice here throws an exception, so | |
| 437 // we can't use goog.isFunction. Calling typeof directly returns 'unknown' | |
| 438 // so that will work. In this case, this function will return false and | |
| 439 // most array functions will still work because the array is still | |
| 440 // array-like (supports length and []) even though it has lost its | |
| 441 // prototype. Custom object cannot have non enumerable length and | |
| 442 // NodeLists don't have a slice method. | |
| 443 if (typeof value.length == 'number' && | |
| 444 typeof value.splice != 'undefined' && | |
| 445 !goog.propertyIsEnumerable_(value, 'length')) { | |
| 446 return 'array'; | |
| 447 } | |
| 448 | |
| 449 // IE in cross-window calls does not correctly marshal the function type | |
| 450 // (it appears just as an object) so we cannot use just typeof val == | |
| 451 // 'function'. However, if the object has a call property, it is a | |
| 452 // function. | |
| 453 if (typeof value.call != 'undefined') { | |
| 454 return 'function'; | |
| 455 } | |
| 456 } else { | |
| 457 return 'null'; | |
| 458 } | |
| 459 | |
| 460 // In Safari typeof nodeList returns function. We would like to return | |
| 461 // object for those and we can detect an invalid function by making sure that | |
| 462 // the function object has a call method | |
| 463 } else if (s == 'function' && typeof value.call == 'undefined') { | |
| 464 return 'object'; | |
| 465 } | |
| 466 return s; | |
| 467 }; | |
| 468 | |
| 469 if (Object.prototype.propertyIsEnumerable) { | |
| 470 /** | |
| 471 * Safe way to test whether a property is enumarable. It allows testing | |
| 472 * for enumarable on objects where 'propertyIsEnumerable' is overridden or | |
| 473 * does not exist (like DOM nodes in IE). | |
| 474 * @param {Object} object The object to test if the property is enumerable. | |
| 475 * @param {string} propName The property name to check for. | |
| 476 * @return {boolean} True if the property is enumarable. | |
| 477 * @private | |
| 478 */ | |
| 479 goog.propertyIsEnumerable_ = function(object, propName) { | |
| 480 return Object.prototype.propertyIsEnumerable.call(object, propName); | |
| 481 }; | |
| 482 } else { | |
| 483 /** | |
| 484 * Safe way to test whether a property is enumarable. It allows testing | |
| 485 * for enumarable on objects where 'propertyIsEnumerable' is overridden or | |
| 486 * does not exist (like DOM nodes in IE). | |
| 487 * @param {Object} object The object to test if the property is enumerable. | |
| 488 * @param {string} propName The property name to check for. | |
| 489 * @return {boolean} True if the property is enumarable. | |
| 490 * @private | |
| 491 */ | |
| 492 goog.propertyIsEnumerable_ = function(object, propName) { | |
| 493 // KJS in Safari 2 is not ECMAScript compatible and lacks crucial methods | |
| 494 // such as propertyIsEnumerable. We therefore use a workaround. | |
| 495 // Does anyone know a more efficient work around? | |
| 496 if (propName in object) { | |
| 497 for (var key in object) { | |
| 498 if (key == propName) { | |
| 499 return true; | |
| 500 } | |
| 501 } | |
| 502 } | |
| 503 return false; | |
| 504 }; | |
| 505 } | |
| 506 | |
| 507 /** | |
| 508 * Returns true if the specified value is not |undefined|. | |
| 509 * WARNING: Do not use this to test if an object has a property. Use the in | |
| 510 * operator instead. | |
| 511 * @param {*} val Variable to test. | |
| 512 * @return {boolean} Whether variable is defined. | |
| 513 */ | |
| 514 goog.isDef = function(val) { | |
| 515 return typeof val != 'undefined'; | |
| 516 }; | |
| 517 | |
| 518 | |
| 519 /** | |
| 520 * Returns true if the specified value is |null| | |
| 521 * @param {*} val Variable to test. | |
| 522 * @return {boolean} Whether variable is null. | |
| 523 */ | |
| 524 goog.isNull = function(val) { | |
| 525 return val === null; | |
| 526 }; | |
| 527 | |
| 528 | |
| 529 /** | |
| 530 * Returns true if the specified value is defined and not null | |
| 531 * @param {*} val Variable to test. | |
| 532 * @return {boolean} Whether variable is defined and not null. | |
| 533 */ | |
| 534 goog.isDefAndNotNull = function(val) { | |
| 535 return goog.isDef(val) && !goog.isNull(val); | |
| 536 }; | |
| 537 | |
| 538 | |
| 539 /** | |
| 540 * Returns true if the specified value is an array | |
| 541 * @param {*} val Variable to test. | |
| 542 * @return {boolean} Whether variable is an array. | |
| 543 */ | |
| 544 goog.isArray = function(val) { | |
| 545 return goog.typeOf(val) == 'array'; | |
| 546 }; | |
| 547 | |
| 548 | |
| 549 /** | |
| 550 * Returns true if the object looks like an array. To qualify as array like | |
| 551 * the value needs to be either a NodeList or an object with a Number length | |
| 552 * property. | |
| 553 * @param {*} val Variable to test. | |
| 554 * @return {boolean} Whether variable is an array. | |
| 555 */ | |
| 556 goog.isArrayLike = function(val) { | |
| 557 var type = goog.typeOf(val); | |
| 558 return type == 'array' || type == 'object' && typeof val.length == 'number'; | |
| 559 }; | |
| 560 | |
| 561 | |
| 562 /** | |
| 563 * Returns true if the object looks like a Date. To qualify as Date-like | |
| 564 * the value needs to be an object and have a getFullYear() function. | |
| 565 * @param {*} val Variable to test. | |
| 566 * @return {boolean} Whether variable is a like a Date. | |
| 567 */ | |
| 568 goog.isDateLike = function(val) { | |
| 569 return goog.isObject(val) && typeof val.getFullYear == 'function'; | |
| 570 }; | |
| 571 | |
| 572 | |
| 573 /** | |
| 574 * Returns true if the specified value is a string | |
| 575 * @param {*} val Variable to test. | |
| 576 * @return {boolean} Whether variable is a string. | |
| 577 */ | |
| 578 goog.isString = function(val) { | |
| 579 return typeof val == 'string'; | |
| 580 }; | |
| 581 | |
| 582 | |
| 583 /** | |
| 584 * Returns true if the specified value is a boolean | |
| 585 * @param {*} val Variable to test. | |
| 586 * @return {boolean} Whether variable is boolean. | |
| 587 */ | |
| 588 goog.isBoolean = function(val) { | |
| 589 return typeof val == 'boolean'; | |
| 590 }; | |
| 591 | |
| 592 | |
| 593 /** | |
| 594 * Returns true if the specified value is a number | |
| 595 * @param {*} val Variable to test. | |
| 596 * @return {boolean} Whether variable is a number. | |
| 597 */ | |
| 598 goog.isNumber = function(val) { | |
| 599 return typeof val == 'number'; | |
| 600 }; | |
| 601 | |
| 602 | |
| 603 /** | |
| 604 * Returns true if the specified value is a function | |
| 605 * @param {*} val Variable to test. | |
| 606 * @return {boolean} Whether variable is a function. | |
| 607 */ | |
| 608 goog.isFunction = function(val) { | |
| 609 return goog.typeOf(val) == 'function'; | |
| 610 }; | |
| 611 | |
| 612 | |
| 613 /** | |
| 614 * Returns true if the specified value is an object. This includes arrays | |
| 615 * and functions. | |
| 616 * @param {*} val Variable to test. | |
| 617 * @return {boolean} Whether variable is an object. | |
| 618 */ | |
| 619 goog.isObject = function(val) { | |
| 620 var type = goog.typeOf(val); | |
| 621 return type == 'object' || type == 'array' || type == 'function'; | |
| 622 }; | |
| 623 | |
| 624 | |
| 625 /** | |
| 626 * Adds a hash code field to an object. The hash code is unique for the | |
| 627 * given object. | |
| 628 * @param {Object} obj The object to get the hash code for. | |
| 629 * @return {number} The hash code for the object. | |
| 630 */ | |
| 631 goog.getHashCode = function(obj) { | |
| 632 // In IE, DOM nodes do not extend Object so they do not have this method. | |
| 633 // we need to check hasOwnProperty because the proto might have this set. | |
| 634 | |
| 635 if (obj.hasOwnProperty && obj.hasOwnProperty(goog.HASH_CODE_PROPERTY_)) { | |
| 636 return obj[goog.HASH_CODE_PROPERTY_]; | |
| 637 } | |
| 638 if (!obj[goog.HASH_CODE_PROPERTY_]) { | |
| 639 obj[goog.HASH_CODE_PROPERTY_] = ++goog.hashCodeCounter_; | |
| 640 } | |
| 641 return obj[goog.HASH_CODE_PROPERTY_]; | |
| 642 }; | |
| 643 | |
| 644 | |
| 645 /** | |
| 646 * Removes the hash code field from an object. | |
| 647 * @param {Object} obj The object to remove the field from. | |
| 648 */ | |
| 649 goog.removeHashCode = function(obj) { | |
| 650 // DOM nodes in IE are not instance of Object and throws exception | |
| 651 // for delete. Instead we try to use removeAttribute | |
| 652 if ('removeAttribute' in obj) { | |
| 653 obj.removeAttribute(goog.HASH_CODE_PROPERTY_); | |
| 654 } | |
| 655 /** @preserveTry */ | |
| 656 try { | |
| 657 delete obj[goog.HASH_CODE_PROPERTY_]; | |
| 658 } catch (ex) { | |
| 659 } | |
| 660 }; | |
| 661 | |
| 662 | |
| 663 /** | |
| 664 * {String} Name for hash code property | |
| 665 * @private | |
| 666 */ | |
| 667 goog.HASH_CODE_PROPERTY_ = 'goog_hashCode_'; | |
| 668 | |
| 669 | |
| 670 /** | |
| 671 * @type {number} Counter for hash codes. | |
| 672 * @private | |
| 673 */ | |
| 674 goog.hashCodeCounter_ = 0; | |
| 675 | |
| 676 | |
| 677 /** | |
| 678 * Clone an object/array (recursively) | |
| 679 * @param {Object} proto Object to clone. | |
| 680 * @return {Object} Clone of x;. | |
| 681 */ | |
| 682 goog.cloneObject = function(proto) { | |
| 683 var type = goog.typeOf(proto); | |
| 684 if (type == 'object' || type == 'array') { | |
| 685 if (proto.clone) { | |
| 686 return proto.clone(); | |
| 687 } | |
| 688 var clone = type == 'array' ? [] : {}; | |
| 689 for (var key in proto) { | |
| 690 clone[key] = goog.cloneObject(proto[key]); | |
| 691 } | |
| 692 return clone; | |
| 693 } | |
| 694 | |
| 695 return proto; | |
| 696 }; | |
| 697 | |
| 698 | |
| 699 /** | |
| 700 * Partially applies this function to a particular 'this object' and zero or | |
| 701 * more arguments. The result is a new function with some arguments of the first | |
| 702 * function pre-filled and the value of |this| 'pre-specified'.<br><br> | |
| 703 * | |
| 704 * Remaining arguments specified at call-time are appended to the pre- | |
| 705 * specified ones.<br><br> | |
| 706 * | |
| 707 * Also see: {@link #partial}.<br><br> | |
| 708 * | |
| 709 * Note that bind and partial are optimized such that repeated calls to it do | |
| 710 * not create more than one function object, so there is no additional cost for | |
| 711 * something like:<br> | |
| 712 * | |
| 713 * <pre>var g = bind(f, obj); | |
| 714 * var h = partial(g, 1, 2, 3); | |
| 715 * var k = partial(h, a, b, c);</pre> | |
| 716 * | |
| 717 * Usage: | |
| 718 * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2'); | |
| 719 * barMethBound('arg3', 'arg4');</pre> | |
| 720 * | |
| 721 * @param {Function} fn A function to partially apply. | |
| 722 * @param {Object} self Specifies the object which |this| should point to | |
| 723 * when the function is run. If the value is null or undefined, it will | |
| 724 * default to the global object. | |
| 725 * @param {Object} var_args Additional arguments that are partially | |
| 726 * applied to the function. | |
| 727 * | |
| 728 * @return {Function} A partially-applied form of the function bind() was | |
| 729 * invoked as a method of. | |
| 730 */ | |
| 731 goog.bind = function(fn, self, var_args) { | |
| 732 var boundArgs = fn.boundArgs_; | |
| 733 | |
| 734 if (arguments.length > 2) { | |
| 735 var args = Array.prototype.slice.call(arguments, 2); | |
| 736 if (boundArgs) { | |
| 737 args.unshift.apply(args, boundArgs); | |
| 738 } | |
| 739 boundArgs = args; | |
| 740 } | |
| 741 | |
| 742 self = fn.boundSelf_ || self; | |
| 743 fn = fn.boundFn_ || fn; | |
| 744 | |
| 745 var newfn; | |
| 746 var context = self || goog.global; | |
| 747 | |
| 748 if (boundArgs) { | |
| 749 newfn = function() { | |
| 750 // Combine the static args and the new args into one big array | |
| 751 var args = Array.prototype.slice.call(arguments); | |
| 752 args.unshift.apply(args, boundArgs); | |
| 753 return fn.apply(context, args); | |
| 754 } | |
| 755 } else { | |
| 756 newfn = function() { | |
| 757 return fn.apply(context, arguments); | |
| 758 } | |
| 759 } | |
| 760 | |
| 761 newfn.boundArgs_ = boundArgs; | |
| 762 newfn.boundSelf_ = self; | |
| 763 newfn.boundFn_ = fn; | |
| 764 | |
| 765 return newfn; | |
| 766 }; | |
| 767 | |
| 768 | |
| 769 /** | |
| 770 * Like bind(), except that a 'this object' is not required. Useful when the | |
| 771 * target function is already bound. | |
| 772 * | |
| 773 * Usage: | |
| 774 * var g = partial(f, arg1, arg2); | |
| 775 * g(arg3, arg4); | |
| 776 * | |
| 777 * @param {Function} fn A function to partially apply. | |
| 778 * @param {Object} var_args Additional arguments that are partially | |
| 779 * applied to fn. | |
| 780 * @return {Function} A partially-applied form of the function bind() was | |
| 781 * invoked as a method of. | |
| 782 */ | |
| 783 goog.partial = function(fn, var_args) { | |
| 784 var args = Array.prototype.slice.call(arguments, 1); | |
| 785 args.unshift(fn, null); | |
| 786 return goog.bind.apply(null, args); | |
| 787 }; | |
| 788 | |
| 789 | |
| 790 /** | |
| 791 * Copies all the members of a source object to a target object. | |
| 792 * This is deprecated. Use goog.object.extend instead. | |
| 793 * @param {Object} target Target. | |
| 794 * @param {Object} source Source. | |
| 795 * @deprecated | |
| 796 */ | |
| 797 goog.mixin = function(target, source) { | |
| 798 for (var x in source) { | |
| 799 target[x] = source[x]; | |
| 800 } | |
| 801 | |
| 802 // For IE the for-in-loop does not contain any properties that are not | |
| 803 // enumerable on the prototype object (for example, isPrototypeOf from | |
| 804 // Object.prototype) but also it will not include 'replace' on objects that | |
| 805 // extend String and change 'replace' (not that it is common for anyone to | |
| 806 // extend anything except Object). | |
| 807 }; | |
| 808 | |
| 809 | |
| 810 /** | |
| 811 * A simple wrapper for new Date().getTime(). | |
| 812 * | |
| 813 * @return {number} An integer value representing the number of milliseconds | |
| 814 * between midnight, January 1, 1970 and the current time. | |
| 815 */ | |
| 816 goog.now = Date.now || (function() { | |
| 817 return new Date().getTime(); | |
| 818 }); | |
| 819 | |
| 820 | |
| 821 /** | |
| 822 * Abstract implementation of goog.getMsg for use with localized messages | |
| 823 * @param {string} str Translatable string, places holders in the form.{$foo} | |
| 824 * @param {Object} opt_values Map of place holder name to value. | |
| 825 */ | |
| 826 goog.getMsg = function(str, opt_values) { | |
| 827 var values = opt_values || {}; | |
| 828 for (var key in values) { | |
| 829 str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), values[key]); | |
| 830 } | |
| 831 return str; | |
| 832 }; | |
| 833 | |
| 834 | |
| 835 /** | |
| 836 * Exposes an unobfuscated global namespace path for the given object. | |
| 837 * Note that fields of the exported object *will* be obfuscated, | |
| 838 * unless they are exported in turn via this function or | |
| 839 * goog.exportProperty | |
| 840 * | |
| 841 * <p>Also handy for making public items that are defined in anonymous | |
| 842 * closures. | |
| 843 * | |
| 844 * ex. goog.exportSymbol('Foo', Foo); | |
| 845 * | |
| 846 * ex. goog.exportSymbol('public.path.Foo.staticFunction', | |
| 847 * Foo.staticFunction); | |
| 848 * public.path.Foo.staticFunction(); | |
| 849 * | |
| 850 * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod', | |
| 851 * Foo.prototype.myMethod); | |
| 852 * new public.path.Foo().myMethod(); | |
| 853 * | |
| 854 * @param {string} publicPath Unobfuscated name to export. | |
| 855 * @param {Object} object Object the name should point to. | |
| 856 */ | |
| 857 goog.exportSymbol = function(publicPath, object) { | |
| 858 goog.exportPath_(publicPath, object); | |
| 859 }; | |
| 860 | |
| 861 | |
| 862 /** | |
| 863 * Exports a property unobfuscated into the object's namespace. | |
| 864 * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction); | |
| 865 * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod); | |
| 866 * @param {Object} object Object whose static property is being exported. | |
| 867 * @param {string} publicName Unobfuscated name to export. | |
| 868 * @param {Object} symbol Object the name should point to. | |
| 869 */ | |
| 870 goog.exportProperty = function(object, publicName, symbol) { | |
| 871 object[publicName] = symbol; | |
| 872 }; | |
| 873 | |
| 874 | |
| 875 | |
| 876 //============================================================================== | |
| 877 // Extending Function | |
| 878 //============================================================================== | |
| 879 | |
| 880 | |
| 881 /** | |
| 882 * An alias to the {@link goog.bind()} global function. | |
| 883 * | |
| 884 * Usage: | |
| 885 * var g = f.bind(obj, arg1, arg2); | |
| 886 * g(arg3, arg4); | |
| 887 * | |
| 888 * @param {Object} self Specifies the object to which |this| should point | |
| 889 * when the function is run. If the value is null or undefined, it will | |
| 890 * default to the global object. | |
| 891 * @param {Object} var_args Additional arguments that are partially | |
| 892 * applied to fn. | |
| 893 * @return {Function} A partially-applied form of the Function on which bind() | |
| 894 * was invoked as a method. | |
| 895 * @deprecated | |
| 896 */ | |
| 897 Function.prototype.bind = function(self, var_args) { | |
| 898 if (arguments.length > 1) { | |
| 899 var args = Array.prototype.slice.call(arguments, 1); | |
| 900 args.unshift(this, self); | |
| 901 return goog.bind.apply(null, args); | |
| 902 } else { | |
| 903 return goog.bind(this, self); | |
| 904 } | |
| 905 }; | |
| 906 | |
| 907 | |
| 908 /** | |
| 909 * An alias to the {@link goog.partial()} global function. | |
| 910 * | |
| 911 * Usage: | |
| 912 * var g = f.partial(arg1, arg2); | |
| 913 * g(arg3, arg4); | |
| 914 * | |
| 915 * @param {Object} var_args Additional arguments that are partially | |
| 916 * applied to fn. | |
| 917 * @return {Function} A partially-applied form of the function partial() was | |
| 918 * invoked as a method of. | |
| 919 * @deprecated | |
| 920 */ | |
| 921 Function.prototype.partial = function(var_args) { | |
| 922 var args = Array.prototype.slice.call(arguments); | |
| 923 args.unshift(this, null); | |
| 924 return goog.bind.apply(null, args); | |
| 925 }; | |
| 926 | |
| 927 | |
| 928 /** | |
| 929 * Inherit the prototype methods from one constructor into another. | |
| 930 * | |
| 931 * Usage: | |
| 932 * <pre> | |
| 933 * function ParentClass(a, b) { } | |
| 934 * ParentClass.prototype.foo = function(a) { } | |
| 935 * | |
| 936 * function ChildClass(a, b, c) { | |
| 937 * ParentClass.call(this, a, b); | |
| 938 * } | |
| 939 * | |
| 940 * ChildClass.inherits(ParentClass); | |
| 941 * | |
| 942 * var child = new ChildClass('a', 'b', 'see'); | |
| 943 * child.foo(); // works | |
| 944 * </pre> | |
| 945 * | |
| 946 * In addition, a superclass' implementation of a method can be invoked | |
| 947 * as follows: | |
| 948 * | |
| 949 * <pre> | |
| 950 * ChildClass.prototype.foo = function(a) { | |
| 951 * ChildClass.superClass_.foo.call(this, a); | |
| 952 * // other code | |
| 953 * }; | |
| 954 * </pre> | |
| 955 * | |
| 956 * @param {Function} parentCtor Parent class. | |
| 957 */ | |
| 958 Function.prototype.inherits = function(parentCtor) { | |
| 959 goog.inherits(this, parentCtor); | |
| 960 }; | |
| 961 | |
| 962 | |
| 963 /** | |
| 964 * Static variant of Function.prototype.inherits. | |
| 965 * @param {Function} childCtor Child class. | |
| 966 * @param {Function} parentCtor Parent class. | |
| 967 */ | |
| 968 goog.inherits = function(childCtor, parentCtor) { | |
| 969 /** @constructor */ | |
| 970 function tempCtor() {}; | |
| 971 tempCtor.prototype = parentCtor.prototype; | |
| 972 childCtor.superClass_ = parentCtor.prototype; | |
| 973 childCtor.prototype = new tempCtor(); | |
| 974 childCtor.prototype.constructor = childCtor; | |
| 975 }; | |
| 976 | |
| 977 | |
| 978 /** | |
| 979 * Mixes in an object's properties and methods into the callee's prototype. | |
| 980 * Basically mixin based inheritance, thus providing an alternative method for | |
| 981 * adding properties and methods to a class' prototype. | |
| 982 * | |
| 983 * <pre> | |
| 984 * function X() {} | |
| 985 * X.mixin({ | |
| 986 * one: 1, | |
| 987 * two: 2, | |
| 988 * three: 3, | |
| 989 * doit: function() { return this.one + this.two + this.three; } | |
| 990 * }); | |
| 991 * | |
| 992 * function Y() { } | |
| 993 * Y.mixin(X.prototype); | |
| 994 * Y.prototype.four = 15; | |
| 995 * Y.prototype.doit2 = function() { return this.doit() + this.four; } | |
| 996 * }); | |
| 997 * | |
| 998 * // or | |
| 999 * | |
| 1000 * function Y() { } | |
| 1001 * Y.inherits(X); | |
| 1002 * Y.mixin({ | |
| 1003 * one: 10, | |
| 1004 * four: 15, | |
| 1005 * doit2: function() { return this.doit() + this.four; } | |
| 1006 * }); | |
| 1007 * </pre> | |
| 1008 * | |
| 1009 * @param {Object} source from which to copy properties. | |
| 1010 * @see goog.mixin | |
| 1011 * @deprecated | |
| 1012 */ | |
| 1013 Function.prototype.mixin = function(source) { | |
| 1014 goog.mixin(this.prototype, source); | |
| 1015 }; | |
| OLD | NEW |