Let's say I was attaching an event handler of jQuery click event to one of the function of my objects. But why does it return undefined on my properties?
var buttonView = {
label : 'underscore',
onClick : function(){ alert('clicked: ' + this.label); },
};
$('#bind').bind('click', buttonView.onClick); //clicked: undefined --> why is it undefined ?
In the below onclick handler this points to dom element with id "bind" and it do not have a label property. If you have any custom attribute as label you should use $(this).attr("label") to retreieve it. Try this
function(){ alert('clicked: ' + $(this).attr("label")) };
You're passing the function referenced by buttonView.onClick, but it's association with buttonView is not retained.
To retain the reference via this, you can use the jQuery.proxy()[docs] method.
$('#bind').bind('click', $.proxy(buttonView,'onClick'));
Now this in the onClick function will refer to your buttonView object.
Live example: http://jsfiddle.net/K72qs/
Or simply make an explicit reference to buttonView in the onClick function:
onClick : function(){ alert('clicked: ' + buttonView.label); },
Live example: http://jsfiddle.net/K72qs/1/
You could just use:
$('#bind')
.data('label', 'underscore')
.click(function() {
alert('clicked: ' + $(this).data('label'));
});
Related
I'm new to ES6, and can't quite get this to work:
$(this) returns undefined on click?
dom.videoLinks.click((e) => {
e.preventDefault();
console.log($(this));
var self = $(this),
url = self.attr(configuration.attribute);
eventHandlers.showVideo(url);
// Deactivate any active video thumbs
dom.videoLinks.filter('.video-selected').removeClass('video-selected');
// Activate selected video thumb
self.addClass('video-selected');
});
However if I change it so not be an arrow function like so, it works as expected?:
dom.videoLinks.click(function(e) {
e.preventDefault();
console.log(this);
console.log($(this));
var self = e.this,
url = self.attr(configuration.attribute);
eventHandlers.showVideo(url);
// Deactivate any active video thumbs
dom.videoLinks.filter('.video-selected').removeClass('video-selected');
// Activate selected video thumb
self.addClass('video-selected');
});
So how would I go about it if I use an arrow function in the callback?
With arrow function as a callback, instead of using this to get the element to which the handler is bound, you should use event.currentTarget.
Value of this inside an arrow function is determined by where the arrow function is defined, not where it is used.So from now on, keep in mind that
event.currentTarget always refers to the DOM element whose EventListeners are currently being processed.
.currentTarget vs .target
Use event.currentTarget instead of event.target because of event bubbling/capturing:
event.currentTarget- is the element that has the event listener attached to.
event.target- is the element that triggered the event.
From the documentation:
currentTarget of type EventTarget, readonly Used to indicate the
EventTarget whose EventListeners are currently being processed. This
is particularly useful during capturing and bubbling.
Check the basic example in the below snippet
var parent = document.getElementById('parent');
parent.addEventListener('click', function(e) {
document.getElementById('msg').innerHTML = "this: " + this.id +
"<br> currentTarget: " + e.currentTarget.id +
"<br>target: " + e.target.id;
});
$('#parent').on('click', function(e) {
$('#jQmsg').html("*jQuery<br>this: " + $(this).prop('id')
+ "<br>currenTarget: " + $(e.currentTarget).prop('id')
+ "<br>target: " + $(e.target).prop('id'));
});
$('#parent').on('click', e => $('#arrmsg').html('*Arrow function <br> currentTarget: ' + e.currentTarget.id));
#parent {background-color:red; width:250px; height:220px;}
#child {background-color:yellow;height:120px;width:120px;margin:0 auto;}
#grand-child {background-color:blue;height:50px;width:50px;margin:0 auto;}
#msg, #jQmsg, #arrmsg {font-size:16px;font-weight:600;background-color:#eee;font-family:sans-serif;color:navy;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">Parent-(attached event handler)<br><br>
<div id="child"> Child<br><br>
<p id="grand-child">Grand Child</p>
</div>
</div>
<div id="msg"></div><br>
<div id="jQmsg"></div><br>
<div id="arrmsg"></div>
You wouldn't.
Changing the value of this is the primary point of using an arrow function.
If you don't want to do that then an arrow function is the wrong tool for the job.
You can use $(event.target) instead of $(this) even inside of an arrow function. Arrow functions are preserving this of the scope where they were defined. In your case it is undefined.
arrow functions and this selector?
Arrow functions retain this from enclosing context.
Eg.
obj.method = function(){
console.log(this);
$('a').click(e=>{
console.log(this);
})
};
obj.method(); // logs obj
$('a').click(); // logs obj
So how would I go about it if I use an arrow function in the callback?
You already can - to access event target you can use something like $(e.target), but beware of bubbling. So I recommend to use normal functions instead as callbacks.
p.num = 100;
$('body').on('click', '.del', this.delete.bind(this));
p.delete = function(e) {
console.log(this.num); //100
//how can I get the .del element?
}
I'm trying to get the element that produced the click, but I also need access to the num property.
How can I access both types of 'this' inside my delete method?
The callback for an event receives an Event object that you can use to retrieve the element on which the event was called.
function(e) {
var element = $(e.target); //This is the element that the event was called on.
}
Disclaimer : This is the my exact answer (adapted with the current code) taken from here : Pass additional arguments to event handler?
Yet, the question doesn't seem to be an exact duplicate (but i may be wrong).
As said in the documentation of .on, you can pass datas to your event.
.on( events [, selector ] [, data ], handler )
data
Type: Anything
Data to be passed to the handler in event.data when an event is triggered.
So your event could look like that :
p.num = 100;
$('body').on('click', '.del', {object : this}, this.delete);
p.delete = function(e) {
var myObj = e.data.object;
// [myObj] will be your plugin
// [this] will be the clicked element
// [e] will be you event
}
if you're using jquery, you can combine those functions all into one like below:
note: num is an attribute so you have to use .attr().
$(document).ready(function() {
$('body').on('click', '.del', function() {
var num = $(this).attr('num');
alert('click function and num = ' + num);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Delete
or if you really want to keep them separate functions....:
$(document).ready(function() {
$('.del').on('click', function() {
deleteThis($(this));
});
});
function deleteThis(element){
var num = element.attr('num');
alert('click function and num = ' + num);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Delete
also, if youre using separate functions for the click and the delete, pass the element from click to delete: pass element - callDeleteFunction($(this)), and retrieve element - myDeleteFunction(element aka $(this))
I'm not sure what you're asking about but maybe this is what you want:
var p = {};
p.num = 100;
$('body').on('click', '.del', p.delete); // don't bind to this
p.delete = function(e) {
console.log(p.num); // here you still can call p
// this is del DOM element
}
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);
There are 10 li elements and 5 of those have a element inside. And I'd like to add an event on the li elements using Mootools.
A class has few variables and method including the event for the li elements and my problem comes from here. please see the event for li below,
li.addEvents({
mouseover: function(e){
console.log(this.id + ' / ' + this.classVar);
}.bind(this)
});
In the event I need to refer li itself and a class variable because each li has unique id and the classVar has also information. But problem is if I use bind(this) to the event, this.id won't work or if not using it, *this.classVar' won't work.
If I use e.target.id instead of this.id, it returns correct id IF ONLY the li doesn't have a element. Otherwise e.target refers the a element.
Can anyone help me on this please? Many thanks in advance
The simplest way is to use the self or me workaround, like so...
function myClass()
{
var self = this;
this.classVar = 'foo';
// some other code
li.addEvents({
mouseover: function(e){
console.log(this.id + ' / ' + self.classVar);
}
});
}
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
});