Passing function and function argument in .on('click') event handler? [duplicate] - javascript

This question already has answers here:
How can I pass arguments to event handlers in jQuery?
(6 answers)
Closed 6 years ago.
When I click on the button it will say Bruce Wayne is Batman. In the last jQuery line, for the 'click' function, if I pass the parameter 'guy', the jQuery wont run, but if I don't pass in a parameter I get undefined. What am I doing wrong? Thanks in advance.
$("div").on('click', 'button', click(guy));
The jsFiddle link, HTML and JS are below.
https://jsfiddle.net/wrj5w1Lk/
<div>
<button>
Click Me! Click Me!
</button>
<p>Hello</p>
</div>
$(document).ready(function() {
var Person = function(first, last, secret) {
this.first = first;
this.last = last;
this.secret = secret;
}
var guy = new Person("Bruce", "Wayne", "Batman");
var click = function(person) {
$(this).closest('div').find('p').text(person.first + " " + person.last + " is " + person.secret);
};
$("div").on('click', 'button', click(guy));
});

You have two issues, firstly you need to wrap the call to click() in an anonymous function. Secondly you need to pass the reference of the current button element to your click() function. Try this:
var click = function($element, person) {
$element.closest('div').find('p').text(person.first + " " + person.last + " is " + person.secret);
};
$("div").on('click', 'button', function() {
click($(this), guy);
});
Updated fiddle

I think what you're looking for is how to pass custom data to the event handler using .on(). The link references the optional [ data ] object of the .on() function. This allows you to pass custom data outside of the normal event data to your event handler for further processing. An example is shown below:
$(document).ready(function() {
var Person = function(first, last, secret) {
this.first = first;
this.last = last;
this.secret = secret;
}
var guy = new Person("Bruce", "Wayne", "Batman");
var click = function(event) {
$(this).closest('div').find('p').text(event.data.first + " " + event.data.last + " is " + event.data.secret);
};
$("div").on('click', 'button', guy, click);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button>
Click Me! Click Me!
</button>
<p>Hello</p>
</div>
I've edited your snippet from your question to use this method of passing data. Your custom object is passed in the event.data object of the callback. By accessing, event.data.[first,last,secret] you can reference the properties of the Person(...) object from within your callback.

Related

Get element id using element class

I'd like to get the id of the pressed element.
I know it's a very common question but I do not want a solution in jquery (I'm trying to use it as few as possible)
I cannot modify the html, supposing is something like:
<p id='123' class='my_class'>x</p>
I cannot create something like:
<p id='123' class='my_class' onclick='console.log(this.id + " pressed");'>x</p>
This is my personal attempt:
$(document).on('click', '.my_class', this.id, function (id) {
console.log( id + " pressed!");
});
But I keep obtaining this:
[object Object] pressed!
var elems = document.getElementsByClassName("my_class");
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener('click', function() {
console.log(this.id + " pressed");
});
}
Here is solution without jquery.
You are almost right. Use the below code:
$(document).on('click', '.my_class', function () {
console.log( this.id + " pressed!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='123' class='my_class'>x</p>
Explanation
You should not be sending the third argument with this as it is not contextual. The syntax of the .on is:
.on( events [, selector ] [, data ], handler )
You can completely ignore the third option and that doesn't matter. Always, inside the function, the this will point to the current element, the event is triggered on.
And in your code, you are passing id as the parameter to the call back function, which is the event (EventObject). That's why you got [Object object].
Hope it makes sense.
id in the arguments points to the event object, make it
$(document).on('click', '.my_class', this.id, function (id) {
console.log( id.target.id + " pressed!");
});
or
$(document).on('click', '.my_class', this.id, function (e) {
console.log( e.target.id + " pressed!");
});

How to loop over an array and add jQuery click events? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
I'm trying to loop over a simple array, find elements based on the array values, and then add a click event for each element. For some reason (maybe related to the scope?) all the events think they're at the end of the array.
Example HTML:
<!-- "Sectors" -->
<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>
Corresponding javascript:
var sectorArray = ["a", "b", "c"];
// Loop over sector letters
for (var s in sectorArray) {
var sector = sectorArray[s];
console.log("Adding click event for sector: " + sector);
$('div.' + sector).on("click", function(e){
console.log("Clicked sector: " + sector);
});
}
When I click on any div, I get the message that I'm on sector "c". Here is a jsfiddle: http://jsfiddle.net/luken/Pd66m/
I was able to fix the problem by making everything inside the for-loop into it's own, separate function... and there are other solutions... But I'd like to figure out why this, above, won't work. Thanks.
closure issue, try this. I added an anonymous function to "enclose" loop values.
var sectorArray = ["a", "b", "c"];
// Loop over sector letters
for (var s in sectorArray) {
var sector = sectorArray[s];
(function(sec){
$('div.' + sec).on("click", function(e){
console.log("Clicked sector: " + sec);
});
}(sector))
}
Another way with pure js, by adding a closure:
for (var s in sectorArray) {
(function(s){ //This line creates a 'per loop cycle' s var
var sector = sectorArray[s];
console.log("Adding click event for sector: " + sector);
$('div.' + sector).on("click", function(e){
console.log("Clicked sector: " + sector);
});
})(s); //Calls the function
}
This way the inner s is not 'shared' and each loop cycle will have its own copy, so it does not get overwritten.
Hope this helps. Cheers
It is a known issue with using closure in a loop
$.each(sectorArray, function (i, sector) {
console.log("Adding click event for sector: " + sector);
$('div.' + sector).on("click", function (e) {
$selection.html(sector);
console.log("Clicked sector: " + sector);
});
})
You can also make a function which returns the the event handler function, pass in the sector and execute it immediately like this:
$('div.' + sector).on("click",
function(sec){
return function(e) {
console.log("Clicked sector: " + sec);
};
}(sector)
);

See what events are linked to the element in jQuery

I need to know what codes are being executed when an event is triggered on jQuery.
Common in JavaScript when I add an event it gets saved in their name only variable that jQuery is not in the same place.
example:
/ / Adding code to an event
window.onclick = function () {alert ('hi!')};
/ / To see the event code
console.log (window.onclick);
And in jQuery?
As of jQuery 1.7 the whole event system was rewritten from the ground up.
But you can use jQuery's method that isn't officially documented...
$._data($('selector')[0],'events');
I'd suggest not to use this in your production code .
You can view all jquery event handlers in next way:
jQuery._data(document.getElementById('id-of-the-element'))
or
jQuery._data(jQuery('#id-of-the-element')[0])
Try this:
// UPDATED -> NOW WORKS WITH jQuery 1.3.1
$.fn.listHandlers = function(events, outputFunction) {
return this.each(function(i){
var elem = this,
dEvents = $(this).data('events');
if (!dEvents) {return;}
$.each(dEvents, function(name, handler){
if((new RegExp('^(' + (events === '*' ? '.+' : e vents.replace(',','|').replace(/^on/i,'')) + ')$' ,'i')).test(name)) {
$.each(handler, function(i,handler){
outputFunction(elem, '\n' + i + ': [' + name + '] : ' + handler );
});
}
});
});
};
And to get click event:
// List onclick handlers of window:
$(window).listHandlers('onclick', console.info);

calling javascript function too many times

I'm just getting into Javascript and I've run into the same problem a number of times with different pieces of code: I have a function that creates a type of element and a function that does something with that type of element. It seems obvious to me that I need to call the "do something" function after the element has been created, but when I do, it ends up running more times than I'd like.
Here's an example of my problem:
function rightClick(){
$(".element").mousedown(function(e){
switch (e.which){case 3: alert( $(this).attr("id") )};
});
};
function doubleClick(){
var counter = 0;
$(document).dblclick(function(e){
counter++;
elementId = "element" + counter;
$("#new_elements").append("<div class='element'" +
"id='" + elementId + "'" +
"style='position:absolute;" +
"top:" + e.pageY + ";" +
"left:" + e.pageX + ";'>" +
elementId+ "</div>");
rightClick();
});
In this example, if I create 4 elements and I right-click on the first one I created, I end up getting 4 alert boxes instead of one. If I right-click on the second element I created, I get three alerts; the third: 2 alerts; the fourth: one alert.
Can anyone explain to me why this is happening, and how to fix it so that I only get one alert each time I right-click on an element?
Binding is the act of associating an event with a DOM element. The .mousedown and similar events only bind on elements that already exist.
Each time you call rightClick() you bind a new event to all current .element elements.
You can bind functions to the same element as much as you'd like, which is why you see the function being called many times.
For dynamic elements should checkout .on or .delegate which work like this:
Example of jQuery.fn.on
$(document.body).on("mousedown", ".element", function(e) {
if (e.which === 3) alert($(this).attr("id"));
});
Example of jQuery.fn.delegate
$(document.body).delegate(".element", "mousedown", function(e) {
if (e.which === 3) alert($(this).attr("id"));
});
Only call this once and you should be pretty much okay. If you're not using jQuery 1.7 or higher you will want to use .delegate() instead of .on.
You do not need to bind the event everytime you insert and element into the DOM. You can use .on to attach event handlers for elements that are dynamically inserted.
$(document).on('mousedown','.element', (function(e){
switch (e.which){
case 3: alert( $(this).attr("id") );
break;
};
});
var counter = 0;
$(document).dblclick(function(e){
counter++;
elementId = "element" + counter;
$("#new_elements").append("<div class='element'" +
"id='" + elementId + "'" +
"style='position:absolute;" +
"top:" + e.pageY + ";" +
"left:" + e.pageX + ";'>" +
elementId+ "</div>");
});
I believe you are adding the same handler several times, meaning that when you click a button you are re-binding the action to the same function.
You've bound your event handler to the class '.element'. This means that every element with the class '.element' on your page will fire that event when the right click occurs.

JQuery attach event to method in instance

I have code that looks like this....
function Finder(id) {
this.id = id;
this.input = $("#" + this.id + " :input[type='text']:first")[0];
$(this.input).bind('keyup'....);
this.KeyUpHandler = function (e) { ..the event should trigger this.. }
this.input = the 1st element of type input found within 'id' which is what I will be referencing. This works fine for what I need.
What I want to do then is to bind the keyup event on 'input'. However I want the event to reference the instance method contained in my function - this.KeyUpHandler().
Also I need 'e' to be event that would have been passed into the function had I just done this on the markup for the input (onkeypress="keyuphandler();").
Any ideas how I can bind the event to the a function in the instance of the function I am working within?
function Finder(id) {
this.id = id;
this.input = $("#" + this.id + " :input[type='text']:first")[0];
that=this;
this.KeyUpHandler = function (e) { ..the event should trigger this.. }
$(this.input).bind('keyup', this.KeyUpHandler);
}
It is important that you call bind() after defining the function!
this.KeyUpHandler = function (e) { ..the event should trigger this.. }
$(this.input).bind('keyup', function(){
this.KeyUpHandler(event);
//more code can go here
});

Categories