/* * L.Util contains various utility functions used throughout Leaflet code. */ L.Util = { // extend an object with properties of one or more other objects extend: function (dest) { var sources = Array.prototype.slice.call(arguments, 1), i, j, len, src; for (j = 0, len = sources.length; j < len; j++) { src = sources[j]; for (i in src) { dest[i] = src[i]; } } return dest; }, // create an object from a given prototype create: Object.create || (function () { function F() {} return function (proto) { F.prototype = proto; return new F(); }; })(), // bind a function to be called with a given context bind: function (fn, obj) { var slice = Array.prototype.slice; if (fn.bind) { return fn.bind.apply(fn, slice.call(arguments, 1)); } var args = slice.call(arguments, 2); return function () { return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments); }; }, // return unique ID of an object stamp: function (obj) { // jshint camelcase: false obj._leaflet_id = obj._leaflet_id || ++L.Util.lastId; return obj._leaflet_id; }, lastId: 0, // return a function that won't be called more often than the given interval throttle: function (fn, time, context) { var lock, args, wrapperFn, later; later = function () { // reset lock and call if queued lock = false; if (args) { wrapperFn.apply(context, args); args = false; } }; wrapperFn = function () { if (lock) { // called too soon, queue to call later args = arguments; } else { // call and lock until later fn.apply(context, arguments); setTimeout(later, time); lock = true; } }; return wrapperFn; }, // wrap the given number to lie within a certain range (used for wrapping longitude) wrapNum: function (x, range, includeMax) { var max = range[1], min = range[0], d = max - min; return x === max && includeMax ? x : ((x - min) % d + d) % d + min; }, // do nothing (used as a noop throughout the code) falseFn: function () { return false; }, // round a given number to a given precision formatNum: function (num, digits) { var pow = Math.pow(10, digits || 5); return Math.round(num * pow) / pow; }, // trim whitespace from both sides of a string trim: function (str) { return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); }, // split a string into words splitWords: function (str) { return L.Util.trim(str).split(/\s+/); }, // set options to an object, inheriting parent's options as well setOptions: function (obj, options) { if (!obj.hasOwnProperty('options')) { obj.options = obj.options ? L.Util.create(obj.options) : {}; } for (var i in options) { obj.options[i] = options[i]; } return obj.options; }, // make an URL with GET parameters out of a set of properties/values getParamString: function (obj, existingUrl, uppercase) { var params = []; for (var i in obj) { params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); } return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); }, // super-simple templating facility, used for TileLayer URLs template: function (str, data) { return str.replace(L.Util.templateRe, function (str, key) { var value = data[key]; if (value === undefined) { throw new Error('No value provided for variable ' + str); } else if (typeof value === 'function') { value = value(data); } return value; }); }, templateRe: /\{ *([\w_]+) *\}/g, isArray: Array.isArray || function (obj) { return (Object.prototype.toString.call(obj) === '[object Array]'); }, // minimal image URI, set to an image when disposing to flush memory emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' }; (function () { // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ function getPrefixed(name) { return window['webkit' + name] || window['moz' + name] || window['ms' + name]; } var lastTime = 0; // fallback for IE 7-8 function timeoutDefer(fn) { var time = +new Date(), timeToCall = Math.max(0, 16 - (time - lastTime)); lastTime = time + timeToCall; return window.setTimeout(fn, timeToCall); } var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer, cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; L.Util.requestAnimFrame = function (fn, context, immediate, element) { if (immediate && requestFn === timeoutDefer) { fn.call(context); } else { return requestFn.call(window, L.bind(fn, context), element); } }; L.Util.cancelAnimFrame = function (id) { if (id) { cancelFn.call(window, id); } }; })(); // shortcuts for most used utility functions L.extend = L.Util.extend; L.bind = L.Util.bind; L.stamp = L.Util.stamp; L.setOptions = L.Util.setOptions;