Can you use hash navigation without affecting history?

48,370

Solution 1

location.replace("#hash_value_here"); worked fine for me until I found that it doesn't work on IOS Chrome. In which case, use:

history.replaceState(undefined, undefined, "#hash_value")

history.replaceState() operates exactly like history.pushState() except that replaceState() modifies the current history entry instead of creating a new one.

Remember to keep the # or the last part of the url will be altered.

Solution 2

location.replace("#hash_value_here"); 

The above seems to do what you're after.

Solution 3

Edit: It's been a couple years now, and browsers have evolved.

@Luxiyalu's answer is the way to go

--Old Answer--

I too think it is impossible (at this time). But why do you need to change the hash value if you are not going to use it?

I believe the main reason why we use the hash value as programmers is to let the user bookmark our pages, or to save a state in the browser history. If you don't want to do any of this, then just save the state in a variable, and work from there.

I think that the reason to use a hash is to work with a value that is out of our control. If you don't need it, then it probably means you have everything under your control, so just store the state in a variable and work with it. (I like repeating myself)

I hope this helps you out. Maybe there's an easier solution to your problem.

UPDATE: How about this:

  1. Setup a first hash, and make sure it gets saved in the browser history.
  2. When a new tab gets selected, do window.history.back(1), that will make the history go back from your first init hash.
  3. Now you set the new hash, therefore the tabbing will only make one entry in the history.

You'll probably have to use some flags, to know if the current entry can be "deleted" by going back, or if you just skip the first step. And to make sure, that your loading method for the "hash" doesn't execute, when you force the history.back.

Share:
48,370

Related videos on Youtube

Admin
Author by

Admin

Updated on July 08, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm afraid it might be impossible but is there a way to change the hash value of a URL without leaving an entry in the browser's history and without reloading? Or do the equivalent?

    As far as specifics go, I was developing some basic hash navigation along the lines of:

    //hash nav -- works with js-tabs
    var getHash = window.location.hash;
    var hashPref = "tab-";
    function useHash(newHash) {
        //set js-tab according to hash
        newHash = newHash.replace('#'+hashPref, '');
        $("#tabs li a[href='"+ newHash +"']").click();
    }
    function setHash(newHash) {
        //set hash according to js-tab
        window.location.hash = hashPref + newHash;
    
        //THIS IS WHERE I would like to REPLACE the location.hash
        //without a history entry
    
    }
        // ... a lot of irrelavent tabs js and then....
    
        //make tabs work
        $("#tabs.js-tabs a").live("click", function() {
            var showMe = $(this).attr("href");
            $(showMe).show();
            setHash(showMe);
            return false;
        });
        //hash nav on ready .. if hash exists, execute
        if ( getHash ){
            useHash(getHash);
        }
    

    Using jQuery, obviously. The idea is that in this specific instance 1) making the user go back over every tab change could effectively 'break the back button' by piling up needless references, and 2) not retaining which tab they're currently on if they hit refresh is an annoyance.

    • Ionuț Staicu
      Ionuț Staicu over 14 years
      Why do you want to change hash if you don't want to keep history track? :|
    • Admin
      Admin over 14 years
      Because on refresh it would be best to present the user with the tab they were on, but since they may be flipping back and forth between tabs, it would glut their history with entries unnecessarily, making the back button actually less useful. This is just an example, though--it could be for any time you need to save a temporary state but don't want to rely on cookies or fill the user's temp file with them. When you refresh, the js content is as you left it--you haven't left the page, and it's not a jump-to point or a psuedo-page, so the history entry can only interfere with standard nav.
  • Admin
    Admin over 14 years
    It's very possible there's something basic I'm missing (exhaustion's a nice excuse, I'll go with that) but are you saying I can set a variable that will retain its changed value on reload? Besides with a cookie? (Cookies seem overkill, somehow..) Maybe that's what wasn't clear. I will be using the hash value--particularly on reload. Thanks for responding!
  • Admin
    Admin over 14 years
    To clarify my clarification: if the user hits reload. That's what the hash is for. I'm still trying to avoid reload in their normal use (changing/clicking tabs).
  • guzart
    guzart over 14 years
    Ok, so you will be using some values for info after reloading. Well unfortunately, the hash value will get picked by some browser's history. Sorry to say this, but from my exp, cookies are your best bet. If you want something that the browser history doesn't detect, but to retain after reload, unfortunately, cookies. If the user was clicking a link, then you could setup the link to be a query (?mystate=greatness), even though it doesn't need to be ajax, you could save info for the javascript to read when initializing the request.
  • guzart
    guzart over 14 years
    Yes, the hash is for saving the user's info after hitting reload, but the problem for you situation, is that some browsers will save those changes in the history, that's just the way they work... :(
  • Admin
    Admin over 14 years
    Yep, think you're right. Ah well. (Would love to be proven wrong by some other method or something.)
  • guzart
    guzart over 14 years
    I was thinking that you could use the hash, then check the history, and if it was added remove it. But after some research, it seems that JS access to the history is limited for security reasons. So there is no way to remove info saved in the history.
  • Admin
    Admin over 14 years
    Agh, okay. Got too excited and started testing the wrong stuff. This won't work because refresh doesn't retain the tab state, which negates the point of using the hash to begin with. Very good idea though. Sad. Doesn't seem possible.
  • guzart
    guzart over 14 years
    Maybe that is browser specific. I tried in Firefox 3.6, Chrome 3.0.195, IE 8.0.76, Safari 4.0.4, Opera 10.10 and they all retain the hash after I hit refresh.
  • tedders
    tedders over 12 years
    This is it. And if you have uri segments, location.replace(window.location + "#hash") will preserve them.
  • joeellis
    joeellis about 12 years
    Seconding this method, much cleaner, wish it was marked as the correct answer.
  • jdeuce
    jdeuce almost 12 years
    Works for me in Chrome and Firefox. Note that it still inserts the history item in IE6 (see: splintor.wordpress.com/2007/04/12/…)
  • johnstorm
    johnstorm over 11 years
    window.location.replace(('' + window.location).split('#')[0] + '#' + hash); to just update the hash
  • Dan
    Dan over 11 years
    Had to use @johnstorm's solution to handle changing hash of iframe w/o logging to history.
  • Jörn Berkefeld
    Jörn Berkefeld almost 11 years
    @johnstorm for which browser did you need that? Matt's solution worked just fine in Chrome27 on Win7
  • Admin
    Admin almost 11 years
    Finally saw this, marked as correct answer. I think it could use an updated answer in terms of the HTML5, right?
  • TechAurelian
    TechAurelian over 10 years
    I'm testing it in Chrome 30 under Windows 8, if I go to Chrome History and select "More from this site" under my test url, I can see all the hashes that were added with this method.
  • Matt
    Matt over 9 years
    Totally the way to go for modern browsers; be aware of the partial support session history management has though.
  • Bram Vanroy
    Bram Vanroy about 9 years
    I'm confused as to how to use this. Should I still use window.location.hash = 'my-hash'; followed by history.replaceState(undefined, undefined, "#my-hash")?
  • Lucia
    Lucia about 9 years
    @BramVanroy No, using the latter is sufficient.
  • morphles
    morphles almost 8 years
    Unless you use :target selectors ... then history functions are useless, as that part of the spec (css interaction with history ops) seems to be not defined currently, and style does not get recomputed on history replace by most/all browsers.
  • Luis A. Florit
    Luis A. Florit over 7 years
    I don't think location.replace(url) is a solution if you need to load/change frames with different origins. Frames are blocked.
  • Tyler Kasten
    Tyler Kasten almost 7 years
    Beware that location.replace('#hash_value_here') only changes the hash fragment and not the path, so it doesn't trigger a page load.... Except when the document contains a base tag: <base href ="http://example.com/" /> If it does contain a base tag, then when you use the replace method with just a leading "#hash_value_here" it actually will be as if you said `location.replace('example.com/#hash_value_here'). This seem obvious when you read it here, but is a gotcha when you're on a page with a path fragment and don't realize base is set.
  • Pacerier
    Pacerier over 6 years
    @Luxiyalu, How does history.replaceState differ from location.replace?
  • Grief
    Grief about 5 years
    Just as a note: history.replaceState() and location.replace() still create entries in Chrome history which can be considered unacceptable in some cases: stackoverflow.com/questions/26793130/…
  • Matt
    Matt almost 4 years
    Note: interestingly, history.replaceState(...) does not trigger a window.onhashchange event. location.replace does. Weird, right?
  • George Birbilis
    George Birbilis over 3 years
    be careful with iframes, you need to specify the page too at the "replace", not just the # part
  • ZachB
    ZachB about 3 years
    @Matt that is mentioned in the spec: Since this is neither a navigation of the browsing context nor a history traversal, it does not cause a hashchange event to be fired.