javascripthtmlhttp-redirectwindow.location

How to redirect after click on download link if onclick already used?


I have the following (partial) code:

<input type="checkbox" id="myCheck">
span class="checkmarkz"></span>

<a href="test.zip" class="download" onclick="return ifchecked()">One-time download!</a>

<script>
        function ifchecked() {
            if (document.getElementById('myCheck').checked) {
                return true;
            } else {
                let warning = document.getElementById('warning');
                warning.style.display = "block";
                return false;
            }
        }
</script>

I would need that after the download, the user is redirect to success.php.

NOTE: I know there are other questions were users ask for redirect after download link, but in this case I have already onclick="return ifchecked()", then I don't know how to or where I could add a redirect since I need to check the checkbox first. Please consider this before giving me -1 or -2 or -3. Please be kind. Thank you.


Solution

  • Don't use inline HTML event attributes in the first place as this is a 25+ year old event wiring technique that just will not die because people just keep copying other people's code.

    Instead, use the modern approach, which is .addEventListener(). With this method, you can register multiple event listeners to the same event and the listeners will fire in the order that you've registered them.

    Here's an example:

    const btn = document.querySelector("button");
    
    btn.addEventListener("click", foo1); // Register 1st handler
    btn.addEventListener("click", foo2); // Register 2nd handler
    btn.addEventListener("click", foo3); // Register 3rd handler
    
    function foo1(){
      console.log("foo1");
    }
    
    function foo2(){
      console.log("foo2");
    }
    
    function foo3(){
      console.log("foo3");
    }
    <button type="button">Click Me</button>

    But, in your use case, you don't seem to need multiple callbacks. You'd do something like this:

    // Get DOM references just once, not everytime the function runs
    const label = document.querySelector("label");
    const chk = document.getElementById('myCheck');
    const warning = document.getElementById('warning');
    const link = document.querySelector(".download");
    const success = document.querySelector("#success");
    
    // Set up the event callback
    link.addEventListener("click", ifChecked);
    
    function ifChecked(event) {
      event.preventDefault();  // Cancel the click event on the link
      
      // Check to see if the checkbox is checked
      if (chk.checked) {
        link.click();  // Begin the download
        warning.classList.add("hidden");    // Hide the warning
        label.classList.add("hidden");      // Hide the checkbox and link
        success.classList.remove("hidden"); // Show the success message
      } else {
        warning.classList.remove("hidden");  // Unhide the warning
        chk.focus();   // Set the focus on the checkbox
      }  
    }
    .hidden { display:none; }
    <label>
      <input type="checkbox" id="myCheck">
      <a href="test.zip" class="download">One-time download!</a>
    </label>
    <span id="warning" class="warning hidden">You must agree by checking the checkbox.</span>
    <span id="success" class="hidden">Congrats!</span>

    Keep in mind that this code won't actually prevent someone from downloading the file more than once if they really want to. All they'd have to do is look at the source code of the page and see the path and file name of the download file and then manually navigate to that location. If you really want to secure the file, you'd need some kind of server-side validation.