Home > Software design >  How to make Javascript "focusout" event only fire once?
How to make Javascript "focusout" event only fire once?

Time:09-17

Here is my current function:

document.getElementById('textarea').addEventListener('focusin', () => {
    document.getElementById('UserTextArea').classList.add('text-selected');
    document.getElementById('textarea').style.marginBottom = "0px";

    document.getElementById('textarea').addEventListener('focusout', () => {
    let CommentText = document.querySelector('.textarea').innerText;
    chrome.storage.local.set({SavedComments: CommentText}, function() {
    });
});
});

It works, and it's functional. However as is made clear when I insert some "alert('hello world')"s in there to test it out? The "focusout" event doesn't just fire once. It fires at least a few times, sometimes a very large number of times. The program works, and the functionality is there -- however a concern I have is, as I add more and more features to the application, this poorly written code will cause some issues to emerge.

Upon further inspection, the way this is written? It seems increment the event listener each time. So each time the person focuses in on the textbox, then focuses out? It fires the accompanying function one additional time. So after focusing in and out 13 times, it will fire 13 in a row. On the 20th time, 20 times in a row, etc.

What's the cleanest way to make a "focusout" event only fire once?

Thanks!

CodePudding user response:

It seems increment the event listener each time.

Exactly – an event listener for focusout gets added each time focusin fires, and never gets removed.

Keep just one listener for each event at all times:

document.getElementById('textarea').addEventListener('focusin', () => {
    document.getElementById('UserTextArea').classList.add('text-selected');
    document.getElementById('textarea').style.marginBottom = "0px";
});

document.getElementById('textarea').addEventListener('focusout', () => {
    let CommentText = document.querySelector('.textarea').innerText;
    chrome.storage.local.set({SavedComments: CommentText}, function() {
    });
});

Also, if .textarea is a <textarea>, you want .value, not .innerText. (And is textarea both its id and class?)

Separately, consider using CSS to apply the margin change if it wasn’t intentional that you didn’t remove it in focusout:

#textarea:focus {
    margin-bottom: 0px;
}
  • Related