Item Lister

Page section: posts

Item Lister

Add items

Items

  • item 1
  • item 2
  • item 3
  • item 4

How it was made

Some HTML is added to the page:

  • a form with 3 inputs: 2 text types (for the search field and entry field) and a submit type.
  • the ul with the first 4 li items.
  • each item has a button for deleting added.

The JS:

First create some variables that grab the submit input and the ul.

The main function to add items

A function is created called addItem(e). The first thing this does is prevent the default behaviour:

e.preventDefault();

Next variable is created to get the text in the input field:

let newItem = document.getElementById("new-item").value;

A new <li> is created with a class name.

const li = document.createElement('li');
li.className = 'list-group-item';

To get the text stored in newItem above a new text node is create to add it there:

li.appendChild(document.createTextNode(newItem));

A variable for new delete buttons is created, still inside addItem function. This has the cross symbol added and this is then appended to the new item.

const deleteBtn = document.createElement('button');
deleteBtn.innerHTML = '&#10005;';

li.appendChild(deleteBtn);

Finally this new li with it’s delete button is added to the list of items:

itemList.appendChild(li);

A function to remove items

When the delete button is clicked it runs this function:

function removeItem(e) {
  const li = e.target.parentElement;
  itemList.removeChild(li);
}

The e refers to the event and the target is the event’s element, so the button. What needs to be removed is the list item though, so the parent of the button.

Then we need a click event to trigger the function:

itemList.addEventListener("click", removeItem);

The search box is basically a way to filter the items based on a text string. So a variable to grab the search input is created called filter and then a function called filterItems(e) to do the search.

The first thing the function does is save the search string to a variable and convert it to lower case

const text = e.target.value.toLowerCase();

Next step is to store all the items in the list. So a new variable is created grabbing all the items in the list. The ul for the list was previously stored in a variable as itemList so:

const items = itemList.getElementsByTagName("li");

The final part of the function creates an array from the items variable and loops through it using the forEach array method.

First it stores the text of each item in a variable called itemName. The .firstChild bit means the delete button is left out.

Then comes the if statement where a relevant result is displayed.

Array.from(items).forEach(function (item) {
  let itemName = item.firstChild.textContent;

  if (itemName.toLowerCase().indexOf(text) != -1) {
    item.style.display = "block";
  } else {
    item.style.display = "none";
  }



First create some variable to grab different elements of the form:

  • The submit button called form here
  • The <ul> element named itemList.

Notes

  1. “It is wrong to change a character to an HTML entity reference in client-side JavaScript, since client-side JavaScript operates on the DOM, where entities do not exist.”

    I used an extra line of code here:

    deleteBtn.innerHTML = "&#10005;"
    
  2. The <input> submit button only works with a click event rather than a submit for some reason.

  3. I removed the confirm dialogue for deleting items. Too slow.

The Code

const form = document.getElementById("add-form");
const itemList = document.getElementById("items");
// const filter = document.getElementById("filter");

// Submit EVENT

form.addEventListener("click", addItem);

itemList.addEventListener("click", removeItem);

function addItem(e) {
  e.preventDefault();

  // Get new input item
  let newItem = document.getElementById("new-item").value;

  // Create new li
  const li = document.createElement("li");
  // Add class name
  li.className = "list-group-item";

  // Add text node with input value
  li.appendChild(document.createTextNode(newItem));
  console.log(li);

  const deleteBtn = document.createElement("button");

  //   deleteBtn.appendChild(document.createTextNode(""));
  // This doesn't allow HTML entities so...

  deleteBtn.innerHTML = "&#10005;";

  // add delete button to list item
  li.appendChild(deleteBtn);

  itemList.appendChild(li);
}

// Remove item

function removeItem(e) {
  //   itemList.removeChild("li");
  //   if (confirm("Are you sure?") == true) {
  //     const li = e.target.parentElement;
  //     itemList.removeChild(li);
  //   } else {
  //     console.log("gone");
  //   }
  const li = e.target.parentElement;
  itemList.removeChild(li);
}

// Filter EVENT

filter.addEventListener("keyup", filterItems);

function filterItems(e) {
  const text = e.target.value.toLowerCase();
  console.log(text);

  const items = itemList.getElementsByTagName("li");

  Array.from(items).forEach(function (item) {
    let itemName = item.firstChild.textContent;
    // console.log(itemName);
    if (itemName.toLowerCase().indexOf(text) != -1) {
      item.style.display = "block";
    } else {
      item.style.display = "none";
    }
  });
}

Using console.dir

These buttons show the console.log() run on the document. (first button uses console.dir(document))

Using document.all you can get a number referring to the depth

  1. Codepen of original
  2. Original video on Youtube
View contents of: /static/js/item-lister.js
const form = document.getElementById("add-form");
const itemList = document.getElementById("items");
const filter = document.getElementById("filter");

// Submit EVENT

form.addEventListener("click", addItem);

itemList.addEventListener("click", removeItem);

function addItem(e) {
  e.preventDefault();

  // Get new input item
  let newItem = document.getElementById("new-item").value;

  // Create new li
  const li = document.createElement("li");
  // Add class name
  li.className = "list-group-item";

  // Add text node with input value
  li.appendChild(document.createTextNode(newItem));
  console.log(li);

  const deleteBtn = document.createElement("button");

  //   deleteBtn.appendChild(document.createTextNode(""));
  // This doesn't allow HTML entities so...

  deleteBtn.innerHTML = "&#10005;";

  // add delete button to list item
  li.appendChild(deleteBtn);

  itemList.appendChild(li);
}


// Remove item

function removeItem(e) {
  const li = e.target.parentElement;
  itemList.removeChild(li);
}


// Filter EVENT

filter.addEventListener("keyup", filterItems);

function filterItems(e) {
  const text = e.target.value.toLowerCase();
  console.log(text);

  const items = itemList.getElementsByTagName("li");

  Array.from(items).forEach(function (item) {
    let itemName = item.firstChild.textContent;
    // console.log(itemName);
    if (itemName.toLowerCase().indexOf(text) != -1) {
      item.style.display = "block";
    } else {
      item.style.display = "none";
    }
  });
}