THIS ISSUE HAS BEEN FIXED
Note: You can read the solution and the evaluation that I carried out thanks to the answers after the explanation of the problem.
I am trying to create a small JavaScript script in order to solve some needs for users (a UserLand Script).
The operation is very simple, and to make it as simple as possible, I need to add some elements to the DOM, with CSS, text, functions etc.
So that the script knows what elements to create, what CSS to apply, what text, etc. I have created an object that has the following form:
options: {
/* Button */
'button': {
'tagName' : 'button',
'innerHTML' : 'X',
'css' : {
'position' : 'fixed',
'z-index' : '9999999',
'bottom' : '20px',
'left' : '20px',
'background-color' : 'black',
'cursor' : 'pointer',
'color' : 'white',
'width' : '60px',
'height' : '60px',
'border' : 'none',
'border-radius' : '50%',
'font-weight' : 'bold',
'font-size' : '1.5rem'
},
'onClick' : 'objectName.method()'
}
}
My script executes the following code through a loop:
createElement: (element) => {
/* Create element */
const createElement = document.createElement( element.tagName );
/* Add innerHTML */
createElement.innerHTML = element.innerHTML;
/* Add CSS */
objectName.addCSStoElement( createElement, element.css );
/* Add onClick event*/
createElement.addEventListener( 'click', element.onClick, false );
/* Add to DOM */
document.body.appendChild ( createElement );
}
Everything runs correctly, except for the instruction:
createElement.addEventListener( 'click', element.onClick, false );
I guess it's because it is as a string, and this is how it is appended by JS to the "onClick" event.
Assuming I am not mistaken, how could I go about adding the name of the function so that it can be executed when clicking on the created element?
I hope I have expressed myself well and that my bad English does not lead to confusion.
Thanks for your time and your help, greetings to all!
Regards, Alex
SOLUTION:
I have realized that the information that I contributed when exposing my problem was not completely complete, for example, I did not indicate if it was a global or local object, I am very sorry.
It is a local Object, and, in this case, it is code that can be trusted since it is code that I myself am injecting into the browser every time it enters a website with the aim of favoring me in certain tasks.
Taking this into account, we can proceed, if in any case this is not your case, please take into account the information that the colleagues added in their answers, they are very interesting and important.
The changes I had to make are: First, modify, inside "options", the value that "onClick" had by the following:
'onClick' : '(function(){objectName.method();})'
Finally, I modified the way in which the event to the HTML element is added by the following:
createElement.addEventListener( 'click',eval(element.onClick), false );
And, with these simple changes, I managed to solve and understand what the problem was!
Thank you very much to all who responded and gave me their help and time, I wish you the best!
Since you're asking specifically about using a string to create an HTML event handler fro a string, and you know you can trust the conents of the string (that it doesn't have malicious content), you could use setAttribute
:
createElement.setAttribute("onclick", element.onClick);
Live Example:
const objectName = {
method() {
console.log("objectName.method() called");
}
};
const btn = document.createElement("button");
btn.textContent = "Click Me";
const onClick = "objectName.method()";
btn.setAttribute("onclick", onClick);
document.body.appendChild(btn);
Note that objectName
must be a global variable, not local to the code doing this.
Alternatively, you can do it the way this question's answers show, which I wrote up below before realizing I should look for a duplicate (now un-dupehammered per comments):
Since you can trust the source of the string containing the code, you can use new Function
to create a function using that code as its body:
createElement.addEventListener( 'click', new Function(element.onClick), false );
Don't do this with strings you can't trust.
Note that any variables the code refers to will have to be globals.
Live Example:
const objectName = {
method() {
console.log("objectName.method() called");
}
};
const btn = document.createElement("button");
btn.textContent = "Click Me";
const onClick = "objectName.method()";
btn.addEventListener("click", new Function(onClick), false);
document.body.appendChild(btn);
If you need to refer to local variables, you can use eval
(again: don't if you can't trust the source of the text! you're eval
ing!):
createElement.addEventListener( 'click', eval("(function() { " + element.onClick + "})"), false );
Live Example:
{ // A block so the code isn't at global scope
const objectName = {
method() {
console.log("objectName.method() called");
}
};
const btn = document.createElement("button");
btn.textContent = "Click Me";
const onClick = "objectName.method()";
btn.addEventListener("click", eval("(function() { " + onClick + "})"), false);
document.body.appendChild(btn);
}