History Keeper – Deep Linking in Flash & JavaScript

Update: Beta 4 is out.

unFocus History Keeper – a JavaScript tool for managing browser history (back button) and deep linking in Flash and Ajax applications, enabling SEO.

You can check out an example page in SVN or check out adcSTUDO or Terminal Design’s fonts catalog for a demo. The test page contains a small JavaScript application that takes what you put in a text box, and makes a history entry out of it – a deep link will display that history entry in the body of the page as well.

Download the latest release archive from the downloads page on the google code site. You will find two packer compressed JavaScript files in the root of the archives, unFocus-History-p.js and unFocus-HistorySwf-p.js.

unFocus-History-p.js contains:

  • EventManager.js
  • History.js

unFocus-HistorySwf-p.js contains:

  • EventManager.js
  • History.js
  • FlashPlayerInfo.js
  • SwfUtilities.js
  • SwfHTML.js

NOTE: You should include only one of the two files, not both.

You can also check out the latest version from SVN from either the trunk (I try to keep it working there, but no guarantees) or one of the tagged releases (each release gets a tag) if you want to be cutting edge.

Features:

  • Enables back button support, for your client-side web apps!
  • Hash based deep linking (Anchor Style – index.html#/foo/bar)
  • Event driven – Event Dispatcher
  • Support for all current browsers:
    • Opera
    • Firefox
    • Safari 1.2+
    • IE 5.5+
    • Google Chrome

Known Limitations: (I have to confirm if many of these are still a problem)

  • All history entries (back button states) modify the location string.
  • Doesn’t remember last entry if you leave the app and come back in some browsers (that’s a bug, I’ll fix it).
  • Editing the url manually will stop further updates to the url in some browsers.
  • Konqueror support is still a bit flaky (this history is off by one in an odd way).
  • Deep linking and back  button functionality relies on ExternalInterface – so “allowScriptAccess” has to be set and working (platform defendant) for History Keeper to work (though you can actually get deep linking to work using flashvars, in a pinch).
  • Make sure whatever embed solution you are using, you have set the “id” attribute on your object or embed tag.

Related Links – Note: I’m trying to put links to everyone who helped me out over the years. If I left you out, please let me know.

49 thoughts on “History Keeper – Deep Linking in Flash & JavaScript”

  1. — swf communicating with html on runtime —

    … first-of-all: thanks for all of your work !!!

    i wonder if/how one may send/receive data to/from the embedded swf on runtime
    without reloading the swf – may you please let me know ?

  2. There are a number of ways to do that. I used to have something in the unFocus tool set that would allow for that, but have discontinued it, since there is a built in (and more reliable) way to do that since Flash Player 8.

    It’s called External Interface, and is fairly easy to use, once you wrap your head around it.

    To send info into the swf from javascript, you’ll need to use ExternalInterface.addCallback to add a javascript function handle, then call that from Javascript by getting a reference to the embedded swf’s DOM object, and calling that method. Here is an example: unFocus.SwfUtilities.getSwfReference(“swfID”).yourCallbackFunction();

    You’ll need to make sure you set Allowscriptaccess to a value that allows that communication with the script.

    (Akizmet marked this as SPAM, LOL)

  3. I’m change your method “_getHash” in “unFocus-History-p.js”. See changes. My variant is more correctly:

    var _getHash = function() {

    if (/MSIE/.test(navigator.userAgent) || window.opera) {

    var result = /\?([^\?\#]*)$/.exec( location.href );
    var search = (result && result[0]) ? result[0] : ”;

    return location.hash.substring(1) + search;
    }

    return location.hash.substring(1);
    };

  4. It’s possible I am blind…. But have tried finding instructions on this site in regard to implementing History Keeper, with no luck. I am new to flash and AS3, the examples provided in the download folder are not self-explanatory to myself… Advice/Insight/Direct me to further information? Would be much appreciated…

  5. Hi! It’s me again!

    Released IE8 and it took some refinement :( Now hash parsing your code in my app looks like this:

    var _getHash = function() {

    var ua = navigator.userAgent;

    if (/MSIE/.test(ua))
    {
    var index = ua.indexOf(‘MSIE’);
    var MSIE = parseFloat( ua.substring(index + 5) );
    }

    if ( (MSIE && MSIE<8) || window.opera)
    {
    var result = /?([^?#]*)$/.exec( location.href );
    var search = (result && result[0]) ? result[0] : ”;

    return location.hash.substring(1) + search;
    }

    return location.hash.substring(1);
    };

    In IE8 hash (params after “?” symbol) presented like in any normal browser. But in IE < 8 this problem anyway exist.

    Sorry for my English :)

    (Note: This got caught up in Akismet for some reason. Sorry about that. I wonder what else gets lost in there.)

  6. Hi

    I understand
    unFocus-History-p.js contains, EventManager.js and History.js .

    but unFocus-History-p.js is in a minimized format. Can i get the original version of unFocus-History-p.js ?

    Thanks
    Sree

  7. Sure, you can find the original version in the archive in the javascript folder (you’ll find both EventManager.js and History.js). You can also find them in SVN (linked in this comment).

    All I did before packing them, was to copy them to one file – EventManager first, then History Keeper. In the future I’ll try to remember to leave the compiled js file in the archive.

  8. This code works great… except after document.domain is set in IE.

    If you set document.domain then IE gives ‘Access is denied’ when trying to read (but, bizarrely, not change) window.location.

    The reason we set document.domain is so that the main document on example.com can communicate with a child iframe on ajax.example.com. Both the main and child iframe documents need document.domain explicitly set to ‘example.com’, even if the main document is at http://example.com already (i.e. although the domain is example.com, it still needs to be explicitly set).

    To clarify, the problem can be recreated just be running these two lines of JSript on a page:
    document.domain = ‘yourdomainhere';
    alert(window.location); // will throw an access denied error in IE

    Hoping someone can help!

    Jake.

  9. Hi,

    If I leave the current page (say Page1.aspx, that implemented the history Keeper), and go to Page2.aspx.
    Now if I try hitting the history back button and come back to Page1.aspx. I could see that the history is lost!
    Is there any fix for this? Thanks in advance.

    Also history is nto workgin in Opera Version 9.25

    Regards
    Sree

  10. Hi Sreejith. I’m not sure what is causing that. I don’t remember this being a problem, but I was able to reproduce this easily enough. I have some work to do it looks like. Thanks for the bug report. Opera is a PIA, but I’ll look into that too.

  11. About that bug – This seems to only apply to IE6 and 7, and it’s a bug in general with keeping a history using iframes, which affects other history scripts as well. I’ll keep looking for a fix, but it does look like Microsoft cleaned it up in IE8 (in IE8 mode), along with a bunch of other issues (like the title getting all screwed up).

    I have noticed that most RIAs that use flash and history/deep linking techniques are making external links open in a new window. Maybe it’s partly to deal with this.

  12. Kevin thanks for the response… Looking forward to hear from you, if there any update.

    ~Sree

  13. @ Egor

    About that IE bug with “?” after the hash “#” – this appears to be a bug in IE that can’t be worked around. I’ll keep an eye out for a fix, but I think the answer will be that you simply can’t put a ? in the string after the hash, and maintain compatibility with IE < 8. Sorry about that. If you know of anyone that’s done it, please let me know. :-)

  14. Can this track the history of multiple iframes too? When you click on something in an iframe it is added to the history but when you look at the history array you can’t se the iframe url, only the main page url. Why is that? When you press back the iframe goes back, how did it know to what url to go back to?

  15. I haven’t looked at the history array in a while, but I suspect you are running up against the limits of what the browser can keep track of. Theoretically, all the browsers should be able to do what you are saying without error – but I bet reality is different. Most of the issues around that center on security issues – parent pages being able to access information about the content in an iframe – even the location – could be a security problem. So most of the browsers have erred on the side of caution and made it difficult or impossible to get that information across frames. Unfortunately, History Keeper really doesn’t deal with iframes too much, except to use a hidden iframe for IE5.5 – 7 compatibility, so I doubt it’ll be of any help.

  16. Awesome utility, seems to work 99% of the time in all the major browsers according to my tests. The biggest flaw is that on some browsers users have to hit the back button twice. Though, overall highly recommended and suitable for use on high-traffic sites. Please, keep this code independent of any JavaScript library, as that is the best feature of all.

  17. Thanks for the kind words. If you have any specific information on when the user must press the back button twice (browser/version/platform/etc.), I’d love to squash that bug.

    A core design goal of HistoryKeeper is to keep it light, and dependent free (for easier and more flexible deployment). I’ll never add dependency on a third party library like jQuery, though I may eventually wrap a plugin around it to make things a bit easier for those who wish to integrate with jQuery.

  18. this.historyListener = function(historyHash) doesn’t fire in Chrome. It works fine in all other browsers

  19. any progress on some type of tutorial on implementing History Keeper? or do you know of anyone else who has compiled some type of guide/tutorial? i really like what ive seen so far with it and would be very interested in implementing it in my own flash website, but im still pretty much a beginner with flash and js, but experience with html.

  20. I have made progress. It’s half in WP, and half in an AS file. The as file is currently in SVN, and contains most of the good stuff. You can find that here, in the inline comments:

    http://code.google.com/p/unfocus-history-keeper/source/browse/trunk/tests/HistoryKeeperSwf.as

    Getting that finished, and posted is on my short-list, for right after I finish this huge months long project I’ve been working on. One day that’ll be finished (in like 2 months!)

  21. How can I store dropdown array values in the history? If I do, I see everything on the URL. Is there a way to mask the values with a key or something like that? I’d very much appreciate your help!

  22. I have one in the works, but so much has changed since I started it – I think I’ll just publish it in a rough state, and be done. I’ll try to get to that over Christmas break.

    Eventually, I’ll write a tut for the new HTML5 history/deep link stuff (once I figure out how it works, which I will do for an upcoming project).

  23. Ißve got the scritp running, when I click on a link the info is stored, when I go back and foward the address bar changes but the page in the browser does not change. Any idea? Thanks!

  24. Hi Kevin,

    Great work; thanks for sharing it with us. I am curious: have you tried using this inside an iframe? I’m having an issue with IE (what else is new?) whereby when you click the back button the iframe’s location will replace the parent’s location.

    Any thoughts would be much appreciated; thanks!

  25. I vaguely remember something about a problem with using this inside of an iframe. I’d bet it simply will not work (hk creates it’s own iframe via javascript behind the scenes – stuff like that tends to make IE freak out). I’ll see if I can find some time to mess with it – but it seems I never do. :-(

  26. Hi Kevin,

    Thanks for replying. Yes, I’ve been looking at History.js & see what it’s doing. And when I get the time I’ll try running against the unpacked scripts & see what I can come up with as well; maybe we’ll get lucky ;-)

  27. Hi friends, it is possible that the addHistory() method don’t call the historyListener() method when a new entry is added?

    thanks so much

  28. @ Gustavo

    I’ve tried it both ways – it’s more consistent if dispatches immediately Just make sure you store your current value locally, and check it in your listener. There are browser quirks that’ll cause this to fire at any rate, so it’s important to check the incoming value against your current state. You should probably also be filtering the URL data, to make sure it’s the same when it does come back from the browser (each of which encode special characters differently – ugh). At this point, I’ve actually been recommending alternative frameworks to history keeper, I just haven’t been on top of maintaining it, and there are some vital tools missing from the stack (like a URL filtering/cleaning tool, and some kind of state manager). Have a look at jQuery BBQ as a good alternative.

Leave a Reply

Your email address will not be published. Required fields are marked *

Connect with Facebook

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Home of Scripts 'n Styles for WordPress, Backstage2D and History Keeper!