1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
6 * @requires OpenLayers/BaseTypes/Class.js
7 * @requires OpenLayers/BaseTypes/LonLat.js
8 * @requires OpenLayers/BaseTypes/Size.js
9 * @requires OpenLayers/BaseTypes/Pixel.js
10 * @requires OpenLayers/BaseTypes/Bounds.js
11 * @requires OpenLayers/BaseTypes/Element.js
12 * @requires OpenLayers/Lang/en.js
13 * @requires OpenLayers/Console.js
17 * Header: OpenLayers Base Types
18 * OpenLayers custom string, number and function functions are described here.
22 * Namespace: OpenLayers.String
23 * Contains convenience functions for string manipulation.
28 * APIFunction: startsWith
29 * Test whether a string starts with another string.
32 * str - {String} The string to test.
33 * sub - {Sring} The substring to look for.
36 * {Boolean} The first string starts with the second.
38 startsWith: function(str, sub) {
39 return (str.indexOf(sub) == 0);
43 * APIFunction: contains
44 * Test whether a string contains another string.
47 * str - {String} The string to test.
48 * sub - {String} The substring to look for.
51 * {Boolean} The first string contains the second.
53 contains: function(str, sub) {
54 return (str.indexOf(sub) != -1);
59 * Removes leading and trailing whitespace characters from a string.
62 * str - {String} The (potentially) space padded string. This string is not
66 * {String} A trimmed version of the string with all leading and
67 * trailing spaces removed.
70 return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
74 * APIFunction: camelize
75 * Camel-case a hyphenated string.
76 * Ex. "chicken-head" becomes "chickenHead", and
77 * "-chicken-head" becomes "ChickenHead".
80 * str - {String} The string to be camelized. The original is not modified.
83 * {String} The string, camelized
85 camelize: function(str) {
86 var oStringList = str.split('-');
87 var camelizedString = oStringList[0];
88 for (var i=1, len=oStringList.length; i<len; i++) {
89 var s = oStringList[i];
90 camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
92 return camelizedString;
97 * Given a string with tokens in the form ${token}, return a string
98 * with tokens replaced with properties from the given context
99 * object. Represent a literal "${" by doubling it, e.g. "${${".
102 * template - {String} A string with tokens to be replaced. A template
103 * has the form "literal ${token}" where the token will be replaced
104 * by the value of context["token"].
105 * context - {Object} An optional object with properties corresponding
106 * to the tokens in the format string. If no context is sent, the
107 * window object will be used.
108 * args - {Array} Optional arguments to pass to any functions found in
109 * the context. If a context property is a function, the token
110 * will be replaced by the return from the function called with
114 * {String} A string with tokens replaced from the context object.
116 format: function(template, context, args) {
124 var replacer = function(str, match) {
127 // Loop through all subs. Example: ${a.b.c}
128 // 0 -> replacement = context[a];
129 // 1 -> replacement = context[a][b];
130 // 2 -> replacement = context[a][b][c];
131 var subs = match.split(/\.+/);
132 for (var i=0; i< subs.length; i++) {
134 replacement = context;
137 replacement = replacement[subs[i]];
140 if(typeof replacement == "function") {
142 replacement.apply(null, args) :
146 // If replacement is undefined, return the string 'undefined'.
147 // This is a workaround for a bugs in browsers not properly
148 // dealing with non-participating groups in regular expressions:
149 // http://blog.stevenlevithan.com/archives/npcg-javascript
150 if (typeof replacement == 'undefined') {
157 return template.replace(OpenLayers.String.tokenRegEx, replacer);
161 * Property: OpenLayers.String.tokenRegEx
162 * Used to find tokens in a string.
163 * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
165 tokenRegEx: /\$\{([\w.]+?)\}/g,
168 * Property: OpenLayers.String.numberRegEx
169 * Used to test strings as numbers.
171 numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
174 * APIFunction: OpenLayers.String.isNumeric
175 * Determine whether a string contains only a numeric value.
179 * OpenLayers.String.isNumeric("6.02e23") // true
180 * OpenLayers.String.isNumeric("12 dozen") // false
181 * OpenLayers.String.isNumeric("4") // true
182 * OpenLayers.String.isNumeric(" 4 ") // false
186 * {Boolean} String contains only a number.
188 isNumeric: function(value) {
189 return OpenLayers.String.numberRegEx.test(value);
193 * APIFunction: numericIf
194 * Converts a string that appears to be a numeric value into a number.
197 * {Number|String} a Number if the passed value is a number, a String
200 numericIf: function(value) {
201 return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value;
206 if (!String.prototype.startsWith) {
208 * APIMethod: String.startsWith
209 * *Deprecated*. Whether or not a string starts with another string.
212 * sStart - {Sring} The string we're testing for.
215 * {Boolean} Whether or not this string starts with the string passed in.
217 String.prototype.startsWith = function(sStart) {
218 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
219 {'newMethod':'OpenLayers.String.startsWith'}));
220 return OpenLayers.String.startsWith(this, sStart);
224 if (!String.prototype.contains) {
226 * APIMethod: String.contains
227 * *Deprecated*. Whether or not a string contains another string.
230 * str - {String} The string that we're testing for.
233 * {Boolean} Whether or not this string contains with the string passed in.
235 String.prototype.contains = function(str) {
236 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
237 {'newMethod':'OpenLayers.String.contains'}));
238 return OpenLayers.String.contains(this, str);
242 if (!String.prototype.trim) {
244 * APIMethod: String.trim
245 * *Deprecated*. Removes leading and trailing whitespace characters from a string.
248 * {String} A trimmed version of the string - all leading and
249 * trailing spaces removed
251 String.prototype.trim = function() {
252 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
253 {'newMethod':'OpenLayers.String.trim'}));
254 return OpenLayers.String.trim(this);
258 if (!String.prototype.camelize) {
260 * APIMethod: String.camelize
261 * *Deprecated*. Camel-case a hyphenated string.
262 * Ex. "chicken-head" becomes "chickenHead", and
263 * "-chicken-head" becomes "ChickenHead".
266 * {String} The string, camelized
268 String.prototype.camelize = function() {
269 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
270 {'newMethod':'OpenLayers.String.camelize'}));
271 return OpenLayers.String.camelize(this);
276 * Namespace: OpenLayers.Number
277 * Contains convenience functions for manipulating numbers.
279 OpenLayers.Number = {
282 * Property: decimalSeparator
283 * Decimal separator to use when formatting numbers.
285 decimalSeparator: ".",
288 * Property: thousandsSeparator
289 * Thousands separator to use when formatting numbers.
291 thousandsSeparator: ",",
294 * APIFunction: limitSigDigs
295 * Limit the number of significant digits on a float.
302 * {Float} The number, rounded to the specified number of significant
305 limitSigDigs: function(num, sig) {
308 fig = parseFloat(num.toPrecision(sig));
314 * APIFunction: format
315 * Formats a number for output.
319 * dec - {Integer} Number of decimal places to round to.
320 * Defaults to 0. Set to null to leave decimal places unchanged.
321 * tsep - {String} Thousands separator.
323 * dsep - {String} Decimal separator.
327 * {String} A string representing the formatted number.
329 format: function(num, dec, tsep, dsep) {
330 dec = (typeof dec != "undefined") ? dec : 0;
331 tsep = (typeof tsep != "undefined") ? tsep :
332 OpenLayers.Number.thousandsSeparator;
333 dsep = (typeof dsep != "undefined") ? dsep :
334 OpenLayers.Number.decimalSeparator;
337 num = parseFloat(num.toFixed(dec));
340 var parts = num.toString().split(".");
341 if (parts.length == 1 && dec == null) {
342 // integer where we do not want to touch the decimals
346 var integer = parts[0];
348 var thousands = /(-?[0-9]+)([0-9]{3})/;
349 while(thousands.test(integer)) {
350 integer = integer.replace(thousands, "$1" + tsep + "$2");
358 var rem = parts.length > 1 ? parts[1] : "0";
360 rem = rem + new Array(dec - rem.length + 1).join("0");
362 str = integer + dsep + rem;
368 if (!Number.prototype.limitSigDigs) {
370 * APIMethod: Number.limitSigDigs
371 * *Deprecated*. Limit the number of significant digits on an integer. Does *not*
378 * {Integer} The number, rounded to the specified number of significant digits.
379 * If null, 0, or negative value passed in, returns 0
381 Number.prototype.limitSigDigs = function(sig) {
382 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
383 {'newMethod':'OpenLayers.Number.limitSigDigs'}));
384 return OpenLayers.Number.limitSigDigs(this, sig);
389 * Namespace: OpenLayers.Function
390 * Contains convenience functions for function manipulation.
392 OpenLayers.Function = {
395 * Bind a function to an object. Method to easily create closures with
399 * func - {Function} Input function.
400 * object - {Object} The object to bind to the input function (as this).
403 * {Function} A closure with 'this' set to the passed in object.
405 bind: function(func, object) {
406 // create a reference to all arguments past the second one
407 var args = Array.prototype.slice.apply(arguments, [2]);
409 // Push on any additional arguments from the actual function call.
410 // These will come after those sent to the bind call.
411 var newArgs = args.concat(
412 Array.prototype.slice.apply(arguments, [0])
414 return func.apply(object, newArgs);
419 * APIFunction: bindAsEventListener
420 * Bind a function to an object, and configure it to receive the event
421 * object as first parameter when called.
424 * func - {Function} Input function to serve as an event listener.
425 * object - {Object} A reference to this.
430 bindAsEventListener: function(func, object) {
431 return function(event) {
432 return func.call(object, event || window.event);
437 if (!Function.prototype.bind) {
439 * APIMethod: Function.bind
440 * *Deprecated*. Bind a function to an object.
441 * Method to easily create closures with 'this' altered.
444 * object - {Object} the this parameter
447 * {Function} A closure with 'this' altered to the first
450 Function.prototype.bind = function() {
451 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
452 {'newMethod':'OpenLayers.Function.bind'}));
453 // new function takes the same arguments with this function up front
454 Array.prototype.unshift.apply(arguments, [this]);
455 return OpenLayers.Function.bind.apply(null, arguments);
459 if (!Function.prototype.bindAsEventListener) {
461 * APIMethod: Function.bindAsEventListener
462 * *Deprecated*. Bind a function to an object, and configure it to receive the
463 * event object as first parameter when called.
466 * object - {Object} A reference to this.
471 Function.prototype.bindAsEventListener = function(object) {
472 OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
473 {'newMethod':'OpenLayers.Function.bindAsEventListener'}));
474 return OpenLayers.Function.bindAsEventListener(this, object);
479 * Namespace: OpenLayers.Array
480 * Contains convenience functions for array manipulation.
486 * Filter an array. Provides the functionality of the
487 * Array.prototype.filter extension to the ECMA-262 standard. Where
488 * available, Array.prototype.filter will be used.
490 * Based on well known example from http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
493 * array - {Array} The array to be filtered. This array is not mutated.
494 * Elements added to this array by the callback will not be visited.
495 * callback - {Function} A function that is called for each element in
496 * the array. If this function returns true, the element will be
497 * included in the return. The function will be called with three
498 * arguments: the element in the array, the index of that element, and
499 * the array itself. If the optional caller parameter is specified
500 * the callback will be called with this set to caller.
501 * caller - {Object} Optional object to be set as this when the callback
505 * {Array} An array of elements from the passed in array for which the
506 * callback returns true.
508 filter: function(array, callback, caller) {
510 if (Array.prototype.filter) {
511 selected = array.filter(callback, caller);
513 var len = array.length;
514 if (typeof callback != "function") {
515 throw new TypeError();
517 for(var i=0; i<len; i++) {
520 if (callback.call(caller, val, i, array)) {