Do you have something important to do? Here's a Notes App

I'm a fucking mess when it comes to setting a to do list, and even though I already did a To-Do-List App that works perfectly in a PC and it gets stored in the local memory of any user's computer, I want to improve my To-do abilities and set some Notes all over my Screen so that I don't forget what must be done. This mini project is for that. I will use the local storage API which is built into the browser. I will style the notes and set a toggle button so the notes can be edited. The notes will be able to use markdown in order to make the notes look nicer. This project is useful to practice how to work with local storage and how to work with the DOM.

I'm no longer including the HTML code here because the Hive editor gets confused with my HTML and it is a hazzle to check where the issues come from.

This is what I get after the HTML code, just so you get an idea.

image.png

CSS Code



* {
  box-sizing: border-box;
}

body {
  background-color: rgb(53, 47, 47);
  font-family: "Poppins", sans-serif;
  display: flex;

Wrapping the notes so they occupy the next line when needed

  flex-wrap: wrap;
  margin: 0;
  padding-top: 3rem;
}

.add {
  position: fixed;
  top: 1rem;

REM is just a multiplier of the root element, which by default is 16px

  right: 1rem;
  border: none;
  border-radius: 3px;

With padding and margin the 1st number is Top-Bottom, the 2nd is Left-Right.

  padding: 0.5rem 1rem;
  color: rgb(0, 0, 0);
  cursor: pointer;
}

.add:active {
  transform: scale(0.98);
}

.note {
  background-color: rgb(255, 255, 255);

For box shadow the values are: offset-x | offset-y | blur-radius | spread-radius | color

  box-shadow: 0 0 10px 4px rgb(143, 52, 10);
  margin: 30px 20px;
  height: 400px;
  width: 400px;
}

.note .tools {
  background-color: rgb(148, 84, 55);
  display: flex;

Flex-end puts the content to the right

  justify-content: flex-end;
  padding: 0.5rem;
}

.note .tools button {
  background-color: transparent;
  border: none;
  color: rgb(0, 0, 0);
  cursor: pointer;
  font-size: 1rem;
  margin-left: 0.5rem;
}

.note textarea {
  outline: none;
  font-family: inherit;
  font-size: 1.2rem;
  border: none;

The height and width have to be the same as the note's

  height: 400px;
  width: 400px;
  padding: 20px;
}

I add the class of hidden so that I can addClassList with JS to anything I don't want to show

.hidden {
  display: none;
}

.main {
  padding: 20px;
}

As you can see, the little app is already responsive to the size of the window:

gif1.gif

JavaScript Code

const addNote = document.getElementById("add");

addNote.addEventListener("click", () => addNewNote());

function addNewNote(text = "") {
  const note = document.createElement("div");
  note.classList.add("note");

In here I will insert everything I first added on the HTML, this inserts it dynamically into any note I want to add:

  note.innerHTML = `
  <div class="tools">
    <button class="edit"><i class="fas fa-edit"></i></button>
    <button class="delete"><i class="fas fa-trash-alt"></i></button>
  </div>

  
  <div class="main ${text ? "" : "hidden"}"></div>
  <textarea class="${text ? "hidden" : ""}"></textarea>
`;

Using the Ternary Operator I dynamically add the class of main or hidden.

  document.body.appendChild(note);
}

gif2.gif

But the buttons of edit and delete don't work yet, my job here isn't done at all, not nearly, this post will be longer than usual.

const addNote = document.getElementById("add");

addNote.addEventListener("click", () => addNewNote());

function addNewNote(text = "") {
  const note = document.createElement("div");
  note.classList.add("note");

  // In here I will insert everything I first added on the HTML, this inserts it dynamically into any note I want to add:
  note.innerHTML = `
  <div class="tools">
    <button class="edit"><i class="fas fa-edit"></i></button>
    <button class="delete"><i class="fas fa-trash-alt"></i></button>
  </div>

  
  <div class="main ${text ? "" : "hidden"}"></div>
  <textarea class="${text ? "hidden" : ""}"></textarea>
`;

  // Using the Ternary Operator I dynamically add the class of *main* or *hidden*.

  const editNote = note.querySelector(".edit");
  const deleteNote = note.querySelector(".delete");
  const main = note.querySelector(".main");
  const textArea = note.querySelector("textarea");

  textArea.value = text;
  main.innerHTML = marked(text);

I can use the markdown library by simply wraping the text in marked as follows:

  deleteNote.addEventListener("click", () => {
    note.remove();
  });

  editNote.addEventListener("click", () => {
    main.classList.toggle("hidden");
    textArea.classList.toggle("hidden");
  });

  textArea.addEventListener("input", (e) => {

I will use destructuring to pull .value from e.target

    const { value } = e.target;
    // from **e.target.value**
    main.innerHTML = marked(value);
    // then I update the innerHTML using the markdown form of said value
  });

  document.body.appendChild(note);
}

gif3.gif

As you can see shit is cash right now, but if I refresh the page the notes go away, I need to store the notes in the local storage of any user that wants to use this little app, which is what I am going to do right now:

const addNote = document.getElementById("add");

const notes = JSON.parse(localStorage.getItem("notes"));

if (notes) {
  notes.forEach((note) => addNewNote(note));
}

addNote.addEventListener("click", () => addNewNote());

function addNewNote(text = "") {
  const note = document.createElement("div");
  note.classList.add("note");

  // In here I will insert everything I first added on the HTML, this inserts it dynamically into any note I want to add:
  note.innerHTML = `
  <div class="tools">
    <button class="edit"><i class="fas fa-edit"></i></button>
    <button class="delete"><i class="fas fa-trash-alt"></i></button>
  </div>

  
  <div class="main ${text ? "" : "hidden"}"></div>
  <textarea class="${text ? "hidden" : ""}"></textarea>
`;

  // Using the Ternary Operator I dynamically add the class of *main* or *hidden*.

  const editNote = note.querySelector(".edit");
  const deleteNote = note.querySelector(".delete");
  const main = note.querySelector(".main");
  const textArea = note.querySelector("textarea");

  textArea.value = text;
  main.innerHTML = marked(text);
  // I can use the markdown library by simply wraping the text in marked as follows:

  deleteNote.addEventListener("click", () => {
    note.remove();

    updateLS();
  });

  editNote.addEventListener("click", () => {
    main.classList.toggle("hidden");
    textArea.classList.toggle("hidden");
  });

  textArea.addEventListener("input", (e) => {
    // I will use destructuring to pull *.value* from *e.target*
    const { value } = e.target;
    // from **e.target.value**
    main.innerHTML = marked(value);
    // then I update the innerHTML using the markdown form of said value

    // This function will be defined once I close the general function }
    updateLS();
  });

  document.body.appendChild(note);
}

// I will run this function every time I delete, edit or create new note
function updateLS() {
  const notesText = document.querySelectorAll("textarea");

  // I create an empty array to store the next loop

  const notes = [];

  notesText.forEach((note) => notes.push(note.value));

  localStorage.setItem("notes", JSON.stringify(notes));
}

// Note: This clears the local storage
// localStorage.clear();

// Note: sessionStorage let's you store stuff in the local storage until you close the browser.

End Result

This little project took 4 hours, not because I spent a lot of time coding, but because I spent like two hours checking what I was doing wrong because once I added the markdown values and wanted to store them in the local storage my code would crash.

Little did I know that I was pulling the wrong script version from the source and after 7 code revisions I realized it wasn't my mistake in the code, but the source.

What the hell, I now understand the coding memes of when you realize the code mistake was a comma and stuff like that.

Damn...

gif4.gif

Sort:  

Nice post @anomadsoul. This looks really cool and it shows that you really know and understand Javascript to a large extent. Am impressed 👍.

same here bro. semicolon is the things troubled me the most past 5 years

This is cool great work @anomadsoul.

Thanks a lot for sharing. I'm new to programming and development and I think I will learn a lot from you. This is an excellent work. Thanks again.