javascripthtmldom-eventshashchange

Is it possible to capture the window.location.replace event?


If I'm currently at the URL"example.com/somepage#somehash" and I invoke window.location.hash = "anotherhash", the URL changes to "example.com/somepage#anotherhash". This fires the window.hashashchange event.

If I am currently at the URL "example.com/somepage?a=1&b=two" and I invoke window.location.replace("?one=1&two=2"), then the URL changes to "example.com/somepage?one=1&two=2".

I've read the MDN docs, and I can't find an even that this fires.

  1. Is there one?
  2. If not, is there a simple way to capture that event?

Note:

It's my fault for saying that I want to make sure I don't trigger a page reload. I want to use the new URL for updating the page based on the query string, for example with an AJAX request. window.history.pushState is another option, but as far as I can tell, it does not fire an event either.

Edit

I took a look at @Taki's answer. I create a repl.it because you can see the URL change when you go to the full-page view. However, even with the preventDefault the page is reloading, which is proved by the fact that the info posted to the page in the unload event callback disappears. Consequently, this can't be used for client-side routing, which is my goal.

index.html

<button id="myBtn">Click me</button>
<div id="info"></div>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="index.js"></script>

index.js

console.log("index.js");

$('#myBtn').on('click', function(e)
{
  console.log("button clicked")
  window.location.replace("?one=1&two=2")
  console.log(window.location.href);
});

$(window).on("beforeunload", function (event) 
{
  event.preventDefault(); // just to pause and see the cosdole
  console.log("beforeunload");
  console.log(event);
  $('#info').append("<p>beforeunload</p>");
  console.log(window.location.href); // capture the url
});

Solution

  • window.location.replace acts like a redirection, so you can listen for the BeforeUnload event

    The Location.replace() method replaces the current resource with the one at the provided URL

    ( don't know why it can't replace the window.location in the snippet :P but it'll work outside it )

    document.querySelector('#myBtn').addEventListener('click', function(){
      window.location.replace("?one=1&two=2")
    });
    
    window.addEventListener("beforeunload", function (event) {
    
      console.log(window.location.href); // capture the url
      event.preventDefault(); // just to pause and see the condole
      
    });
    <button id="myBtn">Click me</button>

    EDIT :

    apparently you can't prevent the page from reloading when changing location.href , but like you mentioned, you can use history.pushState and if it doesn't fire an event, create a custom one, attach it to the window and listen for it :

    let evt = new CustomEvent('myEvent', ...
    window.dispatchEvent(evt); 
    
    ... 
    
    window.addEventListener('myEvent', function(e){ ...
    

    this time it's working inside the snippet, see that it's not reloading and you get to keep urls in the history and you get your location

    document.querySelectorAll('a').forEach(function(elem){
    		
      elem.addEventListener('click', function(e){
    			
        e.preventDefault();
        window.history.pushState("object or string", "Title", this.href);
    				
        let evt = new CustomEvent('urlChange');
        window.dispatchEvent(evt);
    				
      });
    			
    }); 
    
    window.addEventListener('urlChange', function(e){
      document.querySelector('#myUrl').innerHTML = window.location.href;
    });
    #myUrl{
      display: block;
      font-size: 20px;
      margin-top: 20px;
    }
    <h1>hello</h1>
    <a href="/one">Got to One</a><br />
    <a href="/two">Got to Two</a><br />
    <a href="?three=3">Got to Three</a><br />
    
    <span id="myUrl"></span>