Skip to content
Advertisement

Save form values to localStorage

I have been studying JS for a while so at some point a couldn’t complete the assignment that my teacher gave me so its all about to create a input to fill with 3 selectors to change some properties of the text.

What I’m trying to do is:
whenever the user he closes the page and opens it again – apply the values from localStorage back into the form, and apply the styles to an element. I.e:

Font: Roboto
Color: Green
fontSize: 24px

How I am supposed to do it, and why my code is wrong?
Here’s the code :

function iterator() {
  for (let i = 16; i <= 30; i++) {
    let fontsSize = document.getElementById("fontsSize");
    let CreateElmt = document.createElement("option");
    fontsSize.append(CreateElmt);
    CreateElmt.textContent = i + "px";
    CreateElmt.value = i + "px";
  }
}
iterator();

function finalItreator() {
  let parent = document.querySelector(".daddyDiv");
  let div = document.querySelector(".paragragh");
  let Fonts = document.getElementById("Fonts");
  let Colors = document.getElementById("Colors");
  let fontSizes = document.getElementById("fontsSize");
  parent.addEventListener("input", (e) => {
    window.localStorage.setItem("Font", Fonts.value);
    window.localStorage.setItem("Color", Colors.value);
    window.localStorage.setItem("FontSize", fontSizes.value);
    div.style.fontFamily = Fonts.value;
    div.style.color = Colors.value;
    div.style.fontSize = fontSizes.value;
    for (i = 0; i < Fonts.children.length; i++) {
      if (Fonts.children[i].value === window.localStorage.getItem("Font")) {
        Fonts.forEach((e) => {
          e.removeAttribute("selected");
        });
        Fonts.children[i].classList.add("active");
      }
      if (Fonts.children[i].classList.contains("active")) {
        Fonts.children[i].setAttribute("selected", "");
      }
    }
  });
}
finalItreator();
.paragragh {
  margin: 10px auto;
  width: 400px;
  min-height: 300px;
  background-color: #ddd;
  text-align: center;
  padding-top: 30px;
}
<form class="daddyDiv">
  <select name="Fonts" id="Fonts">
    <option value="Open Sans">Open Sans</option>
    <option value="Cairo">Cairo</option>
    <option value="Roboto">Roboto</option>
  </select>
  <select name="Colors" id="Colors">
    <option value="Black">Black</option>
    <option value="Green">Green</option>
    <option value="Blue">Blue</option>
    <option value="Red">Red</option>
    <option value="Purple">Purple</option>
  </select>
  <select name="fontsSize" id="fontsSize"></select>
  <div class="paragragh" contenteditable="true"></div>
</form>

Advertisement

Answer

  • There’s no need to query the DOM inside a for loop for the same element again and again.
    Cache the elements you plan to reuse beforehand.
  • Use const when the variable value will not change through the life of your app
  • What means “paragragh” you mean paragraph? (BTW, it’s a DIV)
  • There’s no need to use id if you already use name
  • Don’t name a function iterator if its job is clearly to populate a Select box with <option>s. createFontSizeOptions seems like a better choice.
  • Don’t name a function finalItreator it means nothing.
    Describe your function names as concisely, meaningfully, and short as possible.
  • (Actually, you don’t need those functions at all)
  • Don’t name your ID’s PascalCase. Use camelCase.
  • Assign the "input" Event to a class selector, i.e: .command which is assigned to your Select (or other imput) elements.
  • Use a proper name which value is exactly the expected CSS property as camelCase, i.e: fontFamily or fontSize
  • Store into LocalStorage a Stringified Object literal using JSON.stringify
  • Retrieve from localStorage using JSON.parse
  • Create three functions, one that gets the String as Object from localStorage, the second to save an Object to localStorage, and a third one to apply the key/value pairs styles to a desired element using Object.assign
  • Create some reusable DOM utilities to help you with getting or creating elements in the DOM

(Since Stack Overflow Snippets for security reasons doesn’t accept access to localStorage from Iframe, here’s a live jsFiddle demo)

Code:

// DOM utility functions:

const el = (sel, par) => (par || document).querySelector(sel);
const els = (sel, par) => (par || document).querySelectorAll(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);


// TASK:

// Cache DOM Elements:
const elForm = el("#formSettings"); // It's not a ".daddyDiv"... it's a Form!
const elEditable = el("#editable"); // It's an editable div! (What means "paragragh" anyways?!)
const elsCommand = els(".command"); // All your input/selects
const elFontSize = el("[name=fontSize]");

// Create the font-size Options
// (You don't need a function here if it's a one-time operation on DOM ready)
for (let i = 16; i <= 30; i++) {
  elFontSize.append(elNew("option", {
    textContent: `${i}px`,
    value: `${i}px`
  }));
}

const commandsGet = () => {
  // If we have no commands stored in localStorage, save them!
  if (!localStorage.commands) commandsSave();
  // Convert string from localStorage to Object Literal
  const commands = JSON.parse(localStorage.commands);
  // Apply values to DOM input/select elements by name
  Object.entries(commands).forEach(([name, value]) => {
    el(`[name="${name}"]`).value = value;
  });
};

const commandsSave = () => {
  // Create an Object of the commands to save to localStorage
  const commands = [...elsCommand].reduce((obj, elem) => {
    obj[elem.name] = elem.value;
    return obj;
  }, {});
  // Convert object Literal to String and save to localStorage
  localStorage.commands = JSON.stringify(commands);
};

const commandsApply = () => {
  // Apply styles to the desired contenteditable element:
  Object.assign(elEditable.style, JSON.parse(localStorage.commands));
};

// Assign an event listener to all your inputs/selects to store and apply the 
// styles (commands) on "input"
elsCommand.forEach(elem => {
  elem.addEventListener("input", () => {
    commandsSave();
    commandsApply();
  });
});

// Init:
// On page load read the commands from LocalStorage
// and apply them to your editable element
commandsGet();
commandsApply();
/*QuickReset */

* {
  margin: 0;
  box-sizing: border-box;
}

.paragragh {
  margin: 10px auto;
  min-width: 400px;
  min-height: 300px;
  background-color: #ddd;
  text-align: center;
  padding-top: 30px;
}
<form id="formSettings">
  <select class="command" name="fontFamily">
    <option value="Arial">Arial</option>
    <option value="Times New Roman">Times New Roman</option>
    <option value="Courier New">Courier New</option>
  </select>
  <select class="command" name="color">
    <option value="black">Black</option>
    <option value="green">Green</option>
    <option value="blue">Blue</option>
    <option value="red">Red</option>
    <option value="purple">Purple</option>
  </select>
  <select class="command" name="fontSize"></select>

  <div id="editable" contenteditable="true">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
</form>
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement