I’m a beginner, so I apologize if I’m missing something obvious.
I’m trying to write a simple web app. When you type text into a textarea and click a button, a “card” (div) is created with that textarea’s value as its innerText. When you click on a card, its innerText is then copied to the clipboard.
It works when I write out the function this way:
el.setAttribute(
"onclick",
"console.log(navigator.clipboard.writeText(this.innerText));"
);
But if I write out the function separately and call it when setting the attribute, undefined
is copied to the keyboard:
el.setAttribute("onclick", "copyText()");
I’d stick with the first, working option, except for two things:
- Primarily I’m just trying to learn, so avoiding difficulties because I don’t understand them doesn’t really make sense.
- I want to add more lines of code to the copyText() function so that it works on mobile devices, too. Can I even do that the first way?
Here’s my code in full:
const app = document.getElementById("app");
function createCard() {
let input = document.getElementById("textarea").value;
if (input == "") {
console.log("You must enter text to create a card.");
} else {
const el = document.createElement("div");
el.innerText = document.getElementById("textarea").value;
el.setAttribute("class", "item card");
el.setAttribute("onclick", "copyText()");
app.appendChild(el);
document.getElementById("textarea").value = "";
}
}
function copyText() {
navigator.clipboard.writeText(this.innerText);
}
I expected it to work exactly the same as the following, but it doesn’t. It returns undefined
.
const app = document.getElementById("app");
function createCard() {
let input = document.getElementById("textarea").value;
console.log(input);
if (input == "") {
console.log("You must enter text to create a card.");
} else {
const el = document.createElement("div");
el.setAttribute("class", "item card");
el.setAttribute(
"onclick",
"console.log(navigator.clipboard.writeText(this.innerText));"
);
el.innerText = document.getElementById("textarea").value;
app.appendChild(el);
document.getElementById("textarea").value = "";
}
}
I suspect it’s an issue with “this” and scope, but I can’t figure it out. Sorry again—I know this is very much a beginner’s question. Thanks for your help.
CodePudding user response:
Calling copyText()
calls it without a this
context. You would need to use
el.setAttribute("onclick", "copyText.call(this)");
// ideally also pass the event object:
el.setAttribute("onclick", "copyText.call(this, event)");
However, the best practice is to install an event handler function instead of using the onclick
attribute, so you should do
el.onclick = copyText;
// or
el.addEventListener("click", copyText);
Notice these refer to the copyText
function that is in scope, it doesn't need to be a global variable.
const input = document.getElementById("textarea");
const app = document.getElementById("app");
function createCard() {
console.log(input.value);
if (!input.value) {
console.log("You must enter text to create a card.");
} else {
const el = document.createElement("div");
el.className = "item card";
el.onclick = function() {
console.log(navigator.clipboard.writeText(this.textContent));
};
el.textContent = input.value;
app.appendChild(el);
input.value = "";
}
}