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

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 doesn't listen for newly added DOM nodes, etc. The .on(..) is what listens for new DOM nodes, but requires an event name params, which I don't have until I have the DOM node.
Seems like a chick and the egg sort of situation.
Thoughts?
Test 1
Test 2
$(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) doesn't appear to be in the right scope.
Test 1
Test 2
$(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 ...

$('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!")
});

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!");
});​

If you want to trigger an event whenever a matching element is added to the DOM, you might want to have a look at livequery - http://docs.jquery.com/Plugins/livequery.

This code will allow you to register multiple event handlers as a function array. It's tested and working. See this jsfiddle demo and test cases.
JavaScript:
$(document).ready(function() {
eventFnArray = [];
eventFnArray["click"] = function(e) {
if(e.type != "click") return ;
alert("click event fired - do xyz here");
// do xyz
};
eventFnArray["mouseover"] = function(e) {
if(e.type != "mouseover") return ;
alert("mouseover fired - do abc here");
// do abc
};
eventFnArray["mouseout"] = function(e) {
if(e.type != "mouseout") return ;
alert("mouseout fired - do JKL here");
// do JKL
};
$('.js-test').each( (function(fn) {
return function(i) {
if(i != 0) return;
var _that = this;
var events = [];
events = $(_that).attr("data-events").split(" ");
// alert($(_that).attr("data-events") + " : " + events.join(" "));
$(this).parent().on(
events.join(" "),
'.js-test',
function() {
console.info("hello - this is the " + event.type + " event");
// alert("data-events = " + $(this).attr("data-events") + " : event.type = " + event.type);
// delegate to the correct event handler based on the event type
if($(this).attr("data-events").indexOf(event.type) != -1)
fn[ event.type ](event);
}
);
}
})(eventFnArray)); // pass function array into closure
});
HTML:
<div id="container">
Test 1
Test 2
</div>
Testing adding more elements:
Here are 3 test cases:
// adds a link with the click event attached.
$('#container').append("<a href='#' class='js-test' data-events='click'>TEst333</a>");
// adds a link with the mouseover event
$('#container').append("<a href='#' class='js-test' data-events='mouseover'>TEst444</a>");
// adds a link with mouseout
$('#container').append("<a href='#' class='js-test' data-events='mouseout'>TEs555</a>");
// adds a link with both mouseover and mouseout attached
$('#container').append("<a href='#' class='js-test' data-events='mouseout mouseover'>TEstLast</a>");
// mouseout and click
$('#container').append("<a href='#' class='js-test' data-events='mouseout click'>TEstLastForREAL</a>");
Word of caution:
I noticed that one of your links has both the click and mouseover attached. While this code will handle multiple events per link, as demonstrated by the last test case, the click event will not fire if a mouseover event is present.
This is not a fault in the above code but in the way events are processed, as demonstrated here:
// mouseover and mouseout fire, but not the click event
$('#container').on('mouseover mouseout click', '.js-test',function() { alert("afdas " + event.type); });

Related

onclick event: select item to be clicked by id

I have a button with name="testo_da_inviare" and I can trigger it's click event with:
document.forms['form_da_ricordare'].elements['testo_da_inviare'].onclick
Now I want to replace the button element with an a element that doesn't support the name attribute. So I gave the a element the id="testo_da_inviare"
How do I have to edit my js to trigger the onclick? Javascript is not my cup of tea and I am still learning how to use plain javascript.
You can use getElementById to select it:
document.getElementById('testo_da_inviare').onclick
If you want to fire an event of an element, the right way is to use dispatch method or createEventObject, not to call the element handler name
var eventName = "click";
var element = document.getElementById("testo_da_inviare");
if (document.createEventObject) {
// Dispatch for IE
var evt = document.createEventObject();
element.fireEvent("on" + eventName, evt);
}
else {
// Dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
// Event type, bubbling, cancelable
evt.initEvent(eventName, true, true);
element.dispatchEvent(evt);
}
1- You can let the onclick event trigger on the link/button itself like this:
description
<button onclick="thefunct()">description</button>
function thefunct() {
alert("button clicked");
}
2- Or on the script like this:
document.getElementById("id").onclick = function thefunct(){ alert('button clicked'); };
3- Or using an eventlistener like this:
document.getElementById("id").addEventListener("click", thefunct);
function thefunct() {
alert('button clicked');
}
4- Or using jQuery like this:
$("#id").click(function(){
alert('button clicked');
});
<script src="http://code.jquery.com/jquery-2.2.1.min.js"></script>

Turn on() event back after apply off

How can I turn an on('click') event back on after I apply event off()?
$('#btn-aluno').on('click', function() {
$('.new-step-email-aluno').toggle();
$('#btn-familiar').off();
});
$('#btn-familiar').on('click', function() {
$('.new-step-email-familiar').toggle();
$('#btn-aluno').off();
});
new-step-email-familiar and new-step-email-aluno = <input>
btn-aluno and btn-familiar = <span> (used as a button)
Instead of turning off the event listener, you could do the same thing by using event delegation,
$(document).on('click',"#btn-aluno.active", function() {
$('.new-step-email-aluno').toggle();
$('#btn-familiar').removeClass("active");
});
$(document).on('click',"#btn-familiar.active", function() {
$('.new-step-email-familiar').toggle();
$('#btn-aluno').removeClass("active");
});
And whenever you want to activate the event listeners, just add the class active to the relevant elements. Also in the place of document try to use any closest static parent of the element on which the event gonna be bound.
As per your requirement, you have edit your logic like below,
$(document).on('click',"#btn-aluno.active", function() {
$('.new-step-email-aluno').toggle();
$('#btn-familiar').toggleClass("active");
});
$(document).on('click',"#btn-familiar.active", function() {
$('.new-step-email-familiar').toggle();
$('#btn-aluno').toggleClass("active");
});
DEMO

Why is click event handler for a submit button in a colorbox defined in a jQuery prototype method not invoked

I have added a function to jQuery prototype as below. What I want to do is when this method is invoked, generate an html form based on the arguments passed to the method and show it in a colorbox.
(function($) {
$.fn.myFunction = function(data){
var form = $('<form name="people"></form>');
var index;
for (index = 0; index < data.length; index++) {
var match = data[index];
$('<input type="radio" name="person">' + match['name'] + ' [' + match['uri'] + ']<br> ')
.attr("value", match['uri'])
.appendTo(form);
}
$('<input type="button" id="a_button" value="Add"/><br>')
.appendTo(form);
var list = $('<div>').append(form).html();
$('#a_button').click(
function(){
console.log('message from event handler');
}
);
$.colorbox({ innerWidth:420, innerHeight:315, html: list });
};
})(jQuery);
As you can see, form has a button called Add using which I hope to make an ajax request. But unfortunately click event handler attached to this button doesn't seem to be invoked.
Does anyone have any idea about what's wrong here? myFunction is actually invoked by a drupal ajax command in case if that's helpful.
You are appending the form to the DOM after attaching the event handler.
$('#a_button') searches the DOM at that specific point in time, but the form is not added to the DOM until after your call to colorbox with list as a parameter.
Try a permanent delegated event handler instead (or simply add the click handler after the colorbox line).
e.g.
$(document).on("click", "#a_button", function(){
console.log('message from event handler');
});
or
$.colorbox({ innerWidth:420, innerHeight:315, html: list });
$('#a_button').click(
function(){
console.log('message from event handler');
}
);

Trigger click event on DOM element

I tried to trigger a click event on an selected DOM element but my code won't work.
You can see my attempt on JSFiddle.
<ul class="list-group">
LG GOLA 8M
LG 5-6M
LP 5-6M
</ul>
$(document).ready(function() {
// I get the string tr from URL parameters
var tr = "fix_LG%20GOLA%208M";
if (tr !== null) {
var terminrahmen = $('.list-group-item').filter(function() {
return $(this).text() === decodeURI(tr).substring(4);
});
// Trigger click event on .list-group-item
terminrahmen.click();
}
// The function to be executed
$('.list-group-item').click(function() {
alert($(this).text());
});
});
When the DOM was loaded I collect some data from URL parameters and compare the data with DOM elements. This part works fine.
After that I get an element and I would like to trigger an click event. The click event should "execute" a specified function.
Have anyone a good solution for me? Thanks in advance.
http://jsfiddle.net/azg2R/2/
Put the click event on top in the ready event.. The click event needs to be triggered after registering the event. It was not happening before
$(document).ready(function() {
// The function to be executed
$('.list-group-item').click(function() {
alert($(this).text());
});
// I get the string tr from URL parameters
var tr = "fix_LG%20GOLA%208M";
if (tr !== null) {
var terminrahmen = $('.list-group-item').filter(function() {
return $(this).text() === decodeURI(tr).substring(4);
});
// Trigger click event on .list-group-item
terminrahmen.click();
}
});
The problem is that you are triggering click event before attaching event handler to it. So you just need to move click handler before triggering click and everything would work as you expected:
$(document).ready(function() {
// The function to be executed
$('.list-group-item').click(function() {
alert($(this).text());
});
// I get the string tr from URL parameters
var tr = "fix_LG%20GOLA%208M";
if (tr !== null) {
var terminrahmen = $('.list-group-item').filter(function() {
return $(this).text() === decodeURI(tr).substring(4);
});
// Trigger click event on .list-group-item
terminrahmen.click();
}
});
JSFiddle

How can I attach event to a tag which is in string form?

I'm creating html on runtime like this:
var myVar = "<div id='abc'>some clickable text</div>"
Now, I want to attach some event, say onclick, to this div. How can I do that on next line? I'll add this to DOM later.
PS: I've to accomplish this without using JQuery.
Instead of building your div as a string, you'll want to use document.createElement('div'). This way you will have a real dom object, and can get and set it's propeties, including onClick
Will this help? Since you dynamically generate it, you know the control id of the DIV.
document.getElementbyId('abc').onClick = foo;
function foo()
{
alert("All your impl to go here");
}
Try building the div as a DOM element first.
var myVar = document.createElement("div"),
parentDiv = document.getElementById("parent_div");
parentDiv.appendChild(myVar);
myVar.innerHTML = "some clickable text";
if(myVar.addEventListener){
myVar.addEventListener("click", clickFn, false);
}
else if(myVar.attachEvent){
myVar.attachEvent("onclick", clickFn);
}
else{
myVar.onclick = clickFn;
}
The addEventListener method is standard, but not every browser plays nice with the standard.
EDIT: As mentioned, an element must be added to the DOM first.
Or you can use this technique: attach event to the document.body. Then if the event target is not the needed div than just do nothing. It is the same techinque jquery uses for its live function:
// crossbrowser event attachment function
function listen(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt, func, false);
}
else if (elem.attachEvent) {
var r = elem.attachEvent("on" + evnt, func);
return r;
}
else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
}
// this is an analog of the jquery.live
var assignLiveEvent = function(id, evnt, callback) {
var handler = function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.id == id) {
//your code here
callback(e);
}
};
listen(evnt, document.body, handler);
};
var myVar = "<div id='abc'>some clickable text</div>";
assignLiveEvent("abc", "click", function(e) {
//your code here
});
// now you can add your div to DOM even after event handler assignation
Here is demo.
Brian Glaz is totally right but, if for some reason, you really need to do it this way, you have two options:
you can only add events to something that is already in the DOM, using pure javascript, so you would have to include it in the html like:
document.body.innerHTML += myVar;
and then, attach the event with
document.getElementById('abc').addEventListener('click', function(e){
//your code
}, 1);
With jQuery, you could use .live() to attach events to elements that are not yet present in the DOM:
$('#abc').live('click', function(e){
//your code here
});
so you could add the div later...

Categories

Resources