0

If I'm adding a form to my page dynamically (whether through AJAX or other JS), how can I add event listeners to those elements on pageload before they exist?

I know with jquery it's fairly easy to bind to a parent element, something like this:

$(document).on('blur', 'input', function() {...})

but I'm unclear on how to do this with vanilla JS as addEventListener must be applied directly to the element itself and can't specify the parent element for which the event should propagate? (I think, right..?)

Westwick
  • 2,367
  • 3
  • 28
  • 51
  • Well, `$(document).on(...)` binds the event to `document`. You'd do the same. All you have to do manually in the event handler is to check whether the event originates from an `input` element. – Felix Kling Sep 26 '16 at 18:14
  • 1
    You can do it in a similar way. You attach the listener to the `document` and check if the clicked target is the one you want and perform your action from there. – putvande Sep 26 '16 at 18:14
  • In this example I'm specifically looking for input blur, so if I `addEventListener` to document for the 'blur' event, won't that never fire? I need to specifically say, essentially, if an input within the document blurs, not the document itself. – Westwick Sep 26 '16 at 18:16
  • 1
    Thats how delegation works. Will work the same for the `blur` event. – putvande Sep 26 '16 at 18:18
  • The problem is `focus` and `blur` don't bubble in some browsers. jQuery patches this in. – Niet the Dark Absol Sep 26 '16 at 18:21
  • There's an answer in the duplicate question that shows how to do it with pure Javascript. – Barmar Sep 26 '16 at 18:21
  • Good point @NiettheDarkAbsol, that seems to be the problem I'm running in to. Although the `focusout` event seems to work the same. Any idea on differences between `blur` and `focusout` event, should work the same? – Westwick Sep 26 '16 at 18:27
  • Just to add to my answer below: focus/blur can be made to work if you make the "container" your attaching listener's to focus/blur-able (for example by sticking a tabindex on them). Please see the quicksmode blog on the subject :) – Carl Sep 26 '16 at 18:30
  • jQuery is still JavaScript so look into how it patches it. – putvande Sep 26 '16 at 18:39

3 Answers3

1

Here's how I would do it. Delegation is simple. Bound to the top parent. The closer, the better and faster. For example, if you want to delegate event in a specific div, that would be better; avoid conflict. Compare event.target with your target you're after, and call your callback function

document.addEventListener('blur', function(event){
  
  if(event.target.tagName == 'INPUT'){
      onInputBlur.apply(this, arguments);
  }

}, true);

function onInputBlur(event){
   
  // console.log(event); // event
  console.log(event.target.value);
  
}
<input type="text"/>
<input type="text"/>
<input type="number"/>
Adam Azad
  • 11,171
  • 5
  • 29
  • 70
0

You can add event listeners in vanilla js pretty easily, much like you normally would. Annoyingly focus/blur behave a little different to most events (See: http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html#link2 ) so to make this actually work you need to add a tab index to your container element.

document.querySelector(".container").addEventListener("blur", function(e){ 
   if(e.target.tagName == "input"){
      // do stuff
   }
},false);

A quick example of this in action https://jsfiddle.net/2n0v43gc/ (Edit: to see output, you need your console open (F12 on windows))

Carl
  • 1,816
  • 13
  • 17
0
function addEvent(a,b,c){
document.addEventListener(a,e=> {
      if (e.target !== e.currentTarget) {
      if(e.target.id==b){
      c();
      }
      }
      e.stopPropagation();
  },false);
  }

Use like this:

addEvent("click","elem",function(){});
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151