Update Leaflet
authorJohn Firebaugh <john.firebaugh@gmail.com>
Thu, 1 Nov 2012 03:27:28 +0000 (21:27 -0600)
committerJohn Firebaugh <john.firebaugh@gmail.com>
Fri, 9 Nov 2012 20:59:29 +0000 (12:59 -0800)
Vendorfile
vendor/assets/leaflet/leaflet.css
vendor/assets/leaflet/leaflet.ie.css
vendor/assets/leaflet/leaflet.js

index 6d0eb1196394159b5a95b9e90656eccc5650ca77..000a05ff7601b725b8dc118dc0f638b17717da71 100644 (file)
@@ -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'
index a9e44fd92dc816821470577b8d2bc307840465ab..dce84046dc1944b9f1416f96788636b219501964 100644 (file)
 .leaflet-image-layer,\r
 .leaflet-layer { /* TODO optimize classes */\r
        position: absolute;\r
+       left: 0;\r
        }\r
 .leaflet-container {\r
        overflow: hidden;\r
        outline: 0;\r
+       -ms-touch-action: none;\r
        }\r
 .leaflet-tile,\r
 .leaflet-marker-icon,\r
index 9d2a52fba440a585a416ea78730e90ca8f5bcb01..5b65c400a155407d17599ce84b51fdcbe6c0dd38 100644 (file)
@@ -41,4 +41,7 @@
        }\r
 .leaflet-control-attribution, .leaflet-control-layers {\r
        background: white;\r
+       }\r
+.leaflet-zoom-box {\r
+       filter: alpha(opacity=50);\r
        }
\ No newline at end of file
index 7c5b717e77389fd839d659f677793a1c19ab7828..90c52bddf32ee8e8df5bebc0d8e0a4135b55931d 100644 (file)
@@ -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) {