\n * var md = new MobileDetect(window.navigator.userAgent);\n * if (md.mobile()) {\n * location.href = (md.mobileGrade() === 'A') ? '/mobile/' : '/lynx/';\n * }\n *\n *\n * @param {string} userAgent typically taken from window.navigator.userAgent or http_header['User-Agent']\n * @param {number} [maxPhoneWidth=600] only for browsers specify a value for the maximum\n * width of smallest device side (in logical \"CSS\" pixels) until a device detected as mobile will be handled\n * as phone.\n * This is only used in cases where the device cannot be classified as phone or tablet.
UnknownPhone
, UnknownTablet
or\n * UnknownMobile
is returned.screen.width/height
.UnknownTablet
\n * and UnknownMobile
, so you will get UnknownMobile
here.UnknownMobile
only for:\n * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}.\n * In versions before v1.0.0 all 3 methods returned UnknownMobile
which was tedious to use.\n * UnknownPhone
or UnknownMobile
is returned.screen.width/height
.UnknownTablet
\n * and UnknownMobile
, so you will get null
here, while {@link MobileDetect#mobile}\n * will return UnknownMobile
.UnknownMobile
only for:\n * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}.\n * In versions before v1.0.0 all 3 methods returned UnknownMobile
which was tedious to use.\n * UnknownTablet
or UnknownMobile
is returned.screen.width/height
.UnknownTablet
\n * and UnknownMobile
, so you will get null
here, while {@link MobileDetect#mobile}\n * will return UnknownMobile
.UnknownMobile
only for:\n * {@link MobileDetect#mobile}, not for {@link MobileDetect#phone} and {@link MobileDetect#tablet}.\n * In versions before v1.0.0 all 3 methods returned UnknownMobile
which was tedious to use.\n * screen.width
.\n * undefined
if screen size wasn't detectable, else true
\n * when screen.width is less or equal to maxPhoneWidth, otherwise false
.undefined
server-side.\n */\n isPhoneSized: function (maxPhoneWidth) {\n return MobileDetect.isPhoneSized(maxPhoneWidth || this.maxPhoneWidth);\n },\n\n /**\n * Returns the mobile grade ('A', 'B', 'C').\n *\n * @returns {String} one of the mobile grades ('A', 'B', 'C').\n * @function MobileDetect#mobileGrade\n */\n mobileGrade: function () {\n if (this._cache.grade === undefined) {\n this._cache.grade = impl.mobileGrade(this);\n }\n return this._cache.grade;\n }\n };\n\n // environment-dependent\n if (typeof window !== 'undefined' && window.screen) {\n MobileDetect.isPhoneSized = function (maxPhoneWidth) {\n return maxPhoneWidth < 0 ? undefined : impl.getDeviceSmallerSide() <= maxPhoneWidth;\n };\n } else {\n MobileDetect.isPhoneSized = function () {};\n }\n\n // should not be replaced by a completely new object - just overwrite existing methods\n MobileDetect._impl = impl;\n \n MobileDetect.version = '1.4.4 2019-09-21';\n\n return MobileDetect;\n}); // end of call of define()\n})((function (undefined) {\n if (typeof module !== 'undefined' && module.exports) {\n return function (factory) { module.exports = factory(); };\n } else if (typeof define === 'function' && define.amd) {\n return define;\n } else if (typeof window !== 'undefined') {\n return function (factory) { window.MobileDetect = factory(); };\n } else {\n // please file a bug if you get this error!\n throw new Error('unknown environment');\n }\n})());","var MapboxInspect = require('./lib/MapboxInspect');\nmodule.exports = MapboxInspect;\n","var randomColor = require('randomcolor');\n\n/**\n * Assign a color to a unique layer ID and also considering\n * common layer names such as water or wood.\n * @param {string} layerId\n * @return {string} Unique random for the layer ID\n */\nfunction brightColor(layerId, alpha) {\n var luminosity = 'bright';\n var hue = null;\n\n if (/water|ocean|lake|sea|river/.test(layerId)) {\n hue = 'blue';\n }\n\n if (/state|country|place/.test(layerId)) {\n hue = 'pink';\n }\n\n if (/road|highway|transport/.test(layerId)) {\n hue = 'orange';\n }\n\n if (/contour|building/.test(layerId)) {\n hue = 'monochrome';\n }\n\n if (/building/.test(layerId)) {\n luminosity = 'dark';\n }\n\n if (/contour|landuse/.test(layerId)) {\n hue = 'yellow';\n }\n\n if (/wood|forest|park|landcover/.test(layerId)) {\n hue = 'green';\n }\n\n var rgb = randomColor({\n luminosity: luminosity,\n hue: hue,\n seed: layerId,\n format: 'rgbArray'\n });\n\n var rgba = rgb.concat([alpha || 1]);\n return 'rgba(' + rgba.join(', ') + ')';\n}\n\nexports.brightColor = brightColor;\n","var stylegen = require('./stylegen');\nvar InspectButton = require('./InspectButton');\nvar isEqual = require('lodash.isequal');\nvar renderPopup = require('./renderPopup');\nvar colors = require('./colors');\n\nfunction isInspectStyle(style) {\n return style.metadata && style.metadata['mapbox-gl-inspect:inspect'];\n}\n\nfunction markInspectStyle(style) {\n return Object.assign(style, {\n metadata: Object.assign({}, style.metadata, {\n 'mapbox-gl-inspect:inspect': true\n })\n });\n}\n\nfunction fixRasterSource(source) {\n if (\n (source.type === 'raster' || source.type === 'raster-dem') &&\n source.tileSize && source.tiles\n ) {\n return {\n type: source.type,\n tileSize: source.tileSize,\n tiles: source.tiles\n };\n }\n if (\n (source.type === 'raster' || source.type === 'raster-dem') &&\n source.url\n ) {\n return {\n type: source.type,\n url: source.url\n };\n }\n return source;\n}\n\n//TODO: We can remove this at some point in the future\nfunction fixStyle(style) {\n Object.keys(style.sources).forEach(function (sourceId) {\n style.sources[sourceId] = fixRasterSource(style.sources[sourceId]);\n });\n return style;\n}\n\nfunction notifyVersion(mapboxgl) {\n var versions = mapboxgl.version.split('.').map(parseFloat);\n if (versions[0] < 1 && versions[1] < 29) {\n console.error('MapboxInspect only supports Mapbox GL JS >= v0.29.0. Please upgrade your Mapbox GL JS version.');\n }\n}\n\nfunction MapboxInspect(options) {\n if (!(this instanceof MapboxInspect)) {\n throw new Error('MapboxInspect needs to be called with the new keyword');\n }\n\n var popup = null;\n if (window.mapboxgl) {\n notifyVersion(window.mapboxgl);\n popup = new window.mapboxgl.Popup({\n closeButton: false,\n closeOnClick: false\n });\n } else if (!options.popup) {\n console.error('Mapbox GL JS can not be found. Make sure to include it or pass an initialized MapboxGL Popup to MapboxInspect if you are using moduleis.');\n }\n\n this.options = Object.assign({\n showInspectMap: false,\n showInspectButton: true,\n showInspectMapPopup: true,\n showMapPopup: false,\n showMapPopupOnHover: true,\n showInspectMapPopupOnHover: true,\n blockHoverPopupOnClick: false,\n backgroundColor: '#fff',\n assignLayerColor: colors.brightColor,\n buildInspectStyle: stylegen.generateInspectStyle,\n renderPopup: renderPopup,\n popup: popup,\n selectThreshold: 5,\n useInspectStyle: true,\n queryParameters: {},\n sources: {}\n }, options);\n\n this.sources = this.options.sources;\n this.assignLayerColor = this.options.assignLayerColor;\n this.toggleInspector = this.toggleInspector.bind(this);\n this._popup = this.options.popup;\n this._popupBlocked = false;\n this._showInspectMap = this.options.showInspectMap;\n this._onSourceChange = this._onSourceChange.bind(this);\n this._onMousemove = this._onMousemove.bind(this);\n this._onStyleChange = this._onStyleChange.bind(this);\n\n this._originalStyle = null;\n this._toggle = new InspectButton({\n show: this.options.showInspectButton,\n onToggle: this.toggleInspector.bind(this)\n });\n}\n\nMapboxInspect.prototype.toggleInspector = function () {\n this._showInspectMap = !this._showInspectMap;\n this.render();\n};\n\nMapboxInspect.prototype._inspectStyle = function () {\n var coloredLayers = stylegen.generateColoredLayers(this.sources, this.assignLayerColor);\n return this.options.buildInspectStyle(this._map.getStyle(), coloredLayers, {\n backgroundColor: this.options.backgroundColor\n });\n};\n\nMapboxInspect.prototype.render = function () {\n if (this._showInspectMap) {\n if (this.options.useInspectStyle) {\n this._map.setStyle(fixStyle(markInspectStyle(this._inspectStyle())));\n }\n this._toggle.setMapIcon();\n } else if (this._originalStyle) {\n if (this._popup) this._popup.remove();\n if (this.options.useInspectStyle) {\n this._map.setStyle(fixStyle(this._originalStyle));\n }\n this._toggle.setInspectIcon();\n }\n};\n\nMapboxInspect.prototype._onSourceChange = function () {\n var sources = this.sources;\n var map = this._map;\n var mapStyle = map.getStyle();\n var mapStyleSourcesNames = Object.keys(mapStyle.sources);\n var previousSources = Object.assign({}, sources);\n\n //NOTE: This heavily depends on the internal API of Mapbox GL\n //so this breaks between Mapbox GL JS releases\n Object.keys(map.style.sourceCaches).forEach(function (sourceId) {\n var sourceCache = map.style.sourceCaches[sourceId] || {_source: {}};\n var layerIds = sourceCache._source.vectorLayerIds;\n if (layerIds) {\n sources[sourceId] = layerIds;\n } else if (sourceCache._source.type === 'geojson') {\n sources[sourceId] = [];\n }\n });\n\n Object.keys(sources).forEach(function (sourceId) {\n if (mapStyleSourcesNames.indexOf(sourceId) === -1) {\n delete sources[sourceId];\n }\n });\n\n if (!isEqual(previousSources, sources) && Object.keys(sources).length > 0) {\n this.render();\n }\n};\n\nMapboxInspect.prototype._onStyleChange = function () {\n var style = this._map.getStyle();\n if (!isInspectStyle(style)) {\n this._originalStyle = style;\n }\n};\n\nMapboxInspect.prototype._onMousemove = function (e) {\n var queryBox;\n if (this.options.selectThreshold === 0) {\n queryBox = e.point;\n } else {\n // set a bbox around the pointer\n queryBox = [\n [\n e.point.x - this.options.selectThreshold,\n e.point.y + this.options.selectThreshold\n ], // bottom left (SW)\n [\n e.point.x + this.options.selectThreshold,\n e.point.y - this.options.selectThreshold\n ] // top right (NE)\n ];\n }\n\n var features = this._map.queryRenderedFeatures(queryBox, this.options.queryParameters) || [];\n this._map.getCanvas().style.cursor = (features.length) ? 'pointer' : '';\n\n if (this._showInspectMap) {\n if (!this.options.showInspectMapPopup) return;\n if (e.type === 'mousemove' && !this.options.showInspectMapPopupOnHover) return;\n if (e.type === 'click' && this.options.showInspectMapPopupOnHover && this.options.blockHoverPopupOnClick) {\n this._popupBlocked = !this._popupBlocked;\n }\n } else {\n if (!this.options.showMapPopup) return;\n if (e.type === 'mousemove' && !this.options.showMapPopupOnHover) return;\n if (e.type === 'click' && this.options.showMapPopupOnHover && this.options.blockHoverPopupOnClick) {\n this._popupBlocked = !this._popupBlocked;\n }\n }\n\n if (!this._popupBlocked && this._popup) {\n if (!features.length) {\n this._popup.remove();\n } else {\n this._popup.setLngLat(e.lngLat);\n\n var type = typeof this.options.renderPopup(features);\n\n if (type === 'string') {\n this._popup.setHTML(this.options.renderPopup(features));\n } else {\n this._popup.setDOMContent(this.options.renderPopup(features));\n }\n\n this._popup.addTo(this._map);\n }\n }\n};\n\nMapboxInspect.prototype.onAdd = function (map) {\n this._map = map;\n\n // if sources have already been passed as options\n // we do not need to figure out the sources ourselves\n if (Object.keys(this.sources).length === 0) {\n map.on('tiledata', this._onSourceChange);\n map.on('sourcedata', this._onSourceChange);\n }\n\n map.on('styledata', this._onStyleChange);\n map.on('load', this._onStyleChange);\n map.on('mousemove', this._onMousemove);\n map.on('click', this._onMousemove);\n return this._toggle.elem;\n};\n\nMapboxInspect.prototype.onRemove = function () {\n this._map.off('styledata', this._onStyleChange);\n this._map.off('load', this._onStyleChange);\n this._map.off('tiledata', this._onSourceChange);\n this._map.off('sourcedata', this._onSourceChange);\n this._map.off('mousemove', this._onMousemove);\n this._map.off('click', this._onMousemove);\n\n var elem = this._toggle.elem;\n elem.parentNode.removeChild(elem);\n this._map = undefined;\n};\n\nmodule.exports = MapboxInspect;\n"],"sourceRoot":""}