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);