Reputation: 53
I have this code:
$('.counter_d').mouseover(function() {
$('#description').html('Counter');
});
$('.selector_d').mouseover(function() {
$('#description').html('Selector');
});
$('.date_d').mouseover(function() {
$('#description').html('Date');
});
and several more, but I think the file could be smaller and even reusable using loops, but I'm not able to bind the description (HTML method) with the selector.
I want to use something like this:
var selectors=['.counter_d','.selector_d','.date_d'];
var description=['Counter', 'Selector', 'Date'];
for(var i=0; i<selectors.length; i++)
$(selectors[i]).mouseover(function() {
$('#description').html(description[i]);
});
Any help? Thanks
Upvotes: 4
Views: 169
Reputation: 137360
Since correct solutions have already been given (Andrew Whitaker's accepted answer being my favorite), I will actually tell you what is the problem with your code (yoshi's answer has some clues, but does not explain it in detail).
The problem is, that even though the value of i
changes within the loop, when it is executed, i
stays the same (the same as when the for
loop has ended) when event handlers are executed.
The proof looks like this (see jsfiddle):
var selectors=['.counter_d','.selector_d','.date_d'];
var description=['Counter', 'Selector', 'Date'];
for(var i=0; i<selectors.length; i++)
$(selectors[i]).mouseover(function() {
$('#description').html(i); // i is always equal to 3
});
The problem is event handlers use i
from outer scope, which at the time of handlers' execution is equal to 3
. So even though the i
variable has the value you wanted when handlers are attached, the value changes before they are executed.
To solve that, you can slightly modify your code to use anonymous functions that are immediately called by passing it then-correct value of i
:
var selectors=['.counter_d','.selector_d','.date_d'];
var description=['Counter', 'Selector', 'Date'];
for(var i=0; i<selectors.length; i++)
(function(i){
$(selectors[i]).mouseover(function() {
// i is the same as when the outer function was called
$('#description').html(description[i]);
});
})(i); // executing function by passing current i
To prove that it works correctly: http://jsfiddle.net/ZQ6PB/
JavaScript closure inside loops - simple practical example,
Upvotes: 1
Reputation: 18078
Constructing the HTML as follows (assuming the elements are spans) ...
<span class="d counter_d" data-desc="Counter">...</span>
<span class="d selector_d" data-desc="Selector">...</span>
<span class="d date_d" data-desc="Date">...</span>
... allows the javascript to as simple as this :
var $description = $("#description");
$(".d").mouseover(function() {
$description.text($(this).data('desc'));
});
The class names '.counter_d','.selector_d','.date_d' are redundant and can be deleted unless they are required for some other reason - eg. styling.
Of course, if you had hundreds of such elements, then the HTML would be a pain to write handraulically. You would be better off with another approach.
Upvotes: 0
Reputation: 2688
The problem is the variable i
is assigned to 3 at the time the mouseover callback is executing.
As description[3]
is undefined
no new HTML is assigned.
Fiddle enable your browser console to read the console.log!
I think a more elegant solution is to give the HTML elements an extra attribute description
and in the mouseover callback simply do:
$('#description').html($(this).attr("description"));
(You see it in the fiddle above)
In my opinion you can even select all elements in a more elegant way and get rid off the loop as jQuery will handle this for you:
$(".counter_d, .selector_d, .date_d").mouseover(function() {
$('#description').html($(this).attr("description"));
});
Upvotes: 1
Reputation: 9225
I'd go for something like this:
var obj = {
'a': 'content a',
'b': 'content b',
'c': 'content c'
};
$('.a,.b,.c').mouseover(function() {
$('#d').html(obj[this.className]);
});
Don't really like loop idea, since it makes it much less readable.
UPD: You can always expand the solution for more classes
var obj = {
'.a': 'content a',
'.b': 'content b',
'.c': 'content c'
};
var selector = Object.keys(obj).join(',');
$(selector).mouseover(function() {
$('#d').html(obj['.' + this.className]);
});
Upvotes: 0
Reputation: 50787
It looks like your selectors all end with _d. It seems reasonable that we could do the following.
$('[class$=_d]').mouseover(function(){
var str = $(this).prop('class').split('_')[0];
var desc = str.charAt(0).toUpperCase() + str.slice(1);
$('#description').html(desc);
});
Upvotes: 0
Reputation: 126052
var selectors = {
'.counter_d': 'Counter',
'.selector_d': 'Selector',
'.date_d': 'Date'
};
$.each(selectors, function (key, value) {
$(key).mouseover(function () {
$("#description").html(value);
});
});
Example: http://jsfiddle.net/andrewwhitaker/bS28q/
Upvotes: 8