I have a class which uses jQuery functions inside it's internal function.
How can I refer to the member variable inside the jQuery callback function?
See the code below:
var UriParser = function(uri) {
this._uri = uri; // let's say its http://example.com
};
UriParser.prototype.testAction = function() {
$('a').on('click', function(event) {
// I need the above this._uri here,
// i.e. http://example.com
}
}
The problem is this inside the event handler does not refer the UriParser object, it is referring the dom element which was clicked.
One solution is to use a closure variable
UriParser.prototype.testAction = function () {
var self = this;
$('a').on('click', function (event) {
//use self._uri
})
}
another is to use $.proxy() to pass a custom execution context
UriParser.prototype.testAction = function () {
$('a').on('click', $.proxy(function (event) {
//use this._uri
}, this))
}
Related
i have a normal function which works and when i console log this it returns jQuery.fn.init [small.expand, context: small.expand
My function below:
jQuery(document).on('click', 'h3.shipping-name small.expand', function (e) {
var me = jQuery(this);
console.log(me);
var next = me.parent().next().next();
if (next.is(":hidden")) {
me.find('i').removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');
} else {
me.find('i').removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');
}
next.slideToggle();
});
But if i want to get it from another function like this:
var smallExpand = jQuery('h3.shipping-name small.expand');
smallExpand.on("click", function () {
expandDetails();
});
function expandDetails(e) {
alert("oki2");
var me = jQuery(this);
console.log(me);
var next = me.parent().next().next();
console.log(next)
if (next.is(":hidden")) {
me.find('i').removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-up');
} else {
me.find('i').removeClass('glyphicon-chevron-up').addClass('glyphicon-chevron-down');
}
next.slideToggle();
}
But it returns only empy object like this: jQuery.fn.init {}
What am i doing wrong?
Problem with your implementation is that this doesn't refers to current element it refers to window object thus the code doesn't work
You can use call() to set the this value
smallExpand.on("click", function (event) {
expandDetails.call(this, event);
});
Or, You could just pass the function reference to attach event handler
smallExpand.on("click", expandDetails);
Set the variable first out side your functions, then you can retrieve it for later.
var me;
Then
function first() {
me = $(this);
}
Now you can use the variable in another function
function thisorthat() {
$(‘.class’).val(me);
}
You are calling expandDetails as a static method.
as mentioned by #Satpal, you should just do smallExpand.on("click", expandDetails);.
this exists in the smallExpand.on("click", function() {}); scope, but once you call expandDetails(); it gets lost.
Here is my example object to demonstrate the issue.
Dog = Backbone.Model.extend({
initialize: function () {
},
Speak: function (sayThis) {
console.log(sayThis);
},
CallInternalSpeak: function () {
this.Speak("arf! from internal function.");
},
CallSpeakFromClosure: function () {
this.Speak("arf! fron outside closure.");
var callClosure = function () { // think of this closure like calling jquery .ajax and trying to call .Speak in your success: closure
console.log("we get inside here fine");
this.Speak("say hi fron inside closure."); // THIS DOES NOT WORK
}
callClosure();
}
});
var rover = new Dog;
rover.Speak("arf! from externally called function");
rover.CallInternalSpeak();
rover.CallSpeakFromClosure();
Since you are in Backbone, you can always use Underscore's bind function as well. After you define callClosure, you can wrap it with a proper binding:
callClosure = _.bind(callClosure, this);
The old "self" trick... make a reference to this, call it self, and reference it in the function.
CallSpeakFromClosure: function () {
this.Speak("arf! fron outside closure.");
var self = this;
var callClosure = function () {
console.log("we get inside here fine");
self.Speak("say hi fron inside closure."); // THIS DOES NOT WORK
}
callClosure();
}
I have a function that listens for a click on the screen and fires a callback. It is part of a Helper object (which is why is preceded by the term Helper in my sample code. That is irrelevant however.
var Helper = {
bodyClickListener: function(fn) {
var window = document.getElementsByTagName('body')[0];
window.click();
CORE.dom.on(window, 'click', function(event) {
CORE.dom.off(window, 'click');
fn(event);
});
}
}
I need to be able to pass a function into this function with a parameter that has been previously set.
function someFunction() {
var popup = document.getElementById('tagResultsPopup');
Helper.bodyClickListener(function(popup) {
return function(event) {
event.stopPropagation();
removePopup(popup);
};
}(document.getElementById('tagResultsPopup')));
function removePopup(element) {
if(element) {
element.parentNode.removeChild(element);
}
};
}
The code above works, but you'll notice that I have to set the popup variable inside of the callback function. It has already been set above. How do I pass a reference to the earlier variable into the callback function.
If I understand your question correctly, you don't need to do much. You can just use the popup variable defined outside.
var popup = document.getElementById('tagResultsPopup');
Helper.bodyClickListener(function(event) {
event.stopPropagation();
//Don't set it
//var popup = document.getElementById('tagResultsPopup');
removePopup(popup);//popup will refer to the correct variable
});
The function that you are passing to bodyClickListener is a closure. You can simply reference 'popup' inside that function without any problem. You don't have to create a new variable.
The answer was to use closure in this way:
Helper.bodyClickListener(function(popup) {
return function(event) {
event.stopPropagation();
removePopup(popup);
};
}(document.getElementById('tagResultsPopup')));
That way the callback function has access to the variable I pass into the parameter function. So here, the return is actually the function I am passing as the callback.
var some_name =
{
moving:false,
show : function ()
{
this.moving = true;
$('element').slideDown(5000, function ()
{
this.moving = false; //How to access to attribute "moving" of class some_name?
});
},
}
Question in code.
You can bind the callback function to the current context:
$('element').slideDown(5000, $.proxy(function() {
this.moving = false;
}), this); // "this" inside of the function will be this "this"
See jQuery.proxy
Alternatively you could do this:
this is the current context, it's value depends on how the function is called. You can assign this to a variable outside of the function, and use this variable instead:
var that = this;
$('element').slideDown(5000, function() {
that.moving = false; //use that instead of this here
});
Use moving instead of this.moving (in both occurences)
Variables are bound to the context when they are used, so even inside your event callback you can access the variables above.
In the event callbacks, this refers to event.target, or the element that captured the event.
You can take the advantage of closures in javascript and access the moving attribute like this:
show : function ()
{
var moving = true;
$('element').slideDown(5000, function ()
{
moving = false;
});
},
Note, though, that this moving will be different of the first moving that lives in some_name
this.remove() is not a function. How come?
var vehicle = function () {
return {
init: function () {
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
this.remove();
});
},
remove: function () {
alert('test');
}
}
}();
jQuery().ready(vehicle.init);
Sorry for the confusion. I'm trying to call my own "remove" function. This is simply a class to manage vehicles on my page. This is the beginning of it and it will have a lot more functions than just init/remove.
this is a DOM element. To use jQuery's .remove() method, you need to wrap it in a jQuery object.
$(this).remove();
EDIT: If you were hoping to call the remove() function in the vehicle object, then call:
vehicle.remove();
Also, if you were hoping to shorten your .ready() call, you can do this:
jQuery(vehicle.init);
From the jQuery 1.4 release notes:
The jQuery().ready() technique still works in 1.4 but it has been deprecated. Please use either jQuery(document).ready() or jQuery(function(){}).
Maybe you're looking for something like this?
var vehicle = new function () {
var self = this;
this.init = function () {
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
self.remove();
});
};
this.remove = function () {
alert('test');
};
};
...or like this maybe? It's kind of hard to tell what you're going for...
var vehicle = new function () {
function remove () {
alert('test');
}
this.init = function () {
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
remove.call(this);
});
};
};
Note - we're all somewhat confused because it's not clear which "remove" function you want to call.
The problem is that you're passing in the reference to the "init" function, but when it's called the "this" variable will refer to the window object, not the value of "vehicle". Why? Because in Javascript the "this" value depends only on how a function is called. The fact that two functions are defined in the same object has absolutely nothing to do with it.
Try doing this instead:
jQuery(function() {
vehicle.init();
});
When you call the "init" function that way — by explicitly referencing it as a property of the "vehicle" object — then Javascript will bind "this" to the value of "vehicle".
edit oh wait I just noticed that you're also going to have to revise your "init" function, because that code inside the "click" handler is going to be called by jQuery in such a way as to bind "this" in that context to the affected element. Thus if you want to keep the "vehicle" reference around, you'd do this:
init: function () {
var originalThis = this;
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
originalThis.remove();
});
},
Since you said you're trying to call your own remove function, here's how to do it:
var vehicle = (function () {
return {
init: function () {
var that = this; // step one
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
that.remove();
});
},
remove: function () {
alert('test');
}
}
}()); // step zero - wrap the immediate invocation in parens
jQuery(function () {
vehicle.init(); // step two
);
var vehicle = function () {
return {
init: function () {
var self = this;
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
self.remove();
});
},
remove: function () {
alert('test');
}
}
}();
jQuery().ready(function() {
vehicle.init();
});
When invoking a function as a method "this" refers to the object that is invoking it. In jQuery the function passed is invoked as a method of the html element so "this" becomes the element.
To make sure you are refering to the correct object you'll need to create a reference to the original object.
var vehicle = function () {
var that = {
init: function () {
jQuery('.vehicle-year-profile .options .delete').bind('click', function (e) {
e.preventDefault();
that.remove();
});
},
remove: function () {
alert('test');
}
}
return that;
}();
jQuery().ready(vehicle.init);