//set the options var center = new L.LatLng(42.3584308,-71.0597732); var zoom = 14; var url= "http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"; var options={ subdomains:["otile1","otile2",/*"otile3",*/"otile4"],//we'd usually use all 4 but something is up with #3 at the moment attribution:"Tiles Courtesy of MapQuest " }; //create the tiles var tiles = new L.TileLayer(url,options); //create the map var m = new L.Map('map',{ center:center, zoom:zoom, layers:[tiles] }); var gj = new L.GeoJSON(); //create empty geojson object and add it to the map m.addLayer(gj); //create the popups gj.on("featureparse", function (e) { if (e.properties){ e.layer.bindPopup(makePop(e.properties)); } }); //get the current bounds var bbox=m.getBounds().toBBoxString(); //the url. note we're only getting a subset of fields var url = "http://services.massdot.state.ma.us/ArcGIS/rest/services/Assets/Outfalls/MapServer/0/query?outFields=OutfallType,OutfallShape,Material,Town&f=json&outSR=4326&inSR=4326&geometryType=esriGeometryEnvelope&geometry=" //get the features $.get(url+bbox,parseJSONP,"JSONP"); //this is the call back from the jsonp ajax request function parseJSONP(data){ /*you'd think you'd want to put the command to clear the old layer here instead of after zooming, but the markers are not not visible when you zoom, so it ends up being much less noticeable clearing them earlier*/ toGeoJSON(data,function(d){gj.addGeoJSON(d)}); } //set up listeners on both drag and zoom events m.on("dragend",redo); m.on("zoomend",redo); //the function called by those event listeners function redo(){ bbox=m.getBounds().toBBoxString();//get the new bounds gj.clearLayers();//clear the current layers $.get(url+bbox,parseJSONP,"JSONP");//ajax request } //the function called earlier to make the popup, it goes through all the attributes and makes them into a nice key value list function makePop(p){ var a = []; for(var key in p){ a.push(key+": "+p[key]); } return a.join("
"); };