How to create listeners for multiple elements in a loop?

Asked

Viewed 105 times

-3

My code is very repetitive, I want to use a loop to solve this, but I don’t know how to do it.

$(document).ready(function()
{

  //Atribui aos campos de código do Pokemon a função que carrega os dados dos pokemons:
  $("#pok11").focusout(function(){
    carregarPokemon("pok11");
  });
  $("#pok12").focusout(function(){
    carregarPokemon("pok12");
  });
  $("#pok13").focusout(function(){
    carregarPokemon("pok13");
  });
  $("#pok14").focusout(function(){
    carregarPokemon("pok14");
  });
  $("#pok15").focusout(function(){
    carregarPokemon("pok15");
  });
  $("#pok16").focusout(function(){
    carregarPokemon("pok16");
  });
  $("#pok21").focusout(function(){
    carregarPokemon("pok21");
  });
  $("#pok22").focusout(function(){
    carregarPokemon("pok22");
  });
  $("#pok23").focusout(function(){
    carregarPokemon("pok23");
  });
  $("#pok24").focusout(function(){
    carregarPokemon("pok24");
  });
  $("#pok25").focusout(function(){
    carregarPokemon("pok25");
  });
  $("#pok26").focusout(function(){
    carregarPokemon("pok26");
  });
  ```
  • 2

    Could insert the Html concerning a doubt tbm?

  • As you did not inform the HTML, follow a "kick": https://jsfiddle.net/eckqrxoy/3/ - the idea is to use Event delegation, as already said in a comment below: instead of having several focusout, put only one in the parent element, which will already serve the children as well - of course it depends on how the HTML is, but as it was not informed, is the suggestion

  • 2

    @Augustovasques As it was just to give a general idea (and not a solution - otherwise I would have answered), nor did I care for these details. But yes, depending on the user’s actions, you can loop in (and I’m too lazy to tidy up) :-)

  • If any answer solved your problem and there was no doubt left, mark it as correct/accepted by clicking on the " " that is next to it, which also marks your question as solved. If you prefer one of the other answers, you can mark it as correct/accepted, but only one answer can be marked that way. If you still have any questions or would like further clarification, feel free to comment. Also see How to say thank you in replies?

  • Regarding your new question. Create a new question by pressing the button Ask a question located in the upper right corner of the page. To learn more about the operation of the site see the Community FAQ.

3 answers

3

A simple alternative is in HTML to design a class attribute common to the elements you want to add the listeners and in Javascript(Jquery) add the System to all elements that contain this class.

$(document).ready(function() {
  //Todos os elementos cujo o atributo classe contenha a classe pokload adiciona o listener.
  $(".pokload").focusout(function() {
    carregarPokemon(this.id);
  });
});
//Implementação hipotética da função carregarPokemon()
function carregarPokemon(n) {
  console.log(n);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="pok11" class="pokload"><br>
<input id="pok12" class="pokload"><br>
<input id="pok13" class="pokload"><br>
<input id="pok14" class="pokload"><br>
<input id="pok15" class="pokload"><br>
<input id="pok16" class="pokload"><br>
<input id="pok21" class="pokload"><br>
<input id="pok22" class="pokload"><br>
<input id="pok23" class="pokload"><br>
<input id="pok24" class="pokload"><br>
<input id="pok25" class="pokload"><br>
<input id="pok26" class="pokload"><br>

2

The issue here is not "creating a jQuery loop", but "creating a Javascript loop". The fact that using jQuery does not make you have a specific implementation, just using the Javascript structure is enough.

Basic things to refactor duplicate code:

Isolate what is common:

$("#pokXX").focusout(function(){
  carregarPokemon("pokXX");
});

Find a way to manipulate what is variable (XX), whether in a method, loop, etc:

Here are the values from 11 to 26 (XX), so you can make a loop with for:

for(var cont=11; cont<=25; cont++) {
  var idPok = "pok" + cont;
  
  $("#"+idPok).focusout(function(){
     carregarPokemon(idPok);
  });
}

EDIT: as well noted by @rafael-Tavares, there are "holes" in the sequence, that is, numbers that do not have an element, and when making the loop with values between 11 and 26, will try to associate an event to a non-existent element (in practice, will give error when returning a null for not finding the element). In this case, an option is to create an array with the list of valid ids, and take advantage of the for using this array:

let poks = ['pok11', 'pok12', 'pok13', 'pok14', 'pok15', 'pok16', 'pok21', 'pok22','pok23','pok24','pok25','pok26'];

for(var i=0; i<poks.length; i++) {
  $("#"+poks[i]).focusout(function(){
    carregarPokemon(poks[i]);
  });
}
  • Your for will attempt to create listeners for elements that do not exist (at least, which are not in the question). I think a better solution for this case would be to create an array: ['pok11', 'pok12', 'pok13', 'pok14', 'pok15', 'pok16', 'pok21'...]

  • yes @Rafaeltavares well noticed, I put a more "generic" example, but had not noticed it, I will edit the question with this suggestion thanks :)

  • 4

    Better than several listeners is to create only one Listener, attached at least in common relative to all elements, and make use of Event delegation.

  • is right @Luizfelipe, and may have several ways to solve, but I tried to make a more didactic approach that at the same answer what has in the question "I want to use a loop to solve this"

0

I leave one more alternative to how it can be done, depending on your HTML, that was not posted. Vc can be based on a parent element and by the method find() find the child element desfocado:

$(document).ready(function() {
  $('#pai').find('input').focusout(function() {
    carregarPokemon($(this).attr('id'));
  });
})

function carregarPokemon(val) {
  console.log(val);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="pai">
  <input id="pok11"><br>
  <input id="pok12"><br>
  <input id="pok13"><br>
  <input id="pok14"><br>
  <input id="pok15"><br>
  <input id="pok16"><br>
  <input id="pok21"><br>
  <input id="pok22"><br>
  <input id="pok23"><br>
  <input id="pok24"><br>
  <input id="pok25"><br>
  <input id="pok26"><br>
</div>

This way you can better control what you want to catch, including filter what you need to take:

$(document).ready(function() {
  $('#pai').find('input').focusout(function() {
    if($(this).attr('name') === 'teste') carregarPokemon($(this).attr('id'));
    if($(this).attr('class') === 'pokload') carregarPokemon($(this).attr('id'));
  });
})

function carregarPokemon(val) {
  console.log(val);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="pai">
  <input id="pok11" name="teste"><br>
  <input id="pok12"><br>
  <input id="pok13"><br>
  <input id="pok14"><br>
  <input id="pok15" class="pokload"><br>
  <input id="pok16"><br>
  <input id="pok21"><br>
  <input id="pok22"><br>
  <input id="pok23"><br>
  <input id="pok24"><br>
  <input id="pok25"><br>
  <input id="pok26"><br>
</div>

  • How you put the elements <input> inside a container does not need to use the find(). just think the focusout in the container like this: $('#pai').focusout(function() {.... ....});

  • @Augustovasques I didn’t understand what you meant, as well as remove the find() because of a container?? I didn’t understand your placement!

  • Just clarify that it was not I who denied. When assigning the event focusout a container that event is triggered when a nested element loses focus. $('#pai').focusout(function(e) {carregarPokemon(e.target.id);});. Behold Event delegation(topic just above link destination )

  • 1

    Right, but, uh, the find('input') is on purpose even. As in all responses my tbm was based on a HTML non-existent and suggestive, what if, for example, within the cointaner there are other elements that can both receive focus and lose it (button, textarea, select, etc.)? As you showed, soon these fields tbm would perform the function unnecessarily! As for the score, I don’t care about that ;)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.