Preventing preventDefault() from firing in JQuery only when necessary

I have come up with a script that I recently created.

  <script>
    $(document).ready(function(){
      $('a').data('loop',true);
      $('body').on('click', 'a', function(event){
        console.log($(this).data('loop'));
        if ($(this).data('loop') == 'true') {
          console.log('hit');
          event.preventDefault();
          caller = $(this);
          $(this).data('loop',false);
          var linkref = $(this).attr('href');
          var linkpos = $(this).offset();
          var screenwidth = $(window).width();
          var json_data = JSON.stringify({linkref: linkref, linkpos: linkpos, screenwidth: screenwidth});
          $.ajax({
            url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
            method: "POST",
            data: "json=" + json_data,
            complete: function (jqXHR, status) {
              console.log(status);
              console.log(caller);
              $(caller).click();
            }
          });
        } else {
          console.log(event.isDefaultPrevented());
          console.log('miss');
          $(this).data('loop',true);
        } 
      });
    });
  </script>

The script works perfectly and provides me with the information I need. However...

When I click on a link, it sends the details via Ajax as expected, but the link does not redirect to its destination page. This seems to be happening because of the event.preventDefault() line.

If I remove the event.preventDefault(); line, then everything works as intended.

It appears that event.preventDefault is being triggered even during the second call, causing the normal action of the event not to occur.

Apologies if this explanation is a bit complex. I am also trying to figure out what could be causing this issue. Is it a bug or something specific in my code?

To help understand the situation better, I have created a jsfiddle: https://jsfiddle.net/atg5m6ym/2001/

Answer №1

If you're tired of dealing with the "loop" issue, try this solution:

$(document).ready(function () {
    $('body').on('click', 'a', function (event) {
        event.preventDefault();
        var caller = $(this);
        var linkref = $(this).attr('href');
        var linkpos = $(this).offset();
        var screenwidth = $(window).width();
        var json_data = JSON.stringify({linkref: linkref, linkpos: linkpos, screenwidth: screenwidth});
        $.ajax({
            url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
            method: "POST",
            data: "json=" + json_data,
            complete: function (jqXHR, status) {
                console.log(status);
                console.log(caller);
                window.location.href = linkref; // Redirect happens here
            }
        });

    });
});

UPDATE

Here are a few important notes:

1) Some links may not need redirection, such as bootstrap model links or internal document anchors.

To address this, it's best to identify specific classes or data attributes added by Bootstrap to these links like so:

$('body').on('click', 'a:not(list of things to exclude)'..

In my opinion, I would define tracked links like this:

<a href=<link> data-tracked='true'...

<script> 
      $('body').on("click","a[data-tracked='true']"...

Alternatively, if you want to track most links but exclude a few, you can do:

     <a href=<link> data-tracked='false'...
     <script> 
          $('body').on("click","a:not([data-tracked='false'])"...

Or in a more general approach:

 <script> 
      $('body').on("click","a", function () {
            if ($(this).attr("data-tracked") == "false" || <you can check more things here>){ 
                  return true; //Click passes through
             } 
             //Rest of the tracking code here
      });

Answer №2

In the code snippet below, the if statement will evaluate to true if the data-loop attribute is present on an element, regardless of its content:

if ($(this).data('loop')) {

To check for a specific value, modify it as follows:

if ($(this).data('loop') == 'true') {

It is important to compare the attribute value as a string since all attributes are considered strings in JavaScript.

Answer №3

Event.preventDefault() isn't running the second time it's called.

When the method is complete, redirection takes place. In this scenario, redirection occurs once the complete method of the ajax call is finished.

Imagine having two objects in the code: event1 and event2. Event1 represents the object in the ajax call method, while event2 represents the event object in the recursive call (second call) method.

Therefore, when a link is clicked for the second time, the complete method still needs to run. When the code returns to the complete method of the ajax call, it recognizes that event1 has the property preventDefault true, preventing the redirect from happening.

Answer №4

Give this a try ;)

$(document).ready(function(){
  $('body').on('click', 'a', function(event){
    event.preventDefault();

    var caller = $(this);
    var linkref = $(this).attr('href');
    var linkpos = $(this).offset();
    var screenwidth = $(window).width();

    var json_data = JSON.stringify({
      linkref: linkref,
      linkpos: linkpos,
      screenwidth: screenwidth
    });

    $.ajax({
      url: "content/submitcontenthandler?handler=core/_dashboard&method=tracking_ping",
      method: "POST",
      /* Use async: false to temporarily block the browser */
      async: false,
      data: "json=" + json_data,
      complete: function(jqXHR, status){
        /* Add the class **ignore** to an element you don't want to redirect (tabs, modals, dropdowns, etc) */
        if(!caller.hasClass('ignore')){
          /* Redirect occurs here */
          window.location.href = linkref;
        }
      }
    });

  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to modify an object similar to manipulating an array collection

Hey there, I've heard that iterating and editing objects (not arrays) is not the best practice. Is there a more efficient way to do it as easily as it can be done with an array of objects? Check out this link for reference new Vue({ el: '#app ...

Reload the MEN stack webpage without the need to reload the entire page

I am in the process of developing a data analytics dashboard using the MEN stack (MongoDB, Express.js, Node.js). I have successfully implemented functionality to display real-time data that refreshes every 5 seconds without the need to reload the entire ...

Issue with OnClientClick functionality not functioning as expected

I am having trouble with the validation function that is supposed to be triggered when clicking on the back and next buttons in my code. For some reason, the OnClientClick validation function is not being called when I click on the buttons. Can anyone pro ...

Waiting for an Element to Become Visible in Selenium-Webdriver Using Javascript

When using selenium-webdriver (api docs here), how can you ensure that an element is visible before proceeding? Within a set of custom testing helpers, there are two functions provided. The first function successfully waits for an element to exist, howeve ...

Developing Attributes in JSON

Greetings stackOverflow Community, I'm struggling a bit with creating JSON objects. I have code snippet that is meant to populate a list called members with names, and then add a property to each of those names. Here is the specific snippet in questi ...

Discovering the reason behind a DOM element's visual alteration upon hovering: Where to start?

Visit this page, then click on the next button to navigate to the time slots section. As you hover over any time slot, you will notice a change in appearance. Despite inspecting Chrome's developer tools, I was unable to locate a style with a hover dec ...

VIDEOJS ERROR: A peculiar mistake has occurred. TypeError: The property 'value' cannot be read since it is undefined in the context of

Recently, I came across a fascinating plugin called videojs-thumbnails for video.js, and I'm eager to incorporate it into my angular component. However, I keep encountering an error that says: VIDEOJS: ERROR: TypeError: Cannot read property 'val ...

Is it possible to conceal and completely empty the TextBox once the checkbox is deselected?

When the checkbox is checked, the textbox is displayed; otherwise, it remains hidden. However, the value is not being cleared. Can someone please help me with this issue? Thank you in advance. HTML <div class="munna"> <in ...

Displaying a variable in a live HTML user interface

I have successfully created a Python program that captures data from an Arduino Potentiometer and shows it on the Python console. Now, I am working on enhancing the output by displaying it in a local HTML file. I am seeking guidance on how to incorporate t ...

Looking for help understanding a basic piece of code

$('#ID').on('click', function() { if(!CommonUtil.compareDateById('startDt','endDt',false, false, true)) { return false; } var cnt = 0; if(!CommonUtil.isNullOrEmptyById('startD ...

The POST function is executed twice, with the first attempt resulting in a failed API call, but the second attempt is

I am experiencing issues with my subscribe dialog, as it seems to be running the API call twice. The first time it fails, but on the second attempt, it succeeds and inserts the email into the database. This double run is causing errors in my AJAX function, ...

Autocomplete fails to recognize any modifications made to the original object

I am currently utilizing the jQuery library's autocomplete() method on a text input field, setting Object.getOwnPropertyNames(projects) as the source: $(function() { $("#project").autocomplete({source: Object.getOwnPropertyNames(projects)}); } B ...

Deactivating the drag feature when setting the duration of a new event in FullCalendar

Hello there! I've integrated full calendar into my Angular project and I'm facing a challenge. I want to restrict users from defining the duration of an event by holding click on an empty schedule in the weekly calendar, where each date interval ...

Can Jquery be utilized to signal a language change?

I'm working on my portfolio website that will be available in two languages, Thai and English. I have successfully implemented language buttons for changing between the two languages. However, I am facing an issue with the language selection when nav ...

The useCallback hooks persist outdated values when the list is refreshed

Why am I not getting the expected values every time the function onRefresh is called using Hooks? Example when onRefresh is called twice: Expected values: true 0 20 false true 0 20 false Received values: false 0 0 false false 20 20 false Initial st ...

What could be the reason for REQ.BODY being consistently devoid of any

I understand that there are already several solutions marked as working, but I am struggling to get it to work in my specific case. Please refrain from marking it as answered. Here is the scenario I'm facing: AJAX CLIENT-SIDE var data ={}; data.test ...

Fade the colors of the jQuery UI slider handle before it's clicked

I am looking to enhance the visibility of my vertical slider created with Jquery UI by changing its color until it is clicked for the first time. However, I am struggling to identify the correct element to modify. My attempted solution involves using the ...

Optimizing Your HTML/CSS/JavaScript Project: Key Strategies for Modular

When it comes to web frontend projects (html/css/javascript), they are often perceived as more complex to read and maintain compared to Java/C#/C/C++ projects. Is it possible to outline some optimal strategies for enhancing the readability, modularizatio ...

What is the best way to modify the state of an array of objects by applying a filter in Vue 3?

I am currently facing an issue with a component that is listening for an emit and then attempting to filter out a user with a specific userId from the users state. The challenge lies in the fact that assigning filteredUsers to users does not appear to be ...

Limitations of GitHub's rate limiting are causing a delay in retrieving user commit history

I have developed a code snippet to retrieve the user's GitHub "streak" data, indicating how many consecutive days they have made commits. However, the current implementation uses recursion to send multiple requests to the GitHub API, causing rate-limi ...