contentEditable doesn't work with localStorage after page refresh - javascript

When you click the addFruit button, the input text value gets appended to the fruitList as it should. localStorage is activated at the same time, and it works, the data is still there after page refresh.
When you double click on the item that you just appended, you can edit it (contentEditiable), but when you refresh the page, the localStorage retrieves the original name instead of the modified one.
I think it's an an updating issue. When you double click on a list item, it should call the storestate function as soon as you're done editing, so it overwrites what was previously added to localStorage.
I've tried adding storestate() numerous places, and tried to move around my functions, suspecting that my code is written in the wrong order.
Sometimes it actually works after page refresh, but it's usually if I add several items, and then edit one of them. But not always. It's confusing!
I can't find a single similar example on SO, can someone point me in the right direction? :)
(function() {
var fruitList = document.querySelector('#fruitList');
var fruitInput = document.querySelector('.fruitInput');
var addFruitButton = document.querySelector('.addFruitButton');
var removeFruits = document.querySelector('.removeFruits');
// Add fruits
// Store fruits
function storestate() {
localStorage.fruitList = fruitList.innerHTML;
};
// Retrieve stored fruits from localStorage
function retrievestate() {
if (localStorage.fruitList) {
fruitList.innerHTML = localStorage.fruitList;
}
}
retrievestate();
// Remove fruit storage
function removeStorage() {
localStorage.clear(fruitList);
fruitList.innerHTML = ''; // removes HTML
}
function addFruit() {
if (fruitInput.value) {
var li = document.createElement('li');
li.className = 'fruit-item';
li.innerHTML = fruitInput.value;
li.contentEditable = 'true';
fruitList.append(li);
fruitInput.value = ''; // Reset input field
}
storestate();
}
// Clear all fruits
removeFruits.onclick = removeStorage;
//Add fruit
addFruitButton.onclick = addFruit;
})();
I tried to embed the entire code-snippet on SO, but I get an error because of localStorage. Works fine on jsFiddle and other editors:
https://jsfiddle.net/bx39gd0n/10/

https://jsfiddle.net/xbrra7yt/1/
(function() {
...
//change state of item
function changestate() {
console.log('changed');
}
...
fruitList.addEventListener('keyup', changestate);
})();
You would simply chain an eventlistener to be called on keyup. In the fiddle it simply logs 'changed' to the console. Just replace that with your own code to replace the list in localStorage and you should be fine!

Related

onClick Add to Grid from an Array but duplicates on second iteration

Use case is to create Add/show/select/delete text messages on a page. I have used array to store the messages on each click till here it works fine but when I try to create Divs and show the messages in grid, I am having duplication on each click. I can see that my function is reading the array fine and creating the div's on the first click but it does not clear the previously created div on second iteration. Not sure how to approach this. Please advise.
here is the snippet.
<script>
//<!-- Fetch data from Textarea when user Click Save and create or push in an array -->
let ArrNotes = [];
function SaveNote() {
let edittext = document.getElementById("editor").value;
ArrNotes.push(edittext);
document.getElementById("SavedNote").innerHTML = ArrNotes;
let container = document.getElementById("GridNotes");
container.className= "GridNotes";
ArrNotes.forEach(createGrid);
function createGrid(item,index)
{
text = undefined;
var tag = document.createElement("div");
tag.className= "grid";
var text = document.createTextNode(index + ": " + item);
//tag.appendChild(text);
container.appendChild(text);
}
}

I am having trouble capturing the vale of a text area, and saving it into local storage

Hi I just wondering if i can get some pointers with my code, I am trying to capture and save the input value of a textarea. I am fairly new to JavaScript and I have been wrecking my brain trying to figure it out. My issue is regarding the saveEntry() function, which isn't complete I have only posted how my code is right now, and isn't causing errors/unwanted effects. Any tips or hints would be fantastic, as I keep getting errors
function addTextEntry(key, text, isNewEntry) {
// Create a textarea element to edit the entry
var textareaElement = document.createElement("textarea");
textareaElement.rows = 5;
textareaElement.placeholder = "(new entry)";
// Set the textarea's value to the given text (if any)
textareaElement.value = text;
// Add a section to the page containing the textarea
addSection(key, textareaElement);
// If this is a new entry (added by the user clicking a button)
// move the focus to the textarea to encourage typing
if (isNewEntry) {
textareaElement.focus();
}
// Create an event listener to save the entry when it changes
// (i.e. when the user types into the textarea)
function saveEntry() {
// Save the text entry:
// ...get the textarea element's current value
var currentValue = document.getElementById('textarea').value;
// ...make a text item using the value
// ...store the item in local storage using the given key
localstroage.setItem(key, item);
}
// Connect the saveEntry event listener to the textarea element 'change' event
textareaElement.addEventListener("change", saveEntry());
}
function addImageEntry(key, url) {
// Create a image element
var imgElement = new Image();
imgElement.alt = "Photo entry";
// Load the image
imgElement.src = url;
// Add a section to the page containing the image
addSection(key, imgElement);
}
/**
* Function to handle Add text button 'click' event
*/
function addEntryClick() {
// Add an empty text entry, using the current timestamp to make a key
var key = "diary" + Date.now();
var text = "";
var isNewEntry = true;
addTextEntry(key, text, isNewEntry);
I was told to utilise something similar to this code below, but not exactly the same as I need to capture the data value of the user input text, not pre-created data.
function createDemoItems() {
console.log("Adding demonstration items to local storage");
var item, data, key;
// Make a demo text item
data =
"Friday: We arrived to this wonderful guesthouse after a pleasant journey " +
"and were made most welcome by the proprietor, Mike. Looking forward to " +
"exploring the area tomorrow.";
item = makeItem("text", data);
// Make a key using a fixed timestamp
key = "diary" + "1536771000001";
// Store the item in local storage
localStorage.setItem(key, item);
// Make a demo text item
data =
"Saturday: After a super breakfast, we took advantage of one of the many " +
"signed walks nearby. For some of the journey this followed the path of a " +
"stream to a charming village.";
item = makeItem("text", data);
// Make a key using a fixed timestamp
key = "diary" + "1536771000002";
// Store the item in local storage
localStorage.setItem(key, item);
// Make a demo image item
data = window.DUMMY_DATA_URL;
item = makeItem("image", data);
// Make a key using a fixed timestamp
key = "diary" + "1536771000003";
// Store the item in local storage
localStorage.setItem(key, item);
// Make a demo text item
data =
"Sunday: Following a tip from Mike we drove to a gastropub at the head of " +
"the valley - a great meal and fabulous views all round.";
item = makeItem("text", data);
// Make a key using a fixed timestamp
key = "diary" + "1536771000004";
// Store the item in local storage
localStorage.setItem(key, item);
}
You are very close, you just have to make some adjustments here and there!
Just as a disclaimer, I had to re-create your addSection() function, in order to have it properly working. If you already had one, you could discard mine
When we create a new entry, in order to make it distinguishable, I have assigned it the id of the key. Before, you were trying to call getElemenyById("textarea"), but no element had id textarea, which is in fact the tag name of the textarea element that you created. Read more about getElementByTagName if you want.
I have changed the way the event listener is set to:
textareaElement.addEventListener(
'input',
function () { saveEntry(); },
false
);
The difference between change and input are that change will fire only when you are done with the changes and click outside of the textarea, whilst input will fire everytime that you input something. Now you know, so of course, feel free to change it to what you would like it to behave.
Lastly, I have made the just-created item to be retrieved immediately and logged to console. This will be useful just for testing, you can comment out those lines when you are happy.
Beware that the snippet below is playable, but it won't actually save data to LocalStorage because of SO limitations, so you won't be able to fully test it on this page.
function addSection(key, element) {
element.id = key;
var test = document.querySelector("#test");
test.appendChild(element);
}
function addTextEntry(key, text, isNewEntry) {
// Create an event listener to save the entry when it changes
// (i.e. when the user types into the textarea)
function saveEntry() {
// Save the text entry:
// ...get the textarea element's current value
var currentValue = document.getElementById(key).value;
// ...store the item in local storage using the given key
localStorage.setItem(key, currentValue);
//Testing if we can retrieve the item, comment out when you're happy
var item = localStorage.getItem(key);
console.log(item);
}
// Create a textarea element to edit the entry
var textareaElement = document.createElement("textarea");
textareaElement.rows = 5;
textareaElement.placeholder = "(new entry)";
// Set the textarea's value to the given text (if any)
textareaElement.value = text;
// Add a section to the page containing the textarea
addSection(key, textareaElement);
// If this is a new entry (added by the user clicking a button)
// move the focus to the textarea to encourage typing
if (isNewEntry) {
textareaElement.focus();
}
textareaElement.addEventListener(
'input',
function () { saveEntry(); },
false
);
// Connect the saveEntry event listener to the textarea element 'change' event
//textareaElement.addEventListener("change", saveEntry());
}
function addImageEntry(key, url) {
// Create a image element
var imgElement = new Image();
imgElement.alt = "Photo entry";
// Load the image
imgElement.src = url;
// Add a section to the page containing the image
addSection(key, imgElement);
}
/**
* Function to handle Add text button 'click' event
*/
function addEntryClick() {
// Add an empty text entry, using the current timestamp to make a key
var key = "diary" + Date.now();
var text = "";
var isNewEntry = true;
addTextEntry(key, text, isNewEntry);
}
window.onload = () => addEntryClick();
<html>
<head>
</head>
<body>
<div id="test"></div>
</body>
</html>
There are a number of things wrong with the way you're doing things, but you know that: that's why you're here!
You have a typo: localstroage should be localStorage
You create a text area but don't give it an ID. In your saveData function you attempt to find it, but you're searching for it by tag name. There's no need to search: your event handler will already have this set to the element.
In your event handler you refer to your function as saveData(). This will invoke the function immediately and assign its return value as an event handler. Just pass the function name.
Here's a demonstration of concept for you:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Explore local storage</title>
</head>
<body>
<textarea id="txt" placeholder="Enter text and press TAB"></textarea>
<script>
"use strict";
let txtKey = "someKey"
// Save the data. No need to search for the text area:
// the special value 'this' is already set to it.
function saveEntry() {
localStorage.setItem(txtKey, this.value);
}
// Look fr the previous text and if it exists, put it in the textarea
let storedText = localStorage.getItem(txtKey);
if (storedText) {
document.getElementById('txt').value = storedText;
}
// Now add the event listener.
tArea.addEventListener('change', saveEntry); // Pass just the function name
</script>
</body>
</html>
This code uses a hard-coded value for txtKey. Your code might need to generate and track some value for the key, otherwise you risk overwriting earlier data with later data.

Add a js function to the DOM?

I have a very simple HTML page. After everything is loaded, the user can interact with it perfectly. Now, at some point, the user clicks on an element. An ajax call is made and new data is being requested. I now want to remove the previous element the user clicked on with the element(s) the user has requested (on the same page) - practically remove the old element from the DOM and add the new one. Well, I did this as well, but I am unable to add a function to the newly created element. This is my function:
setCountry = function(value){
document.getElementById('country').innerHTML = value;
}
and I'm trying to add it like this to my element
a_tag.setAttribute("href", "javascript:setCountry(countries[i]);");
The function is being called and writes "undefined" to the innerHTML element. I set the attribute using a for loop and just above the for loop I alert an element from the array to be sure it's correct, and it prints out the correct value.
I assume the problem happens because the function is being created on the first load of the DOM, but I'm not sure. Can anyone shed some light on what is really happening here and what I should do to correct it? I want to be able to add more functions so not looking for a work around writing an innerHTML tag, I just want to understand what I'm doing wrong.
Thank you.
Edited with more code
//declare an array to hold all countries form the db
var countries = new Array();
function getCountries(region) {
document.getElementById('scroller').innerHTML = '';
//send the data to the server and retreive a list of all the countries based on the current region
$.ajax({
type: "POST",
url: "scripts/get_countries.php",
data: {
region: region
},
success: saveDataToArray,
async: false,
dataType: 'json'
});
//save the data to an array
function saveDataToArray(data){
var i = 0;
while (data[i]){
countries[i] = data[i];
i++;
}
}
scroller = document.getElementById('scroller');
//create a ul element
var holder = document.createElement("ul");
//here create a back button which will recreate the whole list of regions
var total = countries.length;
for(i=0;i<total;i++){
//create the first field in the list
var bullet_item = document.createElement("li");
//create an a tag for the element
var a_tag = document.createElement("a");
//set the redirect of the tag
a_tag.setAttribute("href", "javascript:setCountry(this);");
//create some text for the a_tag
var bullet_text = document.createTextNode(countries[i]);
//apend the text to the correct element
a_tag.appendChild(bullet_text);
//apend the a_tag to the li element
bullet_item.appendChild(a_tag);
//apend the item to the list
holder.appendChild(bullet_item);
}
//apend the holder to the scroller
scroller.appendChild(holder);
}
function setRegion(region){
document.getElementById('region').innerHTML = region;
}
setCountry = function(value){
document.getElementById('country').innerHTML = value;
}
There is no need for quoting the code in a string. Instead of this:
a_tag.setAttribute("href", "javascript:...")
Try to form a closure:
a_tag.onclick = function () { ... }
Note that by default <A> elements without HREF do not look normal, but you can fix that with CSS.
Problem solved
Everything was good apart from the way I was declaring the href parameter
a_tag.setAttribute("href", "javascript:setCountry("+'"'+countries[i]+'"'+")");
it's all the usual, a game of single quotes and double quotes.
Thanks everyone for pitching in ideas. Much appreciated as usual
Adrian

Adding value from one list to another depanding on button clicked

I have two multi lists. In first multi list, i got all the attributes of table by using query then now by selecting one attribute from this list, when i click on "ADD" button i want that copy of this attribute should go into another list.
What i have done is i added javascript onclick function for ADD button in that i got the selected value from first multilist. But now I am not getting how to put that value in to second multi list?
What i have done in java script function is:
var index=document.getElementById("List1").selectedIndex;
var fieldval=document.getElementById("List1").options[index].value;
document.getElementById("List2").options[0].value=fieldvalue;
But this is not working. Temporarily I am adding value at first position.
Thanks in advance.
From here:
If you want to move an element from the first list to the second:
var index=document.getElementById("List1").selectedIndex;
var elOpt = document.getElementById('List1').options[index];
var elSel = document.getElementById('List2');
try {
elSel.add(elOpt, null); // standards compliant; doesn't work in IE
}
catch(ex) {
elSel.add(elOpt); // IE only
}
If you want to add one:
var index=document.getElementById("List1").selectedIndex;
var elOpt = document.getElementById('List1').options[index];
var elSel = document.getElementById('List2');
var elOptNew = document.createElement('option');
elOptNew.text = elOpt.text;
elOptNew.value = elOpt.value;
try {
elSel.add(elOptNew, null); // standards compliant; doesn't work in IE
}
catch(ex) {
elSel.add(elOptNew); // IE only
}

jQuery removing elements from DOM put still reporting as present

I have an address finder system whereby a user enters a postcode, if postcode is validated then an address list is returned and displayed, they then select an address line, the list dissappears and then the address line is split further into some form inputs.
The issue i am facing is when they have been through the above process then cleared the postcode form field, hit the find address button and the address list re-appears.
Event though the list and parent tr have been removed from the DOM it is still reporting it is present as length 1?
My code is as follows:
jQuery
// when postcode validated display box
var $addressList = $("div#selectAddress > ul").length;
// if address list present show the address list
if ($addressList != 0) {
$("div#selectAddress").closest("tr").removeClass("hide");
}
// address list hidden by default
// if coming back to modify details then display address inputs
var $customerAddress = $("form#detailsForm input[name*='customerAddress']");
var $addressInputs = $.cookies.get('cpqbAddressInputs');
if ($addressInputs) {
if ($addressInputs == 'visible') {
$($customerAddress).closest("tr").removeClass("hide");
}
} else {
$($customerAddress).closest("tr").addClass("hide");
}
// Need to change form action URL to call post code web service
$("input.findAddress").live('click', function(){
var $postCode = encodeURI($("input#customerPostcode").val());
if ($postCode != "") {
var $formAction = "customerAction.do?searchAddress=searchAddress&custpc=" + $postCode;
$("form#detailsForm").attr("action", $formAction);
} else {
alert($addressList);}
});
// darker highlight when li is clicked
// split address string into corresponding inputs
$("div#selectAddress ul li").live('click', function(){
$(this).removeClass("addressHover");
//$("li.addressClick").removeClass("addressClick");
$(this).addClass("addressClick");
var $splitAddress = $(this).text().split(",");
$($customerAddress).each(function(){
var $inputCount = $(this).index("form#detailsForm input[name*='customerAddress']");
$(this).val($splitAddress[$inputCount]);
});
$($customerAddress).closest("tr").removeClass("hide");
$.cookies.set('cpqbAddressInputs', 'visible');
$(this).closest("tr").fadeOut(250, function() { $(this).remove(); });
});
I think you're running into the same issue I recently ran into. If you have a variable pointing to 5 DIV's (example: var divs = $('.mydivs');) and then you call jQuery's remove() on one of the DIV's, like so: divs.eq(0).remove() you'll see that divs.size() still returns 5 items. This is because remove() operates on the DOM. However... if after calling remove() you then re-set your variable: divs = $('.mydivs'); and get the size you'll now get the correct size of the array. I've added sample code displaying this below:
// get all 5 divs
var d = $('.dv');
// remove the first div
d.eq(0).remove();
// you would expect 4 but no, it's 5
alert(d.size());
// re-set the variable
d = $('.dv');
// now we get 4
alert(d.size());

Categories