Reputation: 36421
I have the following use of jQuery UI function:
$('.droppable').droppable({
tolerance: 'touch',
over: function () {
var hasHiddenList = $(this).children('ul.hidden');
if (hasHiddenList.length)
hasHiddenList.removeClass('hidden');
},
out: function () {
var hasEmptyList = $(this).children('ul.empty');
if (hasEmptyList.length)
hasEmptyList.addClass('hidden');
},
drop: function () {
var hasEmptyList = $(this).children('ul.empty');
if (hasEmptyList.length)
hasEmptyList.removeClass('empty');
}
});
And I am wondering if I can define the variables hasHiddenList
and hasEmptyList
outside the callback functions, since it is the same variable in all of them.
Upvotes: 0
Views: 78
Reputation: 24370
If you really, really want the variables, there are two options.
The obvious one (with pitfalls) is this:
var hasHiddenList = $('.droppable').children('ul.hidden');
var hasEmptyList = $('.droppable').children('ul.empty');
$('.droppable').droppable({
tolerance: 'touch',
over: function () {
if (hasHiddenList.length)
hasHiddenList.removeClass('hidden');
},
out: function () {
if (hasEmptyList.length)
hasEmptyList.addClass('hidden');
},
drop: function () {
if (hasEmptyList.length)
hasEmptyList.removeClass('empty');
}
});
Variables have been extracted, the code is less repetitive. All good.
Now, the problem is that the selectors are just run once. The callback over
, out
and drop
are called every time one of those events occur, but hasHiddenList
and hasEmptyList
will not have been updated; they will still be the same thing between every invocation. Probably not what you want.
The way to remedy this is to use functions instead of variables, like this:
var hiddenList = function(target) {
return $(target).children('ul.hidden');
};
var emptyList = function(target) {
return $(target).children('ul.empty');
};
$('.droppable').droppable({
tolerance: 'touch',
over: function () {
var list = hiddenList(this);
if (list.length)
list.removeClass('hidden');
},
out: function () {
var list = emptyList(this);
if (list.length)
list.addClass('hidden');
},
drop: function () {
var list = emptyList(this);
if (list.length)
list.removeClass('empty');
}
});
This abstracts away how the queries are performed (you only have to write $(target).children('ul.empty');
once instead of twice) but in reality the code has not really become simpler. Actually, I would even say that it's harder to follow it now. On the other hand, if you were using the same selector even more than twice, lets say five times, then maybe this would actually be useful.
Also, note that I've removed "has" from the variable names, because "has" makes it sound like they are booleans, which they are not. They are lists of elements.
Upvotes: 1
Reputation: 24370
Better yet, you don't even need the if-statements and the variables:
$('.droppable').droppable({
tolerance: 'touch',
over: function () {
$(this).children('ul.hidden').removeClass('hidden');
},
out: function () {
$(this).children('ul.empty').addClass('hidden');
},
drop: function () {
$(this).children('ul.empty').removeClass('empty');
}
});
Upvotes: 5