Callback being executed the moment you load the page

8

I'm doing some testing to learn more about callback in javascript and found the following difficulty:

function nome_existe(element) {
  console.log(element.id);
}
window.onload = function() {
  Array.from(document.getElementById("form_id")).forEach(function(element, index) {
    element.addEventListener("blur", nome_existe(element));
  });
};
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>
The excerpt puts the elements of a form into a array and theoretically (in my mind) should assign a listner to the field that received the blur event and then log the id of the element in the% console.

The difficulty is: Why is running the onload event on the console the ids of all elements, even without the blur event occurring?

    
asked by anonymous 17.07.2017 / 14:13

3 answers

5

If the function is not anonymous it will be invoked in the event log. In your case, you can invoke nome_existe within an anonymous function in the callback of blur :

function nome_existe(element) {
  console.log(element.id);
}
window.onload = function() {
  Array.from(document.getElementById("form_id")).forEach(function(element, index) {
    element.addEventListener("blur", function() {
      nome_existe(element);
    });
  });
}
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>

Calling a declared function outside callback :

A very common implementation is to invoke a function out without arguments where the function will have the scope of the invoking:

function nome_existe() {
  console.log(this.id);
}
window.onload = function() {
  Array.from(document.getElementById("form_id")).forEach(function(element, index) {
    element.addEventListener("blur", nome_existe);
  });
}
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>

Calling a function declared out of the callback with arguments

If you need to use arguments in the declared function, one way would be to do bind :

function nome_existe(arg) {
  console.log(this.id, arg);
}
window.onload = function() {
  Array.from(document.getElementById("form_id")).forEach(function(element, index) {
    element.addEventListener("blur", nome_existe.bind(element, 'Index: ' + index));
  });
}
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>
    
17.07.2017 / 14:43
4

If you want to save a reference of the element that is being iterated you can use .bind() that will create a function, passing the element as the first argument.

But you really do not need to pass your nome_existe function and use this inside it. The this is always the element that has .addEventListener .

Example:

function nome_existe(event) {
  console.log(this.id, event.type);
}
window.onload = function() {
  Array.from(document.getElementById("form_id")).forEach(function(element, index) {
    element.addEventListener("blur", nome_existe);
  });
};

function valida_check(){

}
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>
    
17.07.2017 / 15:34
1

The callbacks functions that handle events in JavaScript are given as parameters by the object that describes their event. The event object has the target attribute that represents the target element of this event. In this case, the parameter of the nome_existe function will be the blur event, and the target attribute of this object will be the form field. This way, you can access the id of the field with evento.target.id . See the example below:

function nome_existe(evento) {
  console.log(evento.target.id);
}

window.onload = function () {

  for (let element of document.getElementById("form_id")) {
    element.addEventListener("blur", nome_existe);
  }
  
}
<form id="form_id" method="POST" action="/cloud/criar-conta.php" autocomplete="off">
  <input type="text" name="input_nome" id="input_nome" placeholder="Insira um nome" value="" /><br/>
  <input type="text" name="input_email" id="input_email" placeholder="" value="Insira um email" /><br/>
  <input type="text" name="input_email_c" id="input_email_c" placeholder="" value="Confirme seu email" /><br/>
  <input type="text" name="input_tel" id="input_tel" placeholder="" value="(DDD) - _____ - ____" /><br/>
  <input type="password" name="input_senha" id="input_senha" placeholder="Digite uma senha" value="" /><br/>
  <input type="password" name="input_senha_c" id="input_senha_c" placeholder="Confirme sua senha" value="" /><br/>
  <input type="checkbox" name="input_check" id="input_check" onblur="valida_check()" />
  <p id="termo_cad">Concordo com os Termos de Serviçes e Política de Privacidade</p>
  <input type="submit" name="sub_btn" id="sub_btn" value="Enviar" />
</form>

From ECMAScript 2015 you can use the for ... of notation as I used above. The logic about callback , which is the context of the question, is exactly the same. It can be applied together with Array.forEach in the same way. I used it as a way to complete the other answers, presenting a different form.

    
17.07.2017 / 15:13