diff --git a/code/boot.js b/code/boot.js index 1277c6d8..e85cc24d 100644 --- a/code/boot.js +++ b/code/boot.js @@ -100,12 +100,6 @@ window.setupMap = function() { //OpenStreetMap attribution - required by several of the layers osmAttribution = 'Map data © OpenStreetMap contributors'; - - //CloudMade layers - only 500,000 tiles/month in their free plan. nowhere near enough for IITC - //var cmOpt = {attribution: osmAttribution+', Imagery © CloudMade', maxZoom: 18, detectRetina: true}; - //var cmMin = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/22677/256/{z}/{x}/{y}.png', cmOpt); - //var cmMid = new L.TileLayer('http://{s}.tile.cloudmade.com/{your api key here}/999/256/{z}/{x}/{y}.png', cmOpt); - //MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; @@ -130,6 +124,13 @@ window.setupMap = function() { {zoomControl: window.showZoom} )); + // add empty div to leaflet control areas - to force other leaflet controls to move around IITC UI elements + // TODO? move the actual IITC DOM into the leaflet control areas, so dummy
s aren't needed + if(!isSmartphone()) { + // chat window area + $(window.map._controlCorners['bottomleft']).append($('
').width(708).height(108).addClass('leaflet-control').css('margin','0')); + } + var addLayers = {}; var hiddenLayer = []; diff --git a/external/Control.MiniMap.css b/external/Control.MiniMap.css new file mode 100644 index 00000000..c558467f --- /dev/null +++ b/external/Control.MiniMap.css @@ -0,0 +1,31 @@ +.leaflet-control-minimap { + border:solid rgba(255, 255, 255, 0.7) 3px; + box-shadow: 0 1px 7px #999; + background: #f8f8f9; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +.leaflet-control-minimap a { + background-color: rgba(255, 255, 255, 0.75); + background-position: 1px 2px; + background-repeat: no-repeat; + display: block; + outline: none; + z-index: 99999; +} + +.leaflet-control-minimap a.minimized { + background-position: 1px -18px; +} + +.leaflet-control-minimap-toggle-display { + background-image: url(@@INCLUDEIMAGE:images/minimap-toggle.png@@); + border-radius: 4px 4px 4px 4px; + height: 19px; + width: 19px; + position: absolute; + bottom: 0; + right: 0; +} diff --git a/external/Control.MiniMap.js b/external/Control.MiniMap.js new file mode 100644 index 00000000..db912307 --- /dev/null +++ b/external/Control.MiniMap.js @@ -0,0 +1,243 @@ +L.Control.MiniMap = L.Control.extend({ + options: { + position: 'bottomright', + toggleDisplay: false, + zoomLevelOffset: -5, + zoomLevelFixed: false, + zoomAnimation: false, + autoToggleDisplay: false, + width: 150, + height: 150 + }, + + hideText: 'Hide MiniMap', + + showText: 'Show MiniMap', + + //layer is the map layer to be shown in the minimap + initialize: function (layer, options) { + L.Util.setOptions(this, options); + this._layer = layer; + }, + + onAdd: function (map) { + + this._mainMap = map; + + //Creating the container and stopping events from spilling through to the main map. + this._container = L.DomUtil.create('div', 'leaflet-control-minimap'); + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + L.DomEvent.disableClickPropagation(this._container); + L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation); + + + this._miniMap = new L.Map(this._container, + { + attributionControl: false, + zoomControl: false, + zoomAnimation: this.options.zoomAnimation, + autoToggleDisplay: this.options.autoToggleDisplay, + touchZoom: !this.options.zoomLevelFixed, + scrollWheelZoom: !this.options.zoomLevelFixed, + doubleClickZoom: !this.options.zoomLevelFixed, + boxZoom: !this.options.zoomLevelFixed, + crs: map.options.crs + }); + + this._miniMap.addLayer(this._layer); + + //These bools are used to prevent infinite loops of the two maps notifying each other that they've moved. + this._mainMapMoving = false; + this._miniMapMoving = false; + + //Keep a record of this to prevent auto toggling when the user explicitly doesn't want it. + this._userToggledDisplay = false; + this._minimized = false; + + if (this.options.toggleDisplay) { + this._addToggleButton(); + } + + this._miniMap.whenReady(L.Util.bind(function () { + this._aimingRect = L.rectangle(this._mainMap.getBounds(), {color: "#ff7800", weight: 1, clickable: false}).addTo(this._miniMap); + this._shadowRect = L.rectangle(this._mainMap.getBounds(), {color: "#000000", weight: 1, clickable: false,opacity:0,fillOpacity:0}).addTo(this._miniMap); + this._mainMap.on('moveend', this._onMainMapMoved, this); + this._mainMap.on('move', this._onMainMapMoving, this); + this._miniMap.on('movestart', this._onMiniMapMoveStarted, this); + this._miniMap.on('move', this._onMiniMapMoving, this); + this._miniMap.on('moveend', this._onMiniMapMoved, this); + }, this)); + + return this._container; + }, + + addTo: function (map) { + L.Control.prototype.addTo.call(this, map); + this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); + this._setDisplay(this._decideMinimized()); + return this; + }, + + onRemove: function (map) { + this._mainMap.off('moveend', this._onMainMapMoved, this); + this._mainMap.off('move', this._onMainMapMoving, this); + this._miniMap.off('moveend', this._onMiniMapMoved, this); + + this._miniMap.removeLayer(this._layer); + }, + + _addToggleButton: function () { + this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton( + '', this.hideText, 'leaflet-control-minimap-toggle-display', this._container, this._toggleDisplayButtonClicked, this) : undefined; + }, + + _createButton: function (html, title, className, container, fn, context) { + var link = L.DomUtil.create('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = title; + + var stop = L.DomEvent.stopPropagation; + + L.DomEvent + .on(link, 'click', stop) + .on(link, 'mousedown', stop) + .on(link, 'dblclick', stop) + .on(link, 'click', L.DomEvent.preventDefault) + .on(link, 'click', fn, context); + + return link; + }, + + _toggleDisplayButtonClicked: function () { + this._userToggledDisplay = true; + if (!this._minimized) { + this._minimize(); + this._toggleDisplayButton.title = this.showText; + } + else { + this._restore(); + this._toggleDisplayButton.title = this.hideText; + } + }, + + _setDisplay: function (minimize) { + if (minimize != this._minimized) { + if (!this._minimized) { + this._minimize(); + } + else { + this._restore(); + } + } + }, + + _minimize: function () { + // hide the minimap + if (this.options.toggleDisplay) { + this._container.style.width = '19px'; + this._container.style.height = '19px'; + this._toggleDisplayButton.className += ' minimized'; + } + else { + this._container.style.display = 'none'; + } + this._minimized = true; + }, + + _restore: function () { + if (this.options.toggleDisplay) { + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + this._toggleDisplayButton.className = this._toggleDisplayButton.className + .replace(/(?:^|\s)minimized(?!\S)/g, ''); + } + else { + this._container.style.display = 'block'; + } + this._minimized = false; + }, + + _onMainMapMoved: function (e) { + if (!this._miniMapMoving) { + this._mainMapMoving = true; + this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); + this._setDisplay(this._decideMinimized()); + } else { + this._miniMapMoving = false; + } + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMainMapMoving: function (e) { + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMiniMapMoveStarted:function (e) { + var lastAimingRect = this._aimingRect.getBounds(); + var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest()); + var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast()); + this._lastAimingRectPosition = {sw:sw,ne:ne}; + }, + + _onMiniMapMoving: function (e) { + if (!this._mainMapMoving && this._lastAimingRectPosition) { + this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne))); + this._shadowRect.setStyle({opacity:1,fillOpacity:0.3}); + } + }, + + _onMiniMapMoved: function (e) { + if (!this._mainMapMoving) { + this._miniMapMoving = true; + this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false)); + this._shadowRect.setStyle({opacity:0,fillOpacity:0}); + } else { + this._mainMapMoving = false; + } + }, + + _decideZoom: function (fromMaintoMini) { + if (!this.options.zoomLevelFixed) { + if (fromMaintoMini) + return this._mainMap.getZoom() + this.options.zoomLevelOffset; + else + return this._miniMap.getZoom() - this.options.zoomLevelOffset; + } else { + if (fromMaintoMini) + return this.options.zoomLevelFixed; + else + return this._mainMap.getZoom(); + } + }, + + _decideMinimized: function () { + if (this._userToggledDisplay) { + return this._minimized; + } + + if (this.options.autoToggleDisplay) { + if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) { + return true; + } + return false; + } + + return this._minimized; + } +}); + +L.Map.mergeOptions({ + miniMapControl: false +}); + +L.Map.addInitHook(function () { + if (this.options.miniMapControl) { + this.miniMapControl = (new L.Control.MiniMap()).addTo(this); + } +}); + +L.control.minimap = function (options) { + return new L.Control.MiniMap(options); +}; diff --git a/images/minimap-toggle.png b/images/minimap-toggle.png new file mode 100644 index 00000000..026d4c8b Binary files /dev/null and b/images/minimap-toggle.png differ diff --git a/plugins/max-links.user.js b/plugins/max-links.user.js index 5184a20c..eddda059 100644 --- a/plugins/max-links.user.js +++ b/plugins/max-links.user.js @@ -2,7 +2,7 @@ // @id max-links@boombuler // @name IITC plugin: Max Links // @category Layer -// @version 0.3.1.@@DATETIMEVERSION@@ +// @version 0.4.0.@@DATETIMEVERSION@@ // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ // @description [@@BUILDNAME@@-@@BUILDDATE@@] Calculates how to link the portals to create the maximum number of fields. Enable from the layer chooser. @@ -30,15 +30,24 @@ window.plugin.maxLinks.MAX_DRAWN_LINKS_INCREASED_LIMIT = 1000; window.plugin.maxLinks.STROKE_STYLE = { color: '#FF0000', opacity: 1, - weight:2, + weight: 2, clickable: false, - smoothFactor: 10 + dashArray: [8,6], + smoothFactor: 10, }; window.plugin.maxLinks.layer = null; window.plugin.maxLinks._updating = false; window.plugin.maxLinks._renderLimitReached = false; +window.plugin.maxLinks.Point = function(x,y) { + this.x=x; + this.y=y; +} +window.plugin.maxLinks.Point.prototype.toString = function() { + return this.x+","+this.y; +} + window.plugin.maxLinks.updateLayer = function() { if (window.plugin.maxLinks._updating || window.plugin.maxLinks.layer === null || @@ -48,36 +57,62 @@ window.plugin.maxLinks.updateLayer = function() { window.plugin.maxLinks.layer.clearLayers(); var locations = []; - var minX = 0; - var minY = 0; $.each(window.portals, function(guid, portal) { var loc = portal.options.details.locationE6; - var nloc = { x: loc.lngE6, y: loc.latE6 }; - if (nloc.x < minX) - minX = nloc.x; - if (nloc.y < minY) - minY = nloc.y; + var nloc = new window.plugin.maxLinks.Point(loc.latE6/1E6, loc.lngE6/1E6); locations.push(nloc); }); - $.each(locations, function(idx, nloc) { - nloc.x += Math.abs(minX); - nloc.y += Math.abs(minY); - }); - var triangles = window.delaunay.triangulate(locations); - var drawnLinks = 0; + + var drawnLinkCount = 0; window.plugin.maxLinks._renderLimitReached = false; - var renderlimit = window.USE_INCREASED_RENDER_LIMIT ? + var renderLimit = window.USE_INCREASED_RENDER_LIMIT ? window.plugin.maxLinks.MAX_DRAWN_LINKS_INCREASED_LIMIT : window.plugin.maxLinks.MAX_DRAWN_LINKS; + + var orderedPoints = function(a,b) { + if(a.x renderLimit ) { window.plugin.maxLinks._renderLimitReached = true; + return false; //$.each break } }); window.plugin.maxLinks._updating = false; @@ -89,17 +124,6 @@ window.plugin.maxLinks.setup = function() { @@INCLUDERAW:external/delaunay.js@@ try { console.log('done loading delaunay JS'); } catch(e) {} - window.delaunay.Triangle.prototype.draw = function(layer, divX, divY) { - var drawLine = function(src, dest) { - var poly = L.polyline([[(src.y + divY)/1E6, (src.x + divX)/1E6], [(dest.y + divY)/1E6, (dest.x + divX)/1E6]], window.plugin.maxLinks.STROKE_STYLE); - poly.addTo(layer); - }; - - drawLine(this.a, this.b); - drawLine(this.b, this.c); - drawLine(this.c, this.a); - } - window.plugin.maxLinks.layer = L.layerGroup([]); window.addHook('checkRenderLimit', function(e) { @@ -108,9 +132,8 @@ window.plugin.maxLinks.setup = function() { e.reached = true; }); - window.addHook('portalDataLoaded', function(e) { - if (window.map.hasLayer(window.plugin.maxLinks.layer)) - window.plugin.maxLinks.updateLayer(); + window.addHook('requestFinished', function(e) { + window.plugin.maxLinks.updateLayer(); }); window.map.on('layeradd', function(e) { diff --git a/plugins/minimap.user.js b/plugins/minimap.user.js new file mode 100644 index 00000000..68a34e01 --- /dev/null +++ b/plugins/minimap.user.js @@ -0,0 +1,71 @@ +// ==UserScript== +// @id iitc-plugin-minimap@breunigs +// @name IITC plugin: Mini map +// @category Controls +// @version 0.1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Shows a mini map on the corner of the map +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// @grant none +// ==/UserScript== + +function wrapper() { +// ensure plugin framework is there, even if iitc is not yet loaded +if(typeof window.plugin !== 'function') window.plugin = function() {}; + + +// PLUGIN START //////////////////////////////////////////////////////// + + +// use own namespace for plugin +window.plugin.miniMap = function() {}; + +window.plugin.miniMap.setup = function() { + + try { console.log('Loading leaflet.draw JS now'); } catch(e) {} + @@INCLUDERAW:external/Control.MiniMap.js@@ + try { console.log('done loading leaflet.draw JS'); } catch(e) {} + + // we can't use the same TileLayer as the main map uses - it causes issues. + // stick with the MapQuest tiles for now + + //OpenStreetMap attribution - required by several of the layers + osmAttribution = 'Map data © OpenStreetMap contributors'; + + //MapQuest offer tiles - http://developer.mapquest.com/web/products/open/map + //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) + var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; + var mqTileUrlPrefix = window.location.protocol !== 'https:' ? 'http://{s}.mqcdn.com' : 'https://{s}-s.mqcdn.com'; + var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', maxZoom: 18, subdomains: mqSubdomains}; + var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt); + + new L.Control.MiniMap(mqMap, {toggleDisplay: true, position: 'bottomleft'}).addTo(window.map); + + + $('head').append(''); + + +}; + +var setup = window.plugin.miniMap.setup; + +// PLUGIN END ////////////////////////////////////////////////////////// + +if(window.iitcLoaded && typeof setup === 'function') { + setup(); +} else { + if(window.bootPlugins) + window.bootPlugins.push(setup); + else + window.bootPlugins = [setup]; +} +} // wrapper end +// inject code into site context +var script = document.createElement('script'); +script.appendChild(document.createTextNode('('+ wrapper +')();')); +(document.body || document.head || document.documentElement).appendChild(script);