How to use jQuery's on(..) to dynamically bind to multiple events

21,351

Solution 1

$('a.js-test').on('click mouseover', function(event) {
  // you can get event name like following
  var eventName = event.type; // return mouseover/ click
  console.log(eventName);
  // you code
  console.log('Hello, World!');
});

Sample example

If you want something like live event then:

$('body').on('click mouseover', 'a.js-test', function(event) {
  // you can get event name like following
  var eventName = event.type; // return mouseover/ click
  console.log(eventName);
  // you code
  console.log('Hello, World!');
});

According to your last edit try this:

$('.js-test').on($('.js-test').data('test-events'), function() {
    console.log("hello world!")
});

Sample example for edit

and for live event delegation

$('body').on($('.js-test').data('test-events'), '.js-test', function() {
    console.log("hello world!")
});

Solution 2

Afraid you can't do this because you need to provide jQuery with either DOM elements or event names. You can bind events to new DOM elements manually or bind all possible events that can be in data-test-events (if you have 3-5 of them, with all DOM events it will become a silly and slow solution) and check if your element has one of them:

$('body').on("mouseover click mouseout mouseenter mouseleave", '.js-test', function(e) {
    if (!$.inArray(e.type, $(this).data('test-events').split(' '))) {
        return;
    }
    console.log("hello world!");
});​
Share:
21,351
empire29
Author by

empire29

Updated on July 22, 2022

Comments

  • empire29
    empire29 almost 2 years

    I am trying to create leverage jQuery's .on() (ex-live()) to bind multiple events. It is working for elements which exist on document.ready, but if i dynamically add a second link after page load, my event handler isn't triggered.

    This makes sense since the outer-most method iterates over the elements, and doenst listen for newly added DOM nodes, etc. The .on(..) is what listens for new DOM nodes, but requires an event name params, which I dont have until I have the DOM node.

    Seems like a chick and the egg sort of situation.

    Thoughts?

    <a href="/foo.html" class="js-test" data-test-events="['click', 'mouseover']">Test 1</a>
    <a href="/foo.html" class="js-test" data-test-events="['mouseout']">Test 2</a>
    
    $(function() { 
        $('.js-test').each(function() { 
            var $this = $(this);
            var e, events = $this.data('test-events');
    
            for(e in events) {
                $this.on(events[e], function() {
                    console.log("hello world!")
                });
            }
        });
    }); 
    

    Update, The following does seem work either; $(this) doesnt appear to be in the right scope.

    <a href="/foo.html" class="js-test" data-test-events="click mouseover">Test 1</a>
    <a href="/foo.html" class="js-test" data-test-events="mouseout">Test 2</a>
    
    $(function() { 
        $('.js-test').on($(this).data('test-events'), function() { 
            // call third party analytics with data pulled of 'this'
        });
    });     
    

    Update 1:

    I think my best bet will be to create special .on methods for all the methods I want to support like so:

    $(document).on('click', '.js-test[data-test-events~="click"]' function(event) {
        record(this, event);
    });
    
    $(document).on('mouseover', '.js-test[data-test-events~="mouseover"]', function(event) {
        record(this, event);
    });
    
     ... etc ...