Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Marcus Schumacher
Marcus Schumacher
16,616 Points

JS event listener problem

In an unordered list, I added an event listener to update localStorage memory whenever a text area element was changed. I want to update localStorage to reflect the change in the text content of the text area. The problem is, when I try to get the new value of the text area after it has been changed, it gives me what the text content was BEFORE the text area was changed by the user. How does this work? Why would an event listener function this way?

If you need anything clarified, let me know. Thanks :)

ul.addEventListener('change',(e)=> { 
    if(e.target.tagName === "TEXTAREA") { // if the ul was changed and a textarea was targeted
        const li = e.target.parentNode; // the parent list item of the text area
        const liName = li.firstChild.textContent; // this is a string
        var newNotes = e.target.textContent; // PROBLEM : RETURNS WRONG VALUE
        console.log(newNotes);
        updateNotesTo(liName, newNotes); // regarding localStorage         

    }              
});
grant Mitchell
grant Mitchell
6,919 Points

could you send the whole thing?

Marcus Schumacher
Marcus Schumacher
16,616 Points
document.addEventListener('DOMContentLoaded', () => {


const form = document.getElementById('registrar');
const input = form.querySelector('input');
const mainDiv = document.querySelector('.main');
const ul = document.getElementById('invitedList');

const div = document.createElement('div');
const filterLabel = document.createElement('label');
const filterCheckbox = document.createElement('input');

filterLabel.textContent = "Hide those who haven't responded";
filterCheckbox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckbox);

mainDiv.insertBefore(div, ul);




var filterBoxChecked = localStorage.getItem('filterBoxChecked');
var filterBoxChecked = JSON.parse(filterBoxChecked);

function updateLocalStorageFilterBox() {
   var correctBool = JSON.stringify(filterBoxChecked);
   localStorage.setItem('filterBoxChecked', correctBool); 
}

function setFilterBoxTo(boolean) {
   filterBoxChecked = boolean;
   filterCheckbox.checked = boolean;
   updateLocalStorageFilterBox();
}

// this returns the arrray of items in storedItems from localStorage, returned parsed out of JSON
function getStoredListItems() {
  var storedItems = localStorage.getItem('storedItems'); 
  if(storedItems) {
    return JSON.parse(storedItems);
  }
  else {
   return []; 
  }
}

// takes the string name of the li you want to update, and changes it's going value in localStorage
function updateGoingTo(itemNameStr, desiredBool){

  var storedItems = getStoredListItems();
  for(let i=0; i<storedItems.length; i++) {
    if(storedItems[i].name == itemNameStr) {
      var targetedItem = storedItems[i];
      targetedItem.going = JSON.stringify(desiredBool);
      localStorage.setItem('storedItems', JSON.stringify(storedItems));
    }
  }

}

 function updateNotesTo(itemNameStr, notesStr) {
  var storedItems = getStoredListItems();
  for(let i=0; i<storedItems.length; i++) {
    if(storedItems[i].name == itemNameStr) {
      var targetedItem = storedItems[i];
      targetedItem.notes = JSON.stringify(notesStr);
      localStorage.setItem('storedItems',JSON.stringify(storedItems));
    }
  }
} 


// adds a new item with a string name and null going value to stored items. Complete necessary JSON conversions
function addStoredItem(str) {
  var storedItems = getStoredListItems();
  var newItem = {

  name: str,
  going: "null",
  notes: "null"

  };

  storedItems.push(newItem);
  localStorage.setItem('storedItems', JSON.stringify(storedItems));
}


// When the filter checkbox is changed, it modifies all the list items appropriately
filterCheckbox.addEventListener('change', (e) =>{
  const isChecked = e.target.checked;
  const lis = ul.children;
  if(isChecked) {
    for(let i=0; i<lis.length; i++) {
      let li = lis[i];
      const cb = li.children[1].firstElementChild;
      if(li.className === 'responded') {
        li.style.display = '';  
        cb.style.display = 'none';
      } else {
        li.style.display = 'none';
      }
    }
    setFilterBoxTo(true); // regarding localStorage
  } else {
    for(let i=0; i<lis.length; i++) {
      let li = lis[i];
      const cb = li.children[1].firstElementChild;
      li.style.display = '';
      cb.style.display = 'inline';
    }
    setFilterBoxTo(false); // regarding localStorage
  }

});


// This whole function creates a list item with all the required buttons and elements
function createLi(text){

   function createElement(elementName, property, value) {
      const element = document.createElement(elementName);
      element[property] = value;
      return element;
   }
   function appendToLi(elementName, property, value) {
     const element = createElement(elementName, property, value);
     li.appendChild(element);
     return element;
   }

   const li = document.createElement('li');

   appendToLi('span', 'textContent', text);

   appendToLi('label', 'textContent', 'Confirm')
    .appendChild(createElement('input', 'type', 'checkbox'));


   appendToLi('button', 'textContent', 'edit');

   appendToLi('button', 'textContent', 'remove');

  appendToLi('textarea', 'textContent', 'Notes');

   return li;
}


// when the form is submited, it checks to see if there are copies, then creates a list item from the texted entered into the form
form.addEventListener('submit', (e)=> {
   e.preventDefault();  // This prevents the default refreshing of the page upon submit
   const text = input.value;           
   input.value = '';

  // this determines if copies of li's exist
  function thereAreCopiesOf(text) { 
    const allLis = document.querySelectorAll('li');
    var copyExists = false;
    for(let i=0; i<allLis.length; i++) {

      if(allLis[i].firstChild.firstChild.textContent.trim().toUpperCase() === text.trim().toUpperCase()) {
        copyExists = true;
     }
    }
    return copyExists;
  }

  if(thereAreCopiesOf(text) === true){
     alert('No copies allowed');
  } else {

       if(text != '') {
          const li = createLi(text); //take the text and make an li with it
          ul.appendChild(li); // then attatch it to the ul 
          addStoredItem(text);    // and add the item's text to local storage to be used later
         } else {
           alert('Enter a name'); 
         }
      }

});

ul.addEventListener('change', (e) => { // when you change the ul
   if(e.target.type == "checkbox"){                 
      const checkbox = event.target;
      const checked = checkbox.checked;
      const listItem = checkbox.parentNode.parentNode;
      const label = listItem.children[1];
      let labelText = label.firstChild;
      const liText = listItem.firstElementChild.textContent;

      if(checked) { // if a box is checked
        listItem.className = 'responded'; // change the style of its parent
        labelText.textContent = 'Confirmed'; // haha so damn strange. But it works

        updateGoingTo(liText, true); // this updates the local storage object regarding going

      } else {
         listItem.className = '';
         labelText.textContent = 'Confirm';
         updateGoingTo(liText, false);
      }
   }

});

ul.addEventListener('click', (e)=> { // when you click on a button
    if(e.target.tagName === 'BUTTON') {
      const button = e.target;
      const li = button.parentNode;
      const ul = li.parentNode;

      function removeName() {
        ul.removeChild(li);
        var storedItems = getStoredListItems();
        for(let i=0; i<storedItems.length; i++) {
           if(li.firstChild.textContent == storedItems[i].name) {
             storedItems.splice(i,1);
             localStorage.setItem('storedItems', JSON.stringify(storedItems));
           }
        }
      }
      function editName() {
        const span = li.firstElementChild; 
        const input = document.createElement('input');
        input.type = 'text';
        input.value = span.textContent;
        li.insertBefore(input, span); // put the input before the span
        li.removeChild(span); // then get rid of the span
        button.textContent = 'save';
      }
      function saveName() {
         // get the value of the input text
        const input = li.firstElementChild;
        const inputValue = input.value;

        // add a span with the new input
        const span = document.createElement('span');
        span.textContent = inputValue;
        li.appendChild(span);
        li.insertBefore(span, input);

        // remove the input
        li.removeChild(input);

        // change button text back to edit
        button.textContent = 'edit';
      }

      if(button.textContent === 'remove'){
         removeName();
      } else if(button.textContent === 'edit') {
        editName();
      } else if(button.textContent === 'save') {
        saveName();
      }
    }    
});

ul.addEventListener('change',(e)=> {  // xx
    if(e.target.tagName === "TEXTAREA") { // if the ul was changed and a textarea was targeted
        const li = e.target.parentNode; // the parent list item of the text area
        const liName = li.firstChild.textContent; // this is a string
        var newNotes = e.target.textContent; // PROBLEM : RETURNS WRONG VALUE
        console.log(newNotes);
        updateNotesTo(liName, newNotes); // regarding localStorage         

    }              
});

// here we create the list items from the data in local storage
getStoredListItems().forEach(function(obj) {
    const text = obj.name;
    const li = createLi(text);
    ul.appendChild(li);
    let checkbox = li.querySelector('input');
    let checkboxLabel = li.children[1];
    let checkboxLabelText = checkboxLabel.firstChild;

     // if they are marked going in localStorage, give them the responded class name
    if(obj.going == "true") {
      li.className = 'responded';
      checkbox.checked = true;
      // again, line below is strange, but it works
      checkboxLabelText.textContent = "Confirmed";
      checkbox.style.display = 'none';
      // and also make sure the confirmation checkbox is in the right state
    } else if(obj.going == "false" || obj.going == "null") {
      li.className = '';
      checkbox.checked = false;
      checkboxLabelText = "Confirm";
      checkbox.style.display = 'inline';
    }
});

if(filterBoxChecked) {
    const lis = ul.children;
    for(let i=0; i<lis.length; i++) { // for every li element
      let li = lis[i];
      const cb = li.children[1].firstElementChild;
      if(li.className === 'responded') { // properly display them or not
        li.style.display = '';  
        cb.style.display = 'none';
      } else {
        li.style.display = 'none';
      }
    }
    filterCheckbox.checked = true;
  } else {
    const lis = ul.children;
    for(let i=0; i<lis.length; i++) {
      let li = lis[i];
      const cb = li.children[1].firstElementChild;
      li.style.display = '';
      cb.style.display = 'inline';
    }
    filterCheckbox.checked = false;
  }




}); // end of dom loaded event listener