Error with scope

0

I have this code, and a very common error that I have is that we very much control the scope between HTML and Javascript , by that I mean that many times when I call a function directly from the HTML and that function is in a separate js file, it always tells me that the function is not defined , like here:

As you can see by clicking on the text inputs, the function is not defined in the console.

The function that says not to be defined is the checkRealTime , that function is added by onblur to all inputs of the document (I think because in addition the onblur does not work correctly at the first click , then there must be more errors still ...)

How to fix this, and why does it happen?

/* Independent functions */
window.addEventListener('DOMContentLoaded',functions); /* Waiting for DOM Load */

function functions(){
var getLabels = document.getElementsByTagName('label'),j=0,lmax=getLabels.length;
for(;j<lmax;j++) { getLabels[j].style.fontFamily = 'Monospace'; }
validateInputs();
function checkRealTime(id){
	console.log(id);
}
}

function validateInputs(){
	var pattern = /[0-9]/;
	var inputs = document.getElementsByTagName('INPUT');
	for(let i = 0; i<inputs.length;i++) {
		inputs[i].setAttribute('onblur','checkRealTime('+inputs[i].id+')');
	}
	

}
<!DOCTYPE html>
<html>
<head>
<title>zero to hero ?</title>
<meta charset='utf-8'>
<script src="functions.js"></script>
<script src="igenerator.js"></script>
</head>
<!-- I define the default css values !-->
<style>
body { color: gray; margin: 0;}
.title { font-family: monospace; color: black; font-size: 25px; margin-left: 35vw;} 
.ms { font-family: monospace;}
</style>
<body>
  <b class="title">Javascript Input generator(and can be deleted)</b>
  <hr></hr>
   <label for="inputgen"> Number of inputs to be generated: </label>
   <input type="text" placeholder="to add" id='inputgen'> <input type="button" value="Generate" id='b-generate'>

   <label for="idel"> Number of inputs to be deleted: </label>
   <input type="text" placeholder="to delete" id="idel"> <input type="button" value="Delete" id="b-delete">
   <hr></hr>
</body>
</html>
    
asked by Eduardo Sebastian 24.09.2017 в 18:26
source

2 answers

1

The checkRealTime function is defined within the functions method so it will only be visible for the functions / events that are declared within the functions function, so the validateInputs function can never get the reference of the function checkRealTime because it is defined outside of the function functions :

function functions() {
   //.. 
    // solo esta definida para uso interno de la funcion functions
    function checkRealTime(id) {
        console.log(id);
    }
    checkRealTime(1); // valido
}

functions();
setTimeout(checkRealTime, 3000);// invocarla despues de los 3 segundos y fallara diciendo que no esta definida en su ambito

You have to define the function in the same scope of visibility or a higher level of where it is being invoked. For example, defining it outside the function functions official:

function functions() {
    //.. 
    // solo esta definida para uso interno de la funcion functions
    checkRealTime(1); // valido
}
function checkRealTime(id) {
    console.log(id);
}

function validateInputs(){
 functions();
   setTimeout(function(){
    checkRealTime(2);
   }, 3000);// invocarla despues de los 3 segundos e imprimira 2
 }
  validateInputs();

Here it works for both because they are at the same level of scope or reach.

You can also make the function checkRealTime publish if you declare it with the object window that in essence would be the same as declaring it outside the method functions :

    function functions() {
       //.. 
        // solo esta definida para uso interno de la funcion functions
        window.checkRealTime = function(id) {
            console.log(id);
        }
        checkRealTime(1); // valido
    }

    functions();
    setTimeout(function(){ checkRealTime(3); }, 3000);// invocarla despues de los 3 segundos

So your code would be like this:

/* Independent functions */
window.addEventListener('DOMContentLoaded',functions); /* Waiting for DOM Load */

function functions(){
   var getLabels = 
   document.getElementsByTagName('label'),j=0,lmax=getLabels.length;
   for(;j<lmax;j++) { 
     getLabels[j].style.fontFamily = 'Monospace';
   }
   validateInputs();
}

function checkRealTime(id){
    console.log(id);
}

function validateInputs(){
    var pattern = /[0-9]/;
    var inputs = document.getElementsByTagName('INPUT');
    for(let i = 0; i<inputs.length;i++) {
        inputs[i].setAttribute('onblur','checkRealTime('+inputs[i].id+')');
    }
}
    
answered by 24.09.2017 / 19:38
source
0

The problem is where you have defined checkRealTime, since you have created it within another function. Also, when you dynamically create the call to the checkRealTime function, the program will take the parameters as variable names, not as variables. It works for me, leaving it like this:

/* Independent functions */
window.addEventListener('DOMContentLoaded',functions); /* Waiting for DOM Load */

function functions(){

var getLabels = document.getElementsByTagName('label'),j=0,lmax=getLabels.length;
for(;j<lmax;j++) { getLabels[j].style.fontFamily = 'Monospace'; }
validateInputs();

}
function checkRealTime(id){
    console.log(id);
}
function validateInputs(){

    var pattern = /[0-9]/;
    var inputs = document.getElementsByTagName('INPUT');
    for(let i = 0; i<inputs.length;i++) {
        console.log(i)
        inputs[i].setAttribute('onblur','checkRealTime("'+inputs[i].id+'")');
    }
}
    
answered by 24.09.2017 в 19:53