UNPKG

nominatim-geocode

Version:
2,071 lines (1,642 loc) 256 kB
(function () { 'use strict'; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } /** * Helpers. */ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; var y = d * 365.25; /** * Parse or format the given `val`. * * Options: * * - `long` verbose formatting [false] * * @param {String|Number} val * @param {Object} [options] * @throws {Error} throw an error if val is not a non-empty string or a number * @return {String|Number} * @api public */ var ms = function(val, options) { options = options || {}; var type = typeof val; if (type === 'string' && val.length > 0) { return parse(val); } else if (type === 'number' && isNaN(val) === false) { return options.long ? fmtLong(val) : fmtShort(val); } throw new Error( 'val is not a non-empty string or a valid number. val=' + JSON.stringify(val) ); }; /** * Parse the given `str` and return milliseconds. * * @param {String} str * @return {Number} * @api private */ function parse(str) { str = String(str); if (str.length > 100) { return; } var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( str ); if (!match) { return; } var n = parseFloat(match[1]); var type = (match[2] || 'ms').toLowerCase(); switch (type) { case 'years': case 'year': case 'yrs': case 'yr': case 'y': return n * y; case 'days': case 'day': case 'd': return n * d; case 'hours': case 'hour': case 'hrs': case 'hr': case 'h': return n * h; case 'minutes': case 'minute': case 'mins': case 'min': case 'm': return n * m; case 'seconds': case 'second': case 'secs': case 'sec': case 's': return n * s; case 'milliseconds': case 'millisecond': case 'msecs': case 'msec': case 'ms': return n; default: return undefined; } } /** * Short format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function fmtShort(ms) { if (ms >= d) { return Math.round(ms / d) + 'd'; } if (ms >= h) { return Math.round(ms / h) + 'h'; } if (ms >= m) { return Math.round(ms / m) + 'm'; } if (ms >= s) { return Math.round(ms / s) + 's'; } return ms + 'ms'; } /** * Long format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function fmtLong(ms) { return plural(ms, d, 'day') || plural(ms, h, 'hour') || plural(ms, m, 'minute') || plural(ms, s, 'second') || ms + ' ms'; } /** * Pluralization helper. */ function plural(ms, n, name) { if (ms < n) { return; } if (ms < n * 1.5) { return Math.floor(ms / n) + ' ' + name; } return Math.ceil(ms / n) + ' ' + name + 's'; } var debug = createCommonjsModule(function (module, exports) { /** * This is the common logic for both the Node.js and web browser * implementations of `debug()`. * * Expose `debug()` as the module. */ exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; exports.humanize = ms; /** * The currently active debug mode names, and names to skip. */ exports.names = []; exports.skips = []; /** * Map of special "%n" handling functions, for the debug "format" argument. * * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". */ exports.formatters = {}; /** * Previous log timestamp. */ var prevTime; /** * Select a color. * @param {String} namespace * @return {Number} * @api private */ function selectColor(namespace) { var hash = 0, i; for (i in namespace) { hash = ((hash << 5) - hash) + namespace.charCodeAt(i); hash |= 0; // Convert to 32bit integer } return exports.colors[Math.abs(hash) % exports.colors.length]; } /** * Create a debugger with the given `namespace`. * * @param {String} namespace * @return {Function} * @api public */ function createDebug(namespace) { function debug() { var arguments$1 = arguments; // disabled? if (!debug.enabled) { return; } var self = debug; // set `diff` timestamp var curr = +new Date(); var ms$$1 = curr - (prevTime || curr); self.diff = ms$$1; self.prev = prevTime; self.curr = curr; prevTime = curr; // turn the `arguments` into a proper Array var args = new Array(arguments.length); for (var i = 0; i < args.length; i++) { args[i] = arguments$1[i]; } args[0] = exports.coerce(args[0]); if ('string' !== typeof args[0]) { // anything else let's inspect with %O args.unshift('%O'); } // apply any `formatters` transformations var index = 0; args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { // if we encounter an escaped % then don't increase the array index if (match === '%%') { return match; } index++; var formatter = exports.formatters[format]; if ('function' === typeof formatter) { var val = args[index]; match = formatter.call(self, val); // now we need to remove `args[index]` since it's inlined in the `format` args.splice(index, 1); index--; } return match; }); // apply env-specific formatting (colors, etc.) exports.formatArgs.call(self, args); var logFn = debug.log || exports.log || console.log.bind(console); logFn.apply(self, args); } debug.namespace = namespace; debug.enabled = exports.enabled(namespace); debug.useColors = exports.useColors(); debug.color = selectColor(namespace); // env-specific initialization logic for debug instances if ('function' === typeof exports.init) { exports.init(debug); } return debug; } /** * Enables a debug mode by namespaces. This can include modes * separated by a colon and wildcards. * * @param {String} namespaces * @api public */ function enable(namespaces) { exports.save(namespaces); exports.names = []; exports.skips = []; var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); var len = split.length; for (var i = 0; i < len; i++) { if (!split[i]) { continue; } // ignore empty strings namespaces = split[i].replace(/\*/g, '.*?'); if (namespaces[0] === '-') { exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); } else { exports.names.push(new RegExp('^' + namespaces + '$')); } } } /** * Disable debug output. * * @api public */ function disable() { exports.enable(''); } /** * Returns true if the given mode name is enabled, false otherwise. * * @param {String} name * @return {Boolean} * @api public */ function enabled(name) { var i, len; for (i = 0, len = exports.skips.length; i < len; i++) { if (exports.skips[i].test(name)) { return false; } } for (i = 0, len = exports.names.length; i < len; i++) { if (exports.names[i].test(name)) { return true; } } return false; } /** * Coerce `val`. * * @param {Mixed} val * @return {Mixed} * @api private */ function coerce(val) { if (val instanceof Error) { return val.stack || val.message; } return val; } }); var debug_1 = debug.coerce; var debug_2 = debug.disable; var debug_3 = debug.enable; var debug_4 = debug.enabled; var debug_5 = debug.humanize; var debug_6 = debug.names; var debug_7 = debug.skips; var debug_8 = debug.formatters; var browser = createCommonjsModule(function (module, exports) { /** * This is the web browser implementation of `debug()`. * * Expose `debug()` as the module. */ exports = module.exports = debug; exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; exports.storage = 'undefined' != typeof chrome && 'undefined' != typeof chrome.storage ? chrome.storage.local : localstorage(); /** * Colors. */ exports.colors = [ 'lightseagreen', 'forestgreen', 'goldenrod', 'dodgerblue', 'darkorchid', 'crimson' ]; /** * Currently only WebKit-based Web Inspectors, Firefox >= v31, * and the Firebug extension (any Firefox version) are known * to support "%c" CSS customizations. * * TODO: add a `localStorage` variable to explicitly enable/disable colors */ function useColors() { // NB: In an Electron preload script, document will be defined but not fully // initialized. Since we know we're in Chrome, we'll just detect this case // explicitly if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { return true; } // is webkit? http://stackoverflow.com/a/16459606/376773 // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || // is firebug? http://stackoverflow.com/a/398120/376773 (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || // is firefox >= v31? // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || // double check webkit in userAgent just in case we are in a worker (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } /** * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. */ exports.formatters.j = function(v) { try { return JSON.stringify(v); } catch (err) { return '[UnexpectedJSONParseError]: ' + err.message; } }; /** * Colorize log arguments if enabled. * * @api public */ function formatArgs(args) { var useColors = this.useColors; args[0] = (useColors ? '%c' : '') + this.namespace + (useColors ? ' %c' : ' ') + args[0] + (useColors ? '%c ' : ' ') + '+' + exports.humanize(this.diff); if (!useColors) { return; } var c = 'color: ' + this.color; args.splice(1, 0, c, 'color: inherit'); // the final "%c" is somewhat tricky, because there could be other // arguments passed either before or after the %c, so we need to // figure out the correct index to insert the CSS into var index = 0; var lastC = 0; args[0].replace(/%[a-zA-Z%]/g, function(match) { if ('%%' === match) { return; } index++; if ('%c' === match) { // we only are interested in the *last* %c // (the user may have provided their own) lastC = index; } }); args.splice(lastC, 0, c); } /** * Invokes `console.log()` when available. * No-op when `console.log` is not a "function". * * @api public */ function log() { // this hackery is required for IE8/9, where // the `console.log` function doesn't have 'apply' return 'object' === typeof console && console.log && Function.prototype.apply.call(console.log, console, arguments); } /** * Save `namespaces`. * * @param {String} namespaces * @api private */ function save(namespaces) { try { if (null == namespaces) { exports.storage.removeItem('debug'); } else { exports.storage.debug = namespaces; } } catch(e) {} } /** * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private */ function load() { var r; try { r = exports.storage.debug; } catch(e) {} // If debug isn't set in LS, and we're in Electron, try to load $DEBUG if (!r && typeof process !== 'undefined' && 'env' in process) { r = process.env.DEBUG; } return r; } /** * Enable namespaces listed in `localStorage.debug` initially. */ exports.enable(load()); /** * Localstorage attempts to return the localstorage. * * This is necessary because safari throws * when a user disables cookies/localstorage * and you attempt to access it. * * @return {LocalStorage} * @api private */ function localstorage() { try { return window.localStorage; } catch (e) {} } }); var browser_1 = browser.log; var browser_2 = browser.formatArgs; var browser_3 = browser.save; var browser_4 = browser.load; var browser_5 = browser.useColors; var browser_6 = browser.storage; var browser_7 = browser.colors; /** * Module dependencies */ var debug$1 = browser('jsonp'); /** * Module exports. */ var jsonp_1 = jsonp; /** * Callback index. */ var count = 0; /** * Noop function. */ function noop(){} /** * JSONP handler * * Options: * - param {String} qs parameter (`callback`) * - prefix {String} qs parameter (`__jp`) * - name {String} qs parameter (`prefix` + incr) * - timeout {Number} how long after a timeout error is emitted (`60000`) * * @param {String} url * @param {Object|Function} optional options / callback * @param {Function} optional callback */ function jsonp(url, opts, fn){ if ('function' == typeof opts) { fn = opts; opts = {}; } if (!opts) { opts = {}; } var prefix = opts.prefix || '__jp'; // use the callback name that was passed if one was provided. // otherwise generate a unique name by incrementing our counter. var id = opts.name || (prefix + (count++)); var param = opts.param || 'callback'; var timeout = null != opts.timeout ? opts.timeout : 60000; var enc = encodeURIComponent; var target = document.getElementsByTagName('script')[0] || document.head; var script; var timer; if (timeout) { timer = setTimeout(function(){ cleanup(); if (fn) { fn(new Error('Timeout')); } }, timeout); } function cleanup(){ if (script.parentNode) { script.parentNode.removeChild(script); } window[id] = noop; if (timer) { clearTimeout(timer); } } function cancel(){ if (window[id]) { cleanup(); } } window[id] = function(data){ debug$1('jsonp got', data); cleanup(); if (fn) { fn(null, data); } }; // add qs component url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id); url = url.replace('?&', '?'); debug$1('jsonp req "%s"', url); // create script script = document.createElement('script'); script.src = url; target.parentNode.insertBefore(script, target); return cancel; } var strictUriEncode = function (str) { return encodeURIComponent(str).replace(/[!'()*]/g, function (x) { return ("%" + (x.charCodeAt(0).toString(16).toUpperCase())); }); }; var token = '%[a-f0-9]{2}'; var singleMatcher = new RegExp(token, 'gi'); var multiMatcher = new RegExp('(' + token + ')+', 'gi'); function decodeComponents(components, split) { try { // Try to decode the entire string first return decodeURIComponent(components.join('')); } catch (err) { // Do nothing } if (components.length === 1) { return components; } split = split || 1; // Split the array in 2 parts var left = components.slice(0, split); var right = components.slice(split); return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); } function decode(input) { try { return decodeURIComponent(input); } catch (err) { var tokens = input.match(singleMatcher); for (var i = 1; i < tokens.length; i++) { input = decodeComponents(tokens, i).join(''); tokens = input.match(singleMatcher); } return input; } } function customDecodeURIComponent(input) { // Keep track of all the replacements and prefill the map with the `BOM` var replaceMap = { '%FE%FF': '\uFFFD\uFFFD', '%FF%FE': '\uFFFD\uFFFD' }; var match = multiMatcher.exec(input); while (match) { try { // Decode as big chunks as possible replaceMap[match[0]] = decodeURIComponent(match[0]); } catch (err) { var result = decode(match[0]); if (result !== match[0]) { replaceMap[match[0]] = result; } } match = multiMatcher.exec(input); } // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else replaceMap['%C2'] = '\uFFFD'; var entries = Object.keys(replaceMap); for (var i = 0; i < entries.length; i++) { // Replace all decoded components var key = entries[i]; input = input.replace(new RegExp(key, 'g'), replaceMap[key]); } return input; } var decodeUriComponent = function (encodedURI) { if (typeof encodedURI !== 'string') { throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); } try { encodedURI = encodedURI.replace(/\+/g, ' '); // Try the built in decoder first return decodeURIComponent(encodedURI); } catch (err) { // Fallback to a more advanced decoder return customDecodeURIComponent(encodedURI); } }; function encoderForArrayFormat(options) { switch (options.arrayFormat) { case 'index': return function (key, value, index) { return value === null ? [ encode(key, options), '[', index, ']' ].join('') : [ encode(key, options), '[', encode(index, options), ']=', encode(value, options) ].join(''); }; case 'bracket': return function (key, value) { return value === null ? [encode(key, options), '[]'].join('') : [ encode(key, options), '[]=', encode(value, options) ].join(''); }; default: return function (key, value) { return value === null ? encode(key, options) : [ encode(key, options), '=', encode(value, options) ].join(''); }; } } function parserForArrayFormat(options) { var result; switch (options.arrayFormat) { case 'index': return function (key, value, accumulator) { result = /\[(\d*)\]$/.exec(key); key = key.replace(/\[\d*\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = {}; } accumulator[key][result[1]] = value; }; case 'bracket': return function (key, value, accumulator) { result = /(\[\])$/.exec(key); key = key.replace(/\[\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = [value]; return; } accumulator[key] = [].concat(accumulator[key], value); }; default: return function (key, value, accumulator) { if (accumulator[key] === undefined) { accumulator[key] = value; return; } accumulator[key] = [].concat(accumulator[key], value); }; } } function encode(value, options) { if (options.encode) { return options.strict ? strictUriEncode(value) : encodeURIComponent(value); } return value; } function decode$1(value, options) { if (options.decode) { return decodeUriComponent(value); } return value; } function keysSorter(input) { if (Array.isArray(input)) { return input.sort(); } if (typeof input === 'object') { return keysSorter(Object.keys(input)) .sort(function (a, b) { return Number(a) - Number(b); }) .map(function (key) { return input[key]; }); } return input; } function extract(input) { var queryStart = input.indexOf('?'); if (queryStart === -1) { return ''; } return input.slice(queryStart + 1); } function parse$1(input, options) { options = Object.assign({decode: true, arrayFormat: 'none'}, options); var formatter = parserForArrayFormat(options); // Create an object with no prototype var ret = Object.create(null); if (typeof input !== 'string') { return ret; } input = input.trim().replace(/^[?#&]/, ''); if (!input) { return ret; } for (var i = 0, list = input.split('&'); i < list.length; i += 1) { var param = list[i]; var ref = param.replace(/\+/g, ' ').split('='); var key = ref[0]; var value = ref[1]; // Missing `=` should be `null`: // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters value = value === undefined ? null : decode$1(value, options); formatter(decode$1(key, options), value, ret); } return Object.keys(ret).sort().reduce(function (result, key) { var value = ret[key]; if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) { // Sort object keys, not values result[key] = keysSorter(value); } else { result[key] = value; } return result; }, Object.create(null)); } var extract_1 = extract; var parse_1 = parse$1; var stringify = function (obj, options) { var defaults = { encode: true, strict: true, arrayFormat: 'none' }; options = Object.assign(defaults, options); if (options.sort === false) { options.sort = function () {}; } var formatter = encoderForArrayFormat(options); return obj ? Object.keys(obj).sort(options.sort).map(function (key) { var value = obj[key]; if (value === undefined) { return ''; } if (value === null) { return encode(key, options); } if (Array.isArray(value)) { var result = []; for (var i = 0, list = value.slice(); i < list.length; i += 1) { var value2 = list[i]; if (value2 === undefined) { continue; } result.push(formatter(key, value2, result.length)); } return result.join('&'); } return encode(key, options) + '=' + encode(value, options); }).filter(function (x) { return x.length > 0; }).join('&') : ''; }; var parseUrl = function (input, options) { return { url: input.split('?')[0] || '', query: parse$1(extract(input), options) }; }; var queryString = { extract: extract_1, parse: parse_1, stringify: stringify, parseUrl: parseUrl }; var prefix = 'nominatim_callback_'; var BASE_URL = 'https://nominatim.openstreetmap.org/'; var cbCounter = 0; var noop$1 = function () {}; function geocode (options, callback, context) { if ( options === void 0 ) options = { q: '' }; if ( callback === void 0 ) callback = noop$1; options.format = 'json'; options.addressdetails = 1; var url = BASE_URL + 'search?' + queryString.stringify(options); var name = options.callback || prefix + (cbCounter++); jsonp_1(url, { prefix: prefix, param: 'json_callback', name: name }, function () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; console.log(args); callback.apply(context, args); }); } function reverse (options, callback, context) { if ( options === void 0 ) options = {}; if ( callback === void 0 ) callback = noop$1; options.format = 'json'; options.addressdetails = 1; var url = BASE_URL + 'reverse?' + queryString.stringify(options); var name = options.callback || prefix + (cbCounter++); jsonp_1(url, { prefix: prefix, param: 'json_callback', name: name }, function () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; callback.apply(context, args); }); } var nominatim = /*#__PURE__*/Object.freeze({ geocode: geocode, reverse: reverse }); var leafletSrc = createCommonjsModule(function (module) { /* Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com (c) 2010-2013, Vladimir Agafonkin (c) 2010-2011, CloudMade */ (function (window, document, undefined) { var oldL = window.L, L = {}; L.version = '0.7.7'; // define Leaflet for Node module pattern loaders, including Browserify { module.exports = L; // define Leaflet as an AMD module } // define Leaflet as a global L variable, saving the original L to restore later if needed L.noConflict = function () { window.L = oldL; return this; }; window.L = L; /* * L.Util contains various utility functions used throughout Leaflet code. */ L.Util = { extend: function (dest) { // (Object[, Object, ...]) -> 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) { if (src.hasOwnProperty(i)) { dest[i] = src[i]; } } } return dest; }, bind: function (fn, obj) { // (Function, Object) -> Function var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; return function () { return fn.apply(obj, args || arguments); }; }, stamp: (function () { var lastId = 0, key = '_leaflet_id'; return function (obj) { obj[key] = obj[key] || ++lastId; return obj[key]; }; }()), invokeEach: function (obj, method, context) { var i, args; if (typeof obj === 'object') { args = Array.prototype.slice.call(arguments, 3); for (i in obj) { method.apply(context, [i, obj[i]].concat(args)); } return true; } return false; }, limitExecByInterval: function (fn, time, context) { var lock, execOnUnlock; return function wrapperFn() { var args = arguments; if (lock) { execOnUnlock = true; return; } lock = true; setTimeout(function () { lock = false; if (execOnUnlock) { wrapperFn.apply(context, args); execOnUnlock = false; } }, time); fn.apply(context, args); }; }, falseFn: function () { return false; }, formatNum: function (num, digits) { var pow = Math.pow(10, digits || 5); return Math.round(num * pow) / pow; }, trim: function (str) { return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); }, splitWords: function (str) { return L.Util.trim(str).split(/\s+/); }, setOptions: function (obj, options) { obj.options = L.extend({}, obj.options, options); return obj.options; }, 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('&'); }, template: function (str, data) { return str.replace(/\{ *([\w_]+) *\}/g, 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; }); }, isArray: Array.isArray || function (obj) { return (Object.prototype.toString.call(obj) === '[object Array]'); }, emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' }; (function () { // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ function getPrefixed(name) { var i, fn, prefixes = ['webkit', 'moz', 'o', 'ms']; for (i = 0; i < prefixes.length && !fn; i++) { fn = window[prefixes[i] + name]; } return fn; } var lastTime = 0; 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; var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; L.Util.requestAnimFrame = function (fn, context, immediate, element) { fn = L.bind(fn, context); if (immediate && requestFn === timeoutDefer) { fn(); } else { return requestFn.call(window, fn, 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; /* * L.Class powers the OOP facilities of the library. * Thanks to John Resig and Dean Edwards for inspiration! */ L.Class = function () {}; L.Class.extend = function (props) { var this$1 = this; // extended class with the new prototype var NewClass = function () { // call the constructor if (this.initialize) { this.initialize.apply(this, arguments); } // call all constructor hooks if (this._initHooks) { this.callInitHooks(); } }; // instantiate class without calling constructor var F = function () {}; F.prototype = this.prototype; var proto = new F(); proto.constructor = NewClass; NewClass.prototype = proto; //inherit parent's statics for (var i in this$1) { if (this$1.hasOwnProperty(i) && i !== 'prototype') { NewClass[i] = this$1[i]; } } // mix static properties into the class if (props.statics) { L.extend(NewClass, props.statics); delete props.statics; } // mix includes into the prototype if (props.includes) { L.Util.extend.apply(null, [proto].concat(props.includes)); delete props.includes; } // merge options if (props.options && proto.options) { props.options = L.extend({}, proto.options, props.options); } // mix given properties into the prototype L.extend(proto, props); proto._initHooks = []; var parent = this; // jshint camelcase: false NewClass.__super__ = parent.prototype; // add method for calling all hooks proto.callInitHooks = function () { var this$1 = this; if (this._initHooksCalled) { return; } if (parent.prototype.callInitHooks) { parent.prototype.callInitHooks.call(this); } this._initHooksCalled = true; for (var i = 0, len = proto._initHooks.length; i < len; i++) { proto._initHooks[i].call(this$1); } }; return NewClass; }; // method for adding properties to prototype L.Class.include = function (props) { L.extend(this.prototype, props); }; // merge new default options to the Class L.Class.mergeOptions = function (options) { L.extend(this.prototype.options, options); }; // add a constructor hook L.Class.addInitHook = function (fn) { // (Function) || (String, args...) var args = Array.prototype.slice.call(arguments, 1); var init = typeof fn === 'function' ? fn : function () { this[fn].apply(this, args); }; this.prototype._initHooks = this.prototype._initHooks || []; this.prototype._initHooks.push(init); }; /* * L.Mixin.Events is used to add custom events functionality to Leaflet classes. */ var eventsKey = '_leaflet_events'; L.Mixin = {}; L.Mixin.Events = { addEventListener: function (types, fn, context) { var this$1 = this; // (String, Function[, Object]) or (Object[, Object]) // types can be a map of types/handlers if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } var events = this[eventsKey] = this[eventsKey] || {}, contextId = context && context !== this && L.stamp(context), i, len, event, type, indexKey, indexLenKey, typeIndex; // types can be a string of space-separated words types = L.Util.splitWords(types); for (i = 0, len = types.length; i < len; i++) { event = { action: fn, context: context || this$1 }; type = types[i]; if (contextId) { // store listeners of a particular context in a separate hash (if it has an id) // gives a major performance boost when removing thousands of map layers indexKey = type + '_idx'; indexLenKey = indexKey + '_len'; typeIndex = events[indexKey] = events[indexKey] || {}; if (!typeIndex[contextId]) { typeIndex[contextId] = []; // keep track of the number of keys in the index to quickly check if it's empty events[indexLenKey] = (events[indexLenKey] || 0) + 1; } typeIndex[contextId].push(event); } else { events[type] = events[type] || []; events[type].push(event); } } return this; }, hasEventListeners: function (type) { // (String) -> Boolean var events = this[eventsKey]; return !!events && ((type in events && events[type].length > 0) || (type + '_idx' in events && events[type + '_idx_len'] > 0)); }, removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) if (!this[eventsKey]) { return this; } if (!types) { return this.clearAllEventListeners(); } if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } var events = this[eventsKey], contextId = context && context !== this && L.stamp(context), i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; types = L.Util.splitWords(types); for (i = 0, len = types.length; i < len; i++) { type = types[i]; indexKey = type + '_idx'; indexLenKey = indexKey + '_len'; typeIndex = events[indexKey]; if (!fn) { // clear all listeners for a type if function isn't specified delete events[type]; delete events[indexKey]; delete events[indexLenKey]; } else { listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; if (listeners) { for (j = listeners.length - 1; j >= 0; j--) { if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { removed = listeners.splice(j, 1); // set the old action to a no-op, because it is possible // that the listener is being iterated over as part of a dispatch removed[0].action = L.Util.falseFn; } } if (context && typeIndex && (listeners.length === 0)) { delete typeIndex[contextId]; events[indexLenKey]--; } } } } return this; }, clearAllEventListeners: function () { delete this[eventsKey]; return this; }, fireEvent: function (type, data) { // (String[, Object]) if (!this.hasEventListeners(type)) { return this; } var event = L.Util.extend({}, data, { type: type, target: this }); var events = this[eventsKey], listeners, i, len, typeIndex, contextId; if (events[type]) { // make sure adding/removing listeners inside other listeners won't cause infinite loop listeners = events[type].slice(); for (i = 0, len = listeners.length; i < len; i++) { listeners[i].action.call(listeners[i].context, event); } } // fire event for the context-indexed listeners as well typeIndex = events[type + '_idx']; for (contextId in typeIndex) { listeners = typeIndex[contextId].slice(); if (listeners) { for (i = 0, len = listeners.length; i < len; i++) { listeners[i].action.call(listeners[i].context, event); } } } return this; }, addOneTimeEventListener: function (types, fn, context) { if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } var handler = L.bind(function () { this .removeEventListener(types, fn, context) .removeEventListener(types, handler, context); }, this); return this .addEventListener(types, fn, context) .addEventListener(types, handler, context); } }; L.Mixin.Events.on = L.Mixin.Events.addEventListener; L.Mixin.Events.off = L.Mixin.Events.removeEventListener; L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; L.Mixin.Events.fire = L.Mixin.Events.fireEvent; /* * L.Browser handles different browser and feature detections for internal Leaflet use. */ (function () { var ie = 'ActiveXObject' in window, ielt9 = ie && !document.addEventListener, // terrible browser detection to work around Safari / iOS / Android browser bugs ua = navigator.userAgent.toLowerCase(), webkit = ua.indexOf('webkit') !== -1, chrome = ua.indexOf('chrome') !== -1, phantomjs = ua.indexOf('phantom') !== -1, android = ua.indexOf('android') !== -1, android23 = ua.search('android [23]') !== -1, gecko = ua.indexOf('gecko') !== -1, mobile = typeof orientation !== undefined + '', msPointer = !window.PointerEvent && window.MSPointerEvent, pointer = (window.PointerEvent && window.navigator.pointerEnabled) || msPointer, retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && window.matchMedia('(min-resolution:144dpi)').matches), doc = document.documentElement, ie3d = ie && ('transition' in doc.style), webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, gecko3d = 'MozPerspective' in doc.style, opera3d = 'OTransition' in doc.style, any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch)); L.Browser = { ie: ie, ielt9: ielt9, webkit: webkit, gecko: gecko && !webkit && !window.opera && !ie, android: android, android23: android23, chrome: chrome, ie3d: ie3d, webkit3d: webkit3d, gecko3d: gecko3d, opera3d: opera3d, any3d: any3d, mobile: mobile, mobileWebkit: mobile && webkit, mobileWebkit3d: mobile && webkit3d, mobileOpera: mobile && window.opera, touch: touch, msPointer: msPointer, pointer: pointer, retina: retina }; }()); /* * L.Point represents a point with x and y coordinates. */ L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { this.x = (round ? Math.round(x) : x); this.y = (round ? Math.round(y) : y); }; L.Point.prototype = { clone: function () { return new L.Point(this.x, this.y); }, // non-destructive, returns a new point add: function (point) { return this.clone()._add(L.point(point)); }, // destructive, used directly for performance in situations where it's safe to modify existing point _add: function (point) { this.x += point.x; this.y += point.y; return this; }, subtract: function (point) { return this.clone()._subtract(L.point(point)); }, _subtract: function (point) { this.x -= point.x; this.y -= point.y; return this; }, divideBy: function (num) { return this.clone()._divideBy(num); }, _divideBy: function (num) { this.x /= num; this.y /= num; return this; }, multiplyBy: function (num) { return this.clone()._multiplyBy(num); }, _multiplyBy: function (num) { this.x *= num; this.y *= num; return this; }, round: function () { return this.clone()._round(); }, _round: function () { this.x = Math.round(this.x); this.y = Math.round(this.y); return this; }, floor: function () { return this.clone()._floor(); }, _floor: function () { this.x = Math.floor(this.x); this.y = Math.floor(this.y); return this; }, distanceTo: function (point) { point = L.point(point); var x = point.x - this.x, y = point.y - this.y; return Math.sqrt(x * x + y * y); }, equals: function (point) { point = L.point(point); return point.x === this.x && point.y === this.y; }, contains: function (point) { point = L.point(point); return Math.abs(point.x) <= Math.abs(this.x) && Math.abs(point.y) <= Math.abs(this.y); }, toString: function () { return 'Point(' + L.Util.formatNum(this.x) + ', ' + L.Util.formatNum(this.y) + ')'; } }; L.point = function (x, y, round) { if (x instanceof L.Point) { return x; } if (L.Util.isArray(x)) { return new L.Point(x[0], x[1]); } if (x === undefined || x === null) { return x; } return new L.Point(x, y, round); }; /* * L.Bounds represents a rectangular area on the screen in pixel coordinates. */ L.Bounds = function (a, b) { var this$1 = this; //(Point, Point) or Point[] if (!a) { return; } var points = b ? [a, b] : a; for (var i = 0, len = points.length; i < len; i++) { this$1.extend(points[i]); } }; L.Bounds.prototype = { // extend the bounds to contain the given point extend: function (point) { // (Point) point = L.point(point); if (!this.min && !this.max) { this.min = point.clone(); this.max = point.clone(); } else { this.min.x = Math.min(point.x, this.min.x); this.max.x = Math.max(point.x, this.max.x); this.min.y = Math.min(point.y, this.min.y); this.max.y = Math.max(point.y, this.max.y); } return this; }, getCenter: function (round) { // (Boolean) -> Point return new L.Point( (this.min.x + this.max.x) / 2, (this.min.y + this.max.y) / 2, round); }, getBottomLeft: function () { // -> Point return new L.Point(this.min.x, this.max.y); }, getTopRight: function () { // -> Point return new L.Point(this.max.x, this.min.y); }, getSize: function () { return this.max.subtract(this.min); }, contains: function (obj) { // (Bounds) or (Point) -> Boolean var min, max; if (typeof obj[0] === 'number' || obj instanceof L.Point) { obj = L.point(obj); } else { obj = L.bounds(obj); } if (obj instanceof L.Bounds) { min = obj.min; max = obj.max; } else { min = max = obj; } return (min.x >= this.min.x) && (max.x <= this.max.x) && (min.y >= this.min.y) && (max.y <= this.max.y); }, intersects: function (bounds) { // (Bounds) -> Boolean bounds = L.bounds(bounds); var min = this.min, max = this.max, min2 = bounds.min, max2 = bounds.max, xIntersects = (max2.x >= min.x) && (min2.x <= max.x), yIntersects = (max2.y >= min.y) && (min2.y <= max.y); return xIntersects && yIntersects; }, isValid: function () { return !!(this.min && this.max); } }; L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) if (!a || a instanceof L.Bounds) { return a; } return new L.Bounds(a, b); }; /* * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. */ L.Transformation = function (a, b, c, d) { this._a = a; this._b = b; this._c = c; this._d = d; }; L.Transformation.prototype = { transform: function (point, scale) { // (Point, Number) -> Point return this._transform(point.clone(), scale); }, // destructive transform (faster) _transform: function (point, scale) { scale = scale || 1; point.x = scale * (this._a * point.x + this._b); point.y = scale * (this._c * point.y + this._d); return point; }, untransform: function (point, scale) { scale = scale || 1; return new L.Point( (point.x / scale - this._b) / this._a, (point.y / scale - this._d) / this._c); } }; /* * L.DomUtil contains various utility functions for working with DOM. */ L.DomUtil = { get: function (id) { return (typeof id === 'string' ? document.getElementById(id) : id); }, getStyle: function (el, style) { var value = el.style[style]; if (!value && el.currentStyle) { value = el.currentStyle[style]; } if ((!value || value === 'auto') && document.defaultView) { var css = document.defaultView.getComputedStyle(el, null); value = css ? css[style] : null; } return value === 'auto' ? null : value; }, getViewportOffset: function (element) { var top = 0, left = 0, el = element, docBody = document.body, docEl = document.documentElement, pos; do { top += el.offsetTop || 0; left += el.offsetLeft || 0; //add borders top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; pos = L.DomUtil.getStyle(el, 'position'); if (el.offsetParent === docBody && pos === 'absolute') { break; } if (pos === 'fixed') { top += docBody.scrollTop || docEl.scrollTop || 0; left += docBody.scrollLeft || docEl.scrollLeft || 0; break; } if (pos === 'relative' && !el.offsetLeft) { var width = L.DomUtil.getStyle(el, 'width'), maxWidth = L.DomUtil.getStyle(el, 'max-width'), r = el.getBoundingClientRect(); if (width !== 'none' || maxWidth !== 'none') { left += r.left + el.clientLeft; } //calculate full y offset since we're breaking out of the loop top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); break; } el = el.offsetParent; } while (el); el = element; do { if (el === docBody) { break; } top -= el.scrollTop || 0; left -= el.scrollLeft || 0; el = el.parentNode; } while (el); return new L.Point(left, top); }, documentIsLtr: function () { if (!L.DomUtil._docIsLtrCached) { L.DomUtil._docIsLtrCached = true; L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; } return L.DomUtil._docIsLtr; }, create: function (tagName, className, container) { var el = document.createElement(tagName); el.className = className; if (container) { container.appendChild(el); } return el; }, hasClass: function (el, name) { if (el.classList !== undefined) { return el.classList.contains(name); } var className = L.DomUtil._getClass(el); return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); }, addClass: function (el, name) { if (el.classList !== undefined) { var classes = L.Util.splitWords(name); for (var i = 0, len = classes.length; i < len; i++) { el.classList.add(classes[i]); } } else if (!L.DomUtil.hasClass(el, name)) { var className = L.DomUtil._getClass(el); L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); } }, removeClass: function (el, name) { if (el.classList !== undefined) { el.classList.remove(name); } else { L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); } }, _setClass: function (el, name) { if (el.className.baseVal === undefined) { el.className = name; } else { // in case of SVG element el.className.baseVal = name; } }, _getClass: function (el) { return el.className.baseVal === undefined ? el.className : el.className.baseVal; }, setOpacity: function (el, value) { if ('opacity' in el.style) { el.style.opacity = value; } else if ('filter' in el.style) { var filter = false, filterName = 'DXImageTransform.Microsoft.Alpha'; // filters collection throws an error if we try to retrieve a filter that doesn't exist try { filter = el.filters.item(filterName); } catch (e) { // don't set opacity to 1 if we haven't already set an opacity, // it isn't needed and breaks transparent pngs. if (value === 1) { return; } } value = Math.round(value * 100); if (filter) { filter.Enabled = (value !== 100); filter.Opacity = value; } else { el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; } } }, testProp: function (props) { var style = document.documentElement.style; for (var i = 0; i < props.length; i++) { if (props[i] in style) { return props[i]; } } return false; }, getTranslateString: function (point) { // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care // (same speed either way), Opera 12 doesn't support translate3d var is3d = L.Browser.webkit3d, open = 'translate' + (is3d ? '3d' : '') + '(', close = (is3d ? ',0' : '') + ')'; return open + point.x + 'px,' + point.y + 'px' + close; }, getScaleString: f