diff --git a/core/code/map.js b/core/code/map.js index a18443d76..c79baef8a 100644 --- a/core/code/map.js +++ b/core/code/map.js @@ -316,6 +316,32 @@ window.setupMap = function () { map.attributionControl.setPrefix(''); + /** + * Override default Google Maps attribution to use Leaflet's native attribution control + * instead of creating separate DOM elements. Extracts text content from Google's + * attribution container and adds it to Leaflet's control. + */ + L.GridLayer.GoogleMutant.prototype._setupAttribution = function (ev) { + if (!this._map?.attributionControl) { + return; + } + // eslint-disable-next-line + const pos = google.maps.ControlPosition; + const container = ev.positions.get(pos.BOTTOM_RIGHT); + const attribution = container?.querySelector('span')?.textContent; + if (attribution) { + this._attributionText = attribution; // Сохраняем текст атрибуции + this._map.attributionControl.addAttribution(attribution); + } + }; + const originalGoogleMutantOnRemove = L.GridLayer.GoogleMutant.prototype.onRemove; + L.GridLayer.GoogleMutant.prototype.onRemove = function (map) { + originalGoogleMutantOnRemove.call(this, map); + if (this._attributionText && map.attributionControl) { + map.attributionControl.removeAttribution(this._attributionText); + } + }; + window.map = map; map.on('moveend', function () { diff --git a/core/code/portal_detail_display.js b/core/code/portal_detail_display.js index 9c2489b7e..422befd44 100644 --- a/core/code/portal_detail_display.js +++ b/core/code/portal_detail_display.js @@ -161,9 +161,6 @@ window.renderPortalDetails = function (guid, forceSelect) { .text('X') .click(function () { window.renderPortalDetails(null); - if (window.isSmartphone()) { - window.show('map'); - } }), // help cursor via ".imgpreview img" diff --git a/core/code/portal_highlighter.js b/core/code/portal_highlighter.js index c40f6c8bb..0156d2454 100644 --- a/core/code/portal_highlighter.js +++ b/core/code/portal_highlighter.js @@ -61,12 +61,10 @@ window.updatePortalHighlighterControl = function () { if (window._highlighters !== null) { if ($('#portal_highlight_select').length === 0) { - $('body').append(""); + $('.leaflet-top.leaflet-left').first().append(""); $('#portal_highlight_select').change(function () { window.changePortalHighlights($(this).val()); }); - $('.leaflet-top.leaflet-left').css('padding-top', '20px'); - $('.leaflet-control-scale-line').css('margin-top', '25px'); } $('#portal_highlight_select').html(''); $('#portal_highlight_select').append($('').attr('value', window._no_highlighter).text(window._no_highlighter)); diff --git a/core/external/Leaflet.GoogleMutant.js b/core/external/Leaflet.GoogleMutant.js index a6c86a20f..ac2acec77 100644 --- a/core/external/Leaflet.GoogleMutant.js +++ b/core/external/Leaflet.GoogleMutant.js @@ -376,17 +376,9 @@ // 🍂extends GridLayer L.GridLayer.GoogleMutant = L.GridLayer.extend({ options: { - minZoom: 0, maxZoom: 21, // can be 23, but ugly if more than maxNativeZoom - tileSize: 256, - subdomains: "abc", - errorTileUrl: "", - attribution: "", // The mutant container will add its own attribution anyways. - opacity: 1, - continuousWorld: false, - noWrap: false, // 🍂option type: String = 'roadmap' - // Google's map type. Valid values are 'roadmap', 'satellite' or 'terrain'. 'hybrid' is not really supported. + // Google's map type. Valid values are 'roadmap', 'satellite', 'terrain' or 'hybrid'. type: "roadmap", maxNativeZoom: 21, }, @@ -404,7 +396,7 @@ }, onAdd: function (map) { - var this$1 = this; + var this$1$1 = this; L.GridLayer.prototype.onAdd.call(this, map); this._initMutantContainer(); @@ -420,18 +412,18 @@ } waitForAPI(function () { - if (!this$1._map) { + if (!this$1$1._map) { return; } - this$1._initMutant(); + this$1$1._initMutant(); //handle layer being added to a map for which there are no Google tiles at the given zoom - google.maps.event.addListenerOnce(this$1._mutant, "idle", function () { - if (!this$1._map) { + google.maps.event.addListenerOnce(this$1$1._mutant, "idle", function () { + if (!this$1$1._map) { return; } - this$1._checkZoomLevels(); - this$1._mutantIsReady = true; + this$1$1._checkZoomLevels(); + this$1$1._mutantIsReady = true; }); }); }, @@ -457,14 +449,14 @@ // currently following values supported: 'TrafficLayer', 'TransitLayer', 'BicyclingLayer'. // `options`: see https://developers.google.com/maps/documentation/javascript/reference/map addGoogleLayer: function (googleLayerName, options) { - var this$1 = this; + var this$1$1 = this; if (!this._subLayers) { this._subLayers = {}; } this.whenReady(function () { var Constructor = google.maps[googleLayerName]; var googleLayer = new Constructor(options); - googleLayer.setMap(this$1._mutant); - this$1._subLayers[googleLayerName] = googleLayer; + googleLayer.setMap(this$1$1._mutant); + this$1$1._subLayers[googleLayerName] = googleLayer; }); return this; }, @@ -472,13 +464,13 @@ // 🍂method removeGoogleLayer(name: String): this // Removes layer with the given name from the google Map instance. removeGoogleLayer: function (googleLayerName) { - var this$1 = this; + var this$1$1 = this; this.whenReady(function () { - var googleLayer = this$1._subLayers && this$1._subLayers[googleLayerName]; + var googleLayer = this$1$1._subLayers && this$1$1._subLayers[googleLayerName]; if (googleLayer) { googleLayer.setMap(null); - delete this$1._subLayers[googleLayerName]; + delete this$1$1._subLayers[googleLayerName]; } }); return this; @@ -491,8 +483,8 @@ "leaflet-google-mutant leaflet-top leaflet-left" ); this._mutantContainer.id = "_MutantContainer_" + L.Util.stamp(this._mutantContainer); - this._mutantContainer.style.zIndex = 800; //leaflet map pane at 400, controls at 1000 this._mutantContainer.style.pointerEvents = "none"; + this._mutantContainer.style.visibility = "hidden"; L.DomEvent.off(this._mutantContainer); } @@ -514,13 +506,11 @@ }, _initMutant: function () { - var this$1 = this; - if (this._mutant) { return; } - var map = new google.maps.Map(this._mutantContainer, { + var options = { center: { lat: 0, lng: 0 }, zoom: 0, tilt: 0, @@ -530,25 +520,24 @@ draggable: false, disableDoubleClickZoom: true, scrollwheel: false, - streetViewControl: false, - styles: this.options.styles || {}, + styles: this.options.styles || [], backgroundColor: "transparent", - }); + }; + if (this.options.mapId != null) { + options.mapId = this.options.mapId; + } + var map = new google.maps.Map(this._mutantContainer, options); this._mutant = map; - google.maps.event.addListenerOnce(map, "idle", function () { - var nodes = this$1._mutantContainer.querySelectorAll("a"); - for (var i = 0; i < nodes.length; ++i) { - nodes[i].style.pointerEvents = "auto"; - } - }); - this._update(); // 🍂event spawned // Fired when the mutant has been created. this.fire("spawned", { mapObject: map }); + + this._waitControls(); + this.once('controls_ready', this._setupAttribution); }, _attachObserver: function _attachObserver(node) { @@ -562,6 +551,46 @@ Array.prototype.forEach.call(node.querySelectorAll("img"), this._boundOnMutatedImage); }, + _waitControls: function () { + var this$1$1 = this; + + var id = setInterval(function () { + var layoutManager = this$1$1._mutant.__gm.layoutManager; + if (!layoutManager) { return; } + clearInterval(id); + var positions; + // iterate through obfuscated key names to find positions set (atm: layoutManager.o) + Object.keys(layoutManager).forEach(function(key) { + var el = layoutManager[key]; + if (el.get) { + if (el.get(1) instanceof Node) { + positions = el; + } + } + }); + // 🍂event controls_ready + // Fired when controls positions get available (passed in `positions` property). + this$1$1.fire("controls_ready", { positions: positions }); + }, 50); + }, + + _setupAttribution: function (ev) { + if (!this._map) { + return; + } + // https://developers.google.com/maps/documentation/javascript/reference/control#ControlPosition + var pos = google.maps.ControlPosition; + var ctr = this._attributionContainer = ev.positions.get(pos.BOTTOM_RIGHT); + L.DomUtil.addClass(ctr, "leaflet-control leaflet-control-attribution"); + L.DomEvent.disableClickPropagation(ctr); + ctr.style.height = "14px"; + this._map._controlCorners.bottomright.appendChild(ctr); + + this._logoContainer = ev.positions.get(pos.BOTTOM_LEFT); + this._logoContainer.style.pointerEvents = "auto"; + this._map._controlCorners.bottomleft.appendChild(this._logoContainer); + }, + _onMutations: function _onMutations(mutations) { for (var i = 0; i < mutations.length; ++i) { var mutation = mutations[i]; @@ -575,51 +604,6 @@ node.querySelectorAll("img"), this._boundOnMutatedImage ); - - // Check for, and remove, the "Google Maps can't load correctly" div. - // You *are* loading correctly, you dumbwit. - if (node.style.backgroundColor === "white") { - L.DomUtil.remove(node); - } - - // Check for, and remove, the "For development purposes only" divs on the aerial/hybrid tiles. - if (node.textContent.indexOf("For development purposes only") === 0) { - L.DomUtil.remove(node); - } - - // Check for, and remove, the "Sorry, we have no imagery here" - // empty s. The [style*="text-align: center"] selector - // avoids matching the attribution notice. - // This empty div doesn't have a reference to the tile - // coordinates, so it's not possible to mark the tile as - // failed. - Array.prototype.forEach.call( - node.querySelectorAll('div[draggable=false][style*="text-align: center"]'), - L.DomUtil.remove - ); - - // Move Google attributions to leaflet's bottom-right control container - if ( - node.querySelectorAll(".gmnoprint").length > 0 || - node.querySelectorAll('a[title="Click to see this area on Google Maps"]') - .length > 0 - ) { - var ctr = (this._attributionContainer = L.DomUtil.create( - "div", - "leaflet-control leaflet-control-attribution" - )); - L.DomEvent.disableClickPropagation(ctr); - ctr.style.height = "14px"; - ctr.style.background = "none"; - this._map._controlCorners.bottomright.appendChild(ctr); - ctr.appendChild(node); - } - - // Move Google logo to leaflet's bottom-left control container - if (node.style.zIndex == 1000000) { - this._map._controlCorners.bottomleft.appendChild(node); - this._logoContainer = node; - } } } } @@ -628,14 +612,10 @@ // Only images which 'src' attrib match this will be considered for moving around. // Looks like some kind of string-based protobuf, maybe?? // Only the roads (and terrain, and vector-based stuff) match this pattern - _roadRegexp: /!1i(\d+)!2i(\d+)!3i(\d+)!/, + _roadRegexp: /!1i(\d+)!2i(\d+)!3i(\d+|VinaFnapurmBegrtn)!/, // On the other hand, raster imagery matches this other pattern - _satRegexp: /x=(\d+)&y=(\d+)&z=(\d+)/, - - // On small viewports, when zooming in/out, a static image is requested - // This will not be moved around, just removed from the DOM. - _staticRegExp: /StaticMapService\.GetMapImage/, + _satRegexp: /x=(\d+)&y=(\d+)&z=(\d+|VinaFnapurmBegrtn)/, _onMutatedImage: function _onMutatedImage(imgNode) { var coords; @@ -668,7 +648,6 @@ if (coords) { var tileKey = this._tileCoordsToKey(coords); imgNode.style.position = "absolute"; - imgNode.style.visibility = "hidden"; var key = tileKey + "/" + sublayer; // Cache img so it can also be used in subsequent tile requests @@ -679,8 +658,6 @@ this._tileCallbacks[key].forEach(function (callback) { return callback(imgNode); }); delete this._tileCallbacks[key]; } - } else if (imgNode.src.match(this._staticRegExp)) { - imgNode.style.visibility = "hidden"; } }, @@ -793,5 +770,5 @@ return new L.GridLayer.GoogleMutant(options); }; -}()); +})(); //# sourceMappingURL=Leaflet.GoogleMutant.js.map diff --git a/core/smartphone.css b/core/smartphone.css index 3092b9ea4..7de1583a5 100644 --- a/core/smartphone.css +++ b/core/smartphone.css @@ -125,11 +125,6 @@ body { margin-left: 4px; } -.leaflet-top .leaflet-control { - margin-top: 5px !important; - margin-left: 5px !important; -} - #searchwrapper .ui-accordion-header { padding: 0.3em 0; } diff --git a/core/style.css b/core/style.css index 77cbcf33a..082774488 100644 --- a/core/style.css +++ b/core/style.css @@ -161,6 +161,35 @@ a:hover { margin-left: 720px; } +/* leaflet controls */ +.leaflet-left, .leaflet-right { + display: grid; + grid-gap: 10px; + justify-items: baseline; +} + +.leaflet-right { + justify-items: end; +} + +.leaflet-left .leaflet-control, +.leaflet-right .leaflet-control { + margin: 0; +} + +.leaflet-top { + top: 10px; +} +.leaflet-right { + right: 10px; +} +.leaflet-bottom { + bottom: 10px; +} +.leaflet-left { + left: 10px; +} + .help { cursor: help; } @@ -1221,16 +1250,21 @@ td + td { } #portal_highlight_select { - position: absolute; - top:5px; - left:10px; z-index: 2500; font-size:11px; background-color:#0E3C46; color:#ffce00; + order: -100; +} +.leaflet-control-scale { + order: -90; } +.leaflet-bar { + border: 2px solid rgba(0, 0, 0, 0.2); + box-shadow: none; +} .portal_details th, .portal_details td { diff --git a/core/total-conversion-build.js b/core/total-conversion-build.js index 0473e7ddd..21276538c 100644 --- a/core/total-conversion-build.js +++ b/core/total-conversion-build.js @@ -143,13 +143,13 @@ document.head.innerHTML = 'Ingress Intel Map' + '' + '' + '' + '' + // note: smartphone.css injection moved into code/smartphone.js ''; diff --git a/plugins/pan-control.css b/plugins/pan-control.css new file mode 100644 index 000000000..702cddeac --- /dev/null +++ b/plugins/pan-control.css @@ -0,0 +1,17 @@ +.leaflet-left.has-leaflet-pan-control .leaflet-bar { + left: 24.5px; +} + +.leaflet-touch .leaflet-left.has-leaflet-pan-control .leaflet-bar { + left: 34px +} + +.leaflet-control-pan { + order: -50; +} + +.leaflet-control-pan div { + border: 2px solid rgba(0, 0, 0, 0.2); + box-shadow: none; + border-radius: 4px; +} diff --git a/plugins/pan-control.js b/plugins/pan-control.js index 2ffb0681e..55b770f78 100644 --- a/plugins/pan-control.js +++ b/plugins/pan-control.js @@ -40,28 +40,8 @@ function setup() { if (!panControl.options.position) { // default: 'topleft' // to be above all controls - $('.leaflet-top.leaflet-left .leaflet-control').first().before(panControl.control.getContainer()); + $('.leaflet-top.leaflet-left').first().append(panControl.control.getContainer()); } - - // L.Control.Pan.css tries to align zoom control with the pan control, but the result sucks - // so here is our attempt to make it better - // (adapted from https://github.com/kartena/Leaflet.Pancontrol/pull/20) - $('