Monday, October 11, 2010

Great Blog Post on Custom Dojo Dijits

In his new blog "Enterprise Dojo", Dan Lee has an outstanding article titled, "Introduction to Custom Dojo Widgets". It gives a great first taste of developing your own custom Dojo Dijits. I was really excited to learn about the slick way to reference DOM nodes within your dijit using dojoattachpoint. Take 10 minutes and give it a read!

Vehicle Tracking With The JavaScript API

Recently, we have been investigating alternatives to our current AVL solution. The problems with our current solution are licensing costs (big $$ per workstation) and ease of use. I thought that I'd give it a try with ESRI's JavaScript API and this is what I came up with.


The vehicles are graphics that are refreshed from the server every 5 seconds using the JavaScript setTimeout() function. I was surprised at how quickly the browser could clear the graphics and reload them from the server. It looks like they are animated instead of reloaded. Here's a sample of the code that I used:

function AddVehicleGraphics(){ SANDY.qt.execute(SANDY.q, function(fSet){ function sortGraphics(a,b){ return (a.attributes.fleetID < b.attributes.fleetID) ? -1 : 1; } // record bread crumbs, if any dojo.forEach(SANDY.crumbsVehicles, function(key){ var crumbGraphic = dojo.filter(SANDY.avlGraphicsLayer.graphics, function(item){ return item.attributes.mapKey == key; })[0]; SANDY.avlGraphicsLayer.remove(crumbGraphic); // required to allow appropriate refresh on history graphics layer crumbGraphic.setInfoTemplate(SANDY.crumbsTipTemplate); crumbGraphic.setSymbol(SANDY.crumbSymbol); // get associate graphics layer var gLayer = SANDY.mapDij.map.getLayer(key); gLayer.add(crumbGraphic); }); // clear graphics layer SANDY.avlGraphicsLayer.clear(); SANDY.chartsDij.clearContent(); // sort the graphics alphabetically so they are sorted when adding to active vehicles table. fSet.features.sort(sortGraphics); dojo.forEach(fSet.features, function(g){ var symbol; switch (g.attributes.defaultIcon) { case "PLOW TRUCK": symbol = dojo.clone(SANDY.truckSymbol); break; case "SWEEPER": symbol = dojo.clone(SANDY.sweeperSymbol); break; case "SUV": symbol = dojo.clone(SANDY.puSymbol); break; } // rotate symbol symbol.setAngle(g.attributes.headingDegrees); g.setSymbol(symbol); // round mph g.attributes.speedMPH = Math.round(g.attributes.speedMPH); // add to graphics layer SANDY.avlGraphicsLayer.add(g); // add to vehicles list / bold all vehicles that have updated in the last 30 minutes var content; var activeCutOff = new Date().setMinutes(new Date().getMinutes() - 30); if (new Date(g.attributes.timeAtCoordinate) > activeCutOff){ content = "<b>" + g.attributes.fleetID + "</b>"; } else { content = g.attributes.fleetID; } SANDY.chartsDij._addContent(content); // update date updated text var now = new Date(); dojo.byId("update-date").innerHTML = now.toLocaleTimeString(); dojo.style("update-date-background", "backgroundColor", "white"); }); if (fSet.features.length === 0){ SANDY.chartsDij._addContent(SANDY.noVehiclesMsg); } }, function(error){ // change background to indicate error dojo.style("update-date-background", "backgroundColor", "red"); }); }


The other cool thing that I was able to do in this project was link to live UDOT traffic cameras. After getting permission from them, I was able to determine the unique URL for each of them from the CommuterLink website and build a feature class with their locations and urls. It was easy after that to publish them as a map service and load them as graphics onto my map. I used a custom infoTip window from ESRI's code gallery and some mouse events to show the camera images.




// camera graphics dojo.connect(SANDY.mapDij.map.graphics, "onMouseOver", function(evt){ // store old symbol to save for mouse out function SANDY.origSymbol = evt.graphic.symbol; // get orig color rgb's var r = SANDY.origSymbol.color.r; var g = SANDY.origSymbol.color.g; var b = SANDY.origSymbol.color.b; // highlight opacity var a = 0.5; // change symbol to highlight symbol var biggerSize = evt.graphic.symbol.size + 4; evt.graphic.setSymbol(dojo.clone(evt.graphic.symbol).setSize(biggerSize).setColor([r, g, b, a])); SANDY.iTip.setContent(evt.graphic.getContent()); SANDY.iTip.show(evt.screenPoint, SANDY.mapDij.map.height, SANDY.mapDij.map.width); }); dojo.connect(SANDY.mapDij.map.graphics, "onMouseOut", function(evt){ // change symbol back evt.graphic.setSymbol(SANDY.origSymbol); SANDY.iTip.hide(); }); dojo.connect(SANDY.mapDij.map.graphics, "onClick", function(evt){ // hide infowindow SANDY.mapDij.map.infoWindow.hide(); });


The next step after we upgrade to ArcGIS Server 10 is to use the new TimeSlider dijit to enable users to view historical data. Sadly, because I'm changing jobs, I will not be around to implement this cool functionality.  :(

Any other suggestions? Anyone else using the JavaScript API for vehicle tracking? I'd love to hear your experiences.

Friday, October 8, 2010

Onward and Upward - New Job

Recently I was offered a new position at the State of Utah's AGRC. I'm way excited to be working with such an amazing group of people and can't wait to get started. I'll miss all of the cool people and projects that I'll be leaving behind here at Sandy. But the good news is that I'll be doing a lot more programming. Hopefully I'll still have the time and motivation to keep up the blog. Even though I'm pretty sure that the only people that read it are me and my wife...OK...truthfully, I have to read it to my wife to get her to read it. ;)

If you are interested in filling my position at Sandy, you can go here for the job announcement.

I start next week. Wish me luck!

Thursday, September 16, 2010

Cool Census Data App From ESRI Applications Prototype Lab

Here's a cool Silverlight app from the ESRI folks that like to live on the cutting edge. I really like the idea of using the physics engine to reposition the graphics. Obviously the app needs refining (what's with the tool bar on the left that looks disabled until you hover?), but the concept is cool. You can check out their related blog post here, or go right to the app to try it out yourself.

Monday, September 13, 2010

Modify Feature With Sketch

This was something that I really missed when I upgraded to 10. To install go to Customize -> Customize Mode -> Add from file... and select the ModifyWithSketch.tlb file in the folder ModifyWithSketch\bin\Debug. Then you will have a new tool in the Commands tab under "Developer Samples" called "Continue sketching an existing..". You can drag this to any toolbar. To use, just select an existing feature and then click on the tool.

Saturday, September 11, 2010

My Custom Bookmark Manager/Map Book Generator Add-in

When I first got to Sandy City, there were some mxd's set up to produce a map book of all of our work management areas. The problem with making a map book of these areas is that they are irregularly shaped requiring different map extents. So the only solution was to use map bookmarks. To print the map book you had to manually zoom to a bookmark, change the title to match the area, press print and repeat for 20 areas! This got old very quickly so I developed an extension for ArcMap that did the work for me. I called it, "Bookmark Manager" (this was before ArcMap had it's own bookmark manager). It worked well for me and I thought that it was generic enough that others might be interested so I posted it on ESRI's Code Gallery.

Almost 3,000 downloads later, I'm getting emails from people all over the world that are using it. I had no idea that it would be this popular! It's been really fun to talk with them and see how they are using it.

The most common problems that people have with it are related to installation. With the old 9.x COM customization model, I had to create a custom setup project to install my extension. It was complicated and not fool-proof. So when I found out about the new Add-in architecture that ESRI introduced at version 10 I couldn't wait to implement it with my Bookmark Manager. Over the last few days I had some time to work on this. I now have my entire extension packaged into one self-installing .ESRIaddin file. I'm hoping that this will make sharing it a lot easier. If you are interested you can check it out in the new Code Gallery.

Anyone else using Add-in's yet?

Thursday, September 2, 2010

Aptana + JSLint = Better JavaScript & Hurt Feelings

JSLint is a tool developed by Douglas Crockford that searches for errors in your JavaScript code. From his site:
JavaScript is a sloppy language, but inside it there is an elegant, better language. JSLint helps you to program in that better language and to avoid most of the slop.
You can go to www.jslint.com and paste your code into the box and it will help you find errors. However, there is a much better way to take advantage of JSLint built right into Aptana Studio. You can go to ESRI's ArcGIS Server Blog to find out how to implement it. Then try not to be offended when it tears apart your code!

Friday, August 27, 2010

Public Facing Road Construction Projects Web Map

I just updated my only real public facing JavaScript app. This app (which is embedded in the city's web site) shows all of the road construction projects in the city along with relevant information that appears in a custom info window (ESRI dev sample) when you hover over the graphics.

I've also added the UDOT traffic cameras in this latest update. I was able to determine the id number and URL for each of the camera images using the UDOT CommterLink website. With permission from UDOT, I used this information to build my own map service showing the cameras.

What do you think? Anyone have any suggestions on making it better?

Thursday, August 26, 2010

How To Get an ArcGIS Add-in Dockable Window


It wasn't as easy as it first appeared. Here is a quote from an ESRI staff member that replied to my plea for help in the forums:
DockableWindow is a bit tricky here since it is implemented by two classes - 1) the UI part is the designer surface derived from controls and 2) the non-UI part is the class actually inherits from DockableWindow base class. 
FromID can only handle types derived from base classes declared in ESRI.ArcGIS.Desktop.AddIns.dll. You have to pass in the type that inherits DockableWindow, which is the inner class of the designer window itself if you are using the Add-in Wizard.
If you go to the xml declaration of the dockable window, you will see the class attribute is set to “DockableWindow1+AddinImpl”. You have to pass this type to get the dockablewindow implementation class first, then you have to expose a property there get a hold of the UI window.
While I won't pretend to understand stand it perfectly yet, I did come up with a solution that works well.

First, I added added a property called "UI" to the innerclass "AddinImpl" within my dockable window class that points to the dockable window class (why isn't this part of the template?):

/// <summary> /// Implementation class of the dockable window add-in. It is responsible for /// creating and disposing the user interface class of the dockable window. /// </summary> public class AddinImpl : ESRI.ArcGIS.Desktop.AddIns.DockableWindow { private DockableWindow1 m_windowUI; // this property is what I added - the rest was generated by the template internal DockableWindow1 UI { get { return m_windowUI; } } public AddinImpl() { } protected override IntPtr OnCreateChild() { m_windowUI = new DockableWindow1(this.Hook); return m_windowUI.Handle; } protected override void Dispose(bool disposing) { if (m_windowUI != null) m_windowUI.Dispose(disposing); base.Dispose(disposing); } }


Then to get the dockable window from another class it was just a few lines:

// get reference to dockable window DockableWindow1.AddinImpl winImpl = AddIn.FromID<DockableWindow1.AddinImpl>(ThisAddIn.IDs.DockableWindow1); DockableWindow1 dockWin = winImpl.UI; // or you could just do this DockableWindow1 dockWin = AddIn.FromID<DockableWindow1.AddinImpl>(ThisAddIn.IDs.DockableWindow1).UI;


I spent hours trying to figure this out. Hopefully this will save you the head-ache. Anyone else out there using Add-ins yet?

Friday, August 20, 2010

Go Web Mapping API's!

Two interesting quotes from the Deprecation Plans document just released from ESRI:
ArcGIS Server 10.0 is the last ArcGIS Server release with support for local connections from Web ADF applications. The 10.1 Web ADF applications will only support local connections to Server versions prior to 10.1. We recommend developers using local connections for accessing fine-grained ArcObjects migrate their business logic to Server Object Extensions. For Web ADF based editing applications (all of which use Local connections), we urge users to look at alternative web editing tools based in the ArcGIS Web Mapping APIs.
ArcGIS Server 10.1 will be the last planned release for the ArcGIS Server Web ADFs (Application Developer Framework) for both Microsoft .NET and Java. ESRI will continue supporting the Web ADFs during the 10.1 release cycle but only fixes to critical issues will be addressed. No new functionality or enhancement requests will be addressed for the Web ADFs. Web application developers are encouraged to move to a web services based pattern with the ArcGIS Web Mapping APIs for JavaScript, Flex, or Silverlight.
Looks like all of you Web ADF people have only a few years left to transition to the future.

Thursday, August 12, 2010

Local GIS: Utah County Parcel Map

The Utah County Parcel Map JavaScript application is a great, local example of the ESRI JavaScript API. You can easily recognize the use of Dojo in the layout and controls in the pane on the left. It's a simple and clean application that's easy to use.

I also like the use of the Local Government Infrastructure Base Map Template. I think that I'm going to take a look at this template to see if it can help my ugly base map service.

Dave H. and Darin S. from Utah County GIS are raising the bar!

Tuesday, August 3, 2010

Another Reason to Love the JavaScript API

ArcGIS Server Blog : Build applications for iOS using the ArcGIS API for Javascript

With a slight modification to the API reference (add "compact") you can build web maps optimized for Safari on the iPhone with built in goodies like flick to pan and pinch to zoom. I've already noticed it once in the wild that's even using Safari's Geolocation API.

Anyone giving this a try?

Wednesday, July 28, 2010

So That's What "The Cloud" Means

ArcGIS Server Blog : ArcGIS Server on Amazon EC2: The Basics

Cool! It would be so nice to not worry about server issues that invariably arise. Let Amazon worry about that. Then I can focus on GIS.

Anyone going to try it out?

Monday, July 26, 2010

Dojo Dijits: Object Oriented JavaScript Goodness

Object Oriented Programming is a programming style that views the world as a set of objects with properties and methods. When programming with JavaScript, it's easy to fall into a scripting mindset and fire off code in one giant method. This makes your code hard to read and debug. It can also lead to copying/pasting and redundant code. The first step to breaking this habit is to refactor as much as possible. However, this can only take you so far. The next step is breaking out sets of related methods into separate objects. Fortunately for those of us that work with the ArcGIS API for JavaScript, we have access to the wonderful world of Dojo Dijits.

If you've worked with the JS API before you have probably already used a Dojo Dijit. These are prepackaged code and markup that you can plug right into your applications. Dijit.form.Button and Dijit.form.Slider are very common examples. These are great, but the real fun comes in creating your own.

This article by Matthew Russell was my first introduction to creating your own custom Dijits (look for "Creating You Own Widgets"). It's not as complicated as you would think. The building blocks consist of three files (links to my files are included):
  • An .html file containing the markup code (hit view source to see the code).
  • A .js file containing all of the JavaScript.
  • A .css file containing all of your styling.
    After doing the work to create your own Dijit, it's as easy to use as any regular Dojo Dijit. I've created a full screen map dijit that I use for several of my applications. It includes goodies such as map resizing, an animated navigation toolbar, basemap layers and error wiring. It's great to spend time only once refining my design and code and then easily reusing it. And when I make improvements, all of my applications are automatically updated.

    Here's what it looks like in the current app that I'm currently working on. You'll see references to the map dijit and a tools digit.
    HTML:
    <body class="nihilo"> <div id="mapDijit" dojoType="mapDijits.mapDijit_FullScreen"></div> <div id="toolsDijit" dojoType="mapDijits.toolsDijit"></div>


    JavaScript:
    <script type="text/javascript"> //require newly created dijit dojo.require("mapDijits.mapDijit_FullScreen"); dojo.require("mapDijits.toolsDijit"); dojo.require("dojo.parser"); // global var g = {}; g.baseURL = "http://gis.sandy.utah.gov/ArcGIS/rest/services/"; g.PermitsURL = g.baseURL + "Public_Works/Road_Cut_Permits/MapServer"; function init(){ // get map dijit and tools dijit var mapDij = dijit.byId("mapDijit"); var toolsDij = dijit.byId("toolsDijit"); // set map dijit for tools dijit toolsDij.mapDijit = mapDij; toolsDij.setup(); // add permits layer mapDij.addLayer(g.PermitsURL, cached=false, wireErrors=true); // add buttons toolsDij.addButton(label="Add Line", iconClass="drawLineIcon", method=drawLine); toolsDij.addButton(label="Add Point", iconClass="drawPointIcon", method=drawPoint); }


    You can see it in action in my Core Samples and Pavement Markings live applications. Anyone else using custom Dijits out there?

    Tuesday, July 20, 2010

    Salt Lake GIS Users Group (SLUG): 08-11-2010

    Salt Lake GIS Users Group (SLUG): 08-11-2010

    The RSVP's are coming in fast. Better hurry or you'll miss out on lunch.

    While your at the SLUG site, take a minute to complete our annual topics survey to help direct future meetings.

    Monday, July 12, 2010

    ESRI UC Fun

    I, sadly, am not in San Diego right now for the ESRI User Conference. I'm trying to keep up as best as I can through the magic of the internet. "The Fee" is live-blogging the plenary right now if you are interested.

    For those who are there, I would recommend DTS Agile's UC Back Channel. Aside from the beautiful web design and interesting use of the JavaScript API, it looks like a lot of fun. The prizes look interesting although it doesn't look like they're going to get enough participation for iPad's. I like this tee:
    #GEOGLOBALDOMINATION
    I'M KIND OF A BIG DEAL
    ON TWITTER #ESRIUC

    Thursday, July 8, 2010

    Another ESRI API Following The Dinosaurs

    It seemed like only yesterday that the Web ADF was ESRI's next big thing. But after only a few years of existence it looks to be on the way out. If you are jumping up and down with joy right now, you are not alone. I'm feeling quite relieved that I could never wrap my head around it even after taking an ESRI class. Maybe I wasn't the only one?

    Tuesday, July 6, 2010

    My First ESRI Add-in

    I've converted my first ArcMap .NET customization to the new ESRI add-in format. I could have just rebuilt my existing COM project with the new 10 libraries, but I wanted to test out the add-in functionality so I dove into the documentation for converting existing projects. The basic workflow for me was to create a new project in Visual Studio of type "ArcMap Add-in". Then I told the wizard what elements I wanted to include in my add-in which for me included a dockable window and a command button. Then I simply copied the code from my old project to the new one. There were only a few minor changes that I need to make including the slink new global variables that make it a cinch to access commonly used objects like ArcMap.Document. After successful debugging and compiling I came up with this:
    Now, all I have to do to install my tool is double-click on the esriAddIn file. This is so much simpler than worrying about registering COM .dll's. I can't wait to convert the rest of my projects and start passing them around. Anyone else created any add-in's yet?

    Friday, July 2, 2010

    It's Alive! - ArcGIS Desktop 10 Initial Thoughts

    There's just something fun about upgrading. Everything's new and shiny. Aside from the official what's new,  here's a few of my thoughts after using it for a day or so.


    The UI Redesign is beautiful. I like the new icons. They have a modern feel, but are similar enough to the old ones that you can still find what you are looking for. Here's a taste:

    Dynamic Text is a great replacement for my old VBA code that automatically updated text elements that showed the current date and path to the .mxd.

    VBA is officially unsupported at 10. You can still use it but you have to install the VBA developer kit as well as request a license (free) from ESRI and then install it manually on you license server. It's totally gone with the next release. While I knew that this was coming, I'm still amazed at all of the VBA out there that's going to have to be ported to a .NET addin or the arcpy module. Thank goodness that I've got experience with both types of development.

    You cannot administer an ArcGIS Server 9.3.1 instance with version 10 Desktop. This is the reason why I have a laptop on my desk running 9.3.1.   :(

    Basemap Layers are awesome. They give a cached map service feel to your basemap layers in ArcMap. They're not as smooth as I would like, but they are still way better than regular layers.

    Most of the windows are dockable know which can easily be hidden and shown without a map refresh.

    These are just a few of my first impressions. Anyone else out there running 10? What do you think of it?

    Tuesday, June 29, 2010

    WinDirStat - Cool Free Tool

    WinDirStat is a great way to see what files are on your computer and how much memory they are using. After analyzing your drive, it produces a cool, interactive treemap like this:

    Monday, June 28, 2010

    Newbie Dev's Take a Hit with ArcGIS VBA Deprecation

    This was not the first warning that VBA is going the way of the dinosaur. I stopped any new development with it months ago after hearing the it was not going to last.

    While I'm excited about the new arcpy module and nifty add-in framework, I'm a bit sad to see an old friend leave. VBA is where I began my journey in programming and I believe it has played a similar introductory role to many others. It was so nice to have a development environment baked right into ArcGIS Desktop so that within seconds you could be writing and debugging code. While I eventually transitioned into the more robust Visual Studio world, VBA was a great bridge.

    Now I'm worried that people who dabble in VBA will be much less likely to open Visual Studio Express. And while the new python API looks really good for map automation and geoprocessing, it doesn't look like it has any UI capability. I hope that this doesn't discourage the use of custom code in the future.

    Tuesday, June 22, 2010

    One Var To Rule Them All

    As I was watching a great Tech Session video from ESRI's last Developer Summit on the JavaScript API, I was introduced to the concept of global variables being evil. Further research confirmed that I needed to alter my coding patterns a little bit. Since then I have tried to keep global variables to a minimum. If I do need them I have started storing them within a single variable like this:
    // global variable var g = {}; g.baseURL = "http://gis.sandy.utah.gov/ArcGIS/rest/services/"; g.googleBaseURL = g.baseURL + "Public_Works/Google_Basemap/MapServer"; g.bwURL = g.baseURL + "Public_Works/BulkWasteAreas/MapServer"; g.vectorQueryURL = g.baseURL + "Public_Works/Vector_Basemap/MapServer/6"; g.locatorURL = g.baseURL + "Sandy_Address_Locator/GeocodeServer"; g.fldBW_DATE = "BW_DATE"; g.fldAREA_NUM = "AREA_NUM";

    This has kept my code a little cleaner and has made it far easier to find the evil things during run-time with FireBug. My latest project with bulk waste data was my first attempt at global variable redemption.

    Monday, June 21, 2010

    Easy there boy...

    This was some much needed antidote for the rush-to-upgrade poison that courses through my veins. "Potentially corrupting data" was enough to give me the shivers. I can still upgrade my desktop though, right?

    I [heart] ArcGIS API for JavaScript


    Did you all notice which ArcGIS Server API ESRI chose to use on their fancy, new website? No third-party plugins required.

    Have you also noticed that the AGRC seems to be focusing on this API as well? I was talking with Bert Granberg and he used the phrase, "pure web".

    I'm not saying that Flash and Silverlight are going away, but I just keep seeing more and more of the JavaScript API. With the recent backing of HTML5 by all of the industry's major players (even Adobe), I think that a "pure web" solution is going to continue to be a great choice in the future.

    What do you all think? Who else is there in the region that's working with this API? We need to start a support group. ;)