2

I have a js file with code like this:

var myAnonFun = function (param1) {


function createHTML(){

.....
sHTML += "<select id=param1 onchange='makeCalculations(this)'  >";
}

var vText = document.getElementById("results");
vText.innerHTML = sHTML;


function makeCalculations(){
}

}

Then, in a HTML file I have something like this:

var createAnonFun = myAnonFun (param1);

The code inside the js file will work as expected. However, whenever a value is chnaged in the select html object created inside the js file, I will get an error stating that there is not makeCalculations function.

As far as I understand, the problem is that the select object is trying to reach a function from the global scope, and of course there isnt one there.

So my question is: how can I target the select object to the makeCalculations function inside the myAnonFun var?

thank you in advance!

user3643038
  • 143
  • 12

3 Answers3

0

makeCalculations is declared within var myAnonFun = function (param1) { so its scope is local to that funcion (it will not be accessible globally).

Your best bet is, instead of declaring inline event handler, use an event listener:

So instead of:

sHTML += "<select id=param1 onchange='makeCalculations(this)'  >";

Do:

sHTML += "<select id=param1>";

vText.innerHTML = sHTML; // Without this the following event listener will not work

// and when you are sure the <select> above has been added to the DOM
document.getElementById('param1').addEventListener('change', function() {
    makeCalculations(document.getElementById('param1'));
});


Another option (not recommended, though), is to make makeCalculations available globally:

Change :

sHTML += "<select id=param1 onchange='makeCalculations(this)'  >";

to:

sHTML += "<select id=param1 onchange='createAnonFun.makeCalculations(this)'  >";

And, at the end:

    function makeCalculations(){
    ...
    }
}

to:

    function makeCalculations(){
    ...
    }
    return {makeCalculations};
}

Note that for this to work, you must have executed somewhere (outside of a function):

var createAnonFun = myAnonFun (param1);
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • acdc junior, I thought that using inline event handler would be the same as using an event listener. Is there a difference between them, or the difference is how the function is set in the second one? – user3643038 Dec 27 '17 at 17:17
  • Using `addEventListener()` instead of inline is more of a readability and maintainability thing, see: https://stackoverflow.com/a/15792621/1850609 – acdcjunior Dec 27 '17 at 17:22
  • Then, in the first option, what you are saying is to pass the whole function as a parameter, right? If I only pass the function call, I will get the same scope problem, or not? thank you – user3643038 Dec 27 '17 at 17:39
  • What do you mean by "only pass the function call"? This `document.getElementById('param1').addEventListener('change', makeCalculations);` ? If so, this works, the difference is that the first argument of `makeCalculations` will be the `event`, not the element (which is why I passed a function that wraps to a call to `makeCalculations` with the element as first argument. OTOH, you can still get the element from the `event` object (in `event.target`). – acdcjunior Dec 27 '17 at 17:50
  • acdcjunior, what I dont understand is what makes the addEventListener works if we are still just passing the method call. How the method will be found? The method still belongs to a private scope, right? – user3643038 Dec 27 '17 at 22:02
  • When you use inline, the handler function must be present in the global scope (`window.handlerFunctionName` must exist). When using `.addEventListener('event', handler)` the handler must exist only in the scope where `.addEventListener()` is called, not necessarily in the global scope. What do you think? – acdcjunior Dec 27 '17 at 22:08
  • Amazing difference between the two. I didnt realize it before. Very good answer. It is working now. thank you! – user3643038 Dec 28 '17 at 14:55
0

You could make makeCalculations available in the global scope:

this.makeCalculations = function() {
  // ....
}

// Outside:

myAnonFun.makeCalculations();
Jacques Marais
  • 2,666
  • 14
  • 33
0

Instead of sHTML += "<select id=param1 onchange='makeCalculations(this)' >";

you could use the following.

var selectElement = document.createElement("select");
selectElement.addEventListener("change", makeCalculations);
vText.appendChild(selectElement); //this or replace all contents of vText

This method also removes unnecesary string concatenation confusions.

xadhix
  • 174
  • 15