UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

251 lines (211 loc) 9.13 kB
/* * @namespace Util * * Various utility functions, used by Leaflet internally. */ L.Util = { // @function extend(dest: Object, src?: Object): Object // Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut. extend: function (dest) { var i, j, len, src; for (j = 1, len = arguments.length; j < len; j++) { src = arguments[j]; for (i in src) { dest[i] = src[i]; } } return dest; }, // @function create(proto: Object, properties?: Object): Object // Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create) create: Object.create || (function () { function F() {} return function (proto) { F.prototype = proto; return new F(); }; })(), // @function bind(fn: Function, …): Function // Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). // Has a `L.bind()` shortcut. 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); }; }, // @function stamp(obj: Object): Number // Returns the unique ID of an object, assiging it one if it doesn't have it. stamp: function (obj) { /*eslint-disable */ obj._leaflet_id = obj._leaflet_id || ++L.Util.lastId; return obj._leaflet_id; /*eslint-enable */ }, // @property lastId: Number // Last unique ID used by [`stamp()`](#util-stamp) lastId: 0, // @function throttle(fn: Function, time: Number, context: Object): Function // Returns a function which executes function `fn` with the given scope `context` // (so that the `this` keyword refers to `context` inside `fn`'s code). The function // `fn` will be called no more than one time per given amount of `time`. The arguments // received by the bound function will be any arguments passed when binding the // function, followed by any arguments passed when invoking the bound function. // Has an `L.bind` shortcut. 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; }, // @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number // Returns the number `num` modulo `range` in such a way so it lies within // `range[0]` and `range[1]`. The returned value will be always smaller than // `range[1]` unless `includeMax` is set to `true`. 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; }, // @function falseFn(): Function // Returns a function which always returns `false`. falseFn: function () { return false; }, // @function formatNum(num: Number, digits?: Number): Number // Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default. formatNum: function (num, digits) { var pow = Math.pow(10, digits || 5); return Math.round(num * pow) / pow; }, // @function trim(str: String): String // Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) trim: function (str) { return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); }, // @function splitWords(str: String): String[] // Trims and splits the string on whitespace and returns the array of parts. splitWords: function (str) { return L.Util.trim(str).split(/\s+/); }, // @function setOptions(obj: Object, options: Object): Object // Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut. 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; }, // @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String // Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}` // translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will // be appended at the end. If `uppercase` is `true`, the parameter names will // be uppercased (e.g. `'?A=foo&B=bar'`) 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('&'); }, // @function template(str: String, data: Object): String // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'` // and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string // `('Hello foo, bar')`. You can also specify functions instead of strings for // data values — they will be evaluated passing `data` as an argument. 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, // @function isArray(obj): Boolean // Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) isArray: Array.isArray || function (obj) { return (Object.prototype.toString.call(obj) === '[object Array]'); }, // @function indexOf(array: Array, el: Object): Number // Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) indexOf: function (array, el) { for (var i = 0; i < array.length; i++) { if (array[i] === el) { return i; } } return -1; }, // @property emptyImageUrl: String // Data URI string containing a base64-encoded empty GIF image. // Used as a hack to free memory from unused images on WebKit-powered // mobile devices (by setting image `src` to this string). 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); }; // @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number // Schedules `fn` to be executed when the browser repaints. `fn` is bound to // `context` if given. When `immediate` is set, `fn` is called immediately if // the browser doesn't have native support for // [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame), // otherwise it's delayed. Returns a request ID that can be used to cancel the request. L.Util.requestAnimFrame = function (fn, context, immediate) { if (immediate && requestFn === timeoutDefer) { fn.call(context); } else { return requestFn.call(window, L.bind(fn, context)); } }; // @function cancelAnimFrame(id: Number): undefined // Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame). 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;