Has anyone implemented html5 browser history for a complex javascript Mapping application?

4019
3
Jump to solution
01-28-2015 06:36 AM
MarkAndrews
New Contributor

I have a requirement to implement HTML 5 history tracking in my javascript application.  To Keep it simple I wanted to update the history state every time the user panned or zoomed on the map.  The problem is that each popstate event that gets triggered and I would reset the extent to the previous extent it also triggered the original event adding another item in the history state. 

This is the code that sets the listener on the pan event...

var eventHandlers = [];

      var currentState = {};

      function setEventTriggers() {       

        

           var e = map.on("pan-end", function (e) {                      

               var pt = e.extent.getCenter();

               var state = { action: "pan", x: pt.x, y: pt.y };

               if (currentState && (currentState.x == pt.x && pt.y == currentState.y)) {

                   console.debug("this is history");

               } else {

                   window.history.pushState(state, null, "CreateTract.aspx?x=" + pt.x + "&y=" + pt.y);                 

               }              

           });

           eventHandlers.push(e);          

      }

this is the code that handles the pop state

      window.addEventListener("popstate", function (e) {

          event.stop(e);

          console.debug(e);

          prevStates = [];

          currentState = e.state;

          var url = document.location.href;

          //console.debug(url);

          var u = urlUtils.urlToObject(url);

          if (u.query) {

              if (u.query.x && u.query.y) {

                  var pt = new Point(u.query.x, u.query.y, map.spatialReference);

                  var state = { action: "pan", x: pt.x, y: pt.y };

                  prevStates.push(state);

                  map.centerAt(pt);                 

              }             

          }

          fsMap._processBasicRequest();

      });

As you can see I set a Current state variable at the beginning of the pop state routine and then check to see whether the current state is the same as state which I would be putting into history...

As this is rather kluggy, I was hoping someone else had a better idea.

I also tried to disconnect the event triggers but that could get really complicated in my application which has alot of UI javascript classes that trigger there own events...

Mark Andrews

Durham, NC

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JoshHevenor
Occasional Contributor II

Here's a little more on how I would do this (untested). I see now that you did pans only but the approach should work.

// Listen for the map extent to change
var extentListener = on.pausable(map, "extent-change", function(evt){
    // Write to history
    if (typeof history.pushState !== "undefined") {
        window.history.pushState(state, null, "CreateTract.aspx?x=" + pt.x + "&y=" + pt.y);
    }
});

// Listen for history stack to the be popped
window.on("popstate", function (evt) {
    // don't worry about writting new history until we're done
    extentListener.pause();

    // When the map has had its extent changed then resume writing history <<<<<<<<  A >>>>>>>>>>>
    on.once(map, "extent-change", function(evt){
        extentListener.resume();
    });

    // Get the extent from evt.state or url
    var center = ...;
    var zoom = ...;

    // Set map location from history event...this triggers our one time listener at << A >>
    map.centerAndZoom(center, zoom);    
});

View solution in original post

3 Replies
JoshHevenor
Occasional Contributor II

There's a sample that's not quite related:

History API to track selected feature | ArcGIS API for JavaScript

The key may be to turn off your listener when you're setting your history.  Or check out

dojo/on view /dojo/on

0 Kudos
JoshHevenor
Occasional Contributor II

Here's a little more on how I would do this (untested). I see now that you did pans only but the approach should work.

// Listen for the map extent to change
var extentListener = on.pausable(map, "extent-change", function(evt){
    // Write to history
    if (typeof history.pushState !== "undefined") {
        window.history.pushState(state, null, "CreateTract.aspx?x=" + pt.x + "&y=" + pt.y);
    }
});

// Listen for history stack to the be popped
window.on("popstate", function (evt) {
    // don't worry about writting new history until we're done
    extentListener.pause();

    // When the map has had its extent changed then resume writing history <<<<<<<<  A >>>>>>>>>>>
    on.once(map, "extent-change", function(evt){
        extentListener.resume();
    });

    // Get the extent from evt.state or url
    var center = ...;
    var zoom = ...;

    // Set map location from history event...this triggers our one time listener at << A >>
    map.centerAndZoom(center, zoom);    
});
MarkAndrews
New Contributor

Josh,

thanks.  That was helpful.

0 Kudos