9

I have a single page application that uses Knockout.js for data binding and Sammy.js for routing client-side (hash-based) URLs.

I'm seeing a weird problem in Internet Explorer, however: sometimes links, when clicked, will change the URL in the browser's address bar, but the corresponding Sammy route will not execute.

It doesn't happen every time (but I can consistently reproduce the error), and it only happens in IE10 (Chrome works fine every time). It appears to be related to Knockout as well, since a set of hard-coded links don't exhibit the same problem.

To illustrate, I've stripped away everything but the bare minimum to recreate the problem and created two jsbin examples:

Example 1 (with Knockout): http://jsbin.com/aretis/2/

To see the problem, open the link above and click "Record #1", then "Baz", then "Record #1" again. The URL for record 1 will appear in the address bar, but the route for that record will not be appended to the list.

Example 2 (without Knockout): http://jsbin.com/amivoq/1/

In this example, I have a static list of record links instead of a data-bound list. Clicking on any of the links (in any order) will result in that route being appended to the list (as it should).

A reminder that these must be run in IE to reproduce the problem.

Any ideas?

Matt Peterson
  • 5,169
  • 4
  • 32
  • 34
  • I have the same problem in an app right now with IE 10. Do you have an activate method exposed? Does that get called when switching back and forth? – Boone Jul 31 '13 at 23:23
  • 1
    I solved (perhaps "worked around" is a better phrase) the problem by just binding to $(window).on("hashchange") and writing my own URL router. My needs were very simple, and I suspect I was only using about 10% of Sammy.js's capabilities anyway. I'm still curious as to the source of my problem, so I'm leaving this question up. – Matt Peterson Aug 05 '13 at 20:35
  • Can you re-create the example 1 with sammy JS unminified ? I also created my own router based on SammyJS. @Matt Peterson, thanks for the tip. I was not aware of the 'hashchange' event. I was checking the windows.location with a timer :). – Damien Aug 15 '13 at 20:36
  • A example or code would be great. I am having this same issue and not sure how to resolve it. – jmogera Oct 02 '13 at 19:56
  • 1
    It looks like you're describing https://github.com/quirkey/sammy/pull/183 - this has been resolved, but you'll probably have to wait a while for it to be in a stable release - I suggest that you apply the patch yourself since it's not massive. – Hayden Crocker Oct 21 '13 at 11:09

1 Answers1

2

As per my comment above, I worked around this problem by just catching the window.hashchange event and parsing out the URL myself. This is the only part of Sammy.js I was really using and I wasn't having any luck tracking down the actual problem. Hopefully, this will help someone else.

The first thing I did was bind the hashchange event:

$(function () {
    $(window).on("hashchange", HandleUrl);

    // Call our URL handler to deal with any initial URL given to us.
    HandleUrl();
}

This calls the following URL parser:

function HandleUrl() {
    var hash = location.hash;

    if (hash.indexOf("#Account") >= 0) {
        var splitParts = hash.split("/");

        if (splitParts.length >= 2) {
            ShowLoadingBox();
            ShowAccountDetailFromId(splitParts[1]);
        }
    } else if (hash.indexOf("#Contact") >= 0) {
        var splitParts = hash.split("/");

        if (splitParts.length >= 2) {
            ShowLoadingBox();
            ShowContactDetailFromId(splitParts[1]);
        }
    } else if (hash.indexOf("#ThingsToDo") >= 0) {
        SwitchToPanel("navPanelThingsToDo");
    } else if (hash.indexOf("#ThingsIveDone") >= 0) {
        SwitchToPanel("navPanelThingsIveDone");
    } else if (hash.indexOf("#Reports") >= 0) {
        SwitchToPanel("navPanelReports");
    } else {
        SwitchToPanel("navPanelMyAccounts");
    }
}

The functions like ShowAccountDetailFromId() and SwitchToPanel() just show and populate (using Ajax calls to web services) the appropriate <div>. This is probably a completely naive approach, but it is working (i.e. you can bookmark URLs, the back button and browser history work, etc.) My apologies for the non-answer "answer".

Matt Peterson
  • 5,169
  • 4
  • 32
  • 34