/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the Clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/BaseTypes/Class.js * @requires OpenLayers/BaseTypes/LonLat.js * @requires OpenLayers/BaseTypes/Size.js * @requires OpenLayers/BaseTypes/Pixel.js * @requires OpenLayers/BaseTypes/Bounds.js * @requires OpenLayers/BaseTypes/Element.js * @requires OpenLayers/Lang/en.js * @requires OpenLayers/Console.js */ /** * Header: OpenLayers Base Types * OpenLayers custom string, number and function functions are described here. */ /** * Namespace: OpenLayers.String * Contains convenience functions for string manipulation. */ OpenLayers.String = { /** * APIFunction: startsWith * Test whether a string starts with another string. * * Parameters: * str - {String} The string to test. * sub - {Sring} The substring to look for. * * Returns: * {Boolean} The first string starts with the second. */ startsWith: function(str, sub) { return (str.indexOf(sub) == 0); }, /** * APIFunction: contains * Test whether a string contains another string. * * Parameters: * str - {String} The string to test. * sub - {String} The substring to look for. * * Returns: * {Boolean} The first string contains the second. */ contains: function(str, sub) { return (str.indexOf(sub) != -1); }, /** * APIFunction: trim * Removes leading and trailing whitespace characters from a string. * * Parameters: * str - {String} The (potentially) space padded string. This string is not * modified. * * Returns: * {String} A trimmed version of the string with all leading and * trailing spaces removed. */ trim: function(str) { return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }, /** * APIFunction: camelize * Camel-case a hyphenated string. * Ex. "chicken-head" becomes "chickenHead", and * "-chicken-head" becomes "ChickenHead". * * Parameters: * str - {String} The string to be camelized. The original is not modified. * * Returns: * {String} The string, camelized */ camelize: function(str) { var oStringList = str.split('-'); var camelizedString = oStringList[0]; for (var i=1, len=oStringList.length; i replacement = context[a]; // 1 -> replacement = context[a][b]; // 2 -> replacement = context[a][b][c]; var subs = match.split(/\.+/); for (var i=0; i< subs.length; i++) { if (i == 0) { replacement = context; } replacement = replacement[subs[i]]; } if(typeof replacement == "function") { replacement = args ? replacement.apply(null, args) : replacement(); } // If replacement is undefined, return the string 'undefined'. // This is a workaround for a bugs in browsers not properly // dealing with non-participating groups in regular expressions: // http://blog.stevenlevithan.com/archives/npcg-javascript if (typeof replacement == 'undefined') { return 'undefined'; } else { return replacement; } }; return template.replace(OpenLayers.String.tokenRegEx, replacer); }, /** * Property: OpenLayers.String.tokenRegEx * Used to find tokens in a string. * Examples: ${a}, ${a.b.c}, ${a-b}, ${5} */ tokenRegEx: /\$\{([\w.]+?)\}/g, /** * Property: OpenLayers.String.numberRegEx * Used to test strings as numbers. */ numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/, /** * APIFunction: OpenLayers.String.isNumeric * Determine whether a string contains only a numeric value. * * Examples: * (code) * OpenLayers.String.isNumeric("6.02e23") // true * OpenLayers.String.isNumeric("12 dozen") // false * OpenLayers.String.isNumeric("4") // true * OpenLayers.String.isNumeric(" 4 ") // false * (end) * * Returns: * {Boolean} String contains only a number. */ isNumeric: function(value) { return OpenLayers.String.numberRegEx.test(value); }, /** * APIFunction: numericIf * Converts a string that appears to be a numeric value into a number. * * Returns * {Number|String} a Number if the passed value is a number, a String * otherwise. */ numericIf: function(value) { return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value; } }; if (!String.prototype.startsWith) { /** * APIMethod: String.startsWith * *Deprecated*. Whether or not a string starts with another string. * * Parameters: * sStart - {Sring} The string we're testing for. * * Returns: * {Boolean} Whether or not this string starts with the string passed in. */ String.prototype.startsWith = function(sStart) { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.String.startsWith'})); return OpenLayers.String.startsWith(this, sStart); }; } if (!String.prototype.contains) { /** * APIMethod: String.contains * *Deprecated*. Whether or not a string contains another string. * * Parameters: * str - {String} The string that we're testing for. * * Returns: * {Boolean} Whether or not this string contains with the string passed in. */ String.prototype.contains = function(str) { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.String.contains'})); return OpenLayers.String.contains(this, str); }; } if (!String.prototype.trim) { /** * APIMethod: String.trim * *Deprecated*. Removes leading and trailing whitespace characters from a string. * * Returns: * {String} A trimmed version of the string - all leading and * trailing spaces removed */ String.prototype.trim = function() { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.String.trim'})); return OpenLayers.String.trim(this); }; } if (!String.prototype.camelize) { /** * APIMethod: String.camelize * *Deprecated*. Camel-case a hyphenated string. * Ex. "chicken-head" becomes "chickenHead", and * "-chicken-head" becomes "ChickenHead". * * Returns: * {String} The string, camelized */ String.prototype.camelize = function() { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.String.camelize'})); return OpenLayers.String.camelize(this); }; } /** * Namespace: OpenLayers.Number * Contains convenience functions for manipulating numbers. */ OpenLayers.Number = { /** * Property: decimalSeparator * Decimal separator to use when formatting numbers. */ decimalSeparator: ".", /** * Property: thousandsSeparator * Thousands separator to use when formatting numbers. */ thousandsSeparator: ",", /** * APIFunction: limitSigDigs * Limit the number of significant digits on a float. * * Parameters: * num - {Float} * sig - {Integer} * * Returns: * {Float} The number, rounded to the specified number of significant * digits. */ limitSigDigs: function(num, sig) { var fig = 0; if (sig > 0) { fig = parseFloat(num.toPrecision(sig)); } return fig; }, /** * APIFunction: format * Formats a number for output. * * Parameters: * num - {Float} * dec - {Integer} Number of decimal places to round to. * Defaults to 0. Set to null to leave decimal places unchanged. * tsep - {String} Thousands separator. * Default is ",". * dsep - {String} Decimal separator. * Default is ".". * * Returns: * {String} A string representing the formatted number. */ format: function(num, dec, tsep, dsep) { dec = (typeof dec != "undefined") ? dec : 0; tsep = (typeof tsep != "undefined") ? tsep : OpenLayers.Number.thousandsSeparator; dsep = (typeof dsep != "undefined") ? dsep : OpenLayers.Number.decimalSeparator; if (dec != null) { num = parseFloat(num.toFixed(dec)); } var parts = num.toString().split("."); if (parts.length == 1 && dec == null) { // integer where we do not want to touch the decimals dec = 0; } var integer = parts[0]; if (tsep) { var thousands = /(-?[0-9]+)([0-9]{3})/; while(thousands.test(integer)) { integer = integer.replace(thousands, "$1" + tsep + "$2"); } } var str; if (dec == 0) { str = integer; } else { var rem = parts.length > 1 ? parts[1] : "0"; if (dec != null) { rem = rem + new Array(dec - rem.length + 1).join("0"); } str = integer + dsep + rem; } return str; } }; if (!Number.prototype.limitSigDigs) { /** * APIMethod: Number.limitSigDigs * *Deprecated*. Limit the number of significant digits on an integer. Does *not* * work with floats! * * Parameters: * sig - {Integer} * * Returns: * {Integer} The number, rounded to the specified number of significant digits. * If null, 0, or negative value passed in, returns 0 */ Number.prototype.limitSigDigs = function(sig) { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.Number.limitSigDigs'})); return OpenLayers.Number.limitSigDigs(this, sig); }; } /** * Namespace: OpenLayers.Function * Contains convenience functions for function manipulation. */ OpenLayers.Function = { /** * APIFunction: bind * Bind a function to an object. Method to easily create closures with * 'this' altered. * * Parameters: * func - {Function} Input function. * object - {Object} The object to bind to the input function (as this). * * Returns: * {Function} A closure with 'this' set to the passed in object. */ bind: function(func, object) { // create a reference to all arguments past the second one var args = Array.prototype.slice.apply(arguments, [2]); return function() { // Push on any additional arguments from the actual function call. // These will come after those sent to the bind call. var newArgs = args.concat( Array.prototype.slice.apply(arguments, [0]) ); return func.apply(object, newArgs); }; }, /** * APIFunction: bindAsEventListener * Bind a function to an object, and configure it to receive the event * object as first parameter when called. * * Parameters: * func - {Function} Input function to serve as an event listener. * object - {Object} A reference to this. * * Returns: * {Function} */ bindAsEventListener: function(func, object) { return function(event) { return func.call(object, event || window.event); }; }, /** * APIFunction: False * A simple function to that just does "return false". We use this to * avoid attaching anonymous functions to DOM event handlers, which * causes "issues" on IE<8. * * Usage: * document.onclick = OpenLayers.Function.False; * * Returns: * {Boolean} */ False : function() { return false; }, /** * APIFunction: True * A simple function to that just does "return true". We use this to * avoid attaching anonymous functions to DOM event handlers, which * causes "issues" on IE<8. * * Usage: * document.onclick = OpenLayers.Function.True; * * Returns: * {Boolean} */ True : function() { return true; } }; if (!Function.prototype.bind) { /** * APIMethod: Function.bind * *Deprecated*. Bind a function to an object. * Method to easily create closures with 'this' altered. * * Parameters: * object - {Object} the this parameter * * Returns: * {Function} A closure with 'this' altered to the first * argument. */ Function.prototype.bind = function() { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.Function.bind'})); // new function takes the same arguments with this function up front Array.prototype.unshift.apply(arguments, [this]); return OpenLayers.Function.bind.apply(null, arguments); }; } if (!Function.prototype.bindAsEventListener) { /** * APIMethod: Function.bindAsEventListener * *Deprecated*. Bind a function to an object, and configure it to receive the * event object as first parameter when called. * * Parameters: * object - {Object} A reference to this. * * Returns: * {Function} */ Function.prototype.bindAsEventListener = function(object) { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", {'newMethod':'OpenLayers.Function.bindAsEventListener'})); return OpenLayers.Function.bindAsEventListener(this, object); }; } /** * Namespace: OpenLayers.Array * Contains convenience functions for array manipulation. */ OpenLayers.Array = { /** * APIMethod: filter * Filter an array. Provides the functionality of the * Array.prototype.filter extension to the ECMA-262 standard. Where * available, Array.prototype.filter will be used. * * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter * * Parameters: * array - {Array} The array to be filtered. This array is not mutated. * Elements added to this array by the callback will not be visited. * callback - {Function} A function that is called for each element in * the array. If this function returns true, the element will be * included in the return. The function will be called with three * arguments: the element in the array, the index of that element, and * the array itself. If the optional caller parameter is specified * the callback will be called with this set to caller. * caller - {Object} Optional object to be set as this when the callback * is called. * * Returns: * {Array} An array of elements from the passed in array for which the * callback returns true. */ filter: function(array, callback, caller) { var selected = []; if (Array.prototype.filter) { selected = array.filter(callback, caller); } else { var len = array.length; if (typeof callback != "function") { throw new TypeError(); } for(var i=0; i