From e6afda8764a6c96fc350d2417154cd0c432eefda Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 31 Oct 2012 21:27:28 -0600 Subject: [PATCH] Update Leaflet --- Vendorfile | 2 +- vendor/assets/leaflet/leaflet.css | 2 + vendor/assets/leaflet/leaflet.ie.css | 3 + vendor/assets/leaflet/leaflet.js | 365 +++++++++++++++++++++++---- 4 files changed, 324 insertions(+), 48 deletions(-) diff --git a/Vendorfile b/Vendorfile index 6d0eb1196..000a05ff7 100644 --- a/Vendorfile +++ b/Vendorfile @@ -1,6 +1,6 @@ folder 'vendor/assets' do folder 'leaflet' do - from 'https://github.com/CloudMade/Leaflet.git' do + from 'https://github.com/jfirebaugh/Leaflet.git', :branch => 'osm' do file 'leaflet.css', 'dist/leaflet.css' file 'leaflet.ie.css', 'dist/leaflet.ie.css' file 'leaflet.js', 'dist/leaflet-src.js' diff --git a/vendor/assets/leaflet/leaflet.css b/vendor/assets/leaflet/leaflet.css index a9e44fd92..dce84046d 100644 --- a/vendor/assets/leaflet/leaflet.css +++ b/vendor/assets/leaflet/leaflet.css @@ -14,10 +14,12 @@ .leaflet-image-layer, .leaflet-layer { /* TODO optimize classes */ position: absolute; + left: 0; } .leaflet-container { overflow: hidden; outline: 0; + -ms-touch-action: none; } .leaflet-tile, .leaflet-marker-icon, diff --git a/vendor/assets/leaflet/leaflet.ie.css b/vendor/assets/leaflet/leaflet.ie.css index 9d2a52fba..5b65c400a 100644 --- a/vendor/assets/leaflet/leaflet.ie.css +++ b/vendor/assets/leaflet/leaflet.ie.css @@ -41,4 +41,7 @@ } .leaflet-control-attribution, .leaflet-control-layers { background: white; + } +.leaflet-zoom-box { + filter: alpha(opacity=50); } \ No newline at end of file diff --git a/vendor/assets/leaflet/leaflet.js b/vendor/assets/leaflet/leaflet.js index 7c5b717e7..90c52bddf 100644 --- a/vendor/assets/leaflet/leaflet.js +++ b/vendor/assets/leaflet/leaflet.js @@ -346,28 +346,40 @@ L.Mixin.Events.fire = L.Mixin.Events.fireEvent; (function () { - var ua = navigator.userAgent.toLowerCase(), - ie = !!window.ActiveXObject, + + var ie = !!window.ActiveXObject, + // http://tanalin.com/en/articles/ie-version-js/ ie6 = ie && !window.XMLHttpRequest, + ie7 = ie && !document.querySelector, + + // terrible browser detection to work around Safari / iOS / Android browser bugs + // see TileLayer._addTile and debug/hacks/jitter.html + + ua = navigator.userAgent.toLowerCase(), webkit = ua.indexOf("webkit") !== -1, - gecko = ua.indexOf("gecko") !== -1, - //Terrible browser detection to work around a safari / iOS / android browser bug. See TileLayer._addTile and debug/hacks/jitter.html chrome = ua.indexOf("chrome") !== -1, - opera = window.opera, android = ua.indexOf("android") !== -1, android23 = ua.search("android [23]") !== -1, - mobile = typeof orientation !== undefined + '' ? true : false, + + mobile = typeof orientation !== undefined + '', + msTouch = (window.navigator && window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints), + retina = (('devicePixelRatio' in window && window.devicePixelRatio > 1) || + ('matchMedia' in window && window.matchMedia("(min-resolution:144dpi)").matches)), + doc = document.documentElement, ie3d = ie && ('transition' in doc.style), - webkit3d = webkit && ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()), - gecko3d = gecko && ('MozPerspective' in doc.style), - opera3d = opera && ('OTransition' in doc.style); + webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()), + gecko3d = 'MozPerspective' in doc.style, + opera3d = 'OTransition' in doc.style, + any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d); + var touch = !window.L_NO_TOUCH && (function () { + var startName = 'ontouchstart'; - // WebKit, etc - if (startName in doc) { + // IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc. + if (msTouch || (startName in doc)) { return true; } @@ -390,15 +402,12 @@ L.Mixin.Events.fire = L.Mixin.Events.fireEvent; return supported; }()); - var retina = (('devicePixelRatio' in window && window.devicePixelRatio > 1) || ('matchMedia' in window && window.matchMedia("(min-resolution:144dpi)").matches)); L.Browser = { - ua: ua, - ie: ie, ie6: ie6, + ie7: ie7, webkit: webkit, - gecko: gecko, - opera: opera, + android: android, android23: android23, @@ -408,17 +417,19 @@ L.Mixin.Events.fire = L.Mixin.Events.fireEvent; webkit3d: webkit3d, gecko3d: gecko3d, opera3d: opera3d, - any3d: !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d), + any3d: any3d, mobile: mobile, mobileWebkit: mobile && webkit, mobileWebkit3d: mobile && webkit3d, - mobileOpera: mobile && opera, + mobileOpera: mobile && window.opera, touch: touch, + msTouch: msTouch, retina: retina }; + }()); @@ -674,7 +685,7 @@ L.DomUtil = { value = el.currentStyle[style]; } - if (!value || value === 'auto') { + if ((!value || value === 'auto') && document.defaultView) { var css = document.defaultView.getComputedStyle(el, null); value = css ? css[style] : null; } @@ -688,10 +699,11 @@ L.DomUtil = { left = 0, el = element, docBody = document.body, - pos; + pos, + ie7 = L.Browser.ie7; do { - top += el.offsetTop || 0; + top += el.offsetTop || 0; left += el.offsetLeft || 0; pos = L.DomUtil.getStyle(el, 'position'); @@ -714,12 +726,32 @@ L.DomUtil = { top -= el.scrollTop || 0; left -= el.scrollLeft || 0; + //Webkit (and ie <= 7) handles RTL scrollLeft different to everyone else + // https://code.google.com/p/closure-library/source/browse/trunk/closure/goog/style/bidi.js + if (!L.DomUtil.documentIsLtr() && (L.Browser.webkit || ie7)) { + left += el.scrollWidth - el.clientWidth; + + //ie7 shows the scrollbar by default and provides clientWidth counting it, so we need to add it back in if it is visible + // Scrollbar is on the left as we are RTL + if (ie7 && L.DomUtil.getStyle(el, 'overflow-y') !== 'hidden' && L.DomUtil.getStyle(el, 'overflow') !== 'hidden') { + left += 17; + } + } + el = el.parentNode; } while (el); return new L.Point(left, top); }, + documentIsLtr: function () { + if (!L.DomUtil._docIsLtrCached) { + L.DomUtil._docIsLtrCached = true; + L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === "ltr"; + } + return L.DomUtil._docIsLtr; + }, + create: function (tagName, className, container) { var el = document.createElement(tagName); @@ -777,7 +809,7 @@ L.DomUtil = { if ('opacity' in el.style) { el.style.opacity = value; - } else if (L.Browser.ie) { + } else if ('filter' in el.style) { var filter = false, filterName = 'DXImageTransform.Microsoft.Alpha'; @@ -1156,6 +1188,13 @@ L.CRS = { +L.CRS.Simple = L.Util.extend({}, L.CRS, { + projection: L.Projection.LonLat, + transformation: new L.Transformation(1, 0, 1, 0) +}); + + + L.CRS.EPSG3857 = L.Util.extend({}, L.CRS, { code: 'EPSG:3857', @@ -2547,7 +2586,7 @@ L.TileLayer.Canvas = L.TileLayer.extend({ }, _redrawTile: function (tile) { - this.drawTile(tile, tile._tilePoint, tile._zoom); + this.drawTile(tile, tile._tilePoint, this._map._zoom); }, _createTileProto: function () { @@ -2564,19 +2603,18 @@ L.TileLayer.Canvas = L.TileLayer.extend({ return tile; }, - _loadTile: function (tile, tilePoint, zoom) { + _loadTile: function (tile, tilePoint) { tile._layer = this; tile._tilePoint = tilePoint; - tile._zoom = zoom; - - this.drawTile(tile, tilePoint, zoom); + + this._redrawTile(tile); if (!this.options.async) { this.tileDrawn(tile); } }, - drawTile: function (tile, tilePoint, zoom) { + drawTile: function (tile, tilePoint) { // override with rendering code }, @@ -2872,7 +2910,9 @@ L.Marker = L.Class.extend({ clickable: true, draggable: false, zIndexOffset: 0, - opacity: 1 + opacity: 1, + riseOnHover: false, + riseOffset: 250 }, initialize: function (latlng, options) { @@ -2966,7 +3006,14 @@ L.Marker = L.Class.extend({ needOpacityUpdate = (this.options.opacity < 1); L.DomUtil.addClass(this._icon, classToAdd); + + if (options.riseOnHover) { + L.DomEvent + .on(this._icon, 'mouseover', this._bringToFront, this) + .on(this._icon, 'mouseout', this._resetZIndex, this); + } } + if (!this._shadow) { this._shadow = options.icon.createShadow(); @@ -2992,6 +3039,12 @@ L.Marker = L.Class.extend({ _removeIcon: function () { var panes = this._map._panes; + if (this.options.riseOnHover) { + L.DomEvent + .off(this._icon, 'mouseover', this._bringToFront) + .off(this._icon, 'mouseout', this._resetZIndex); + } + panes.markerPane.removeChild(this._icon); if (this._shadow) { @@ -3008,7 +3061,13 @@ L.Marker = L.Class.extend({ L.DomUtil.setPosition(this._shadow, pos); } - this._icon.style.zIndex = pos.y + this.options.zIndexOffset; + this._zIndex = pos.y + this.options.zIndexOffset; + + this._resetZIndex(); + }, + + _updateZIndex: function (offset) { + this._icon.style.zIndex = this._zIndex + offset; }, _animateZoom: function (opt) { @@ -3073,6 +3132,14 @@ L.Marker = L.Class.extend({ if (this._shadow) { L.DomUtil.setOpacity(this._shadow, this.options.opacity); } + }, + + _bringToFront: function () { + this._updateZIndex(this.options.riseOffset); + }, + + _resetZIndex: function () { + this._updateZIndex(0); } }); @@ -3311,6 +3378,8 @@ L.Popup = L.Class.extend({ }, _updatePosition: function () { + if (!this._map) { return; } + var pos = this._map.latLngToLayerPoint(this._latlng), is3d = L.Browser.any3d, offset = this.options.offset; @@ -3908,11 +3977,11 @@ L.Map.include({ _animatePathZoom: function (opt) { var scale = this.getZoomScale(opt.zoom), - offset = this._getCenterOffset(opt.center).divideBy(1 - 1 / scale), - viewportPos = this.containerPointToLayerPoint(this.getSize().multiplyBy(-L.Path.CLIP_PADDING)), - origin = viewportPos.add(offset).round(); + offset = this._getCenterOffset(opt.center), + translate = offset.multiplyBy(-scale)._add(this._pathViewport.min); - this._pathRoot.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString((origin.multiplyBy(-1).add(L.DomUtil.getPosition(this._pathRoot)).multiplyBy(scale).add(origin))) + ' scale(' + scale + ') '; + this._pathRoot.style[L.DomUtil.TRANSFORM] = + L.DomUtil.getTranslateString(translate) + ' scale(' + scale + ') '; this._pathZooming = true; }, @@ -5294,7 +5363,9 @@ L.DomEvent = { return fn.call(context || obj, e || L.DomEvent._getEvent()); }; - if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { + if (L.Browser.msTouch && type.indexOf('touch') === 0) { + return this.addMsTouchListener(obj, type, handler, id); + } else if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { return this.addDoubleTapListener(obj, handler, id); } else if ('addEventListener' in obj) { @@ -5336,7 +5407,9 @@ L.DomEvent = { if (!handler) { return; } - if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { + if (L.Browser.msTouch && type.indexOf('touch') === 0) { + this.removeMsTouchListener(obj, type, id); + } else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { this.removeDoubleTapListener(obj, id); } else if ('removeEventListener' in obj) { @@ -5563,6 +5636,7 @@ L.Draggable = L.Class.extend({ }, _onUp: function (e) { + var simulateClickTouch; if (this._simulateClick && e.changedTouches) { var first = e.changedTouches[0], el = first.target, @@ -5573,7 +5647,7 @@ L.Draggable = L.Class.extend({ } if (dist < L.Draggable.TAP_TOLERANCE) { - this._simulateEvent('click', first); + simulateClickTouch = first; } } @@ -5592,6 +5666,11 @@ L.Draggable = L.Class.extend({ this.fire('dragend'); } this._moving = false; + + if (simulateClickTouch) { + this._moved = false; + this._simulateEvent('click', simulateClickTouch); + } }, _setMovingCursor: function () { @@ -5824,7 +5903,7 @@ L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); */ L.Map.mergeOptions({ - scrollWheelZoom: !L.Browser.touch + scrollWheelZoom: !L.Browser.touch || L.Browser.msTouch }); L.Map.ScrollWheelZoom = L.Handler.extend({ @@ -5891,6 +5970,10 @@ L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); L.Util.extend(L.DomEvent, { + + _touchstart: L.Browser.msTouch ? 'MSPointerDown' : 'touchstart', + _touchend: L.Browser.msTouch ? 'MSPointerUp' : 'touchend', + // inspired by Zepto touch code by Thomas Fuchs addDoubleTapListener: function (obj, handler, id) { var last, @@ -5898,23 +5981,55 @@ L.Util.extend(L.DomEvent, { delay = 250, touch, pre = '_leaflet_', - touchstart = 'touchstart', - touchend = 'touchend'; + touchstart = this._touchstart, + touchend = this._touchend, + trackedTouches = []; function onTouchStart(e) { - if (e.touches.length !== 1) { + var count; + if (L.Browser.msTouch) { + trackedTouches.push(e.pointerId); + count = trackedTouches.length; + } else { + count = e.touches.length; + } + if (count > 1) { return; } var now = Date.now(), delta = now - (last || now); - touch = e.touches[0]; + touch = e.touches ? e.touches[0] : e; doubleTap = (delta > 0 && delta <= delay); last = now; } function onTouchEnd(e) { + if (L.Browser.msTouch) { + var idx = trackedTouches.indexOf(e.pointerId); + if (idx === -1) { + return; + } + trackedTouches.splice(idx, 1); + } + if (doubleTap) { + if (L.Browser.msTouch) { + //Work around .type being readonly with MSPointer* events + var newTouch = { }, + prop; + for (var i in touch) { + if (true) { //Make JSHint happy, we want to copy all properties + prop = touch[i]; + if (typeof prop === 'function') { + newTouch[i] = prop.bind(touch); + } else { + newTouch[i] = prop; + } + } + } + touch = newTouch; + } touch.type = 'dblclick'; handler(touch); last = null; @@ -5923,15 +6038,171 @@ L.Util.extend(L.DomEvent, { obj[pre + touchstart + id] = onTouchStart; obj[pre + touchend + id] = onTouchEnd; + //On msTouch we need to listen on the document otherwise a drag starting on the map and moving off screen will not come through to us + // so we will lose track of how many touches are ongoing + var endElement = L.Browser.msTouch ? document.documentElement : obj; + obj.addEventListener(touchstart, onTouchStart, false); - obj.addEventListener(touchend, onTouchEnd, false); + endElement.addEventListener(touchend, onTouchEnd, false); + if (L.Browser.msTouch) { + endElement.addEventListener('MSPointerCancel', onTouchEnd, false); + } return this; }, removeDoubleTapListener: function (obj, id) { var pre = '_leaflet_'; - obj.removeEventListener(obj, obj[pre + 'touchstart' + id], false); - obj.removeEventListener(obj, obj[pre + 'touchend' + id], false); + obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); + (L.Browser.msTouch ? document.documentElement : obj).removeEventListener(this._touchend, obj[pre + this._touchend + id], false); + if (L.Browser.msTouch) { + document.documentElement.removeEventListener('MSPointerCancel', obj[pre + this._touchend + id], false); + } + return this; + } +}); + + +L.Util.extend(L.DomEvent, { + + _msTouches: [], + _msDocumentListener: false, + + // Provides a touch events wrapper for msPointer events. + // Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 + + addMsTouchListener: function (obj, type, handler, id) { + + switch (type) { + case 'touchstart': + return this.addMsTouchListenerStart(obj, type, handler, id); + case 'touchend': + return this.addMsTouchListenerEnd(obj, type, handler, id); + case 'touchmove': + return this.addMsTouchListenerMove(obj, type, handler, id); + default: + throw 'Unknown touch event type'; + } + }, + + addMsTouchListenerStart: function (obj, type, handler, id) { + var pre = '_leaflet_', + touches = this._msTouches; + + var cb = function (e) { + + var alreadyInArray = false; + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + alreadyInArray = true; + break; + } + } + if (!alreadyInArray) { + touches.push(e); + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + obj[pre + 'touchstart' + id] = cb; + obj.addEventListener('MSPointerDown', cb, false); + + //Need to also listen for end events to keep the _msTouches list accurate + //this needs to be on the body and never go away + if (!this._msDocumentListener) { + var internalCb = function (e) { + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + touches.splice(i, 1); + break; + } + } + }; + //We listen on the documentElement as any drags that end by moving the touch off the screen get fired there + document.documentElement.addEventListener('MSPointerUp', internalCb, false); + document.documentElement.addEventListener('MSPointerCancel', internalCb, false); + + this._msDocumentListener = true; + } + + return this; + }, + + addMsTouchListenerMove: function (obj, type, handler, id) { + var pre = '_leaflet_'; + + var touches = this._msTouches; + var cb = function (e) { + + //Don't fire touch moves when mouse isn't down + if (e.pointerType === e.MSPOINTER_TYPE_MOUSE && e.buttons === 0) { + return; + } + + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + touches[i] = e; + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + obj[pre + 'touchmove' + id] = cb; + obj.addEventListener('MSPointerMove', cb, false); + + return this; + }, + + addMsTouchListenerEnd: function (obj, type, handler, id) { + var pre = '_leaflet_', + touches = this._msTouches; + + var cb = function (e) { + for (var i = 0; i < touches.length; i++) { + if (touches[i].pointerId === e.pointerId) { + touches.splice(i, 1); + break; + } + } + + e.touches = touches.slice(); + e.changedTouches = [e]; + + handler(e); + }; + + obj[pre + 'touchend' + id] = cb; + obj.addEventListener('MSPointerUp', cb, false); + obj.addEventListener('MSPointerCancel', cb, false); + + return this; + }, + + removeMsTouchListener: function (obj, type, id) { + var pre = '_leaflet_', + cb = obj[pre + type + id]; + + switch (type) { + case 'touchstart': + obj.removeEventListener('MSPointerDown', cb, false); + break; + case 'touchmove': + obj.removeEventListener('MSPointerMove', cb, false); + break; + case 'touchend': + obj.removeEventListener('MSPointerUp', cb, false); + obj.removeEventListener('MSPointerCancel', cb, false); + break; + } + return this; } }); @@ -6125,8 +6396,8 @@ L.Map.BoxZoom = L.Handler.extend({ L.DomUtil.setPosition(box, newPos); // TODO refactor: remove hardcoded 4 pixels - box.style.width = (Math.abs(offset.x) - 4) + 'px'; - box.style.height = (Math.abs(offset.y) - 4) + 'px'; + box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; + box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; }, _onMouseUp: function (e) { -- 2.43.2