Optimize jQuery with loops

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 a few more, but I think the file can be smaller and even reused using loops, but I can’t associate 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

+4
source share
6 answers
 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/

+8
source

The problem is that the variable i to 3 during the execution of the mouse callback.
Since description[3] is undefined , new HTML is not assigned. Fiddle allow your browser console to read console.log!

I think a more elegant solution is to provide the HTML elements with an additional description attribute and in the mouseover callback is simple:

 $('#description').html($(this).attr("description")); 

(You see this in the fiddle above)

In my opinion, you can even select all the elements in a more elegant way and get rid of the loop, since jQuery will handle this for you:

 $(".counter_d, .selector_d, .date_d").mouseover(function() { $('#description').html($(this).attr("description")); }); 

updated script

+1
source

Since the correct solutions have already been provided ( Andrew Whitaker accepted the answer , which is my favorite), I will actually tell you what the problem is with your code ( yoshi answer has some tips, but does not explain it in detail).

Problem

The problem is that even if the value of i changes in the loop when it is executed, i remains the same (the same as when the for loop ends) when the event handlers are executed.

What really happens in your code

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 });​ 

Problem - event handlers use i from the outer region, which at run time is equal to 3 by the handler. Therefore, even if the variable i has the value that you want when the handlers are bound, the value changes before they are executed.

Decision

To solve this problem, you can slightly modify your code to use anonymous functions that are immediately called, passing then the 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/

More details

Closing JavaScript inside loops is a simple practical example ,

+1
source

I would do something like this:

 var obj = { 'a': 'content a', 'b': 'content b', 'c': 'content c' }; $('.a,.b,.c').mouseover(function() { $('#d').html(obj[this.className]); });​ 

Demo

I do not like the idea of ​​the cycle, as it makes it less readable.

UPD: You can always extend 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]); });​ 

Demo

0
source

It looks like your selectors end in _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); }); 
0
source

Building HTML as follows (assuming 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 javascript as simple as this:

 var $description = $("#description"); $(".d").mouseover(function() { $description.text($(this).data('desc')); }); 

Class names .counter_d ','. selector_d ','. date_d 'are redundant and can be removed if they are not required for any other reason - for example. modeling.

Of course, if you had hundreds of such elements, then HTML would be painful to write by hand. You will be better off with a different approach.

0
source

Source: https://habr.com/ru/post/1433184/


All Articles