Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

window.location.hash refresh in Chrome?

I was doing some snooping on the web and found window.location.hash = "etc" to be a widely adopted method to update the browser's location without reloading / refreshing the page. I've applied that to this example I've cooked up: http://dl.dropbox.com/u/1595444/locationExample/index.html

Works well in Safari, but...

What I've noticed is that in Chrome 10+ upon changing hash:

  • There is something similar to a reload.
  • The resulting symptom is a hiccup as the user scrolls down or up.
  • My console output is preserved (if you check your console the project string's are outputted).
  • The favicon seems to be reloading.
  • Has anyone run into this problem before? Know a fix?

    like image 932
    jonobr1 Avatar asked Apr 13 '11 23:04

    jonobr1


    3 Answers

    There are most likely two things going on here:

    • The favicon and stop/refresh buttons flicker because of a Chrome bug (that mentions pushState, but hash changes are on the same code path).
    • The slight hiccup when scrolling is because Chrome does a full page repaint and high-quality scale to update the page thumbnail, since it's considering hash changes as generating a new URL. That's also a bug. You can see this in the inspector timeline view, most scroll events result in a repaint of window width x some small height, but occasionally there will be a full-window repaint. This blog post has a few more details.

    A workaround for both would be to defer the updating of the hash until the user is done scrolling (you can still update the white bar that appears under the current item immediately). You can do this by having something like:

    var scrollTimeout;
    window.onscroll = function() {
      // update current item display here
      if (scrollTimeout)
        clearTimeout(scrollTimeout);
      scrollTimeout = setTimeout(function() {
        scrolTimeout = undefined;
         // update hash here
      }, 100);
    };
    

    Since it looks like you're using jQuery, there are debouncing plugins that may be helpful.

    like image 79
    Mihai Parparita Avatar answered Nov 09 '22 02:11

    Mihai Parparita


    I don't have a definitive answer, but first I would try:

    1. Prepending the hash mark (#) on to the value (i.e. use window.location.hash = "#etc").
    2. Register a handler for the window.onhashchange handler.
    3. Alternatively, you might consider using history.pushState if what you are trying to accomplish is make the back button return to the previous logical location (it's not clear to me what you are trying accomplish, whether you just want to jump to a section on the page, or something more complex).
    like image 44
    Michael Aaron Safyan Avatar answered Nov 09 '22 03:11

    Michael Aaron Safyan


    var r='#hello';
    if(navigator.userAgent.indexOf('Chrome/')!=-1){
     top.history.pushState("", "", r);
     return;
    };
    if(r.charAt(0)=='/'){
      top.location.replace(r);
     }else{
      top.location.hash=r;
    };
    

    Worked for me. And it actually took me a long time to figure this out. Firefox also supports the history object now, so we may be able to get rid of the whole "hash" thing in a few years.

    EDIT: Yes, the reloading thing is a Chrome bug.

    like image 23
    Zdenek Avatar answered Nov 09 '22 01:11

    Zdenek