My html contains two forms overlapping each other, one used as add form and one as edit form. I use jQuery to show and hide them with the following code:
var editForm = $("#edit-form");
var addForm = $("#add-form");
var showEditForm = function() {
editForm.fadeIn(function() {
addForm.fadeOut();
});
};
var showAddForm = function() {
editForm.fadeOut(function() {
addForm.fadeIn();
});
};
I wanted to make the code more compact so I set the fadeOut()
call directly on the fadeOut()
callback by doing like this:
var showEditForm = function() {
editForm.fadeIn(addForm.fadeOut);
};
var showAddForm = function() {
editForm.fadeOut(addForm.fadeIn);
};
But this productes the following error Uncaught TypeError: Failed to execute 'animate' on 'Element': Valid arities are: [1], but 4 arguments provided.
but why doesn't that work?
That's because calling a function as a property of an object is a special syntax, that calls the function with the object as context.
When you call a function like this:
obj.func();
then this
will be a reference to obj
inside the function.
If you get the reference to the function, and then call it:
var f = obj.func;
f();
then this
will be a reference to the global context, i.e. the window
object.
By using editForm.fadeIn(addForm.fadeOut);
you get the reference to addForm.fadeOut
and send to the fadeIn
method. It's no longer associated with the object, so it will be called with the global context instead of the object as context.
You can use the proxy
method to associate the function with the object, so that it will be called with the correct context:
var showEditForm = function() {
editForm.fadeIn($.proxy(addForm.fadeOut, addForm));
};
var showAddForm = function() {
editForm.fadeOut($.proxy(addForm.fadeIn, addForm));
};
I suspect the problem is that addForm.fadeOut
is being called with a bad combination of arguments, when its passed to the fadeIn
function (and vice versa).
The classic example of this pitfall seems to be:
["0", "1", "2", "3"].map(function(i) {return parseInt(i);})
This, works as expected and gives [1,2,3,4]
as a result. You might expect that you could shorten this, much as you did above, and write
["0", "1", "2", "3"].map(parseInt);
Unfortunately; this evaluates to [0, NaN, NaN, NaN]
. The problem, is that .map
calls any function provided it with three arguments: the value, the index, and the array itself, and parseInt
takes up to two arguments: the value, but also the radix/base to parse in. (e.g. radix 2 to parse a string as binary) So what actually happens is essentially:
[
parseInt("0", 0), //0, radix is ignored
parseInt("1", 1), //NaN, what is base 1?
parseInt("2", 2), //NaN, 2 isn't valid binary
parseInt("3", 3) //NaN, 3 isn't valid ternary/base-3
]
I suspect, based on the error message, that the same thing is going on here. The "arity" of a function is the number of arguments passed to it, so the error message here says that 4 arguments were provided, when only one was expected.
In general with functions that take optional arguments, you need to be careful before passing them to other functions directly, or else you can't control what arguments it will be called with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With