JavaScript DOM Scripting By Example Improving the Application Code Next Steps

brendon hanson
brendon hanson
6,191 Points

The checkbox disappears when I add a new person!

I've been trying to solve some of the problems and I have except this weird thing where whenever I type 2 or more people the checkbox on the li disappears from everyone except 1 person.

document.addEventListener('DOMContentLoaded', (e) => {
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');

const confCheckbox = document.createElement('input');
const confLabel = document.createElement('label');

filterLabel.textContent = "Hide those who haven't confirmed yet";
filterCheckBox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckBox);
mainDiv.insertBefore(div, ul);
filterCheckBox.addEventListener('change', (e) => {
  const lis = ul.children;
  const isChecked = e.target.checked;
  if (isChecked) {
    confCheckbox.style.display = 'none';
    confLabel.style.display = 'none';
    for (let i = 0; i < lis.length; i += 1) {
      let li = lis[i];
      if (li.className === 'responded') {
        li.style.display = '';
      } else {
         li.style.display = "none";
        confCheckbox.style.display = '';
    confLabel.style.display = '';
      }
    } 
  } else {  
  for (let i = 0; i < lis.length; i += 1) {    
    const li = lis[i];
    li.style.display = '';
  }
  }
 });

function createLI(text) {
  const li = document.createElement('li');
  const span = document.createElement('span');  
  span.textContent = text;
  li.appendChild(span);

  confCheckbox.type = 'checkbox';
  confLabel.textContent = 'Confirmed';

  confLabel.appendChild(confCheckbox);
  li.appendChild(confLabel);  

  const editButton = document.createElement('button');
  editButton.textContent = 'edit';
  li.appendChild(editButton);

  const removeButton = document.createElement('button');
  removeButton.textContent = 'remove';
  li.appendChild(removeButton);
  return li;
}

form.addEventListener('submit', (e) => {
  e.preventDefault();
  const text = input.value;
  const li = createLI(text);

       if (input.value === '') {
   alert("Must type a real name!"); 
   li.style.display = 'none';
  }

  input.value = '';
  ul.appendChild(li);


});

ul.addEventListener('change', (e) => {
  const checkbox = event.target;
  const checked = checkbox.checked;
  const listItem = checkbox.parentNode.parentNode;

  if (checked) {
    listItem.className = 'responded';
  } else {
    listItem.className = '';
  }
});

ul.addEventListener('click', (e) => {
  if (e.target.tagName === 'BUTTON') {
    const button = e.target;
    const li = button.parentNode;
    const ul = li.parentNode;
    if (button.textContent === 'remove') {
      ul.removeChild(li);
    } else if (button.textContent === 'edit') { 
      const span = li.firstElementChild;
      const input = document.createElement('input');
      input.type = 'text';
      input.value = span.textContent;
      li.insertBefore(input, span);
      li.removeChild(span);
      button.textContent = 'save';
    } else if (button.textContent === 'save') { 
      const input = li.firstElementChild;
      const span = document.createElement('span');
      span.textContent = input.value;
      li.insertBefore(span, input);
      li.removeChild(input);
      button.textContent = 'edit';
    }
  }
});  
  });
Steven Parker
Steven Parker
174,043 Points

This script doesn't seem to work on its own. There must be an HTML (and perhaps CSS) component missing.

You can share an entire project at once if you make a snapshot of your workspace and post the link to it here.

2 Answers

Steven Parker
Steven Parker
174,043 Points

Well, that certainly made it convenient to have both versions!

I compared the working snapshot code to the non-working code posted here and found that in the working code, the variables "confCheckbox" and "confLabel" are created inside the "createLI" method, so each list item gets it's own checkbox and label. But in the non-working code, those two variables are created as global constants, which means there is always only one of each, and they keep getting moved to the most-recently created list item.

brendon hanson
brendon hanson
6,191 Points

I fixed that, but now when I click the 'hide those who haven't confirmed' box the checkbox on the individual person is still there when I want it to disappear. Note: All I changed from the Original code was I put the same global constants in the createLI

Steven Parker
Steven Parker
174,043 Points

In the handler for the filter checkbox, there were 4 code lines that referenced "confCheckbox" or "confLabel" that should be removed. These lines were not needed; and now that the items no longer exist in that scope, those lines cause syntax errors.

If the original question of this thread has been resolved, you can mark it solved by choosing a "best answer".
Questions on new issues can be started as fresh messages.

Steven Parker
Steven Parker
174,043 Points

I was not able to replicate the issue. I entered 4 people and all of the checkboxes were still visible (and still operated).

brendon hanson
brendon hanson
6,191 Points

here is the code i guess...snapshot was acting weird

document.addEventListener('DOMContentLoaded', (e) => {
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');

const confCheckbox = document.createElement('input');
const confLabel = document.createElement('label');

filterLabel.textContent = "Hide those who haven't confirmed yet";
filterCheckBox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckBox);
mainDiv.insertBefore(div, ul);
filterCheckBox.addEventListener('change', (e) => {
  const lis = ul.children;
  const isChecked = e.target.checked;
  if (isChecked) {
    confCheckbox.style.display = 'none';
    confLabel.style.display = 'none';
    for (let i = 0; i < lis.length; i += 1) {
      let li = lis[i];
      if (li.className === 'responded') {
        li.style.display = '';
      } else {
         li.style.display = "none";
        confCheckbox.style.display = '';
    confLabel.style.display = '';
      }
    } 
  } else {  
  for (let i = 0; i < lis.length; i += 1) {    
    const li = lis[i];
    li.style.display = '';
  }
  }
 });

function createLI(text) {
  const li = document.createElement('li');
  const span = document.createElement('span');  
  span.textContent = text;
  li.appendChild(span);

  confCheckbox.type = 'checkbox';
  confLabel.textContent = 'Confirmed';

  confLabel.appendChild(confCheckbox);
  li.appendChild(confLabel);  

  const editButton = document.createElement('button');
  editButton.textContent = 'edit';
  li.appendChild(editButton);

  const removeButton = document.createElement('button');
  removeButton.textContent = 'remove';
  li.appendChild(removeButton);
  return li;
}

form.addEventListener('submit', (e) => {
  e.preventDefault();
  const text = input.value;
  const li = createLI(text);

       if (input.value === '') {
   alert("Must type a real name!"); 
   li.style.display = 'none';
  }

  input.value = '';
  ul.appendChild(li);


});

ul.addEventListener('change', (e) => {
  const checkbox = event.target;
  const checked = checkbox.checked;
  const listItem = checkbox.parentNode.parentNode;

  if (checked) {
    listItem.className = 'responded';
  } else {
    listItem.className = '';
  }
});

ul.addEventListener('click', (e) => {
  if (e.target.tagName === 'BUTTON') {
    const button = e.target;
    const li = button.parentNode;
    const ul = li.parentNode;
    if (button.textContent === 'remove') {
      ul.removeChild(li);
    } else if (button.textContent === 'edit') { 
      const span = li.firstElementChild;
      const input = document.createElement('input');
      input.type = 'text';
      input.value = span.textContent;
      li.insertBefore(input, span);
      li.removeChild(span);
      button.textContent = 'save';
    } else if (button.textContent === 'save') { 
      const input = li.firstElementChild;
      const span = document.createElement('span');
      span.textContent = input.value;
      li.insertBefore(span, input);
      li.removeChild(input);
      button.textContent = 'edit';
    }
  }
});  
  });
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>RSVP App</title>
  <link href="https://fonts.googleapis.com/css?family=Courgette" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet">
  <link href="css/style.css" rel="stylesheet">

</head>
<body>
  <div class="wrapper">
    <header>
      <h1>RSVP</h1>
      <p>A Treehouse App</p>
      <form id="registrar">
        <input type="text" name="name" placeholder="Invite Someone">
        <button type="submit" name="submit" value="submit">Submit</button>
      </form>
    </header>

    <div class="main">  
      <h2>Invitees</h2>
      <ul id="invitedList"></ul>    
    </div>
  </div>
    <script type="text/javascript" src="app.js"></script>
</body>
</html>
/* ================================= 
  Element Styles
==================================== */

* {
  box-sizing: border-box;
}
body {
  font-family: 'Lato', sans-serif;
  color: #4c4c4c;
  background: #f8fdf3;
}
h1,
p,
form button {
  color: white;  
}
h1 {
  font-family: 'Courgette', cursive;
  text-shadow: 0 1px 0 rgba(0,0,0, .4);
  line-height: .65;
  margin-top: .5em;
  margin-bottom: 0;
}
h2 {
  margin-top: 0;
}
p {
  font-size: 1.1em;
  text-shadow: 0 1px 0 rgba(0,0,0, .25);
}
form {
  width: 60%;
  background: white;
  display: inline-block;
  overflow: hidden;
  display: -webkit-flex;
  display: flex;
  border-radius: .2em;
  border: solid 4px white;
  box-shadow: 0 1px 14px rgba(0,0,0, .12);
}
form button {
  padding: 0 1em;
  font-size: 1em;
  background: #7bcbc4;
  border-radius: .2em;
}
ul {
  list-style: none;
  padding: 0;
  margin: 2em 0 1em;
}
ul li {
  padding: 1em;
  background: #fff;
  border-radius: .2em;
  border: solid 1px rgba(88, 183, 205, .2);
  border-bottom: solid 2px rgba(88, 183, 205, .2);
  position: relative;
}
button {
  cursor: pointer;
}
input, 
button {
  border: none;
  outline: none;
}
header {
  text-align: center;
  background: linear-gradient(90deg, #d4eece, #55b3d0, #1e7eb7),
              url('../images/header-bg.jpg') no-repeat;
              background-blend-mode: multiply;    
              background-size: cover;   
}
header input {
  padding: 12px;
  font-size: 1.15em;
  width: 100%;
}
li span, 
li input[type=text] {
  color: #707070;
  font-size: 1.3em;
  margin-bottom: .3em;
}
li input[type=text] {
  padding: .2em;
  width: 95%;
  border: 1px dotted rgba(0,0,0, .2);
}
li label {
  font-size: .9em;
  display: block;
  color: rgba(112, 112, 112, .55);
}
li span, 
li input[type=text]:first-child {
  display: block;
}
li button {
  font-size: .78em;
  margin-top: 1.65em;
  margin-right: .4em;
  border-radius: .3em;
  padding: .4em .6em;
  color: white;
  background: #58b7cd;
}
li button:last-child {
  background: rgba(88, 183, 205, .5);
}
.wrapper {
  width: 100%;
  max-width: 900px;
  margin: 2.5em auto;
  border-radius: .35em;
  background: #fcfcfc;
  overflow: hidden;
  box-shadow: 0 0 26px rgba(0,0,0, .13);
}
div > input:last-child {
  font-size: 1em;
  margin-left: 6px;
}
div > label {
  color: #767676;
}

/* responded */
.responded {
  transition: 0.4s;
  border-color: rgba(88, 183, 205, .9);
}
.responded label {
  transition: 0.4s;
  color: rgba(88, 183, 205, 1);
}

/* ================================= 
  Media Queries
==================================== */

@media (min-width: 0) and (max-width: 768px) {
  header {
    padding: 1.25em;
  }
  h1 {
    font-size: 3.6em;
    margin: .3em 0 0;
  }
  ul li {
    margin-bottom: 1em;
  }
  form {
    width: 95%;
    -webkit-flex-direction: column;
    flex-direction: column;
    margin: auto;
    margin-top: 2.5em;
  }
  form button {
    padding: 12px 0;
    margin-top: .5em;
  }
  form input {
    font-size: 1em;
    text-align: center;
  }
  .wrapper {
    margin: 0;
  }
  .main {
    padding: 2em 1em .75em;
  }
}

@media (min-width: 769px) {
  header {
    height: 280px;
    padding: 2.5em 1em 1em;  
    background-position: 0 -95px; 
  }
  .main > div {
    float: right;
    display: inline-block;
    margin-top: 12px;
    margin-right: 1.25%;
  }
  div > label {
    margin-top: 12px;
  }
  h1 {
    font-size: 5.8em;
  }
  h2 {
    float: left;
    font-size: 1.9em;
    margin-left: 1.25%;
  }
  form {
    margin: 4.15em auto 0;
    z-index: 3000;
    position: relative;
  }
  .wrapper {
    width: 90%;
  }
  .main {
    padding: 3.8em 1.5em .75em;
    position: relative;
    z-index: 10;
  }
  ul {
    display: -webkit-flex;
    display: flex;
    clear: both;

    -webkit-justify-content: space-between;
    justify-content: space-between;
    -webkit-flex-wrap: wrap;    
    flex-wrap: wrap;
    padding-top: 1.25em;
  }
  ul li {
    -webkit-flex-grow: 1;
    flex-grow: 1;
    -webkit-flex-basis: 47.5%;
    flex-basis: 47.5%;
    margin: 0 1.25% 1em;
  }
}
@media (min-width: 880px) { 
  ul li {
    -webkit-flex-basis: 20%;
    flex-basis: 20%;
  }
}