/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Google Safe Browsing. * * The Initial Developer of the Original Code is Google Inc. * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Aaron Boodman (original author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ // This file has pure js helper functions. Hence you'll find metion // of browser-specific features in here. /** * lang.js - The missing JavaScript language features * * WARNING: This class adds members to the prototypes of String, Array, and * Function for convenience. * * The tradeoff is that the for/in statement will not work properly for those * objects when this library is used. * * To work around this for Arrays, you may want to use the forEach() method, * which is more fun and easier to read. */ /** * Returns true if the specified value is |null| */ function isNull(val) { return val === null; } /** * Returns true if the specified value is an array */ function isArray(val) { return isObject(val) && val.constructor == Array; } /** * Returns true if the specified value is a string */ function isString(val) { return typeof val == "string"; } /** * Returns true if the specified value is a boolean */ function isBoolean(val) { return typeof val == "boolean"; } /** * Returns true if the specified value is a number */ function isNumber(val) { return typeof val == "number"; } /** * Returns true if the specified value is a function */ function isFunction(val) { return typeof val == "function"; } /** * Returns true if the specified value is an object */ function isObject(val) { return val && typeof val == "object"; } /** * Returns an array of all the properties defined on an object */ function getObjectProps(obj) { var ret = []; for (var p in obj) { ret.push(p); } return ret; } /** * Returns true if the specified value is an object which has no properties * defined. */ function isEmptyObject(val) { if (!isObject(val)) { return false; } for (var p in val) { return false; } return true; } var getHashCode; var removeHashCode; (function () { var hashCodeProperty = "lang_hashCode_"; /** * Adds a lang_hashCode_ field to an object. The hash code is unique for the * given object. * @param obj {Object} The object to get the hash code for * @returns {Number} The hash code for the object */ getHashCode = function(obj) { // In IE, DOM nodes do not extend Object so they do not have this method. // we need to check hasOwnProperty because the proto might have this set. if (obj.hasOwnProperty && obj.hasOwnProperty(hashCodeProperty)) { return obj[hashCodeProperty]; } if (!obj[hashCodeProperty]) { obj[hashCodeProperty] = ++getHashCode.hashCodeCounter_; } return obj[hashCodeProperty]; }; /** * Removes the lang_hashCode_ field from an object. * @param obj {Object} The object to remove the field from. */ removeHashCode = function(obj) { obj.removeAttribute(hashCodeProperty); }; getHashCode.hashCodeCounter_ = 0; })(); /** * Fast prefix-checker. */ String.prototype.startsWith = function(prefix) { if (this.length < prefix.length) { return false; } if (this.substring(0, prefix.length) == prefix) { return true; } return false; } /** * Removes whitespace from the beginning and end of the string */ String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ""); } /** * Does simple python-style string substitution. * "foo%s hot%s".subs("bar", "dog") becomes "foobar hotdot". * For more fully-featured templating, see template.js. */ String.prototype.subs = function() { var ret = this; // this appears to be slow, but testing shows it compares more or less equiv. // to the regex.exec method. for (var i = 0; i < arguments.length; i++) { ret = ret.replace(/\%s/, String(arguments[i])); } return ret; } /** * Returns the last element on an array without removing it. */ Array.prototype.peek = function() { return this[this.length - 1]; } // TODO(anyone): add splice the first time someone needs it and then implement // push, pop, shift, unshift in terms of it where possible. // TODO(anyone): add the other neat-o functional methods like map(), etc. /** * Partially applies this function to a particular "this object" and zero or * more arguments. The result is a new function with some arguments of the first * function pre-filled and the value of |this| "pre-specified". * * Remaining arguments specified at call-time are appended to the pre- * specified ones. * * Also see: partial(). * * Note that bind and partial are optimized such that repeated calls to it do * not create more than one function object, so there is no additional cost for * something like: * * var g = bind(f, obj); * var h = partial(g, 1, 2, 3); * var k = partial(h, a, b, c); * * Usage: * var barMethBound = bind(myFunction, myObj, "arg1", "arg2"); * barMethBound("arg3", "arg4"); * * @param thisObj {object} Specifies the object which |this| should point to * when the function is run. If the value is null or undefined, it will default * to the global object. * * @returns {function} A partially-applied form of the function bind() was * invoked as a method of. */ function bind(fn, self, opt_args) { var boundargs = (typeof fn.boundArgs_ != "undefined") ? fn.boundArgs_ : []; boundargs = boundargs.concat(Array.prototype.slice.call(arguments, 2)); if (typeof fn.boundSelf_ != "undefined") { self = fn.boundSelf_; } if (typeof fn.boundFn_ != "undefined") { fn = fn.boundFn_; } var newfn = function() { // Combine the static args and the new args into one big array var args = boundargs.concat(Array.prototype.slice.call(arguments)); return fn.apply(self, args); } newfn.boundArgs_ = boundargs; newfn.boundSelf_ = self; newfn.boundFn_ = fn; return newfn; } /** * An alias to the bind() global function. * * Usage: * var g = f.bind(obj, arg1, arg2); * g(arg3, arg4); */ Function.prototype.bind = function(self, opt_args) { return bind.apply( null, [this, self].concat(Array.prototype.slice.call(arguments, 1))); } /** * Like bind(), except that a "this object" is not required. Useful when the * target function is already bound. * * Usage: * var g = partial(f, arg1, arg2); * g(arg3, arg4); */ function partial(fn, opt_args) { return bind.apply( null, [fn, null].concat(Array.prototype.slice.call(arguments, 1))); } /** * An alias to the partial() global function. * * Usage: * var g = f.partial(arg1, arg2); * g(arg3, arg4); */ Function.prototype.partial = function(opt_args) { return bind.apply( null, [this, null].concat(Array.prototype.slice.call(arguments))); } /** * Convenience. Binds all the methods of obj to itself. Calling this in the * constructor before referencing any methods makes things a little more like * Java or Python where methods are intrinsically bound to their instance. */ function bindMethods(obj) { for (var p in obj) { if (isFunction(obj[p])) { obj[p] = obj[p].bind(obj); } } } /** * Inherit the prototype methods from one constructor into another. * * Usage: *
 * function ParentClass(a, b) { }
 * ParentClass.prototype.foo = function(a) { }
 *
 * function ChildClass(a, b, c) {
 *   ParentClass.call(this, a, b);
 * }
 *
 * ChildClass.inherits(ParentClass);
 *
 * var child = new ChildClass("a", "b", "see");
 * child.foo(); // works
 * 
* * In addition, a superclass' implementation of a method can be invoked * as follows: * *
 * ChildClass.prototype.foo = function(a) {
 *   ChildClass.superClass_.foo.call(this, a);
 *   // other code
 * };
 * 
*/ Function.prototype.inherits = function(parentCtor) { var tempCtor = function(){}; tempCtor.prototype = parentCtor.prototype; this.superClass_ = parentCtor.prototype; this.prototype = new tempCtor(); }