Prevent window.onhashchange from executing a hash using JavaScript

I use the window.onhashchange function to execute code when the user changes the hash of the page:

window.onhashchange = function() { /* do something */ }; 

In some functions, I also set the hash via JavaScript:

 window.location.hash = "#abc"; 

I want the onhashchange event not to fire when I set the hash via JavaScript.

What I have tried so far:

 var currently_setting_hash = false; window.onhashchange = function() { if (currently_setting_hash) return; //... } currently_setting_hash = true; window.location.hash = "#abc"; currently_setting_hash = false; 

This did not work because the event was fired with a delay, so the code first sets the hash, then sets "current_setting_hash" to false, and then fires the onhashchange event.

Any ideas on how to do this? Or maybe there is a way to determine if the hash was set by the user or through JavaScript?

+4
source share
4 answers

You can reset the variable from the event handler itself:

 var currently_setting_hash = false; $(window).on("hashchange", function() { if (currently_setting_hash) { currently_setting_hash = false; return; } currently_setting_hash = false; //... }); currently_setting_hash = true; window.location.hash = "#abc"; 
+7
source

Since the event is delayed, there is a chance of events occurring in a different order than you expect (for example, imagine that the user changes the URL in other ways, either immediately before or after your code). It is important to make sure that you do not become inconsistent in believing that this is your event. So I have a suggestion (based on your code and Adam Bubela):

 var expectedHash; window.onhashchange = function () { if (window.location.hash === expectedHash) { return; } expectedHash = window.location.hash; // ... do actual reaction to change here ... } function changeHash(hash) { hash = canonicalizeHashValue(hash); expectedHash = hash; window.location.hash = hash; } // Helper - return the version of the URL that the browser is expected to // so that the equality test is accurate. function canonicalizeHashValue(value) { // Borrowing an A element ability to resolve/parse URLs. var tmp = document.createElement('a'); tmp.href = ""; tmp.hash = value; return tmp.hash; } 

This code will suppress the change handler only if the change is to the expected value . (Assigning inside onhashchange ensures that the handler also works if the hash temporarily moves to a different value, which, I believe, is more correct than the alternative.)

The third helper function canonicalizeHashValue is only needed for precision if you specify a non-canonical value, for example. changeHash('foo') instead of changeHash('#foo') .

+4
source

If you want to use just Java Script:

  var currently_setting_hash = false; window.onhashchange = function() { if (currently_setting_hash){ currently_setting_hash = false; return; //... } alert('outside the script'); } function changeHash(hash){ currently_setting_hash = true; window.location.hash = hash; } 
+3
source

Well, since the event is delayed, if you change the hash (for some reason) more than once, then more events fire on the line. In this case, you must increment the integer each time the hash changes.

 var setting_hash = 0; window.onhashchange = function() { if (setting_hash){ setting_hash--; return; } //code here } function changeHash(hash) {//hash without '#' if (hash!=window.location.hash.substr(1)) { setting_hash++; } window.location.hash = hash; } 
0
source

Source: https://habr.com/ru/post/1444125/


All Articles