I was trying to do something along these lines:
setTimeout($('#element').hide,3000);
which seems simple enough, but it is crippled by the "this" problem. I want to find a way to just pass the actual function as a parameter, without wrapping it in another function, e.g. I do not want to do this:
setTimeout(function(){$('#element').hide();},3000);
What I've tried:
setTimeout($('#element').hide,3000);
setTimeout($('#element').hide.apply(document),3000); /* jQuery docs say that document is the default context */
setTimeout($('#element',document).hide,3000);
setTimeout($(document).find('#element').hide,3000);
setTimeout($(window).find('#element').hide,3000);
setTimeout($.proxy($('#element').hide,document),3000); /* I know this returns a function, which I don't want, but I have tried it */
setTimeout(($('#element').hide()),3000); /* functional expression */
I'm looking for the way to remedy this problem, but I don't want to wrap it in another function. The less lines of code, the better. I know WHY this isn't working as expected, but HOW can I fix it without wrapping it in a closure?
You can do this way by binding the context of the method with the element itself so that in jquery hide method this will point to jquery object and not global context. You can create bound functions using:
Function.bind
Cross Browser Alternative for this:
$.proxy
Ex:
var $elem = $('#element');
setTimeout($elem.hide.bind($elem),3000);
or
setTimeout($.proxy($elem.hide, $elem),3000);
or
setTimeout($.fn.hide.bind($elem),3000); //setTimeout($.proxy($.fn.hide, $elem),3000);
Fiddle
Related
I am pretty new in JavaScript and JQuery and I have the following doubt.
I know that if I open the FireBug console typing window I see the content of the global object that in a JavaScript application that run into a browser is the current browser tab (the window).
Ok, so in this global object I can see all the global variables and all the global functions (the variables and the functions that are not defined inside another function).
So I have a page in which I link my .js file.
This file will contain some pure JavaScript function like this:
function myFunction() {
.................................
.................................
.................................
}
And so I will see the myFunction function as a field of the window global object because this function is global (it is not defined inside another function). This is perfectly clear to me.
So, into the .js file linked inside my page I also have something like this:
$(document).ready(function() {
$("#myButton").click(function() {
............................................
............................................
DO SOMETHING WHEN THE BUTTON HAVING id="myButton" IS CLICKED
............................................
............................................
});
});
So, this is a JQuery code and it should work in this way (correct me if I am doing wrong assertion).
There is the $ that is the JQuery objet (or what is it?).
On this JQuery object I call the ready() function that is the function that perform its inner callback function when the DOM is completly rendered.
So the inner callback function contain the:
$("#myButton").click(function() {...DO SOMETHING...});
the select a button having id="myButton" and add to it the click event listerner that itself define an inner callback function that is performed when the button is clicked.
Is it true?
Ok...so I think that all these stuff is not direcctly in the global object because it is not directly defined into my .js file but have to be in some memory space dedicate to JQuery.
So looking inside the window object inside the FireBug console I found two objects:
$: that I think is the JQuery object...so I think that my previous custom JQuery function have to be here but I can't find it.
JQuery: that is another object that is inside the window global object.
So, my doubt is: when, inside the ready() function I declare something like
$("#myButton").click(function() {...DO SOMETHING...});
where I can find the definition of the function() {...DO SOMETHING...} inside some object defined inside the window global object? Can I find it? Or am I missing something?
jQuery stores its event-related data in a data object events applied to each element. You can use $._data() to grab this info:
$._data($('#myButton')[0], 'events')
or
$._data(document.getElementById('myButton'), 'events')
To get the callback function that you applied for your button's click listener, you can simply grab the handler. For example:
$("#myButton").click(function () { console.log('clicked'); });
var eventsInfo = $._data(document.getElementById('myButton'), 'events');
console.log(eventsInfo.click[0].handler);
The above should print out "function () { console.log('clicked'); }".
Keep in mind that there is no public documentation available for $._data(), although it is a neat thing to know!
The following blog post mentions $._data() when jQuery v1.8 was released but does warn about this:
Note that this is not a supported public interface; the actual data structures may change incompatibly from version to version.
That was back in 2012. To this day, it seems to be working fine with the latest 1.x and 2.x versions, so I don't see this going away anytime soon.
This is an anonymous function, basically a piece of unique code that you don't really want to write a named function for.
It's a one-time use-case or rather it's used to bind custom click events without littering the global object with variables.
What an anonymous function does is the exact opposite of what you are asking since you can't find it in the global object (anonymous function).
.click is a function defined in $.fn and since $ is part of the window object you could traverse there to find click e.g. window.$.fn.click would be the path to the source of $(...).click(func...) but an anonymous function is a function that gets set and then forgotten (more or less).
After all, you're not giving it a name so there is no reference it can point to which is exactly what this is.
If you use a named function as an argument to another function it's called a callback function
An anonymous function is basically a nameless callback function, a callback function is a normal function that can be passed to other functions as a callable argument - this normal function will then internally use .call() or .apply() to execute the supplied callback which is what jQuery for instance does when you bind a click
The good thing here is that you're not missing anything at all, as a matter of fact - you're asking the right question because this will look like magic if you're just starting out but once you get the hang of it it's easy to understand and use (and misuse so be careful!)
If you'd like to know how this construction works you could always build your own function that accepts a callback / anonymous function e.g.
function result_based_on_callback(a, b, fn) {
fn.call(null, a, b);
}
The above function takes two parameters and a function, it will call the function and supply the two parameters to it (the null is the context of this which is a different kind of question :))
If we were to use the above construct to do a calculation we could do so like this:
console.log(result_based_on_callback(1, 2, function(a, b) { return a + b; }));
This would return 3, you can also do this with a normal function that would otherwise take two numbers and add them - it works the same except for just passing in the function name rather than the body
like this:
function do_add(a, b) {
return a + b;
}
console.log(result_based_on_callback(1, 2, do_add));
Which will do the exact same.
I hope this allows you to understand a bit of how this works, good luck!
when using the multitude of utility functions that can accept it. For example:
function foo () {
_.each ([0,1,2,3], function(val) {
// I don't use this in the body
}, this);
}
It seems like one way is more concise and the other is there in case you add code later.
It seems like one way is more concise
Then use that.
in case you add code later.
You ain't gonna need it. Not until later, at least.
The optional parameter adds the context, in other words what 'this' refers to within the callback.
You only need to add it if you want it that way. If you're using a library like backbone, it can come in very handy (eg. when the function is called from within a view object, and you want 'this' to refer to the view).
I'm making an image gallery, when I click a button I can scroll through to the next image.
I also have the option to 'jump' to a specific image. This all works fine.
However, if I scroll regularly to image 3, then jump to image 7. Once I click the next button, I don't go to image 8 as I would like to - I go to image 4. Because there are two separate functions, and I can't/ don't know how to pass the variable between them. I understand I can use a global variable outside of both functions, but this seems to be discouraged.
Here's an example:
var i = 0;
// i is a global variable
$("#next_button").click(function(){
$(".all_images").eq(i).show();
i++;
});
This would correctly increment through all of my images.
$(".thumbnails").click(function(){
var x = $(this).index();
$(".all_images:visible").hide();
$(".all_images").eq(x).show();
i = x;
});
This shows the image relative to the thumbnail I have clicked.
So, how do I use the 'i' variable from the first function in the second function? This has always confused me. It just seems simpler to use a global variable so each function can change the value of i and use it when necessary. Please enlighten me.
Also, as I understand it's possible to wrap JQuery code in a regular JavaScript functions. It seems, however, that my code doesn't work when I wrap a JQuery .click in a regular JavaScript function (ie my_Function(){ ....$("#something").click.... }
Can anybody explain what I am doing wrong?
You have two options as in most programming languages:
Use a global variable (higher scope),
Pass by reference.
However, you can't really escaoe creating some kind of global variable (object or primitive) so I would suggest you make an object (maybe even key-value) that holdes all your program parameters.
In order to do this you could use the .data method like this to assign data to an arbitrary element:
setter :
$('body').data('myvar','value');
getter:
$('body').data('myvar');
see: http://api.jquery.com/jQuery.data/
In order to pass by reference, you need to pass a object instead of a primitive.
See following link(s) for more details:
Pass Variables by Reference in Javascript
http://snook.ca/archives/javascript/javascript_pass
jQuery's .click - pass parameters to user function
Talking about XBL is not exactly talking about javascript. So I'll create this question that's related to this one, but now about XBL, where I'm not the creator of the root javascript code, but just of the methods and event handlers inside the bindings.
--
In some cases, the this keyword may not refer to the object I expect it to. (recent example: in an key event, in my XBL)
What's the best approach to avoid this kind of mistake?
For now, I'm using always the getElementById (or $.fn from jQuery), but I'm not sure if it's the best approach.
--update
A little bit more details:
Within a XBL method the only way to access the element that was defined in the Xul file (the GUI description file) without using "this" (as it may not be the "this" I expect) is with getElementById, and this makes the code not reusable, so I'm looking for alternatives..
As you've heard elsewhere, the problem is that the this parameter isn't necessarily the object you first thought of, especially when you're talking about event handlers and the like. The best way I found is to write a small function that will bind some object as the this variable and return another function that uses the binding to call the original function.
Take a look at this code:
var bindFunction = function(self, f) {
return function() {
return f.apply(self);
};
};
var foo = function() {
alert(this.hello);
};
var bar = {
hello: "Hello there"
};
var boundFoo = bindFunction(bar, foo);
boundFoo();
What I have is a function called bindFunction that takes an object (called self) and some function, and returns another function that will call the passed-in function applying the self object as the this variable.
The rest of the code is just some test code: a foo function that will alert this.hello, a bar object with a hello member, and how you can bind foo with bar.
In essence, I've taken a function that accepts no parameters and generated another function that will ensure the first is always called with the correct this variable. Ideal for event handlers.
(Sorry, but I know nothing about XBL, so I hope this will be of use.)
If there's not a best answer, a good approach could be use javascript files instead of XBL for the implementation. Looking the Xulrunner source code, looks like most code does this.
But I still would like to use XBL, if there was a way to work fine with it..
window.setInterval("moveUp(fire,2)","100");
in the code above fire is a object represting a div. I want to pass this object to moveUp method and call this method continuosly.
My problem is window.setInterval does not accepts fire object like this and gives error as fire is not defined. Although i am using fire object at other places as well. Besides this i also want to know if i can do the same using jQuery.
If you pass a string to setInterval then it will be evaled in the global scope. Don't do that. Pass a function instead, and keep the existing scope.
var fire = something;
var func = function () {
moveUp(fire, 2);
};
setInterval(func,100);
Besides this i also want to know if i can do the same using jQuery.
jQuery is just a JavaScript library. It isn't a different language. It doesn't have alternatives for basic JavaScript.
Best Way would be to use an anonymous function:
setInterval(function(){
moveUp(fire,2);
},100);
It actually does look a little bit like jQuery now... kidding aside, there is no setInterval Implementation for jQuery since its syntax and the cross browser capabilities are just fine the way they are - are they not?