skip to Main Content

I have an focus and keydown events. Everytime the input element is out of focus or an enter key is pressed, I update the page to reflect the changes.

The Render class rerenders the currently selected page.

The issue here is that when I update the page with the enter key, both the focusout and kedown events are fired. This code seems to work only if I give the event’s callback a timeout.

The question is, is it possible to sovle this "event colission" without setTimeout and why does that happen?

// Page content class
const descriptionInput = document.createElement('textarea');
const handleDescription = function(e){
            if( (e.key === "Enter" && !e.shiftKey) || 
            (e.type === "focusout")
            ){
                task.description = this.value;
                storage.updateTask(task.id, task);
                (new Render).refreshPage()
            }
        }
descriptionInput.addEventListener('keydown', handleDescription)
descriptionInput.addEventListener('focusout', handleDescription)
// Render class
renderPage(contentFunction){
        const pastContent = document.querySelector('.content');
        if(pastContent) this.pageContainer.removeChild(pastContent);
        this.pageContainer.appendChild(contentFunction());
    }
refreshPage(){
    const currentPage = document.querySelector('.sidebar li[selected]');
    switch (currentPage.getAttribute('name')) {
        case 'Active Task':
            this.renderPage(activeTasks);
            break;
        case 'Complete Task':
            this.renderPage(completeTask);
            break;
    }
}
// No error snippit
if( (e.key === "Enter" && !e.shiftKey) || 
        (e.type === "focusout")
        ){
            setTimeout(() => {
                task.description = this.value;
                storage.updateTask(task.id, task);
                (new Render).refreshPage()
            }, 100)
        }

2

Answers


  1. Chosen as BEST ANSWER

    As stated in this thread, focusout is fired when an input is removed from the DOM. What worked for me is removing the event listener.

    const handleDescription = function(e){
                if( e.key === "Enter" && !e.shiftKey ){
                    descriptionInput.removeEventListener('focusout', handleDescription);
                    task.description = this.value;
                    storage.updateTask(task.id, task);
                    (new Render).refreshPage()
                }
                if(e.type === "focusout")
                {
                    task.description = this.value;
                    storage.updateTask(task.id, task);
                    (new Render).refreshPage()
                }
            }
    

  2. When you focusout by pressing the key. You call function handleDescription twice. To solve this problem, you can use a flag and as long as it is true, the function will not be called again.
    now you can remove setTimeout.

    const descriptionInput = document.createElement('textarea');
    
    let descIsUpdating = false;
    
    const handleDescription = function(e) {
    
        if (descIsUpdating) {
          return false;
        }
    
        if ((e.key === "Enter" && !e.shiftKey) ||
            (e.type === "focusout")
           ) {
            descIsUpdating = true; // start updating
            task.description = this.value;
            storage.updateTask(task.id, task);
            (new Render).refreshPage();
            descIsUpdating = false; // updating is finished
        }
    };
    
    descriptionInput.addEventListener('keydown', handleDescription);
    descriptionInput.addEventListener('focusout', handleDescription);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search