Saving values to localStorage() and making them stay when I reload the page in Javascript - javascript

I am currently making a note writing app and need your help.
I'm struggling to understand how localStorage() works and how exactly I saved things to it. I would like to reload the page and have every note that I've written not dissappear.
Thank you.
//// Declare Variables ////
const noteBtn = document.querySelector('.add-note-btn');
const writeNote = document.querySelector('.note-input');
const allSavedNotes = document.querySelector('.added-notes');
//// Write new note and add to list ////
noteBtn.addEventListener('click', function(e){
// Create new paragraph element
let newNote = document.createElement('p');
// Add clas name to element
newNote.className = 'saved-note';
// Add the text input
newNote.textContent = writeNote.value;
// Append element to div
allSavedNotes.appendChild(newNote);
e.preventDefault();
})
<div class="all">
<div>
<div class="title">
<h1 class="heading">Notes List</h1>
</div>
<div>
<div class="writing-notes">
<textarea class="note-input" cols="35" rows="10"></textarea>
Add note
</div>
<div class="added-notes">
</div>
</div>
</div>
</div>

You can save all notes in localStorage by appending the state to an empty array.
I've intitally created a state variable that contains earlier undefined or an empty array.
Then appendNotes function appends a paragraph to the allSavedNotes DOM selector.
//// Declare Variables ////
const noteBtn = document.querySelector('.add-note-btn');
const writeNote = document.querySelector('.note-input');
const allSavedNotes = document.querySelector('.added-notes');
const state = JSON.parse(localStorage.getItem('notes')) || [];
function appendNotes(text) {
let p = document.createElement('p');
p.textContent = text;
// Append element to div
allSavedNotes.appendChild(p);
}
// append notes on page load
state.map(s => appendNotes(s));
//// Write new note and add to list ////
noteBtn.addEventListener('click', function(e) {
// Create new paragraph element
let newNote = document.createElement('p');
// Add class name to element
newNote.className = 'saved-note';
const text = writeNote.value.trim();
// Add the text input
newNote.textContent = text;
// if there are no `notes` in `localStorage` then use empty array
if (text !== "") {
state.push(text)
localStorage.setItem('notes', JSON.stringify(state));
}
// Append element to div
appendNotes(text);
newNote.textContent = "";
e.preventDefault();
})
<div class="all">
<div>
<div class="title">
<h1 class="heading">Notes List</h1>
</div>
<div>
<div class="writing-notes">
<textarea class="note-input" cols="35" rows="10"></textarea>
Add note
</div>
<div class="added-notes">
</div>
</div>
</div>
</div>
The above code won't from StackOverflow directly as it gives a cross-origin error:
Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': The document is sandboxed and lacks the 'allow-same-origin' flag.
But it works on JSFiddle. Here's a working link → https://jsfiddle.net/deadcoder0904/036bp9zy/33/
You can learn more about localStorage in this excellent blog post → https://www.digitalocean.com/community/tutorials/js-introduction-localstorage-sessionstorage

Related

How to add break tags after inserting a paragraph into html using javascript's createElement

I've successfully inserted a paragraph element into html page using javascript but the 2nd consecutive paragraph comes side by side and I wish to add a break tag to print them in another line, how do I do that?
Here is a screenshot of my output:
Here is my javascript code:
function newtask(){
let ask = prompt("Enter the description of task");
const para = document.createElement("p");
const Textnode = document.createTextNode(ask);
para.appendChild(Textnode);
let text= document.getElementById("new")
text.appendChild(Textnode);
}
Here is the relevant html
<script src="index.js"></script>
<h1>To do List</h1>
<button onclick="newtask()">New Task</button>
<div id="new">
<p>test</p>
</div>
You were appending Textnode to your parent element, not your new <p> element. Here's a quick rewrite that should give you your desired results.
Firstly, create the new <p> element, then modify its innerText property. After that, just append your new <p>.
function newtask() {
const text = document.getElementById("new");
const ask = prompt("Enter the description of task");
const para = document.createElement("p");
para.innerText = ask;
text.appendChild(para);
}
You can wrap your p inside a div and add a display: flex configuration.
const paraDiv = document.createElement("div");
// Add your style configuration to your paraDiv
function newtask(){
let ask = prompt("Enter the description of task");
const para = document.createElement("p");
paraDiv.appendChild(para)
const Textnode = document.createTextNode(ask);
para.appendChild(Textnode);
let text= document.getElementById("new")
text.appendChild(Textnode);
}

How to wrap a specific element in a div

Currently, my website has the following structure:
<div class="aa">
<h2 class="bb">example</h2>
</div>
And I want to create a new div and put h2 inside it.
<div class="aa">
<div class="cc"> <---
<h2 class="bb">example</h2>
</div> <---
</div>
I tried using insertBefore code as below.
<script>
const parent = document.querySelector('.bb');
const billingField1 = document.querySelector('.aa');
const newDiv = document.createElement('div');
newDiv.setAttribute('id', 'cc');
newDiv.style.cssText = 'Hi there';
parent.insertBefore(newDiv, billingField1);
</script>
With this method, a new div element is inserted only with
<div class="cc"></div>
I'm wondering if there is any way to put it in.
After you insert the new element, you need to make the old element a child of it.
const parent = document.querySelector('.aa');
const billingField1 = document.querySelector('.bb');
const newDiv = document.createElement('div');
newDiv.setAttribute('id', 'cc');
newDiv.style.cssText = 'Hi there';
parent.insertBefore(newDiv, billingField1);
newDiv.appendChild(billingField1);
<div class="aa">
<h2 class="bb">example</h2>
</div>
You also had the selectors for parent and billingField1 swapped.
Try this
document.getElementByClassName(‘bb’).innerHTML = ‘<div class=“cc”>’ + document.getElementByClassName(‘bb’).innerHTML + ‘</div>’;

how to get text from child element from console

I'm trying to get the which is in
as you can see:
<p class="jmbadge">
<strong>xxx</strong>
<br>
<span class="field-value">text!</span>
</p>
I'm trying to get the <span>
this is inside a website and I want to take the text of <span> via the console (Google Chrome)
here is what I tried:
const jminfo = document.getElementsByClassName("jminfo");
const span = jminfo.querySelector('span');
console.log(span);
And here is the error I get:
Uncaught TypeError: jminfo.querySelector is not a function
at <anonymous>:1:21
const jminfo = document.getElementsByClassName("jmbadge")[0];
const span = jminfo.querySelector('span');
console.log(span);
<p class="jmbadge">
<strong>xxx</strong>
<br>
<span class="field-value">text!</span>
</p>
That is because you selected a punch of elements with a class name but didn’t specify wich elements from these elements list.
Try to use:
const span = document.querySelector('.jminfo > span');
console.log(span);
but in case you know the index of the element in the document you can use:
const jminfo = document.getElementsByClassName("jmbadge")[N];
// n = the index
const span = jminfo.querySelector('span');
console.log(span);

Dynamically add item to an existing list

I need to dynamically insert an element into an existing list of blog posts.
Here is an example of the HTML:
<div id="page">
<div id="post">Post Content</div>
<div id="post">Post Content</div>
<div id="post">Post Content</div>
<div id="post">Post Content</div>
<!---- Dynamic Post Inserted Here--->
<div id="post">Post Content</div>
<div id="post">Post Content</div>
</div>
I've created a for loop that iterates through the posts and returns the location, but the location returned is an integer so I can't append the new post to that variable. So what is the best way to append the item to my current post list?
I don't have the exact function in front of me but this is essentially what i'm doing:
var post = docuemnt.getElementById('post');
var page = docuemnt.getElementById('page');
var pc = 0;
var insert = 5;
var newPost = "new post content";
for(post in page){
if(pc == insert){
**append new post content after this post**
}else{
pc++;
}
}
If you were using jQuery, this would be incredibly easy.
$('#post4').after('<div id="post5">new post content</div>');
If you want to do it in pure JavaScript, then take a look at this question. The basic idea is:
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
In your case, you'd need to create a div node and append to the document directly.
var newpost = document.createElement('div');
newpost.id = 'post5';
newpost.innerText = newpost.textContent = "new post content";
var post = document.getElementById('post4');
post.parentNode.insertBefore(newpost, post.nextSibling);
If you are getting an integer, have the div id be the index. That way you can use document.getElementById('post'+id).innerHTML to append.
Your approach is all wrong, doing a for each on an element won't give you its child nodes but its property keys. You can use getElementsByTagName or querySelector to accomplish your goal
var posts = docuemnt.getElementById('page').getElementsByTagName('div');
var insert = 4;
var newPost = "new post content";
var div = document.createElement('div');
div.appendChild(document.createTextNode(newPost ));
posts[insert].parentNode.insertBefore(div, posts[insert]);//index are zero based so element 4 is actually the 5th element
or
var insert = 5;
var post = docuemnt.querySelector('#page > div:nth-child('+insert+')');//nth child index is one based
var newPost = "new post content";
var div = document.createElement('div');
div.appendChild(document.createTextNode(newPost ));
post.parentNode.insertBefore(div, post);
https://developer.mozilla.org/en-US/docs/DOM/Document.querySelector
https://developer.mozilla.org/en-US/docs/DOM/Node.insertBefore
https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByTagName
Your can create jtag for new post div tag and call .dom() function to receive div element. Try Jnerator library.
function addPost() {
var lastPostElement = page.lastChild;
var count = page.childNodes.length;
var postText = tagPost.value;
var jtag = $j.div({ id: 'post' + count, child: postText });
var newPostElement = jtag.dom();
page.insertBefore(newPostElement, lastPostElement);
}
See an example here: http://jsfiddle.net/jnerator/5nCeV/

find difference in two dom elements then make them same

If I have two elements :
Element A :
<div id="myID">
<div id="a"></div>
<div id="b"><div id="ba"></div></div>
<div id="c"><span id="ca"></span></div>
</div>
and Element B :
<div id="myID">
<div id="a"></div>
<div id="b"><div id="ba"></div></div>
<div id="c"><span id="ca"></span></div>
<div id="d"></div>
</div>
Is it possible to find out that Element B has more children than Element A, then find where is additional element and create it in Element A?
P.S: In real code new element is loaded with Ajax Request, but I don't want to replace all content with loaded content, I need to add only new content and skip existing one.
P.S.S : In my current code I have Md5 checksum to check if new content is not the same as existing, but if new content have only little changes it replaces all content and this is the problem for me.
A piece of my current code :
window.processResponse = function(data) {
// Note : "data" is Ajax responseText;
if(!data) return false;
var $data = document.createElement("div");
$data.innerHTML = data;
var em = $data.getElementsByTagName("*");
for(var i = 0; i < em.length; i++)
{
var parent = sget(em[i].id); // sget function is : document.getElementById
if(parent)
{
var html = em[i].innerHTML.replace(/(\s)+/gim, "").replace(/(\n|\r\n)+/gim, "");
var id = em[i].id;
savedPages[id] = savedPages[id] || [];
var _md5 = md5(html);
if(savedPages[id][0] == _md5) continue;
savedPages[id] = [_md5, getTime()];
parent.innerHTML = em[i].innerHTML;
}
if(em[i].tagName === "SCRIPT")
{
var code = em[i].innerHTML.replace(/(\s)+/gim, "").replace(/(\n|\r\n)+/gim, "");
var id = em[i].id;
savedPages[id] = savedPages[id] || [];
var _md5 = md5(code);
if(savedPages[id][0] == _md5) continue;
savedPages[id] = [_md5, getTime()];
try{eval(em[i].innerHTML)}catch(ex){log(ex)};
}
}
};
So, you can optimize it but it depends also in which browser are you running this code.
I assumed the follows:
All IDs are unique, and you rely on that. You want to compare basically elements that have the same ID, not the same structure.
As you said, all children have IDs, and you want to compare only children – not nested node
The elements received from the server have only additional children not less. For removing children, you have to add some other code.
Therefore, if you have the same number of children, we assume they're the same (to optimize). If this is not true, then you have to implement the removal of children as well
Said that, I believe that this kind of stuff is more suitable on server side, that should send to the client only the part that are actually modified. That what we do usually – or, if we don't care, replace everything.
var div = document.createElement('div');
div.innerHTML = s;
var root = div.firstChild;
var children = root.children;
var documentRoot = document.getElementById(root.id);
if (documentRoot && documentRoot.children.length < children.length) {
var node = null;
var previousNode = null;
var index = 0;
while ( node = children[index++] ) {
var documentNode = document.getElementById(node.id);
if (!documentNode) {
if (previousNode)
documentRoot.insertBefore(node, previousNode.nextSibling);
else
documentRoot.insertBefore(node, documentRoot.firstChild);
documentNode = node;
}
previousNode = documentNode;
}
previousNode = null;
} else {
// probably append as is somewhere
}
The solution is not so simple. What if the parent, myID, did not exist in sample A but the child nodes were in both samples indicating 3 layers in the DOM that need to be compared and adjusted? How would you compare this:
<div id="papa">
<div id="myID">
<div id="a"></div>
<div id="b">
<div id="ba"></div>
</div>
<div id="c">
<span id="ca"></span>
</div>
</div>
</div>
vs
<div id="papa">
<div id="a"></div>
<div id="b">
<div id="ba"></div>
</div>
<div id="c">
<span id="ca"></span>
</div>
</div>
In this case the comparison becomes more complicated. You will actually need a fully fleshed out XML/HTML language aware diff utility with a merge function. You can play around with Pretty Diff to demonstrate just how complicated this can get, but unfortunately it does not have a merge function so it cannot be a fully automated solution to your problem.

Categories