Why is the array empty every time on click? - javascript

So basically every time I click on the icon '.favorite i' it should add an object to my array. If I click the first time it adds the parent div to the array, but on the second time it deletes the first one and grabs the last parent div.
I'm working with three tabs called 'Monday', 'Tuesday' and 'Favorites'. I have a toggle icon which is an empty heart at start 'favorite i'. If I'm in Monday and click on the icon, the empty heart turns to be filled out and its parent is cloned and added to the '#fav' tab. When this happens the clone is saved to local storage. So if people refresh the page, they can still see their preferences.
When the heart is clicked in one of those cloned divs that specific div is removed from '#fav' and will also have to be removed from the array and local storage too.
To conclude, I need to save each cloned div into an array/local storage and then be able to delete each one of those from the array when these are removed from the #fav tab.
How to overcome this issue? Many thanks.
HTML
<div class="container">
<div class="tabs_main">
<div class="col-md-5"><a data-target="#mon" class="btn active" data-toggle="tab">Monday</a></div>
<div class="col-md-5"><a data-target="#tue" class="btn active" data-toggle="tab">Tuesday</a></div>
<div class="col-md-2"><a data-target="#fav" class="btn active" data-toggle="tab"><i class="fa fa-heart" aria-hidden="true"></i></a></div>
</div>
<div class="tab-content">
<div class="tab-pane active" id="mon">
<br>
<div class="spaces">
<div class="box-container">
<div class="box not-selected" id="box1">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</div>
<div class="box-container">
<div class="box not-selected" id="box2">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</div>
</div>
</div>
<div class="tab-pane" id="tue">
<br>
<div class="spaces">
</div>
</div>
<div class="tab-pane" id="fav">
<br>
</div>
</div>
</div>
JS
$('div.tab-pane').on('click', '.favorite', function(e) {
var add = $(this).parent().parent();
add.each(function(){
if ($(add.find('.not-selected .favorite i').hasClass('fa-heart'))) {
var boxContent = $(add).clone(true, true);
var showHide = $(boxContent).find(".session").addClass('selected').removeClass('not-selected');
var get = $(boxContent).wrap('<p/>').parent().html();
$(boxContent).unwrap();
var tempArray = [];
tempArray.push(get);
var myJSONString = JSON.stringify(get);
var parseString = $.parseJSON(myJSONString);
var finalString = myJSONString.replace(/\r?\\n/g, '').replace(/\\/g, '').replace(/^\[(.+)\]$/,'$1').replace (/(^")|("$)/g, '');
var final = localStorage.setItem('sessions', finalString);
$("#fav").append(tempArray);
};
});
});
Fiddle: https://jsfiddle.net/itsfranhere/nbLLc3L0/44/

Your question title is quite clear...
But your question itself and the code you provide prevents anyone to answer with full assurance.
Here is what the provided code produces, as an attempt to reproduce.
Now if I do not bother that code, which I think no one can deduct what it should do exactly...
Your question in title can be can answered by:
Simple! You declare (using var) the tempArray at every click.
That is why it do not retain the information (whatever it is supposed to retain) of the previous click.
I'm not "satisfied" of this answer to you... So if this do not answers completely your issue, please edit your question with more details. Feel free to fork the CodePen to make it look more like your project.
EDIT
From what I get of your script, you want to save "favorited" divs to localstorage. This implies you also have to remove them from localstorage and favorites tab if one is "unfavorited".
Also, you use id on "to be cloned" element. Be extremely cautious with this. An id has to be unique. So if the id is usefull (which was not obvious in the provided code), ensure you make it unique when you clone the element.
I improved you attempt to remove spaces and line feeds in what is to be saved.
Another good advise I have to give you is to use significative variable names in your code. Make your code speak by itself. Readability helps!
Here is your code, updated to do what is mentionned above. Have a close look to comments in code.
var tempArray = [];
// Clones
$('div.tab-pane').on('click', '.favorite', function(e) {
e.preventDefault();
// Elements we play with... Having significative variable names.
var heartLink = $(this);
var box = heartLink.parent('.box');
var container = box.parent('.box-container');
var favoriteTab = $("#fav .spaces");
// I don't know what is the use for those 3 lines below.
var idFind = box.attr("id");
var idComplete = ('#' + idFind);
console.log(idComplete);
//TOGGLE FONT AWESOME ON CLICK
heartLink.find('i').toggleClass('fa-heart fa-heart-o'); // .selected or not, you need those 2 classes to toggle.
box.toggleClass("selected not-selected"); // Toggle selected and not-selected classes
// Clone div
var boxContent = container.clone(true, true);
// Change the id
var thisID = boxContent.attr("id")+"_cloned";
boxContent.attr("id", thisID);
// Get the html to be saved in localstorage
var get = boxContent.wrap('<p>').parent().html();
get = get.replace(/\r?\n/g, "").replace(/>\s*</g, "><"); // remove line feeds and spaces
console.log(get);
boxContent.unwrap();
// Decide to add or remove
if(box.hasClass("selected")){
console.log("Add to array")
tempArray.push(get);
// Add to favorites tab
favoriteTab.append(boxContent);
}else{
console.log("Remove from array");
var index = tempArray.indexOf(get);
tempArray.splice(index);
// Remove from favorite tab
favoriteTab.find("#"+thisID).remove();
}
// Save
localStorage.setItem('sessions', tempArray.join(""));
});
// Append item if localstorage is detected
if (localStorage["sessions"]) {
$("#fav .spaces").append(localStorage["sessions"]);
console.log( localStorage.getItem('sessions') );
}
Updated CodePen

Don't save div elements in localStorage. I recommend you use an object constructor function like below to create a unique object for each [whatever] pushing these into an array then to localStorage in a try block.
localStorage.setItem('myobjects', JSON.stringify(myobjects));
// Object Constructor Functions
function Myobject(id, username, password) {
this.id = id;
this.username = username;
this.password = password;
this.type = 'credential';
}
function duplicate(id,obj){
var result = false;
obj.forEach( function (arrayItem){
if (arrayItem.id == id){
result = true;
}
});
return result;
}
function deleteObject(type, id){
var obj = {};
if (type === 'foo') {
obj = myobjectwhatever;
deleteThis(obj);
//save to local storage
try {
localStorage.setItem('myobject', JSON.stringify(myobjects));
}
catch (e) {
console.log(e);
}
}
else if (type === 'bar') {
//...
}
function deleteThis(o){
try {
for (var i = 0, iLen = o.length; i < iLen; i++) {
if (o[i].id === id) {
o.splice(i, 1);
}
}
}
catch (e) {
console.log(e);
}
}
}

Related

How to make the delete button of a list item work

I am currently working on a contact list program. I want to let people being able to delete the contacts on the list through a trash can button. Each of the contact info has its own button and people can delete which ever they want to remove. My code doesn't show any error through inspect (chrome) but the code is not working.
var demo = document.getElementById("demo");
function addName() {
var fname = document.getElementById("fname").value;
var entry = document.createElement("li");
var img = document.createElement("img");
img.src = "img/talkbox.png";
$(img).addClass("talkbox");
var deleteBtn = document.createElement("img");
deleteBtn.src = "img/delete.png";
$(deleteBtn).addClass("deleteBtn");
entry.appendChild(img);
entry.appendChild(document.createTextNode(fname));
entry.appendChild(deleteBtn);
demo.appendChild(entry);
document.getElementById('fname').value = "";
};
const trashCan = document.getElementById("trashcan");
trashCan.addEventListener('click', removeEvent);
function removeEvent(e) {
const list = document.getElementById("demo");
if (e.target.classList.contains('deleteBtn')) {
list.removeChild(e.target.parentElement);
list.removeChild(list);
};
};
<div>
<ul id="contactlist" class=ppl>
<li id="pplli">
<img id="wetalk" class="talkbox" src="img/talkbox.png">
<p class="contactname">Aiden<img id="trashcan" class="deleteBtn" src="img/delete.png"></p>
</li>
<ol id="demo">
</ol>
<br>
<img id="plus" src="img/plus.png">
</ul>
</div>
const trashCan = document.getElementById("trashcan");
If you have a list of items and you are using this code for it, this isn't going to work because IDs need to be unique in a document. If you create multiple elements and give them all the same ID, when you try to get the element by its ID, the browser won't know which one you are talking about.
On a separate note, you should use appropriate HTML elements to construct your document or you will cause accessibility issues. An image isn't a button. Consider using the <button> element instead.
I'm actually not sure how you are handling the delete work. But if you are planning to delete an item when clicking on the delete button in it. I mean the delete button is inside the item. Then you can just select the item using document.querySelect and use remove method in js. Here is the link

How do I change more than one element?

EDIT: I changed the var to class but I might have some error in here.
Here it goes, I want to have this paragraph in which the user can change the name on the following paragraph. The code I'm using only changes one name but the rest remains the same.
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
<input id="userInput" type="text" value="Name of kid" />
<input onclick="changey()" type="button" value="Change Name" /><br>
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
No error messages, the code only changes one name instead of all three.
Use class="kiddo" instead of id in the html.
You can then use var kiddos = document.getElementsByClassName('kiddo') which will return an array of all the elements of that class name stored in kiddos.
Then you just need to loop through the values and change what you want.
Example of loop below:
for (var i = 0; i < kiddos.length; i++) {
kiddos[i].innerHTML = userInput;
}
id should be unique on the page. Javascript assumes that there is only one element with any given id. Instead, you should use a class. Then you can use getElementsByClassName() which returns an entire array of elements that you can iterate over and change. See Select ALL getElementsByClassName on a page without specifying [0] etc for an example.
Hello You should not use id, instead use class.
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
After That on Js part :
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
you should use class instated of id. if you use id then the id [kiddo] must be unique
In short, document.querySelectorAll('.kiddo') OR
document.getElementsByClassName('kiddo') will get you a list of elements to loop through. Take note of querySelectorAll, though - it uses a CSS selector (note the dot) and doesn't technically return an array (you can still loop through it, though).
See the code below for some full working examples (const and arrow functions are similar to var and function, so I'll put up a version using old JavaScript, too):
const formEl = document.querySelector('.js-name-change-form')
const getNameEls = () => document.querySelectorAll('.js-name')
const useNameFromForm = (formEl) => {
const formData = new FormData(formEl)
const nameValue = formData.get('name')
const nameEls = getNameEls()
// Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(el => el.textContent = nameValue)
}
// Handle form submit
formEl.addEventListener('submit', (e) => {
useNameFromForm(e.target)
e.preventDefault() // Prevent the default HTTP request
})
// Run at the start, too
useNameFromForm(formEl)
.name {
font-weight: bold;
}
<!-- Using a <form> + <button> (submit) here instead -->
<form class="js-name-change-form">
<input name="name" value="dude" placeholder="Name of kid" />
<button>Change Name</button>
<form>
<!-- NOTE: Updated to use js- for js hooks -->
<!-- NOTE: Changed kiddo/js-name to spans + name class to remove design details from the HTML -->
<p>
Welcome to the site, <span class="js-name name"></span>! This is how you create a document that changes the name of the <span class="js-name name"></span>. If you want to say <span class="js-name name"></span> more times, you can!
</p>
var formEl = document.querySelector('.js-name-change-form');
var getNameEls = function getNameEls() {
return document.querySelectorAll('.js-name');
};
var useNameFromForm = function useNameFromForm(formEl) {
var formData = new FormData(formEl);
var nameValue = formData.get('name');
var nameEls = getNameEls(); // Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(function (el) {
return el.textContent = nameValue;
});
};
// Handle form submit
formEl.addEventListener('submit', function (e) {
useNameFromForm(e.target);
e.preventDefault(); // Prevent the default HTTP request
});
// Run at the start, too
useNameFromForm(formEl);
<button class="js-get-quote-btn">Get Quote</button>
<div class="js-selected-quote"><!-- Initially Empty --></div>
<!-- Template to clone -->
<template class="js-quote-template">
<div class="js-quote-root quote">
<h2 class="js-quote"></h2>
<h3 class="js-author"></h3>
</div>
</template>
You have done almost everything right except you caught only first tag with class="kiddo".Looking at your question, as you need to update all the values inside tags which have class="kiddo" you need to catch all those tags which have class="kiddo" using document.getElementsByClassName("kiddo") and looping over the list while setting the innerHTML of each loop element to the userInput.
See this link for examples:https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
try:
document.querySelectorAll('.kiddo')
with
<b class="kiddo">dude</b>

Search for contents of element and click its parent

I am trying to create an extention which clicks on an item of the price given by the user. Here is the relevant popup.html:
<input style="display:none" /><input type="text" id="userInput" value='' />
<button id="clickme">Run</button>
When 'clickme' is clicked, it runs this popup.js:
document.getElementById('clickme').addEventListener('click', function() {
var price = '$'+ document.getElementById("userInput").value+".00";
alert(price);
$("p:contains("price")").parentNode.click();
});
If you type the desired price in in the form as 48, it returns an alert with the value $48.00.
It then shuold click on the item of that price, however this currently isn't working. Here is the code of the relevant part of the website which I am trying to run my extention on (not my website):
<div class="grid__item wide--one-fifth large--one-quarter medium-down--one-half">
<a href="/collections/1seventeenweek7/products/copy-of-supreme-dazzle-warm- up-top-red" class="grid-link text-center">
<p class="grid-link__title">Supreme Corner Cap Light Blue</p>
<p class="grid-link__meta">
<span class="visually-hidden">Regular price</span>
$48.00
</p>
</a>
</div>
I am trying to get it to search for the p element containing $48.00, and then click on the a element which is the parent element, but this is not currently working. What am I doing wrong? - thanks
Here you go. This will work!
document.getElementById('clickme').addEventListener('click', function() {
var price = '$'+document.getElementById('userInput').value+'.00'
var metas = document.getElementsByClassName('grid-link__meta')
alert(price)
for (let i = 0; i < metas.length; i++) {
if (metas[i].innerHTML.includes(price)) metas[i].parentNode.click()
break
}
})
Personally, I'd really like to use something like the following, yet I forgot that getElementsByClassName doesn't return an array, but rather a NodeList object.
var price = '$'+document.getElementById('userInput').value+'.00'
var metas = document.getElementsByClassName('grid-link__meta')
var match = metas.find((curr) => curr.innerHTML.includes(price))
match.parentNode.click()

Within an if-statement inside of a loop, how can I get the children of an element and push them into an array?

I'm making a meal planning / grocery list application with JavaScript and jQuery. Basically, this is how it works:
The user adds recipes through a form. The user enters the name of the recipe as well as the ingredients associated with that recipe.
When submitted, each recipe is stored in a <dl id="recipeList"> element. The name of the recipe is stored as a <dt class="recipe"> and each ingredient is stored as a <dd class="ingredient">.
For each day of the week, the user may click on a "Plan a Meal" anchor. This brings up a copy of the #recipeList. When the user clicks on a <dt>, a class="meal" is applied to it and the rest of the list is removed.
The next step is for the user to click on the "Generate Grocery List" anchor. When the user does this, JavaScript should loop through each .meal and create an array, #mealsArray. JavaScript should then loop through each class="recipe" and check to see if the .innerHTML of it matches an item in the #mealsArray. It does this just fine, but the problem is after a match is found, it should get the children of the class="recipe" (i.e., the <dt class="ingredient">) and push them into #groceriesArray.
JavaScript will not find the children of the <dt class="recipe">. I have tried numerous ways of coding this, such as:
this.children
this.childNodes
this.children()
this.children("dt")
this.children(".ingredient")
this.contents()
this.find(".ingredient")
It usually finds something strange like [Object HTMLElement] or returns an error message like Type Error: this.children() is not a function.
It seems like this so be so simple, but I have no idea what to do. I will provide my code below — apologies for how sloppy it is.
Here is the HTML:
<form id="addRecipeForm">
<label>Name</label><input type="text" id="recipeName">
<label>Ingredients</label><input type="text" class="recipeIngredients">
<label>Ingredients</label><input type="text" class="recipeIngredients">
<label>Ingredients</label><input type="text" class="recipeIngredients">
<button id="recipeButton">Add Recipe</button>
</form>
<dl id="recipeList"></dl>
<div>
<h3>Sunday</h3>
Plan a Meal
</div>
<div>
<h3>Monday</h3>
Plan a Meal
</div>
<!-- And so on, until Saturday -->
Generate Grocery List
<ul id="groceryList"></ul>
Here is the JavaScript:
var recipeList = $("#recipeList");
var recipeIngredients = $(".recipeIngredients");
var planAnchor = $(".planAnchor");
var groceryListAnchor = $("#groceryListAnchor");
var groceryList = $("#groceryList");
////////// ADD A RECIPE //////////
$("#recipeButton").click(function(e) {
e.preventDefault();
var recipeName = $("#recipeName").val();
var recipeIngredients = $(".recipeIngredients");
recipeList.append("<dt class='recipe'></dt>");
recipeList.children("dt").last().text(recipeName);
for (i = 0; i < recipeIngredients.length ; i++) {
$("<dd class='ingredient'></dd>").text(recipeIngredients[i].value).appendTo(recipeList);
};
});
////////// PLAN A MEAL //////////
planAnchor.click(function(e) {
e.preventDefault();
var dayInPlanning = $(this).parent("div");
var availableRecipes = recipeList.clone();
availableRecipes.children("dd").remove();
availableRecipes.attr("id", "availableRecipes");
$(this).parent("div").append(availableRecipes);
$(this).remove();
availableRecipes.children("dt").click(function(e) {
e.preventDefault();
var selectedRecipe = $(this);
var para = $("<p class='meal'></p>");
para.appendTo(dayInPlanning);
para.text(selectedRecipe.text());
availableRecipes.remove();
});
////////// GENERATE GROCERY LIST //////////
///////// THIS IS WHERE THE PROBLEM LIES //////////
groceryListAnchor.click(function(e) {
e.preventDefault();
var mealsArray = [];
var groceriesArray = [];
// Create an array of .meal elements
$(".meal").each(function() {
mealsArray.push(this.innerHTML);
});
console.log("mealsArray is " + mealsArray);
$(".recipe").each(function() {
console.log("Checking " + this.innerHTML);
// Match the innerHTML of each .recipe to the items in the mealsArray
if ($.inArray(this.innerHTML, mealsArray) > -1) {
console.log("We found " + this.innerHTML + " in the array!");
// Get the children of that recipe, and place them in groceriesArray
// *** Not Working ***
groceriesArray.push(this.children.innerHTML)
} else {};
});
console.log("The grocery list is " + groceriesArray);
});
To explain this simply. They're two types of elements jQuery Elements and JavaScript Elements. this is a JavaScript element. jQuery functions only work with jQuery Elements. So to make it work, use:
$(this).myjQueryFunction();
so for you:
$(this).children();
In depth
When creating jQuery elements using $(), it does a few things. jQuery uses Sizzle for selecting elements. If what's passed into $() is already an element. It doesn't do anything. Of it is, it will turn it into an element. Depending on which of the two jQuery uses. It will return an element. This is a regular JavaScript element but what makes it so special? The jQuery functions can only be run after $. The reason is how you create chained-JavaScript functions using prototype:
//Kind of how it's created
$.prototype.children = function () {
//jQuery's code to get children
}
This is making it so children() can only be run off of $.
Can you try cast this Dom Element as a jQuery Element:
//so instead of this.children() use
$(this).children()
and in this case if you want HTML it will be
$(this).children().html()
but it will get you first child HTML only, you can try the followng to get for all:
html_contents = ""
$.each($(this).children(), function(){
html_contents+=$(this).html();
});

How do I dynamically add different elements for when the user clicks a button

Here is the link to the site.
The layout of the page consists of a "fixed" sidebar (left), in which buttons are created when a user clicks the "Add" button, accompanied by their chosen title and amount of points the button is worth. Then, when the button is clicked, the button disappears and the points are added on to the "Points" value, which is in the middle "div" of the page.
On the far right there is an empty div, I tried to make the same kind of thing, except I could never get it to work. What I wanted was to create another similar dynamically created button or "span" of some sort, where when the user clicks it, the points allocated to said button/span are the deducted from the total number of points. I was thinking of it as a redeeming system if that makes sense. Using coins, which I would just assign to be half the number of points.
Also, I was able to simply store the number of points and the level in localStorage, but I wasn't sure how to store the created buttons, so they disappear after every refresh, and I can't figure out how to do it, since they're not specifically coded in?
Also, if possible, how would I go about a notification div that creates an alert for each button that is clicked. The alert would say something along the lines of "You have completed task name", and it would store it in localStorage, so the user can see the buttons that were clicked in notification form.
One more thing, upon creating the button, there is a title and a number of points the user has to assign, under the second input text box, there are 5 different coloured "spans", each representing a different "field" you might say, in this case it's different subject, how would I make it so that when the user clicks one of the "Spans", the button created will be the same colour as the span they clicked?
I know I'm asking for a lot, but I have tried to do all of which I've asked for and have had massive troubles. If anyone thinks they can help me out It would be greatly appreciated. Thank you in advance.
Here is the code, html and javascript. The CSS is bootstrap.
HTML
<div >
<div id='header'>
<h2 style='font-size:71px'>Reward System</h2>
<div>
<ol class="breadcrumb" style="width:58%">
<li class="active">
<center> Home
</li>
<li>
About
</li>
<li>
Refresh </center>
</li>
</ol>
</div></div><center>
<div id='main'>
<div id='rightSide' class='well'>
</div>
<div class='well' id="addc" style='width:520px'>
<div id="addc">
<input class='form-control' maxlength="15" id="btnName" placeholder="New Task"
style='width:480px' type="text"><br>
<input maxlength="3" class='form-control' id="btnPoints" placeholder="Points"
style='width:480px' type="text"><br>
<span class="label label-danger">Mathematics EX1</span>
<span class="label label-primary">Mathematics EX2</span>
<span class="label label-success">Physics</span>
<span class="label label-info">Chemistry</span>
<span class=
"label label-warning">English Advanced</span><br>
<br>
<button id="addBtn" >Add</button>
</div>
</div>
<div class='panel panel-default' style='width:520px;height:100px'>
<h3><Strike>z</strike> Points</span></h3>
<div class='badge' id="result">
0
</div>
</div>
<hr style="width:520px;">
<div class='panel panel-default' style="width:520px;">
<h3>Level</h3>
<p class='badge' style='width:50px' id='lvl'>0</p>
<div class="progress" style='width:300px'>
<div class="progress-bar progress-bar-success" id='perce'
style="width;"></div>
</div>
</div><br>
</div>
<div id='leftSide' class='well'>
<center> <h3> Tasks </h3> </center>
<div class='well' id="container" style='width:260px;height:85%'>
</div>
<div id='reset'>
<button class='btn btn-warning' onclick='clearme()'>Reset</button>
</center>
</div>
</div>
JavaScript
var resDiv = document.getElementById('result');
resDiv.innerText = localStorage.getItem('myResult');
var levelDiv = document.getElementById('lvl');
levelDiv.textContent = localStorage.getItem('myLevel');
var btns = document.querySelectorAll('.btn');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
}
var addBtn = document.getElementById('addBtn');
addBtn.className = "btn btn-default";
addBtn.addEventListener('click', function() {
var container = document.getElementById('container');
var objDiv = document.getElementById("container");
objDiv.scrollTop = objDiv.scrollHeight;
var btnName = document.getElementById('btnName').value;
var btnPoints = parseInt(document.getElementById('btnPoints').value);
if (!btnName)
btnName = "Button ?";
if (!btnPoints)
btnPoints = 50;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
newBtn.className = 'btn btn-info';
newBtn.innerText = btnName;
newBtn.setAttribute('data-points', btnPoints);
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
newPnt.className = 'label label-default';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
function addToResult(pts) {
// NaN is falsy, so you can just use || to make a fall-back to 0
var result = parseInt(resDiv.innerText, 10) || 0,
lvl = 0,
a = 100;
result = result + parseInt(pts, 10) || 0;
var pen = (result/500)*100;
while (result > (5 * a)) {
lvl += 1;
a += 100;
pen -= 100;
}
document.getElementById('perce').style.width = pen +"%";
resDiv.innerText = result;
levelDiv.innerText = lvl;
localStorage.setItem("myResult", result);
localStorage.setItem("myLevel", levelDiv.textContent);
}
function clearme() {
localStorage.clear();
}
To keep your buttons in localStorage you will need to create your own object that holds the button's name and points, then use JSON.stringify to turn an array of these objects into a string. That string can then be used with localStorage.setItem
function MyButtonObject(name,points){
this.name=name;
this.points=points;
}
var list=[new MyButtonObject('example',100)];
localStorage.setItem( 'btnList' , JSON.stringify(list) );
Next I would procede by seperating the code that makes a new buttons into its own function so it can be called when the page loads and you want to rebuild your button elements.
var listJSON=localStorage.setItem( 'btnList' );
var list= listJSON?JSON.parse(listJSON ):[];
list.forEach(function(btn){
makeButtonElements(btn);
});
function makeButtonElements(btn){
var btnName=btn.name, btnPoints=btn.points;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
....etc....
Your existing function that creates buttons would call this one as well as creating a new MyButtonObject adding it to the array of said objects and storing that array with localStorage.setItem. The function that removes buttons will need updating to remove the correct object from the array and calling localStorage.setItem as well as adding your planned notification messages (and storing them).
You should probably take some time to plan what other features you might want (such as deleting buttons without scoring their points, displaying notifications etc) and think about how you can break those processes down into functions that can be reused at different points in your program (eg new button/notification created, existing button/notification loaded from storage)
Here is a handy function that copies a style property from one element to another that should help you set the buttons colours the way you want.
function copyStyle(prop,fromEl,toEl){
toEl.style[prop]=window.getComputedStyle(fromEl)[prop];
}
Note: I haven't check or tested any of this code so make sure you read through it and understand what it is meant to do before you start copying and pasting into your own program.

Categories

Resources