diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index 4cd6e083..334db65a 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -9,5 +9,6 @@ This project is licensed under the permissive ISC license. Parts imported from o - [oms.min.js by George MacKerron; MIT](https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet) - [taphold.js by Rich Adams; unknown](https://github.com/richadams/jquery-taphold) - [L.Control.Pan.js by Kartena AB; same as Leaftlet](https://github.com/kartena/Leaflet.Pancontrol) +- [L.Control.Zoomslider.js by Kartena AB; same as Leaftlet](https://github.com/kartena/Leaflet.zoomslider) - StackOverflow-CopyPasta is attributed in the source; [CC-Wiki](https://creativecommons.org/licenses/by-sa/3.0/) - all Ingress/Niantic related stuff obviously remains non-free and is still copyrighted by Niantic/Google diff --git a/external/L.Control.Zoomslider.css b/external/L.Control.Zoomslider.css new file mode 100644 index 00000000..5e70bbee --- /dev/null +++ b/external/L.Control.Zoomslider.css @@ -0,0 +1,106 @@ +/** Slider **/ +.leaflet-control-zoomslider-slider { + padding-top: 5px ; + padding-bottom: 5px; +} + +.leaflet-control-zoomslider-slider-body { + background-image: url(@@INCLUDEIMAGE:images/zoom-slider.png@@); + background-repeat: repeat-y; + background-position: center 0px; + height: 100%; + cursor: default; +} + +.leaflet-control-zoomslider-slider-knob { + width: 13px; + height:5px; + background-color: black; + background-position: center; + -webkit-border-radius: 15px; + border-radius: 15px; + margin-left: 5px; + /*border: 5px; */ + position:relative; +} + +.leaflet-control-zoomslider-slider-body:hover { + cursor: pointer; +} + +.leaflet-control-zoomslider-slider-knob:hover { + cursor: default; + cursor: -webkit-grab; + cursor: -moz-grab; +} + +.leaflet-dragging .leaflet-control-zoomslider, +.leaflet-dragging .leaflet-control-zoomslider-slider, +.leaflet-dragging .leaflet-control-zoomslider-slider-body, +.leaflet-dragging .leaflet-control-zoomslider a, +.leaflet-dragging .leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled, +.leaflet-dragging .leaflet-control-zoomslider-slider-knob:hover { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; +} + +/** Leaflet Zoom Styles **/ +.leaflet-container .leaflet-control-zoomslider { + margin-left: 13px; + margin-top: 12px; +} +.leaflet-control-zoomslider a { + width: 23px; + height: 22px; + text-align: center; + text-decoration: none; + color: black; + display: block; +} +.leaflet-control-zoomslider a:hover { + background-color: #fff; + color: #777; +} +.leaflet-control-zoomslider-in { + font: bold 19px/24px Arial, Helvetica, sans-serif; +} +.leaflet-control-zoomslider-in:after{ + content:"+" +} +.leaflet-control-zoomslider-out { + font: bold 23px/20px Tahoma, Verdana, sans-serif; +} +.leaflet-control-zoomslider-out:after{ + content:"-" +} +.leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled { + cursor: default; + color: #bbb; +} + +/* Touch */ + +.leaflet-touch .leaflet-control-zoomslider-slider-knob { + width:20px; +} +.leaflet-touch .leaflet-control-zoomslider a { + width: 30px; + height: 30px; +} +.leaflet-touch .leaflet-control-zoomslider-in { + font-size: 24px; + line-height: 29px; +} +.leaflet-touch .leaflet-control-zoomslider-out { + font-size: 28px; + line-height: 24px; +} + +.leaflet-touch .leaflet-control-zoomslider { + box-shadow: none; +} + +.leaflet-touch .leaflet-control-zoomslider { + border: 4px solid rgba(0,0,0,0.3); +} diff --git a/external/L.Control.Zoomslider.js b/external/L.Control.Zoomslider.js new file mode 100644 index 00000000..06b594b0 --- /dev/null +++ b/external/L.Control.Zoomslider.js @@ -0,0 +1,221 @@ +L.Control.Zoomslider = (function(){ + + var Knob = L.Draggable.extend({ + initialize: function (element, steps, stepHeight, knobHeight) { + var sliderHeight = steps * stepHeight; + L.Draggable.prototype.initialize.call(this, element, element); + + this._element = element; + this._maxValue = steps - 1; + + // conversion parameters + // the conversion is just a common linear function. + this._k = -stepHeight; + this._m = sliderHeight - (stepHeight + knobHeight) / 2; + + this.on('predrag', function() { + this._newPos.x = 0; + this._newPos.y = this._adjust(this._newPos.y); + }, this); + }, + + _adjust: function (y) { + var value = Math.round(this._toValue(y)); + value = Math.max(0, Math.min(this._maxValue, value)); + return this._toY(value); + }, + + // y = k*v + m + _toY: function (value) { + return this._k * value + this._m; + }, + // v = (y - m) / k + _toValue: function (y) { + return (y - this._m) / this._k; + }, + + setPosition: function (y) { + L.DomUtil.setPosition(this._element, + L.point(0, this._adjust(y))); + }, + + setValue: function (v) { + this.setPosition(this._toY(v)); + }, + + getValue: function () { + return this._toValue(L.DomUtil.getPosition(this._element).y); + } + }); + + var Zoomslider = L.Control.extend({ + options: { + position: 'topleft', + // Height of zoom-slider.png in px + stepHeight: 9, + // Height of the knob div in px + knobHeight: 5, + styleNS: 'leaflet-control-zoomslider' + }, + + onAdd: function (map) { + var container = L.DomUtil.create('div', this.options.styleNS + ' leaflet-bar'); + + L.DomEvent.disableClickPropagation(container); + + this._map = map; + + this._zoomInButton = this._createZoomButton( + 'in', 'top', container, this._zoomIn); + + this._sliderElem = L.DomUtil.create( + 'div', + this.options.styleNS + "-slider leaflet-bar-part", + container); + + this._zoomOutButton = this._createZoomButton( + 'out', 'bottom', container, this._zoomOut); + + map .on('layeradd layerremove', this._refresh, this) + .on("zoomend", this._updateSlider, this) + .on("zoomend", this._updateDisabled, this) + .whenReady(this._createSlider, this) + .whenReady(this._createKnob, this) + .whenReady(this._updateSlider, this) + .whenReady(this._updateDisabled, this); + + return container; + }, + + onRemove: function (map) { + map .off("zoomend", this._updateSlider) + .off("zoomend", this._updateDisabled) + .off('layeradd layerremove', this._refresh); + }, + + _refresh: function () { + // TODO: listen to zoomlevelschange-event instead in 0.6.x + this._map + .removeControl(this) + .addControl(this); + }, + _zoomLevels: function(){ + return this._map.getMaxZoom() - this._map.getMinZoom() + 1; + }, + + _createSlider: function () { + var zoomLevels = this._zoomLevels(); + + // No tilelayer probably + if(zoomLevels == Infinity){ + return; + } + + this._sliderBody = L.DomUtil.create('div', + this.options.styleNS + '-slider-body', + this._sliderElem); + this._sliderBody.style.height + = (this.options.stepHeight * zoomLevels) + "px"; + L.DomEvent.on(this._sliderBody, 'click', this._onSliderClick, this); + }, + + _createKnob: function () { + var knobElem, + zoomLevels = this._zoomLevels(); + + // No tilelayer probably + if(zoomLevels == Infinity) { + return; + } + + knobElem = L.DomUtil.create('div', this.options.styleNS + '-slider-knob', + this._sliderBody); + L.DomEvent.disableClickPropagation(knobElem); + + this._knob = new Knob(knobElem, + this._zoomLevels(), + this.options.stepHeight, + this.options.knobHeight) + .on('dragend', this._updateZoom, this); + this._knob.enable(); + }, + + _onSliderClick: function (e) { + var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e); + var y = L.DomEvent.getMousePosition(first).y + - L.DomUtil.getViewportOffset(this._sliderBody).y; // Cache this? + this._knob.setPosition(y); + this._updateZoom(); + }, + + _zoomIn: function (e) { + this._map.zoomIn(e.shiftKey ? 3 : 1); + }, + _zoomOut: function (e) { + this._map.zoomOut(e.shiftKey ? 3 : 1); + }, + + _createZoomButton: function (zoomDir, end, container, fn) { + var barPart = 'leaflet-bar-part', + classDef = this.options.styleNS + '-' + zoomDir + + ' ' + barPart + + ' ' + barPart + '-' + end, + title = 'Zoom ' + zoomDir, + link = L.DomUtil.create('a', classDef, container); + link.href = '#'; + link.title = title; + + L.DomEvent + .on(link, 'click', L.DomEvent.preventDefault) + .on(link, 'click', fn, this); + + return link; + }, + _toZoomLevel: function (sliderValue) { + return sliderValue + this._map.getMinZoom(); + }, + _toSliderValue: function (zoomLevel) { + return zoomLevel - this._map.getMinZoom(); + }, + + _updateZoom: function(){ + this._map.setZoom(this._toZoomLevel(this._knob.getValue())); + }, + _updateSlider: function(){ + if(this._knob){ + this._knob.setValue(this._toSliderValue(this._map.getZoom())); + } + }, + _updateDisabled: function () { + var map = this._map, + className = this.options.styleNS + '-disabled'; + + L.DomUtil.removeClass(this._zoomInButton, className); + L.DomUtil.removeClass(this._zoomOutButton, className); + + if (map.getZoom() === map.getMinZoom()) { + L.DomUtil.addClass(this._zoomOutButton, className); + } + if (map.getZoom() === map.getMaxZoom()) { + L.DomUtil.addClass(this._zoomInButton, className); + } + } + }); + return Zoomslider; +})(); + +L.Map.mergeOptions({ + zoomControl: false, + zoomsliderControl: true +}); + +L.Map.addInitHook(function () { + if (this.options.zoomsliderControl) { + this.zoomsliderControl = new L.Control.Zoomslider(); + this.addControl(this.zoomsliderControl); + } +}); + +L.control.zoomslider = function (options) { + return new L.Control.Zoomslider(options); +}; diff --git a/images/zoom-slider.png b/images/zoom-slider.png new file mode 100644 index 00000000..529f451b Binary files /dev/null and b/images/zoom-slider.png differ diff --git a/plugins/zoom-slider.user.js b/plugins/zoom-slider.user.js new file mode 100644 index 00000000..a0b41b7b --- /dev/null +++ b/plugins/zoom-slider.user.js @@ -0,0 +1,55 @@ +// ==UserScript== +// @id iitc-plugin-zoom-slider@fragger +// @name IITC plugin: zoom slider +// @version 0.1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Shows a zoom slider on the map instead of the zoom buttons +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// ==/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.zoomSlider = function() {}; + +window.plugin.zoomSlider.setup = function() { + try { console.log('Loading Leaflet.zoomslider JS now'); } catch(e) {} + @@INCLUDERAW:external/L.Control.Zoomslider.js@@ + try { console.log('done loading Leaflet.zoomslider JS'); } catch(e) {} + + if(map.zoomControl._map) { + window.map.removeControl(map.zoomControl); + } + window.map.addControl(L.control.zoomslider()); + + $('head').append(''); +}; + +var setup = window.plugin.zoomSlider.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);