0

I have a single page app (SPA) with search functionality where I am trying to track how users interact with the search bar in Adobe Analytics. If I navigate to 5 different "pages" of my SPA, the following code will fire the event 6 times. Seems the addEventListener is being set but not cleared if no search happens on a "page". These eventListeners essentially get queued each time a "page" loads, and once a search is entered, they all fire at the same time, clearing the queue.

How can I clear the eventListeners if a search is NOT performed and only have this event fire once a search is performed via pressing enter?

Suppose I have the code:

clearInterval(interval);
var interval = setInterval(function(){
    if (document.querySelector("form div[data-autoid='search_bar'] input")) {       
        inputField = document.querySelector("form div[data-autoid='search_bar'] input")
        inputField.addEventListener('keydown', searchEntered)
        clearInterval(interval);
    } 
}, 500);

function searchEntered(e) {
    if (e.key == "Enter") {
      console.log("search entered");
      var event = new CustomEvent('searchEntered');
     dispatchEvent(event);
    }
}
Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120

3 Answers3

1

If you want remove an existing event listener, use EventTarget.removeEventListener().

As the MDN page states, you need to specify the same type and listener parameters that you passed to addEventListener(). If you passed options, also, you should also pass the same ones to removeEventListener():

Given an event listener previously added by calling addEventListener(), you may eventually come to a point at which you need to remove it. Obviously, you need to specify the same type and listener parameters to removeEventListener(), but what about the options or useCapture parameters?

While addEventListener() will let you add the same listener more than once for the same type if the options are different, the only option removeEventListener() checks is the capture/useCapture flag. Its value must match for removeEventListener() to match, but the other values don't.

Note that is not possible to add multiple identical listeners to the same element. From MDN page:

If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and they do not need to be removed manually with the removeEventListener() method.

Community
  • 1
  • 1
terrymorse
  • 5,564
  • 1
  • 14
  • 19
0

If you add the event listener to window it will capture all keydown events on the page (delegate target) once that happens make a check to see if it was triggered by the Enter key and if the parentNode has the attribute data-autoid='search_bar'. If true dispatch your custom event.

This will continue to work even if the DOM changes

addEventListener('keydown', e => {
  if (e.key == 'Enter' && e.target.parentNode.dataset.autoid == 'search_bar') {
    console.log('search entered');
    const event = new CustomEvent('searchEntered');
    dispatchEvent(event);
  }
})
<div data-autoid='search_bar'> 
  Will trigger <input />
</div>

<label>
  Won't trigger <input />
</label>
Jakob E
  • 3,029
  • 1
  • 15
  • 16
0
var interval = setInterval(function(){
  var inputField = document.querySelector("form div[data-autoid='search_bar'] input");
  if (inputField && !inputField.dataset.searchEventAttached) {
    inputField.addEventListener('keydown', searchEntered);
    inputField.dataset.searchEventAttached = true;
  } 
  clearInterval(interval);
}, 500);
Igor
  • 15,444
  • 1
  • 22
  • 29