diff --git a/README.md b/README.md index ee5a7dae..d36d6b80 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ Leaflet ======= -Leaflet is a lightweight JavaScript library for map display and interaction by [CloudMade](http://cloudmade.com). It will form the core of CloudMade's next generation JavaScript API. +Leaflet is a modern, lightweight BSD-licensed JavaScript library for making tile-based interactive maps for both desktop and mobile web browsers, developed by [CloudMade](http://cloudmade.com) to form the core of its next generation JavaScript API. -It is built from the ground up to work well on both desktop and mobile web browsers, utilizing cutting-edge technologies included in HTML5. It focuses on performance, usability, [A-grade](http://developer.yahoo.com/yui/articles/gbs/) browser support, flexibility and easy to use API. The OOP-based code of the library is designed to be modular, extensible and very easy to understand. +It is built from the ground up to work efficiently and smoothly on both platforms, utilizing cutting-edge technologies included in HTML5. Its top priorities are usability, performance and small size, [A-grade](http://developer.yahoo.com/yui/articles/gbs/) browser support, flexibility and easy to use API. The OOP-based code of the library is designed to be modular, extensible and very easy to understand. ## Contributing to Leaflet -Please send your pull requests to [mourner](http://github.com/mourner) - we'll be happy to accept your contributions! +Let's make the best open-source library for maps that can possibly exist! Please send your pull requests to [mourner](http://github.com/mourner) -- we'll be happy to accept your contributions! ## What's left to do for a feature-complete version @@ -28,7 +28,7 @@ Controls: Known issues to be fixed: - flickering of vector layers on drag end under mobile webkit - - show scaled background until tiles are loaded even with animation disabled + - show scaled background until tiles are loaded on mobile webkit ## Browser support @@ -47,5 +47,6 @@ On mobile: ## Leaflet developers -Lead Developer: [Vladimir Agafonkin](http://github.com/mourner) -Contributors: be the first! \ No newline at end of file +Maintainer: [Vladimir Agafonkin](http://github.com/mourner), CloudMade + +Contributors: (be the first!) \ No newline at end of file diff --git a/dist/leaflet.js b/dist/leaflet.js index a75de889..8a3a5238 100644 --- a/dist/leaflet.js +++ b/dist/leaflet.js @@ -1,9 +1,9 @@ /* - Copyright (c) 2010, CloudMade + Copyright (c) 2010-2011, CloudMade, Vladimir Agafonkin Leaflet is a BSD-licensed JavaScript library for map display and interaction. - Check out the source on GitHub: http://github.com/CloudMade/Leaflet/ + See http://cloudmade.github.com/Leaflet/ for more information. */ -var L={VERSION:"0.1a3",ROOT_URL:function(){for(var a=document.getElementsByTagName("script"),b=0,c=a.length;b= -b.lat&&a.lat<=c.lat&&d.lng>=b.lng&&a.lng<=c.lng}});L.Projection={};L.Projection.Mercator={MAX_LATITUDE:function(){var a=Math.exp(2*Math.PI);return Math.asin((a-1)/(a+1))*L.LatLng.RAD_TO_DEG}(),project:function(a){var b=L.LatLng.DEG_TO_RAD,c=L.Projection.Mercator.MAX_LATITUDE,d=a.lng*b;a=Math.max(Math.min(c,a.lat),-c)*b;a=Math.log(Math.tan(Math.PI/4+a/2));return new L.Point(d,a)},unproject:function(a,b){var c=L.LatLng.DEG_TO_RAD;return new L.LatLng((2*Math.atan(Math.exp(a.y))-Math.PI/2)/c,a.x/c,b)}};L.TileLayer=L.Class.extend({includes:L.Mixin.Events,options:{tileSize:256,minZoom:0,maxZoom:18,subdomains:"abc",copyright:"",unloadInvisibleTiles:L.Browser.mobileWebkit,updateWhenIdle:L.Browser.mobileWebkit,errorTileUrl:""},initialize:function(a,b){L.Util.setOptions(this,b);this._url=a;if(typeof this.options.subdomains=="string")this.options.subdomains=this.options.subdomains.split("")},onAdd:function(a){this._map=a;this._initContainer();this._tileImg=L.DomUtil.create("img","leaflet-tile");this._tileImg.galleryimg= +b.lat&&a.lat<=c.lat&&d.lng>=b.lng&&a.lng<=c.lng}});L.Projection={};L.Projection.Mercator={MAX_LATITUDE:function(){var a=Math.exp(2*Math.PI);return Math.asin((a-1)/(a+1))*L.LatLng.RAD_TO_DEG}(),project:function(a){var b=L.LatLng.DEG_TO_RAD,c=L.Projection.Mercator.MAX_LATITUDE,d=a.lng*b;a=Math.max(Math.min(c,a.lat),-c)*b;a=Math.log(Math.tan(Math.PI/4+a/2));return new L.Point(d,a)},unproject:function(a,b){var c=L.LatLng.RAD_TO_DEG;return new L.LatLng((2*Math.atan(Math.exp(a.y))-Math.PI/2)*c,a.x*c,b)}};L.TileLayer=L.Class.extend({includes:L.Mixin.Events,options:{tileSize:256,minZoom:0,maxZoom:18,subdomains:"abc",copyright:"",unloadInvisibleTiles:L.Browser.mobileWebkit,updateWhenIdle:L.Browser.mobileWebkit,errorTileUrl:""},initialize:function(a,b){L.Util.setOptions(this,b);this._url=a;if(typeof this.options.subdomains=="string")this.options.subdomains=this.options.subdomains.split("")},onAdd:function(a){this._map=a;this._initContainer();this._tileImg=L.DomUtil.create("img","leaflet-tile");this._tileImg.galleryimg= "no";var b=this.options.tileSize;this._tileImg.style.width=b+"px";this._tileImg.style.height=b+"px";a.on("viewreset",this._reset,this);if(this.options.updateWhenIdle)a.on("moveend",this._update,this);else this._limitedUpdate=L.Util.limitExecByInterval(this._update,100,this),a.on("move",this._limitedUpdate,this);this._reset();this._update()},onRemove:function(){this._map.getPanes().tilePane.removeChild(this._container);this._map.off("viewreset",this._reset);this.options.updateWhenIdle?this._map.off("moveend", this._update):this._map.off("move",this._limitedUpdate)},_initContainer:function(){var a=this._map.getPanes().tilePane;if(!this._container||a.empty)this._container=L.DomUtil.create("div","leaflet-layer",a)},_reset:function(){this._tiles={};this._initContainer();this._container.innerHTML=""},_update:function(){var a=this._map.getPixelBounds(),b=this.options.tileSize,c=new L.Point(Math.floor(a.min.x/b),Math.floor(a.min.y/b));a=new L.Point(Math.floor(a.max.x/b),Math.floor(a.max.y/b));c=new L.Bounds(c, a);this._loadTilesFromCenterOut(c);this.options.unloadInvisibleTiles&&this._unloadOtherTiles(c)},getTileUrl:function(a,b){return this._url.replace("{s}",this.options.subdomains[(a.x+a.y)%this.options.subdomains.length]).replace("{z}",b).replace("{x}",a.x).replace("{y}",a.y)},_loadTilesFromCenterOut:function(a){for(var b=[],c=a.getCenter(),d=a.min.y;d<=a.max.y;d++)for(var e=a.min.x;e<=a.max.x;e++)e+":"+d in this._tiles||b.push(new L.Point(e,d));b.sort(function(a,b){return a.distanceTo(c)-b.distanceTo(c)}); @@ -42,7 +42,7 @@ this._updatePosition();this._container.style.visibility="";this._adjustPan()},_u this._containerBottom=-a.y-this.options.offset.y;this._containerLeft=a.x-this._containerWidth/2+this.options.offset.x;this._container.style.bottom=this._containerBottom+"px";this._container.style.left=this._containerLeft+"px"},_adjustPan:function(){if(this.options.autoPan){var a=this._container.offsetHeight,b=this._map.layerPointToContainerPoint(new L.Point(this._containerLeft,-a-this._containerBottom)),c=new L.Point(0,0),d=this.options.autoPanPadding,e=this._map.getSize();if(b.x<0)c.x=b.x-d.x;if(b.x+ this._containerWidth>e.x)c.x=b.x+this._containerWidth-e.x+d.x;if(b.y<0)c.y=b.y-d.y;if(b.y+a>e.y)c.y=b.y+a-e.y+d.y;(c.x||c.y)&&this._map.panBy(c)}},_onCloseButtonClick:function(){this._close();return!1}});L.Icon=L.Class.extend({iconUrl:L.ROOT_URL+"images/marker.png",shadowUrl:L.ROOT_URL+"images/marker-shadow.png",iconSize:new L.Point(25,41),shadowSize:new L.Point(41,41),iconAnchor:new L.Point(13,41),popupAnchor:new L.Point(0,-33),initialize:function(a){if(a)this.iconUrl=a},createIcon:function(){return this._createIcon("icon")},createShadow:function(){return this._createIcon("shadow")},_createIcon:function(a){var b=this[a+"Size"],c=this._createImg(this[a+"Url"]);c.className="leaflet-marker-"+a;c.style.marginLeft= -this.iconAnchor.x+"px";c.style.marginTop=-this.iconAnchor.y+"px";if(b)c.style.width=b.x+"px",c.style.height=b.y+"px";return c},_createImg:function(a){var b;L.Browser.ie6?(b=document.createElement("div"),b.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+a+'")'):(b=document.createElement("img"),b.src=a);return b}});L.Marker=L.Class.extend({includes:L.Mixin.Events,options:{icon:new L.Icon,clickable:!0},initialize:function(a,b){L.Util.setOptions(this,b);this._latlng=a},onAdd:function(a){this._map=a;if(!this._icon)this._icon=this.options.icon.createIcon(),a._panes.markerPane.appendChild(this._icon),this._initInteraction();if(!this._shadow)this._shadow=this.options.icon.createShadow(),a._panes.shadowPane.appendChild(this._shadow);a.on("viewreset",this._reset,this);this._reset()},onRemove:function(a){this._icon&& -a._panes.markerPane.removeChild(this._icon);this._shadow||a._panes.shadowPane.removeChild(this._shadow);a.off("viewreset",this._reset,this)},getLatLng:function(){return this._latlng},_reset:function(){var a=this._map.latLngToLayerPoint(this._latlng).round();L.DomUtil.setPosition(this._icon,a);L.DomUtil.setPosition(this._shadow,a);this._icon.style.zIndex=a.y},_initInteraction:function(){this.options.clickable&&(this._icon.className+=" leaflet-clickable",L.DomEvent.addListener(this._icon,"mousedown", +a._panes.markerPane.removeChild(this._icon);this._shadow&&a._panes.shadowPane.removeChild(this._shadow);a.off("viewreset",this._reset,this)},getLatLng:function(){return this._latlng},_reset:function(){var a=this._map.latLngToLayerPoint(this._latlng).round();L.DomUtil.setPosition(this._icon,a);L.DomUtil.setPosition(this._shadow,a);this._icon.style.zIndex=a.y},_initInteraction:function(){this.options.clickable&&(this._icon.className+=" leaflet-clickable",L.DomEvent.addListener(this._icon,"mousedown", this._fireMouseEvent,this),L.DomEvent.addListener(this._icon,"click",this._fireMouseEvent,this),L.DomEvent.addListener(this._icon,"dblclick",this._fireMouseEvent,this))},_fireMouseEvent:function(a){this.fire(a.type);L.DomEvent.stopPropagation(a)}});L.Marker.include({openPopup:function(){this._map.closePopup();this._popup&&this._map.openPopup(this._popup);return this},bindPopup:function(a,b){b=L.Util.extend({offset:this.options.icon.popupAnchor},b);this._popup=new L.Popup(this._latlng,a,b);this.on("click",this.openPopup,this);return this}});L.Path=L.Class.extend({statics:function(){return{SVG_NS:"http://www.w3.org/2000/svg",SVG:!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect),CLIP_PADDING:0.5}}(),options:{stroke:!0,color:"#0033ff",weight:5,opacity:0.5,fill:!1,fillColor:null,fillOpacity:0.2,updateOnMoveEnd:!1},initialize:function(a){L.Util.setOptions(this,a)},onAdd:function(a){this._map=a;this._initElements();this.projectLatlngs();this._updatePath();a.on("viewreset",this.projectLatlngs, this);this._updateTrigger=this.options.updateOnMoveEnd?"moveend":"viewreset";a.on(this._updateTrigger,this._updatePath,this)},onRemove:function(a){a._pathRoot.removeChild(this._container);a.off("viewreset",this._projectLatlngs,this);a.off(this._updateTrigger,this._updatePath,this)},projectLatlngs:function(){},getPathString:function(){},_initElements:function(){this._initRoot();this._initPath();this._initStyle()},_initRoot:function(){if(!this._map._pathRoot)this._map._pathRoot=this._createElement("svg"), this._map._panes.overlayPane.appendChild(this._map._pathRoot),this._map.on("moveend",this._updateSvgViewport,this),this._updateSvgViewport()},_updateSvgViewport:function(){this._updateViewport();var a=this._map._pathViewport,b=a.min,c=a.max;a=c.x-b.x;c=c.y-b.y;var d=this._map._pathRoot,e=this._map._panes.overlayPane;L.Browser.mobileWebkit&&e.removeChild(d);L.DomUtil.setPosition(d,b);d.setAttribute("width",a);d.setAttribute("height",c);d.setAttribute("viewBox",[b.x,b.y,a,c].join(" "));L.Browser.mobileWebkit&& @@ -55,27 +55,28 @@ document.createElement("div"),this._map._pathRoot.className="leaflet-vml-contain this.options.fillColor||this.options.color,this._fill.opacity=this.options.fillOpacity},_updatePath:function(){this._container.style.display="none";this._path.v=this.getPathString();this._container.style.display=""}});L.Polyline=L.Path.extend({initialize:function(a,b){L.Path.prototype.initialize.call(this,b);this._latlngs=a},options:{smoothFactor:1,noClip:!1,updateOnMoveEnd:!0},projectLatlngs:function(){this._originalPoints=[];for(var a=0,b=this._latlngs.length;a=7E5&&L.Browser.gecko)this._draggable._updatePosition=L.Util.deferExecByInterval(this._draggable._updatePosition,0,this._draggable);this._draggable.on("dragstart",this._onDragStart,this);this._draggable.on("drag",this._onDrag,this);this._draggable.on("dragend",this._onDragEnd,this)}this._draggable.enable(); +[this._originalPoints].concat(this._holePoints);if(!this.options.noClip)for(var a=0,b=this._parts.length;a=7E5&&L.Browser.gecko)this._draggable._updatePosition=L.Util.deferExecByInterval(this._draggable._updatePosition,0,this._draggable);this._draggable.on("dragstart",this._onDragStart,this);this._draggable.on("drag",this._onDrag,this);this._draggable.on("dragend",this._onDragEnd,this)}this._draggable.enable(); this._enabled=!0}},disable:function(){if(this._enabled)this._draggable.disable(),this._enabled=!1},moved:function(){return this._draggable._moved},_onDragStart:function(){this._map.fire("movestart");this._map.fire("dragstart")},_onDrag:function(){this._map.fire("move");this._map.fire("drag")},_onDragEnd:function(){this._map.fire("moveend");this._map.fire("dragend")}});L.Handler.TouchZoom=L.Handler.extend({enable:function(){if(L.Browser.mobileWebkit&&!this._enabled)L.DomEvent.addListener(this._map._container,"touchstart",this._onTouchStart,this),this._enabled=!0},disable:function(){if(this._enabled)L.DomEvent.removeListener(this._map._container,"touchstart",this._onTouchStart,this),this._enabled=!1},_onTouchStart:function(a){if(a.touches&&a.touches.length==2){var b=this._map.mouseEventToLayerPoint(a.touches[0]),c=this._map.mouseEventToLayerPoint(a.touches[1]),d= this._map.containerPointToLayerPoint(this._map.getSize().divideBy(2));this._startCenter=b.add(c).divideBy(2,!0);this._startDist=b.distanceTo(c);this._startTransform=this._map._mapPane.style.webkitTransform;this._moved=!1;this._centerOffset=d.subtract(this._startCenter);L.DomEvent.addListener(document,"touchmove",this._onTouchMove,this);L.DomEvent.addListener(document,"touchend",this._onTouchEnd,this);L.DomEvent.preventDefault(a)}},_onTouchMove:function(a){if(a.touches&&a.touches.length==2){if(!this._moved)this._map._panes.popupPane.style.display= "none",this._moved=!0;var b=this._map.mouseEventToLayerPoint(a.touches[0]),c=this._map.mouseEventToLayerPoint(a.touches[1]);this._scale=b.distanceTo(c)/this._startDist;this._delta=b.add(c).divideBy(2,!0).subtract(this._startCenter);this._map._mapPane.style.webkitTransform=[this._startTransform,L.DomUtil.getTranslateString(this._delta),L.DomUtil.getScaleString(this._scale,this._startCenter)].join(" ");L.DomEvent.preventDefault(a)}},_onTouchEnd:function(a){if(a.touches&&!(a.touches.length>=2)&&this._scale){a= this._map.getZoom()+Math.round(Math.log(this._scale)/Math.LN2);var b=this._centerOffset.subtract(this._delta).divideBy(this._scale);this._map.setView(this._map.unproject(this._map.getPixelOrigin().add(this._startCenter).add(b)),a,!0);this._map._panes.popupPane.style.display="";this._scale=null;L.DomEvent.removeListener(document,"touchmove",this._onTouchMove);L.DomEvent.removeListener(document,"touchend",this._onTouchEnd)}}});L.Handler.ScrollWheelZoom=L.Handler.extend({enable:function(){if(!this._enabled)L.DomEvent.addListener(this._map._container,"mousewheel",this._onWheelScroll,this),this._delta=0,this._enabled=!0},disable:function(){if(this._enabled)L.DomEvent.removeListener(this._map._container,"mousewheel",this._onWheelScroll),this._enabled=!1},_onWheelScroll:function(a){this._delta+=L.DomEvent.getWheelDelta(a);this._lastMousePos=this._map.mouseEventToContainerPoint(a);clearTimeout(this._timer);this._timer=setTimeout(L.Util.bind(this._performZoom, -this),50);L.DomEvent.preventDefault(a)},_performZoom:function(){var a=Math.round(this._delta);this._delta=0;if(a){var b=this._getCenterForScrollWheelZoom(this._lastMousePos,a);a=this._map.getZoom()+a;this._map._limitZoom(a)!=this._map._zoom&&this._map.setView(b,a)}},_getCenterForScrollWheelZoom:function(a,b){var c=this._map.getPixelBounds().getCenter(),d=this._map.getSize().divideBy(2);d=a.subtract(d).multiplyBy(1-Math.pow(2,-b));return this._map.unproject(c.add(d))}});L.Handler.DoubleClickZoom=L.Handler.extend({enable:function(){if(!this._enabled)this._map.on("dblclick",this._onDoubleClick,this._map),this._enabled=!0},disable:function(){if(this._enabled)this._map.off("dblclick",this._onDoubleClick,this._map),this._enabled=!1},_onDoubleClick:function(a){this.setView(a.position,this._zoom+1)}});L.Handler.ShiftDragZoom=L.Handler.extend({initialize:function(a){this._container=a._container;this._pane=a._panes.overlayPane;L.Handler.prototype.initialize.apply(this,arguments)},enable:function(){if(!this._enabled)L.DomEvent.addListener(this._container,"mousedown",this._onMouseDown,this),this._enabled=!0},disable:function(){if(this._enabled)L.DomEvent.removeListener(this._container,"mousedown",this._onMouseDown),this._enabled=!1},_onMouseDown:function(a){if(!a.shiftKey||a.which!=1&&a.button!=1)return!1; -L.DomUtil.disableTextSelection();this._startLayerPoint=this._map.mouseEventToLayerPoint(a);this._box=L.DomUtil.create("div","leaflet-zoom-box",this._pane);L.DomUtil.setPosition(this._box,this._startLayerPoint);this._container.style.cursor="crosshair";L.DomEvent.addListener(document,"mousemove",this._onMouseMove,this);L.DomEvent.addListener(document,"mouseup",this._onMouseUp,this);L.DomEvent.preventDefault(a)},_onMouseMove:function(a){var b=this._map.mouseEventToLayerPoint(a);a=b.x-this._startLayerPoint.x; -var c=b.y-this._startLayerPoint.y;b=new L.Point(Math.min(b.x,this._startLayerPoint.x),Math.min(b.y,this._startLayerPoint.y));L.DomUtil.setPosition(this._box,b);this._box.style.width=Math.abs(a)-4+"px";this._box.style.height=Math.abs(c)-4+"px"},_onMouseUp:function(a){this._pane.removeChild(this._box);this._container.style.cursor="";L.DomUtil.enableTextSelection();L.DomEvent.removeListener(document,"mousemove",this._onMouseMove);L.DomEvent.removeListener(document,"mouseup",this._onMouseUp);a=this._map.mouseEventToLayerPoint(a); -this._map.fitBounds(new L.LatLngBounds(this._map.layerPointToLatLng(this._startLayerPoint),this._map.layerPointToLatLng(a)))}});L.Map=L.Class.extend({includes:L.Mixin.Events,options:{projection:L.Projection.Mercator,transformation:new L.Transformation(0.5/Math.PI,0.5,-0.5/Math.PI,0.5),scaling:function(a){return 256*(1< LatLng*/ { - var d = L.LatLng.DEG_TO_RAD, - lng = point.x / d, - lat = (2 * Math.atan(Math.exp(point.y)) - Math.PI/2) / d; + var d = L.LatLng.RAD_TO_DEG, + lng = point.x * d, + lat = (2 * Math.atan(Math.exp(point.y)) - Math.PI/2) * d; return new L.LatLng(lat, lng, unbounded); } diff --git a/src/handler/Handler.js b/src/handler/Handler.js index 73c93c09..195986b8 100644 --- a/src/handler/Handler.js +++ b/src/handler/Handler.js @@ -3,9 +3,8 @@ */ L.Handler = L.Class.extend({ - initialize: function(map, enabled) { + initialize: function(map) { this._map = map; - if (enabled) { this.enable(); } }, enabled: function() { diff --git a/src/handler/ShiftDragZoom.js b/src/handler/ShiftDragZoom.js index 5945da8d..ba216109 100644 --- a/src/handler/ShiftDragZoom.js +++ b/src/handler/ShiftDragZoom.js @@ -3,11 +3,10 @@ */ L.Handler.ShiftDragZoom = L.Handler.extend({ - initialize: function(map, enabled) { + initialize: function(map) { + this._map = map; this._container = map._container; this._pane = map._panes.overlayPane; - - L.Handler.prototype.initialize.apply(this, arguments); }, enable: function() { diff --git a/src/handler/TouchZoom.js b/src/handler/TouchZoom.js index 6ea7a5b1..b041f134 100644 --- a/src/handler/TouchZoom.js +++ b/src/handler/TouchZoom.js @@ -3,7 +3,6 @@ */ L.Handler.TouchZoom = L.Handler.extend({ - enable: function() { if (!L.Browser.mobileWebkit || this._enabled) { return; } L.DomEvent.addListener(this._map._container, 'touchstart', this._onTouchStart, this); diff --git a/src/layer/marker/Marker.js b/src/layer/marker/Marker.js index 64cd997b..074a8392 100644 --- a/src/layer/marker/Marker.js +++ b/src/layer/marker/Marker.js @@ -37,7 +37,7 @@ L.Marker = L.Class.extend({ if (this._icon) { map._panes.markerPane.removeChild(this._icon); } - if (!this._shadow) { + if (this._shadow) { map._panes.shadowPane.removeChild(this._shadow); } map.off('viewreset', this._reset, this); diff --git a/src/map/Map.js b/src/map/Map.js index a5151c1b..03976c7d 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -82,6 +82,12 @@ L.Map = L.Class.extend({ return this.setView(bounds.getCenter(), zoom); }, + fitWorld: function() { + var sw = new L.LatLng(-60, -170), + ne = new L.LatLng(85, 179); + return this.fitBounds(new L.LatLngBounds(sw, ne)); + }, + panTo: function(/*LatLng*/ center) { return this.setView(center, this._zoom); }, @@ -365,7 +371,8 @@ L.Map = L.Class.extend({ }; for (var i in handlers) { if (handlers.hasOwnProperty(i) && handlers[i]) { - this[i] = new handlers[i](this, this.options[i]); + this[i] = new handlers[i](this); + if (this.options[i]) this[i].enable(); } } },