Archive | July, 2014

JavaScript Class for ESRI REST API

29 Jul

Warning: This is sloppy. I have been slowly piecing this together. I could always use ESRI.leaflet plugin, but have had issues with it and am intentionally going another route. I have also used the ESRI JavaScript API, but am also intentionally not using it here.

 

I have been using Leaflet.js as the front end to my ArcServer. I use the ESRI REST API to handle all my CRUD. After copying and parting a bunch of AJAX, I decided to try to start writing a class. I combine this with the Leaflet Vector Layers Plugin available at http://jasonsanford.github.io/leaflet-vector-layers/documentation/#docs-ags. the plugin handles displaying my features and grabbing the properties (OBJECTID in particular).

Here is my attempt at a class.

 

function CRUD(url){ //url should look like: http://MyServer/ArcGIS/rest/services/PaulFeaturewgs84/FeatureServer/1

this.url=url;
}//end function CRUD
CRUD.prototype={

add: function(addFeature){ //needs to look like [{“geometry”:{“x”:-106,”y”:35}, “attributes”:{“name”:”paul”,”number”:123}}]
var addparams = “features=”+addFeature+”&f=json”;
var addurl=this.url+”/addFeatures”;
alert(addFeature);
var http;
if (window.XMLHttpRequest){
http=new XMLHttpRequest();
}

else {
http=new ActiveXObject(“Msxml2.XMLHTTP”);
}
http.open(“POST”, addurl, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(addparams);

}, //end ADD

update: function(updateFeature){
var updateparams = “features=”+updateFeature+”&f=json”;
var updateurl=this.url+”/updateFeatures”;
var http;
if (window.XMLHttpRequest){
http=new XMLHttpRequest();
}

else {
http=new ActiveXObject(“Msxml2.XMLHTTP”);
}
http.open(“POST”, updateurl, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(updateparams);
}, //end UPDATE

delete: function(deleteFeature){ //takes objectid
var deleteparams = “objectIds=”+deleteFeature+”&f=json”;
var deleteurl=this.url+”/deleteFeatures”;
var http;
if (window.XMLHttpRequest){
http=new XMLHttpRequest();
}

else {
http=new ActiveXObject(“Msxml2.XMLHTTP”);
}
http.open(“POST”, deleteurl, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(deleteparams);
}, //end DELETE

query: function(){

} // end QUERY
};//end CRUD.prototype

//USE CASE for DELETE and ADD
//var crud = new CRUD(“http://MyServer/ArcGIS/rest/services/PaulFeaturewgs84/FeatureServer/0”);
//DELETE WORKS
//crud.delete(43);
//ADD WORKS
//var pointToAdd='[{“geometry”:{“x”:-106.79192,”y”:35.06148}, “attributes”:{}}]’;
//crud.add(pointToAdd);
//USE FOR UPDATE
//UPDATE WORKS requires OBJECTID
//var crud2 = new CRUD(“http://MyServer/ArcGIS/rest/services/featuretestproperties/FeatureServer/0”);
//var feature='[{“geometry”:{“x”:-106.73975,”y”:35.12765}, “attributes”:{“OBJECTID”:57,”name”:”Paul”,”number”:123}}]’;
//crud2.update(feature);

 

 

 

to delete a feature, I use the clickEvent from the Vector Layer Plugin to grab it, then you can pass it to the delete function:

clickEvent: function (feature, e) {
objectid=feature.properties.OBJECTID;

crud.delete(objectid);

 

to add a feature, I use the map.on(‘click,function) in Leaflet to get the geometry. I parse out sloppily like this (subTwo[0] is lon or x and theLat[1] is lat or y. then you can pass feature properties however you want:

 

map.on(‘click’,function(x){

theString=String(x.latlng);
subOne=theString.split(“,”);
theLat=subOne[0].split(“(“);
subTwo=subOne[1].split(“)”);
latAsFloat=parseFloat(theLat[1]);
longAsFloat=parseFloat(subTwo[0]);

}

when I want to add properties and not just a point, I use a popup on dblclick:

popup = L.popup()
.setLatLng(x.latlng)
.setContent(‘<h3>Add Point</h3>Name:<input type=”text” id=”name”><br>Number:<input type=”text” id=”number”><br><button onclick=”crud.add(the point object)”>Add Point</button>’)
.openOn(map);

to update an object, I set the popup template in the Vector Layer plugin and call the function:

popupTemplate: ‘<h3>{number}</h3>Name:<input type=”text” id=”newname”><button onclick=”crud.update(feature)”>Update Name?</button>’,

Advertisements

Drag and Drop Leaflet II: Send file or data to DB using Drag and Drop

29 Jul

Using Drag and Drop, I also wanted to be able to drag data – mostly a file – to a feature in my ESRI Geodatabase and have it sent to the DB. To test this, I just setup a marker in Leaflet to represent my feature. I attached a popup to this feature using an iframe.

<html>
<head>
<title></title>
<link rel=”stylesheet” href=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css&#8221; />
<style>
#map{width:100%;height:100%}
</style>
</head>
<body>
<script src=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js”></script&gt;
<div id=”map” ></div>

<script>
var map = L.map(‘map’,
{
center: [35.10418, -106.62987],
zoom: 9
});
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’).addTo(map);

var x =L.marker([35,-106]).addTo(map);
var image = iframe src=”http://dmdview/paul/drag.html&#8221; width=”300″ height=”300″ frameborder=”0″>/iframe ;

//had to modify the iframe tags to get it to display on the blog add <>

var popupContent = image;

x.bindPopup(popupContent);

</script>
</body>
</html>

 

The iframe loads the drag and drop functionality and puts a button in the popup that will call the function to send the file or data. This will use ESRI REST API to update, or send an attachment.

 

<html>
<head>
<title></title>
<style>
#drop_zone{
height: 100%;
width:100%;
}
</style>
</head>
<body>
<div id=”drop_zone” >Drag Data Here</div>
<script>
function go(){alert(“Submitted Data”);}

function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();

var files = evt.dataTransfer.files; // FileList object.
var reader = new FileReader();
reader.onload = function(event) {

var text=event.target.result;
document.getElementById(‘drop_zone’).innerHTML=text+”<button onclick=’go()’>Send Text</button>”;

}
var s = reader.readAsText(files[0],”UTF-8″);

}

function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = ‘copy’; // Explicitly show this is a copy.
}

// Setup the dnd listeners.
var dropZone = document.getElementById(‘drop_zone’);
dropZone.addEventListener(‘dragover’, handleDragOver, false);
dropZone.addEventListener(‘drop’, handleFileSelect, false);

</script>
</body>
</html>

the images show the popup and the popup after a text file is dropped on it. Drag and drop offers some cool possibilities, but I have really enjoyed connecting leaflet to ESRI’s ArcServer vie REST. At work, this has opened up my ability to build front-ends quickly.

12

 

Drag and Drop Geocode Addresses Leaflet.js

29 Jul

I was playing with HTML 5 Drag and Drop and decided to try to make a map where I could drag a list of addresses on to a Leaflet map and have it display them as markers. I have used OpenStreetMap for Geocoding, but in this example I needed to use my ArcServer Geocode service. This was implemented via the ESRI REST API.

<html>

<head>
<title>Leaflet Drag and Drop Geocode from ArcServer Geocode Service</title>
<link rel=”stylesheet” href=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css&#8221; />
<style>
#map{
height: 100%;
width:100%;
}
</style>
</head>
<body>
<script src=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js”></script&gt;
<div id=”map” ></div>
<script>
var map = L.map(‘map’,
{
center: [35.10418, -106.62987],
zoom: 9
});
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’).addTo(map);

function handleGeocode(evt) {
evt.stopPropagation();
evt.preventDefault();

var files = evt.dataTransfer.files; // FileList object.
var reader = new FileReader();
reader.onload = function(event) {

var temp=event.target.result;
var text=temp.replace( /\n/g, “,” );
var c=text.split(“,”);

for(i=0;i<c.length;i++){
url1=”http://ArcServer Name/ArcGIS/rest/services/AddressLocator/GeocodeServer/findAddressCandidates?Street=”;
url2=String(c[i]);
url3=”&outFields=&outSR=4326&f=pjson”;
url=url1.concat(url2,url3);
var xhReq = new XMLHttpRequest();
xhReq.open(“GET”, url, false);
xhReq.send(null);
var serverResponse = xhReq.responseText;
var d=JSON.parse(serverResponse);

if(typeof d.candidates[0] == ‘undefined’){alert(“error in address: “+url2);}
else{
L.marker([parseFloat(d.candidates[0].location.y),parseFloat(d.candidates[0].location.x)]).addTo(map).bindPopup(url2);
}

}

}
var s = reader.readAsText(files[0],”UTF-8”);

}

function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = ‘copy’; // Explicitly show this is a copy.
}

// Setup the dnd listeners.
var dropZone = document.getElementById(‘map’);
dropZone.addEventListener(‘dragover’, handleDragOver, false);
dropZone.addEventListener(‘drop’, handleGeocode, false);

</script>
</body>
</html>