bokeefe

jQuery > REST > ParksFinder Bonus?

Blog Post created by bokeefe on May 1, 2015

Situation / Background

When I was hired for my current position (GIS Analyst, City of Tulsa) my boss passed on the Tulsa Fire Department work that he had been handling since before he became a manager. He had worked for the Fire Department for years and constructed a manual system for providing the Fire Engines with a 'Map and Apartment' book. Being that we are all City Employees he hadn't had a chance to improve the system in awhile. When I came on board I thought I would give it a shot and just never... had... time...

 

Process

The process for maintaining an updated Map Book was as follows...

  1. New Apartment is built (hooray!)
  2. Create a Site Drawing in Visio
    1. This PREVIOUSLY involved driving out to the site and visually inspecting and drawing on site (by hand)
    2. (I came into this position with contacts to previous departments so it changed to...)
      I request the Record Drawings of the site and use those to construct a Site Drawing
  3. Convert the Drawing to PDF
  4. Save 1 copy to Apartments folder using naming convention "ApartmentName - Address.pdf"
  5. Save 1 copy to Apts by number folder using naming convention "#AptsNum.pdf"
  6. Edit HTML file to insert new entry for new Apartment, insert link to PDF's
  7. Compile a new Combination PDF of all Apartments

 

Glitches in the LGM (tl;dr)

I've needed a smoother system for awhile now. I've been studying the lgm so I can figure out a process for managing not only the Apartment Book but also the 'Fire Map Book' which has our City broken down into a grid system. The lgm is NOT intuitive and is barely documented. It doesn't provide an easy understanding of itself that is unifying in any manner... but I need to learn it as I think it will VASTLY simplify the process we have here at work for a majority of our tasks. But even if the lgm had a "Local Government for Dummies" book I would still not have had time to devote to it like I need. The nature of City Government work I guess. EVERYTHING is an emergency to the person asking for the help. I literally have 50+ projects waiting for me to pick up and complete at any given moment... but I digress.

 

ParksFinderPlus

I don't remember what triggered it but I suddenly wondered if I could query the ESRI REST Services from our ArcGIS Server for NON-mapping coding?

 

It seemed like it SHOULD be possible, but I haven't seen it done on ANYLEVEL ANYWHERE. SO it would be brand new for me.

 

Tutorials to the rescue

I discovered the following tutorial Getting Started · Consuming a RESTful Web Service with jQuery and figured it would make a good starting point.

 

It starts out with the following two files.

 

hello.js

$(document).ready(function() {
  $.ajax({
  url: "http://rest-service.guides.spring.io/greeting"
  }).then(function(data) {
  $('.greeting-id').append(data.id);
  $('.greeting-content').append(data.content);
  });
});

index.html

<html>
  <head>
  <title>Hello jQuery</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script src="hello.js"></script>
  </head>


  <body>
  <div>
  <p class="greeting-id">The ID is </p>
  <p class="greeting-content">The content is </p>
  </div>
  </body>
</html>

 

I swapped out the URL with my REST URL... I couldn't get it to work. I tried modifying the JSON objects... data.NAME, data.FACILITYID... I spent a good couple hours on this to no avail. But then I started reading up on what REST is doing. I needed to build a "query" but I don't have time to learn jQuery to THAT level. Let's see what StackExchange says... and it said plenty. I tried out a handful of ideas but what brought me step-by-step closer was using console.log and dumping out the variables at different phases in the code. I kept getting back what looked like the RAW HTML from when you visit the REST Service page.

 

Which got me to thinking. You can query FROM those REST service pages. What happens when you do that?

 

I know that if you want to search a feature class from a REST Service and what you are REALLY trying to do is output ALL of the contents of the database... you use "1=1" in place of a wildcard. Again, if there is more going on that what I'm saying... please understand, I'm a hack. I've coded on several large projects throughout my life. But I've never been to a programming class that I didn't get bored in because the instructor only covered those things I knew already. I read ALOT... and I tinker. SO... from what I understand... you have to use "1=1" to get a wildcard output. You also need to tell the query what OUTPUTFIELDS you need... so here goes...

 

http://maps.cityoftulsa.org/gis/rest/services/LGDM/Parks/MapServer/0/query?where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=NAME%2C+FACILITYID%2C+FULLADDR&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&returnTrueCurves=false&resultOffset=&resultRecordCount=&f=html

 

If you click this link you will see at the bottom of the screen an output of ALL Parks and their coordinates as well as the NAME, FACILITYID, and the FULLADDR. But I was confused... I needed JSON and when I used this URL in my code I was getting problems. But I felt like I was on the right track. I don't remember what triggered it, I know it was something from Geonet, probably a Robert Scheitlin post (or two). But I remembered someone saying that in order to change the output of your URL-based query of a REST Service you needed to change the output parameter... that little "f=html" at the end of my URL above.

 

So I changed it...

http://maps.cityoftulsa.org/gis/rest/services/LGDM/Parks/FeatureServer/0/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=NAME%2C+FACILITYID%2C+FULLADDR&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=&gdbVersion=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&multipatchOption=&f=json

 

There we go... Now I had JSON to play with.

 

The Final Countdown

I was ready. I started tinkering with the console.log and in chrome I use the developer tools. I forget the name of them. But the standard ones. So I was digging through and changing code in the console window, watching the variables fill up and dump out. I started tinkering with a jQuery $.each command to iterate through ALL of those JSON objects and find the parts that I needed. Until... I did.

 

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>City of Tulsa Master Park List</title>
        <script src="../../js/jquery-1.11.2.min.js"></script>
        <script src="parksrest.js"></script>
    </head>


    <body>
        <div>
  <p>Welcome to the City of Tulsa Parks List.</p>
        </div>
    </body>
</html>

 

parksrest.js

$(document).ready(function() 
{
    $.ajax ( {
  type: 'GET',
  url: 'http://maps.cityoftulsa.org/gis/rest/services/LGDM/Parks/FeatureServer/0/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=NAME%2CFULLADDR%2CFACILITYID&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=&gdbVersion=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&multipatchOption=&f=json',
  data: { get_param: 'value' },
  dataType: 'json',
  success: function (data) { $.each( data.features, function(index, element) {
  $('body').append($('<div><a href="http://maps.cityoftulsa.org/parksfinder/?selectedFeatureID=' + element.attributes.FACILITYID + '">' + element.attributes.NAME + '</a></div>') );  } ); } } );
});

And there you have it.

City of Tulsa Master Park List

 

Click on one of the Parks to see what it can do.

 

I haven't styled it... I haven't CSS'd it... I don't plan to. This is my sample... My snippet... So if you check it out, what I'm doing is kinda cool. ESRI has added the ability to craft a URL that jumps you to a selected feature. I don't know WHERE in the code it does this. But I need to find out. How many other URL modifiers are there? Can I jump to selected features on other maps? How do I do that in a feature rich web map? How does it know one feature from another? I maybe created some answers to my basic questions with this process but I created 10 times that number of questions.

 

Future Dev

So now my goal is to get the Apartments into the lgm. No more procrastinating. Convert all of my PDF's into lgm features, Everything from building footprints to paving and more. Generate the necessary Data-Drive Map Books for Apartments from there. Maybe build a ModelBuilder model to automate the process after I add (or modify) an Apartment in the system. And give the Fire Department access to a page created from this code that lists out ALL Apartments with links to the PDF's included. I'm also considering creating a picklist / dropdown for various features in some kind of Widget. Being able to generate a list of javascript objects from a rest service is beyond helpful. I'm wondering if I can't develop some PDF's that connect to our SiteAddressPoint from REST and force users to fill out permits using addresses that are ONLY in our system. Hmmmmm...

Outcomes