odoe

Save maps last location

Blog Post created by odoe on Apr 8, 2015

where_was_i.jpg

Every now and then I'm asked to make a map do something it normally wouldn't do, but actually makes perfect sense. Astonishing, I know.

 

A while ago a user asked if the map could save some information if they had to close the browser and come back later. One of these things was the maps last location. They also wanted auto-save in edits and other things, but the same methods applied here will work for that as well.

 

So I set out like a happy little developer and of course I thought, I'll just use windows.onunload, actually onbeforeunload is the recommended way, and to be safe I'll dojo/_base/unload to handle any quirks. I figured I'll just use LocalStorage and voila, super-happy customer. And it really is that simple... unless you're using an iOS device (or course it had to be an iOS issue). So onbeforeunload isn't supported in mobile Safari, that was a bummer.

 

Then I figured, well, why not update the location on each extent-change event when using an iOS device. This worked and I spent a good five minutes giving myself pats on the back (I also had an itch).

 

So what does all this madness look like?

I present some code!

require([
  'esri/map',
  'dojo/on',
  'dojo/_base/unload',
  'dojo/domReady!'
], function (
        Map, on, baseUnload
) {
  var supports_local_storage = function supports_local_storage() {
    var test = 'has_local';
    try {
      localStorage.setItem(test, test);
      localStorage.removeItem(test);
      return true;
    } catch (e) {
      return false;
    }
  };
  var map = new Map("mapDiv", {
    center: [-118, 34.5],
    zoom: 8,
    basemap: "topo"
  });
  if (supports_local_storage()) {
    var vals, data, iOS, handler;
    vals = localStorage.getItem(location.href + '--location');
    if (vals) {
      data = JSON.parse(vals);
      map.centerAndZoom(data.center, data.zoom);
    }
    // handle this bug https://bugs.webkit.org/show_bug.cgi?id=19324
    // In my testing, a refresh of the browser in iOS will not fire
    // window.onbeforeunload, so if iOS, use map event to write
    // zoom and center to localStorage
    iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
    handler = function() {
      var loc = {
        center: map.extent.getCenter(),
        zoom: map.getLevel()
      };
      localStorage.setItem(location.href + '--location', JSON.stringify(loc));
    };
    if (!iOS) {
      baseUnload.addOnUnload(handler);
    } else {
      on(map, 'extent-change', handler);
    }
  }
});

 

Depending on browser support, you may need to use dojo/json instead of the native JSON to get this working you poor poor soul.

And that's all there is to it. The location gets saved to LocalStorage as needed and when the application starts again, it checks to see if there is a saved location and will load it up again.

 

Easy sauce.

self-five.gif

 

You can see a demo in action here.

 

For more geodev tips and tricks, check out my blog.

Outcomes