(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
    (function (global){
    var L = (typeof window !== "undefined" ? window['L'] : typeof global !== "undefined" ? global['L'] : null)
    var fetchJsonp = require('fetch-jsonp')
    var bboxIntersect = require('bbox-intersect')
    
    /**
     * Converts tile xyz coordinates to Quadkey
     * @param {Number} x
     * @param {Number} y
     * @param {Number} z
     * @return {Number} Quadkey
     */
    function toQuadKey (x, y, z) {
      var index = ''
      for (var i = z; i > 0; i--) {
        var b = 0
        var mask = 1 << (i - 1)
        if ((x & mask) !== 0) b++
        if ((y & mask) !== 0) b += 2
        index += b.toString()
      }
      return index
    }
    
    /**
     * Converts Leaflet BBoxString to Bing BBox
     * @param {String} bboxString 'southwest_lng,southwest_lat,northeast_lng,northeast_lat'
     * @return {Array} [south_lat, west_lng, north_lat, east_lng]
     */
    function toBingBBox (bboxString) {
      var bbox = bboxString.split(',')
      return [bbox[1], bbox[0], bbox[3], bbox[2]]
    }
    
    var VALID_IMAGERY_SETS = [
      'Aerial',
      'AerialWithLabels',
      'AerialWithLabelsOnDemand',
      'Road',
      'RoadOnDemand',
      'CanvasLight',
      'CanvasDark',
      'CanvasGray',
      'OrdnanceSurvey'
    ]
    
    var DYNAMIC_IMAGERY_SETS = [
      'AerialWithLabelsOnDemand',
      'RoadOnDemand'
    ]
    
    /**
     * Create a new Bing Maps layer.
     * @param {string|object} options Either a [Bing Maps Key](https://msdn.microsoft.com/en-us/library/ff428642.aspx) or an options object
     * @param {string} options.BingMapsKey A valid Bing Maps Key (required)
     * @param {string} [options.imagerySet=Aerial] Type of imagery, see https://msdn.microsoft.com/en-us/library/ff701716.aspx
     * @param {string} [options.culture='en-US'] Language for labels, see https://msdn.microsoft.com/en-us/library/hh441729.aspx
     * @return {L.TileLayer} A Leaflet TileLayer to add to your map
     *
     * Create a basic map
     * @example
     * var map = L.map('map').setView([51.505, -0.09], 13)
     * L.TileLayer.Bing(MyBingMapsKey).addTo(map)
     */
    L.TileLayer.Bing = L.TileLayer.extend({
      options: {
        bingMapsKey: null, // Required
        imagerySet: 'Aerial',
        culture: 'en-US',
        minZoom: 1,
        minNativeZoom: 1,
        maxNativeZoom: 19
      },
    
      statics: {
        METADATA_URL: 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{imagerySet}?key={bingMapsKey}&include=ImageryProviders&uriScheme=https',
        POINT_METADATA_URL: 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{imagerySet}/{lat},{lng}?zl={z}&key={bingMapsKey}&uriScheme=https'
      },
    
      initialize: function (options) {
        if (typeof options === 'string') {
          options = { bingMapsKey: options }
        }
        if (options && options.BingMapsKey) {
          options.bingMapsKey = options.BingMapsKey
          console.warn('use options.bingMapsKey instead of options.BingMapsKey')
        }
        if (!options || !options.bingMapsKey) {
          throw new Error('Must supply options.BingMapsKey')
        }
        options = L.setOptions(this, options)
        if (VALID_IMAGERY_SETS.indexOf(options.imagerySet) < 0) {
          throw new Error("'" + options.imagerySet + "' is an invalid imagerySet, see https://github.com/digidem/leaflet-bing-layer#parameters")
        }
        if (options && options.style && DYNAMIC_IMAGERY_SETS.indexOf(options.imagerySet) < 0) {
          console.warn('Dynamic styles will only work with these imagerySet choices: ' + DYNAMIC_IMAGERY_SETS.join(', '))
        }
    
        var metaDataUrl = L.Util.template(L.TileLayer.Bing.METADATA_URL, {
          bingMapsKey: this.options.bingMapsKey,
          imagerySet: this.options.imagerySet
        })
    
        this._imageryProviders = []
        this._attributions = []
    
        // Keep a reference to the promise so we can use it later
        this._fetch = fetchJsonp(metaDataUrl, {jsonpCallback: 'jsonp'})
          .then(function (response) {
            return response.json()
          })
          .then(this._metaDataOnLoad.bind(this))
          .catch(console.error.bind(console))
    
        // for https://github.com/Leaflet/Leaflet/issues/137
        if (!L.Browser.android) {
          this.on('tileunload', this._onTileRemove)
        }
      },
    
      createTile: function (coords, done) {
        var tile = document.createElement('img')
    
        L.DomEvent.on(tile, 'load', L.bind(this._tileOnLoad, this, done, tile))
        L.DomEvent.on(tile, 'error', L.bind(this._tileOnError, this, done, tile))
    
        if (this.options.crossOrigin) {
          tile.crossOrigin = ''
        }
    
        /*
         Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
         http://www.w3.org/TR/WCAG20-TECHS/H67
        */
        tile.alt = ''
    
        // Don't create closure if we don't have to
        if (this._url) {
          tile.src = this.getTileUrl(coords)
        } else {
          this._fetch.then(function () {
            tile.src = this.getTileUrl(coords)
          }.bind(this)).catch(function (e) {
            console.error(e)
            done(e)
          })
        }
    
        return tile
      },
    
      getTileUrl: function (coords) {
        var quadkey = toQuadKey(coords.x, coords.y, coords.z)
        var url = L.Util.template(this._url, {
          quadkey: quadkey,
          subdomain: this._getSubdomain(coords),
          culture: this.options.culture
        })
        if (typeof this.options.style === 'string') {
          url += '&st=' + this.options.style
        }
        return url
      },
    
      // Update the attribution control every time the map is moved
      onAdd: function (map) {
        map.on('moveend', this._updateAttribution, this)
        L.TileLayer.prototype.onAdd.call(this, map)
        this._attributions.forEach(function (attribution) {
          map.attributionControl.addAttribution(attribution)
        })
      },
    
      // Clean up events and remove attributions from attribution control
      onRemove: function (map) {
        map.off('moveend', this._updateAttribution, this)
        this._attributions.forEach(function (attribution) {
          map.attributionControl.removeAttribution(attribution)
        })
        L.TileLayer.prototype.onRemove.call(this, map)
      },
    
      /**
       * Get the [Bing Imagery metadata](https://msdn.microsoft.com/en-us/library/ff701712.aspx)
       * for a specific [`LatLng`](http://leafletjs.com/reference.html#latlng)
       * and zoom level. If either `latlng` or `zoom` is omitted and the layer is attached
       * to a map, the map center and current map zoom are used.
       * @param {L.LatLng} latlng
       * @param {Number} zoom
       * @return {Promise} Resolves to the JSON metadata
       */
      getMetaData: function (latlng, zoom) {
        if (!this._map && (!latlng || !zoom)) {
          return Promise.reject(new Error('If layer is not attached to map, you must provide LatLng and zoom'))
        }
        latlng = latlng || this._map.getCenter()
        zoom = zoom || this._map.getZoom()
        var PointMetaDataUrl = L.Util.template(L.TileLayer.Bing.POINT_METADATA_URL, {
          bingMapsKey: this.options.bingMapsKey,
          imagerySet: this.options.imagerySet,
          z: zoom,
          lat: latlng.lat,
          lng: latlng.lng
        })
        return fetchJsonp(PointMetaDataUrl, {jsonpCallback: 'jsonp'})
          .then(function (response) {
            return response.json()
          })
          .catch(console.error.bind(console))
      },
    
      _metaDataOnLoad: function (metaData) {
        if (metaData.statusCode !== 200) {
          throw new Error('Bing Imagery Metadata error: \n' + JSON.stringify(metaData, null, '  '))
        }
        var resource = metaData.resourceSets[0].resources[0]
        this._url = resource.imageUrl
        this._imageryProviders = resource.imageryProviders || []
        this.options.subdomains = resource.imageUrlSubdomains
        this._updateAttribution()
        return Promise.resolve()
      },
    
      /**
       * Update the attribution control of the map with the provider attributions
       * within the current map bounds
       */
      _updateAttribution: function () {
        var map = this._map
        if (!map || !map.attributionControl) return
        var zoom = map.getZoom()
        var bbox = toBingBBox(map.getBounds().toBBoxString())
        this._fetch.then(function () {
          var newAttributions = this._getAttributions(bbox, zoom)
          var prevAttributions = this._attributions
          // Add any new provider attributions in the current area to the attribution control
          newAttributions.forEach(function (attr) {
            if (prevAttributions.indexOf(attr) > -1) return
            map.attributionControl.addAttribution(attr)
          })
          // Remove any attributions that are no longer in the current area from the attribution control
          prevAttributions.filter(function (attr) {
            if (newAttributions.indexOf(attr) > -1) return
            map.attributionControl.removeAttribution(attr)
          })
          this._attributions = newAttributions
        }.bind(this))
      },
    
      /**
       * Returns an array of attributions for given bbox and zoom
       * @private
       * @param {Array} bbox [west, south, east, north]
       * @param {Number} zoom
       * @return {Array} Array of attribution strings for each provider
       */
      _getAttributions: function (bbox, zoom) {
        return this._imageryProviders.reduce(function (attributions, provider) {
          for (var i = 0; i < provider.coverageAreas.length; i++) {
            if (bboxIntersect(bbox, provider.coverageAreas[i].bbox) &&
              zoom >= provider.coverageAreas[i].zoomMin &&
              zoom <= provider.coverageAreas[i].zoomMax) {
              attributions.push(provider.attribution)
              return attributions
            }
          }
          return attributions
        }, [])
      }
    })
    
    L.tileLayer.bing = function (options) {
      return new L.TileLayer.Bing(options)
    }
    
    module.exports = L.TileLayer.Bing
    
    }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    },{"bbox-intersect":2,"fetch-jsonp":3}],2:[function(require,module,exports){
    module.exports = function(bbox1, bbox2){
      if(!(
          bbox1[0] > bbox2[2] ||
          bbox1[2] < bbox2[0] ||
          bbox1[3] < bbox2[1] ||
          bbox1[1] > bbox2[3]
        )){
          return true;
      } else {
        return false;
      }
    }
    },{}],3:[function(require,module,exports){
    (function (global, factory) {
      if (typeof define === 'function' && define.amd) {
        define(['exports', 'module'], factory);
      } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
        factory(exports, module);
      } else {
        var mod = {
          exports: {}
        };
        factory(mod.exports, mod);
        global.fetchJsonp = mod.exports;
      }
    })(this, function (exports, module) {
      'use strict';
    
      var defaultOptions = {
        timeout: 5000,
        jsonpCallback: 'callback',
        jsonpCallbackFunction: null
      };
    
      function generateCallbackFunction() {
        return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
      }
    
      // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined' error if request timeout
      function clearFunction(functionName) {
        // IE8 throws an exception when you try to delete a property on window
        // http://stackoverflow.com/a/1824228/751089
        try {
          delete window[functionName];
        } catch (e) {
          window[functionName] = undefined;
        }
      }
    
      function removeScript(scriptId) {
        var script = document.getElementById(scriptId);
        document.getElementsByTagName('head')[0].removeChild(script);
      }
    
      var fetchJsonp = function fetchJsonp(url) {
        var options = arguments[1] === undefined ? {} : arguments[1];
    
        var timeout = options.timeout != null ? options.timeout : defaultOptions.timeout;
        var jsonpCallback = options.jsonpCallback != null ? options.jsonpCallback : defaultOptions.jsonpCallback;
    
        var timeoutId = undefined;
    
        return new Promise(function (resolve, reject) {
          var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
    
          window[callbackFunction] = function (response) {
            resolve({
              ok: true,
              // keep consistent with fetch API
              json: function json() {
                return Promise.resolve(response);
              }
            });
    
            if (timeoutId) clearTimeout(timeoutId);
    
            removeScript(jsonpCallback + '_' + callbackFunction);
    
            clearFunction(callbackFunction);
          };
    
          // Check if the user set their own params, and if not add a ? to start a list of params
          url += url.indexOf('?') === -1 ? '?' : '&';
    
          var jsonpScript = document.createElement('script');
          jsonpScript.setAttribute('src', url + jsonpCallback + '=' + callbackFunction);
          jsonpScript.id = jsonpCallback + '_' + callbackFunction;
          document.getElementsByTagName('head')[0].appendChild(jsonpScript);
    
          timeoutId = setTimeout(function () {
            reject(new Error('JSONP request to ' + url + ' timed out'));
    
            clearFunction(callbackFunction);
            removeScript(jsonpCallback + '_' + callbackFunction);
          }, timeout);
        });
      };
    
      // export as global function
      /*
      let local;
      if (typeof global !== 'undefined') {
        local = global;
      } else if (typeof self !== 'undefined') {
        local = self;
      } else {
        try {
          local = Function('return this')();
        } catch (e) {
          throw new Error('polyfill failed because global object is unavailable in this environment');
        }
      }
      
      local.fetchJsonp = fetchJsonp;
      */
    
      module.exports = fetchJsonp;
    });
    },{}]},{},[1]);