Change hash without triggering a hashchange event

JavascriptJquery

Javascript Problem Overview


I'm using the hash to load content dynamically. To make the back button work I am capturing hash changes. However sometimes I need to change the hash without triggering the hash changed function (eg, when the page was redirected server side and I need to update the hash once the content has returned.)

The best solution I have come up with is to unbind the hashchange event, make the change and then rebind it. However, as this happens asynchronously, I am finding that it rebinds too quickly and still catches the hash change.

My solution at the moment is very poor: Rebinding in a setTimeout. Does anyone have a better idea?

    $(window).unbind( 'hashchange', hashChanged);
    window.location.hash  = "!" + url;
    setTimeout(function(){
        $(window).bind( 'hashchange', hashChanged);
    }, 100);


Edit:
Amir Raminfar's suggestion prompted me to a solution that does not require a timeout. I added a class variable

_ignoreHashChange = false;

When I want to change the hash silently I do this:

_ignoreHashChange = true;
window.location.hash  = "!" + url;

and the hash changed event does this :

function hashChanged(event){
    if(_ignoreHashChange === false){
        url = window.location.hash.slice(2);
        fetchContent(url);
    }
    _ignoreHashChange = false;
}

Javascript Solutions


Solution 1 - Javascript

You could use history.replaceState and append the hash, to replace the current URI without triggering the hashchange event:

var newHash = 'test';

history.replaceState(null, null, document.location.pathname + '#' + newHash);

JSFiddle example

Solution 2 - Javascript

You can have a function like this:

function updateHash(newHash){
  ...
  oldHash = newHash
}

then in your setTimeOut you need to do

function(){
  if(oldHash != currenHash){
    updateHash(currenHash);
  }
}

So now you can call update hash manually and it won't be triggered by the event. You can also have more parameters in updateHash to do other things.

By the way, have you looked at the jquery history plugin? http://tkyk.github.com/jquery-history-plugin/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSystemicPluralView Question on Stackoverflow
Solution 1 - JavascriptTimView Answer on Stackoverflow
Solution 2 - JavascriptAmir RaminfarView Answer on Stackoverflow