text: (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', 'Road']
  
  /**
   * 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
    },
  
    statics: {
      METADATA_URL: 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{imagerySet}?key={bingMapsKey}&include=ImageryProviders',
      POINT_METADATA_URL: 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{imagerySet}/{lat},{lng}?zl={z}&key={bingMapsKey}'
    },
  
    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/gmaclennan/leaflet-bing-layer#parameters")
      }
      // Bing maps do not have zoom=0 tiles.
      options.minZoom = Math.max(1, options.minZoom)
  
      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) {
      if (coords.z > this.options.maxNativeZoom) {
        coords.z = this.options.maxNativeZoom;
      }
      var quadkey = toQuadKey(coords.x, coords.y, coords.z)
      return L.Util.template(this._url, {
        quadkey: quadkey,
        subdomain: this._getSubdomain(coords),
        culture: this.options.culture
      })
    },
  
    // 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);
    }
  
    function fetchJsonp(_url) {
      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  
      // to avoid param reassign
      var url = _url;
      var timeout = options.timeout || defaultOptions.timeout;
      var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
  
      var timeoutId = undefined;
  
      return new Promise(function (resolve, reject) {
        var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
        var scriptId = jsonpCallback + '_' + callbackFunction;
  
        window[callbackFunction] = function (response) {
          resolve({
            ok: true,
            // keep consistent with fetch API
            json: function json() {
              return Promise.resolve(response);
            }
          });
  
          if (timeoutId) clearTimeout(timeoutId);
  
          removeScript(scriptId);
  
          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 = scriptId;
        document.getElementsByTagName('head')[0].appendChild(jsonpScript);
  
        timeoutId = setTimeout(function () {
          reject(new Error('JSONP request to ' + _url + ' timed out'));
  
          clearFunction(callbackFunction);
          removeScript(scriptId);
        }, 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]);
  