How can I save user input to local storage? - javascript

I've made a day planner and realised I never set the input up to save to local storage. I'm not very familiar with saving to local storage and quite frankly don't know where to start, and the examples I'm seeing online are very different from the format of my code so they're hard to follow. Any tips?
$(function(){
$(document).on('click','.edit_btn' , function(){
let editable = $(this).prev('.edit_cont').attr('contenteditable');
if(editable){
$(this).text('edit');
$(this).prev('.edit_cont').removeAttr('contenteditable');
$(this).prev('.edit_cont').removeClass('edit_cont_border');
}
else{
$(this).text('save');
$(this).prev('.edit_cont').attr('contenteditable','true');
$(this).prev('.edit_cont').addClass('edit_cont_border');
}
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "container" spellcheck="false">
<div class = "row my-row">
<div class = "col my-col col-a1 colorcode" id = "9"> 9am </div>
<div class = "col my-col col-a2 edit_cont" > </div>
<div class = "col my-col col-a3 edit_btn"> edit </div>
</div>
<div class = "row my-row" >
<div class = "col my-col col-b1 colorcode" id = "10"> 10am </div>
<div class = "col my-col col-b2 edit_cont"> </div>
<div class = "col my-col col-b3 edit_btn"> edit </div>
</div> (+6 more rows)

Quite simple to use localStorage. All you have do is, for example:
localStorage.setItem('your_data_key', yourData);
You can choose if you want to store single input's data in a local storage item or the entire form.
If you want to use single item to store data of entire form, one way is to convert the form's data into JSON. Since you are using jQuery, check the answers in: Convert form data to JavaScript object with jQuery It has an answer for doing it in vanilla JS as well.
Object.fromEntries(new FormData(form))
You can use combination of event listeners to save and load data to and from localstorage.
In jQuery, one way would be something like the following.
$(function() {
// storedData = localStorage.getItem('your_data_key');
// Load the stored Data to the form based on the way you have saved it
});
function storeData(e) {
// yourData = ...; // Collect the data how you want
// localStorage.setItem('your_data_key', yourData);
}
$("form").on('submit', storeData);
$("form :input").on('change', storeData);
The above is incomplete, untested and for guidance purpose only.

Related

Delete product with filter in Localstorage

I'm working on a shopping cart project and I'm stuck at the product removal stage.
I tried to work it with the filter method and it works without really working in the sense that what I defined works only in the case where the product having a dataset id and equivalent to the id of the localstorage but that the color is different then there the deletion of the selected product works and the localStorage is updated.
On the other hand when I want to delete a product having a different id but which has the same color as the product selected previously it deletes both products.
An example :
If I have a sofa that has an id 001 and a blue color and I have another sofa that has an id 002 and a blue color and I press the delete button then both products disappear...
How can I avoid this?
I think the definition of the condition I wrote here is a little shaky but I don't know yet how to fix it:
const deleteProduct = function ()
{
let deleteButton = document.querySelectorAll('.deleteItem');
let localStorageProducts2 = localStorage.getItem('Produits')
// Loop to get all buttons
for (let i = 0; i < deleteButton.length; i++)
{
// More clear for the syntax
let buttons = deleteButton[i];
// Link each button to his article
let myActualProduct = deleteButton[i].closest('article');
let getStorageProducts2 = JSON.parse(localStorageProducts2);
buttons.addEventListener("click",() =>
{
getStorageProducts2 = getStorageProducts2.filter(productsInLocalStorage => productsInLocalStorage.id === myActualProduct.dataset.id && productsInLocalStorage.colors !== myActualProduct.dataset.color);
// Update the localStorage
localStorage.setItem('Produits',JSON.stringify(getStorageProducts2));
myActualProduct.remove()
alert('Le produit a bien été supprimé')
// Reload the page
window.location.href ="cart.html";
// Update the productsInLocalStorage
})
}
}
deleteProduct()
<section id="cart__items">
<article class="cart__item" data-id="{product-ID}" data-color="{product-color}">
<div class="cart__item__img">
<img src="../images/product01.jpg" alt="Photographie d'un canapé">
</div>
<div class="cart__item__content">
<div class="cart__item__content__description">
<h2>Nom du produit</h2>
<p>Vert</p>
<p>42,00 €</p>
</div>
<div class="cart__item__content__settings">
<div class="cart__item__content__settings__quantity">
<p>Qté : </p>
<input type="number" class="itemQuantity" name="itemQuantity" min="1" max="100" value="42">
</div>
<div class="cart__item__content__settings__delete">
<p class="deleteItem">Supprimer</p>
</div>
</div>
</div>
</article>
</section>
The HTML part doesn't work here in JSFiddle , I'm working with an API on local.
I find the solution by myself thanks to an article teaching how to use findIndex on array of object and the splice method.

How can I add the same XML tags multiple times, with different content?

I have some problems with my code. I want to create an XML Document with JQuery / JavaScript. I am now at the point, where I want to create a few Tags and populate them each with the same tags but different content inside the tags.
Here is the code for better understand
function setItems(xmlDoc, channelTag){
const itemList = [];
const itemTitle = xmlDoc.createElement("title");
const itemLink = xmlDoc.createElement("link");
const itemGuid = xmlDoc.createElement("guid");
const itemMediaContent = xmlDoc.createElement("media:content");
const itemMediaDescription = xmlDoc.createElement("media:description");
itemList.push(itemTitle, itemLink, itemGuid, itemMediaContent, itemMediaDescription);
for (var i = 0; i < jsonObj.length; i++){
var item = xmlDoc.createElement("item");
channelTag.appendChild(item);
//Populate the <item> with the tags from "itemList" and content from "jsonObj"
$.each(itemList, function(index) {
$(channelTag).children('item')[i].appendChild(itemList[index]).textContent = jsonObj[0].title;
})
}
}
The Output of the code looks like this:
<item></item>
<item></item>
<item>
<title>Something</title>
<guid>Something</guid>
<link>Something</link>
<media:content>Something</media:description>
<media:description>Something</media:description>
</item>
It always populates the last item-Tag but not the ones above. What I want is that every item-Tag has the same child-Tags (e.g. title, link, guid and so on). Is there something i am missing some unique tags or something like that?
Edited:
Here is some minimal HTML and XML. The values for the function "xmlDoc" and "channelTag" just contains some Document Elements, where my items should be appended, like so:
<rss>
<channel>
<title>SomeTitle</title>
<atom:link href="Link" rel="self" type="application/rss+xml"/>
<link>SomeLink</link>
<description>SomeDesc</description>
<item></item>
<item></item>
<item></item>
</channel>
</rss>
<div class="col-5 col-sm-5 col-lg-3 order-2 count">
<a class="guid1"><img class="card-img image1"></a>
</div>
<div class="col-7 col-sm-7 col-lg-5 order-2">
<div class="card-body">
<a class="guid1">
<h5 class="card-title title1 overflow-title"></h5>
</a>
<p class="card-text body1 text-body overflow-body"></p>
<div class="card-body subtitle">
</div>
</div>
</div>
There are several issues with your code but the area we mostly want to focus on is this:
for (var i = 0; i < jsonObj.length; i++){
var item = xmlDoc.createElement("item");
channelTag.appendChild(item); // you're adding a node here
$.each(itemList, function(index) {
$(channelTag).children('item')[i].appendChild(... // and here
})
}
Instead of appending nodes multiple times per iteration, you should create and populate your node before add it it to channelTag.
Here's a way your could do it:
// use a "$" sign as a variable name prefix, so you know it's a Document Element and not a regular javascript variable
var $item = xmlDoc.createElement("item");
// you don't need jQuery for this iteration
itemList.forEach(function (item, index) {
$item.appendChild(itemList[index]).textContent = jsonObj[0].title;
});
// if "channelTag" is a Document Element, rename it "$channelTag"
$channelTag.appendChild(item);
Couple things about the code above:
you don't need jQuery, use forEach instead
there is no way telling what type is channelTag. If it is a selector (of type string), use $(selector), but you are using the appendChild() method before, suggesting it's actually a Document Element. In that case you don't need to wrap it with $()
I don't have the context needed to test this code, so no guarantee it'll work out of the box. But try and re-read your code and go through it top-to-bottom. For each variable, describe its type and value. I found that to be helpful when I'm lost in code.

Jquery Classes and InnerHtml

So what I'm doing is pulling battery voltage and the state of a battery from a Mysql database processing the data in data.php and putting that into a Json array all that is fine. When I get to the Javascript side I get stuck.
2 Questions:
Question 1: How do insert the value into id voltage in html without removing the span?
HTML Code:
<div id="voltState" class="tile-box bg-green">
<div class="tile-header">
Battery Status
<div class="float-right">
<i class="glyph-icon icon-bolt"></i>
Green
</div>
</div>
<div class="tile-content-wrapper">
<i class="glyph-icon icon-database"></i>
<div id="voltage" class="tile-content">
<span>volts</span>
</div>
</div>
</div>
Questions 2: class="tile-box bg-green"> I want to replace with the var status from the Javascript so it looks something like class="tile-box bg-(status var here)">
$(document).ready(function() {
sensorData();
});
function sensorData(){
$.ajax({
type:'GET',
url:"data.php",
data:"json",
success:function(sensor) {
//document.write(sensor);
var volt = sensor[0];
var status = sensor[1];
var date = sensor[2];
document.getElementById('voltage').innerHTML = (volt);
$("#voltState").toggleClass('bg-green bg-(STATUS VAR HERE??)');
},
dataType:'json'
});
}
setInterval(sensorData, 3000);
You can use $("#voltage").append(volt) or $("#voltage").prepend(volt) based on if you want the span before or after the value. In this case I assume you want the span after the volt so you can use the second code. If you would like the value inside a new span you can also use:
$("#voltage").prepend($("").text(volt));
You can store the previous status value in a variable lets say pastStatus. So once you have set
$("#voltState").removeClass('bg-'+pastStatus).addClass('bg-'+status);
pastStatus = status
Note: toggleClass is used when you want to switch between adding and removing the same class. It can't be used in this case since you want to add a class and remove another.
document.getElementById('voltage').appendChild(volt);
or
document.getElementById('voltage').innerHTML = '<span>'+volt+'</span>';

Loading specific div based on the results of multiple dropdowns

EDIT: Would the approach be much easier if the Javascript listed was removed completely, and the dropdown menus restyled as <div>'s within <li>'s, and the final div was generated by a Javascript onclick event? e.g.
<a id="click_link">click me</a>
$("#click_link").click(function(){
$('#div').load('http://www.link.com/');
});
Either way, the problem at hand...
My decision to use an elegant-looking javascript solution is highlighting my massive inexperience when it comes to javascript! The problem is, on the face of it, simple...
Once an option has been chosen on each of the dropdown menus, I need a final div to load so that a specific button can be shown (a link to buy the item with the specified options, e.g. choosing Necklace D, with Stone Option B, and Delivery Option A = loading div with 'Buy' Button #17)
The dropdowns are divs that are filled and styled through the Javascript (as opposed to using the simpler <form> and <input> method), giving the flexibility to add two lines of differently styled text for each option etc. - This is where I step into the realm of the unknown and my inexperience shines through.
The isolated section is viewable in its entirity here
Ok, to the code.
Here's the Javascript:
function createByJson() {
var pearlData = [
{description:'Choose your pearl...', value:'Pearls', text:'Pearls'},
{description:'Beautiful black stone', value:'Black Pearl', text:'Black Pearl'},
{description:'Classic white stone', value:'White Pearl', text:'White Pearl'}
];
$("#DropItPearls").msDropDown({byJson:{data:pearlData, name:'pearls', width: 200}}).data("dd");
var blodeuweddData = [
{description:'Choose your item...', value:'Blodeuwedd', text:'the Blodeuwedd Collection'},
{description:'A striking statement', value:'BlodeuweddCelticStatement', text:'Celtic Statement Piece'},
{description:'Gold laced flower and pearl', value:'BlodeuweddBracelet', text:'Bracelet'},
];
$("#DropItBlodeuwedd").msDropDown({byJson:{data:blodeuweddData, name:'blodeuwedd', width: 250}})
.msDropDown({on:{change:function(data, ui) {
var val = data.value;
if(val!="")
window.location = val;
}}}).data("dd");
var deliveryData = [
{description:'Choose your method...', value:'Delivery', text:'Delivery Options'},
{description:'4-6 weeks delivery', value:'Four Weeks', text:'Made To Order'},
{description:'(unavailable on this item)', value:'Rush', text:'Express Delivery', disabled:true}
];
$("#DropItDelivery").msDropDown({byJson:{data:deliveryData, name:'delivery', width: 200, selectedIndex: 1}}).data("dd");
paymentData = [
{ description:'How would you like to pay?', value:'Payment', text:'Payment Method'},
{image:'images/msdropdown/icons/Visa-56.png', description:'Secure online payment', value:'Visa', text:'Visa'},
{image:'images/msdropdown/icons/Paypal-56.png', description:'Secure online payment', value:'Paypal', text:'Paypal'},
{image:'images/msdropdown/icons/EmailPay-56.png', description:'Order by email', value:'Email Payment', text:'Send Your Details'},
{image:'images/msdropdown/icons/Mastercard-56.png', description:'(coming soon)', value:'Mastercard', text:'Mastercard', disabled:true},
{image:'images/msdropdown/icons/Collect-56.png', description:'(coming soon)', value:'Collection', text:'Order and Collect', disabled:true},
{image:'images/msdropdown/icons/Email-56.png', description:'email Menna', value:'Other Method', text:'Alternatives'}
];
$("#DropItPayments").msDropDown({byJson:{data:paymentData, name:'payments', width: 250}}).data("dd");
}
$(document).ready(function(e) {
//no use
try {
var pages = $("#pages").msDropdown({on:{change:function(data, ui) {
var val = data.value;
if(val!="")
window.location = val;
}}}).data("dd");
var pagename = document.location.pathname.toString();
pagename = pagename.split("/");
pages.setIndexByValue(pagename[pagename.length-1]);
$("#ver").html(msBeautify.version.msDropdown);
} catch(e) {
//console.log(e);
}
$("#ver").html(msBeautify.version.msDropdown);
//convert
$("select").msDropdown();
createByJson();
$("#tech").data("dd");
});
function showValue(h) {
console.log(h.name, h.value);
}
$("#tech").change(function() {
console.log("by jquery: ", this.value);
})
//
And the html:
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Item</p></div>
<div id="DropItBlodeuwedd"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Precious Stones</p></div>
<div id="DropItPearls"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Payment</p></div>
<div id="DropItPayments"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Delivery</p></div>
<div id="DropItDelivery"></div>
</div>
<div id="dropOptions">
<div id="dropOptionsTitle"><p>Buy Now!</p></div>
<div id="DropItBuy"></div>
</div>
Again, working version viewable here
Many thanks in advance!
What I think you want is for your Buy button to dynamically read what the dropdowns currently say and build a link for redirection based on that, rather than trying to update the Buy button every time a dropdown changes.
From your code I can't see what the form of the final URL is supposed to be. For example, to get the current value of the delivery option, you can check $('#DropItDelivery :selected').text() which will be something like "Made To Order".
Your Buy Now! could be a button with a click event that reads these values and constructs the URL with basic string concatenation, e.g.:
window.location = "buynow.html?delivery=" + $('#DropItDelivery :selected').text() +
"&payment=" + $('#DropItPayments :selected').text()
// etc.
Of course you'd have to handle these options on the server.
In case you want to redirect to the payment page of the processor, you can just branch based on the payment method and give them the URL you want based on that.
var pm = $('#DropItPayments :selected').text();
if (pm == "Visa")
{
// Visa payment URL construction
}
else if (pm == "Send Your Details")
{
// Send your details URL construction
}
// etc.

How to use specific data from arrays - Example of click

I have the following JQuery code:
var test = new Array();
$(".quiz_list_row").each(function(index){
// Gets the data necessary to show game chosen
$quiz_list_id = $(this).data("quizlistId");
$quiz_level_reached = $(this).data("quizlevelReached");
test.push($quiz_list_id,$quiz_level_reached);
$(this).click(function(){
alert("test: "+test);
});
});
The divs (using html5 to send data):
<div class="quiz_list_row" data-quizlist-id="1" data-quizlevel-reached="5">
<div class="inline quiz_list_cell" id="quiz_list_cell_row0_id1">Quiz 1</div>
<div class="inline quiz_list_cell" id="quiz_list_cell_row0_id2">Current level: 5</div>
</div>
<div class="quiz_list_row" data-quizlist-id="2" data-quizlevel-reached="7">
<div class="inline quiz_list_cell" id="quiz_list_cell_row1_id1">Quiz 2</div>
<div class="inline quiz_list_cell" id="quiz_list_cell_row1_id2">Current level: 7</div>
</div>
The problem is that I need to find out how to use the data in the array test when the user clicks on a specific row (I want to use $quiz_list_id and $quiz_level_reached).
Unless there is a specific reason you're extracting the attributes and putting them into an array, I think you're taking some unecessary steps to achieving what you want. Take away the complexity from this, you have access to the data attributes with the .data() method at any time you have access to the elements jQuery object, one of those times is within the click handler itself.
var quizRows = $(".quiz_list_row");
quizRows.click(function(event) {
var self = $(this);
//As the element clicked on has it's data attributes defined
//You would just need to retrieve it when the element is clicked on
var id = self.data('quizlist-id'),
level = self.data('quizlevel-reached');
console.log("id is " + id);
console.log("level is " + level);
}

Categories

Resources