change a inner html id with js - javascript

how do you change a inner id with js and keep it the same id num (e.g hey1, bob2)
my js code
var obj = document.getElementById("chat").cloneNode(true);
var obj1 = document.getElementById("ch");
var obj2 = document.getElementById("chatbox");
var p = $(".chat");
var offset = p.offset();
num = num + 1;
if (num <=15) {
obj.id = obj.id + num; <--- **changing the id (this one works fine but the other two dont**
obj1.id = obj1.id + num; <--- changing the id
obj2.id = obj2.id + num; <--- changing the id
document.body.appendChild(obj);
document.body.appendChild(obj1);
document.body.appendChild(obj2);
var left = offset.left + 275;
document.getElementById("chat").style.left = left + "px";
tell me if i am doing it wrong but this was the easiest way i thought off
(ps i am a beginner at javascript)
thanks to all that try to help...
Edit
ok i clone this
<div class="chat" id="chat">
<div id="ch" class="ch">
<h2>Chat</h2></div>
<div class="chatbox" id="chatbox">
<div class="messages"></div>
<textarea id="message" class="chatinp"
rows="3" cols="27"></textarea>
<button class="send">Send</button></div>
</div>
and everytime it clones it changes the id of chat,ch and chatbox but keeping the original the same
like so...
clone1
<div class="chat" id="chat1">
<div id="ch1" class="ch">
<h2>Chat</h2></div>
<div class="chatbox" id="chatbox1">
<div class="messages"></div>
<textarea id="message" class="chatinp"
rows="3" cols="27"></textarea>
<button class="send">Send</button></div>
</div>
Clone2
<div class="chat" id="chat2">
<div id="ch2" class="ch">
<h2>Chat</h2></div>
<div class="chatbox" id="chatbox2">
<div class="messages"></div>
<textarea id="message" class="chatinp"
rows="3" cols="27"></textarea>
<button class="send">Send</button></div>
</div>

Not sure, but if I'm right, you're trying to create a new 'chatnode'. You'll have to traverse the childNodes array of the node you cloned to change id's. Try something like:
function cloneChat(){
var obj = document.getElementById("chat").cloneNode(true),
children = obj.childNodes
;
num += 1;
obj.id = obj.id+num;
if (num<16){
changeId(children,num);
}
//now appending obj to the document.body should be sufficient
document.body.appendChild(obj);
//change id recursively
function changeId(nodes, n){
for (var i=0;i<nodes.length;i=i+1){
if (nodes[i].childNodes){
changeId(nodes[i].childNodes,n);
}
if(nodes[i].id && /^ch$|^chatbox$/i.test(nodes[i].id)) {
nodes[i].id += String(n);
}
}
}
}
See this jsfiddle for a working example
Furthermore, this code won't work:
var p = $(".chat");
var offset = p.offset();
Because $(".chat") returns a list of nodes, where every node has it's own offset.
You seem to be using jQuery, so I suggest adding a 'jQuery' tag to your question. Maybe some jQuery whizzkid has a solution to offer.

In jQuery try to use
element.attr("id","newId");
See: http://api.jquery.com/attr/

How about this function?
function appendMe() {
var elementsToClone = ["chat"]; //Parent Elements to clone. This is the class name as well as the id
var childrenToHandle = new Array();
childrenToHandle["chat"] = ["ch"]; //Child elements mapping to keep sync. This is the class name as well as the id. Here we say that for the parent element chat, the inner elements to keep in sync is ch
var itemCount = 0;
for(i = 0; i < elementsToClone.length; i++) {
var refObj = document.getElementById(elementsToClone[i]);
if(refObj) {
$("." + elementsToClone[i]).each(
function() {
if(this.id.match(/\d+$/g)) {
itemCount = this.id.match(/\d+$/g);
}
}
);
var newObj = refObj.cloneNode(true);
newObj.id = elementsToClone[i] + ++itemCount;
var childrenArray = childrenToHandle[elementsToClone[i]];
if(childrenArray) {
$(childrenArray).each(
function() {
$(newObj).find("." + this).attr("id", this + itemCount);
}
);
}
document.body.appendChild(newObj);
}
}
}

Since you're already using jQuery in your code, how about:
var $obj = $("#chat").clone(),
$obj1 = obj.find("#ch"),
$obj2 = obj.find("#chatbox");
var p = $(".chat"),
offset = p.offset();
num = num + 1;
if (num <= 15) {
$obj.attr('id', $obj.attr('id') + num);
$obj1.attr('id', $obj1.attr('id') + num);
$obj2.attr('id', $obj2.attr('id') + num);
$('body').append(obj);
var newLeft = offset.left + 275;
$('#chat').css({
left: newLeft
});
}

Related

How can I execute a function without an event?

Solved by # epascarello
Have to execute function without event so that discount can be displayed along with prices at the start without clicking or any other event
You can see in below snippet that 1st one is running automatic while 2nd one is running on click . Can it possible to run 2nd one as automatic because it solves my most of issues using this keyword
Let me know if you need clarification . Any suggestion or comments will be helpful.
function discount1() {
var sendTotal = document.getElementsByClassName("TotalPrice1")[0].innerHTML;
var send1 = sendTotal.replace(/₹/gi, "");
var send2 = send1.replace(/,/gi, "");
var send3 = Number(send2)
var send = document.getElementsByClassName("DiscPrice1")[0].innerHTML;
var send4 = send.replace(/₹/gi, "");
var send5 = send4.replace(/,/gi, "");
var send6 = Number(send5)
var rest = ((send3 - send6) / send3) * 100
document.getElementsByClassName("demo1")[0].innerHTML = rest.toFixed(0) + "% off";
}
discount1();
function discount(rest) {
var sendTotal = rest.parentElement.getElementsByClassName("TotalPrice")[0].innerHTML;
var send1 = sendTotal.replace(/₹/gi, "");
var send2 = send1.replace(/,/gi, "");
var send3 = Number(send2)
var send = rest.parentElement.getElementsByClassName("DiscPrice")[0].innerHTML;
var send4 = send.replace(/₹/gi, "");
var send5 = send4.replace(/,/gi, "");
var send6 = Number(send5)
var rent = ((send3 - send6) / send3) * 100
rest.getElementsByClassName("demo")[0].innerHTML = rent.toFixed(0) + "% off";
}
<div>
<div class="seen" onclick="discount1()">
<div class="TotalPrice1">₹9,728</div>
<div class="DiscPrice1">₹5,435</div>
<div class="demo1"></div>
</div>
</div>
<br>
<div>
<div class="seen" onclick="discount(this)">
<div class="TotalPrice">₹15,670</div>
<div class="DiscPrice">₹13,785</div>
<div class="demo"></div>
</div>
</div>
So you need to call your function with the element.
How you get the elements is up to you. querySelectorAll, getElementsByClassName, ids, etc.
function discount () { /*...*/ }
document.querySelectorAll(".daad").forEach(discount);
you can do it inside of the function
function discount () {
document.querySelectorAll(".daad").forEach(function (reed) {
var saadTotal = reed.parentElement.getElementsByClassName("Total")[0].innerHTML;
console.log('saadTotal', saadTotal);
var saadTotal2 = reed.querySelector(".Total").textContent;
console.log('saadTotal2', saadTotal2);
}
}
discount();
This is answer for previous question you can see in question edits
This is what I needed to do show discount percentage without any event (like onclick or onload) . You can see in below snippet .
function discount(rest) {
var sendTotal = rest.parentElement.getElementsByClassName("TotalPrice")[0].innerHTML;
var send1 = sendTotal.replace(/₹/gi, "");
var send2 = send1.replace(/,/gi, "");
var send3 = Number(send2)
var send = rest.parentElement.getElementsByClassName("DiscPrice")[0].innerHTML;
var send4 = send.replace(/₹/gi, "");
var send5 = send4.replace(/,/gi, "");
var send6 = Number(send5)
var rent = ((send3 - send6) / send3) * 100
rest.getElementsByClassName("demo")[0].innerHTML = rent.toFixed(0) + "% off";
}
document.querySelectorAll(".seen").forEach(discount);;
<div>
<div class="seen" onclick="discount(this)">
<div class="TotalPrice">₹9,728</div>
<div class="DiscPrice">₹5,435</div>
<div class="demo"></div>
</div>
</div>
<br>
<div>
<div class="seen" onclick="discount(this)">
<div class="TotalPrice">₹15,670</div>
<div class="DiscPrice">₹13,785</div>
<div class="demo"></div>
</div>
</div>

All buttons only affect one input instead of respective input

I am making a little project for my self. So basically its main function is to create a base counter for each game.
For example: If there are two players it should create three bases. (This is for the card game "smash up" if that helps you understand better.) But when the Buttons populate they all only effect the last input. I can not figure out how to make them effect their respective inputs.
The problem I am having is that every button I click only effects the last input.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type = "text" placeholder = "How many players?">
<button id = "enter" onclick = "baseMaker()">
Enter
</button>
</div>
<p></p>
</body>
</html>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function baseMaker()
{
for(var i = 0; i <= input.value; i++)
{
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement( "input");
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
This is a common thing to run into especially when not using a framework in javascript.
I am not sure why this happens but when a function is defined directly in a loop, the closure for these created functions becomes whatever it is after the last iteration. I believe it is because the closure for each callback function is only "sealed up" (for lack of a better word) at the end of the loop-containing-function's execution which is after the last iteration. It's really beyond me, though.
There are some easy ways to avoid this behavior:
use bind to ensure a callback gets called with the correct input (used in solution at bottom)
create a function which creates a handler function for you and use that in the loop body
function createIncrementHandler(input, howMuch){
return () => input.valueAsNumber += howMuch;
}
/// then in your loop body:
downButton.addEventListener('click', createIncrementHandler(score, 1));
get the correct input by using the event parameter in the handler
downButton.addEventListener('click', (event) => event.target.valueAsNumber += 1);
make the entire body of the loop into a function, for example:
function createInputs(i) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement( "button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', function() {
score.value++; });
//downbutton
var downButton = document.createElement( "button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', function() {
score.value--; });
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
Here is a full example of one of the possible fixes.
<html>
<title> Base Maker </title>
<body>
<div>
<hl> Score Keeper </h1>
<hr>
<input type="text" placeholder="How many players?">
<button id="enter" onclick="baseMaker()">
Enter
</button>
</div>
<p></p>
<script>
var parent = document.querySelector("p");
var input = document.querySelector("input");
var enter = document.getElementById("enter");
function incrementInput(input, byHowMuch) {
input.valueAsNumber = input.valueAsNumber + byHowMuch;
}
function baseMaker() {
for (var i = 0; i <= input.value; i++) {
//base
var base = document.createElement("p");
base.textContent = "Base " + (i + 1) + ":";
//score
var score = document.createElement("input");
score.type = "number";
score.setAttribute("id", "score" + i);
score.value = 20;
//upbutton
var upButton = document.createElement("button");
upButton.textContent = "+";
upButton.setAttribute("id", "upButton" + i)
upButton.addEventListener('click', incrementInput.bind(null, score, 1));
//downbutton
var downButton = document.createElement("button");
downButton.textContent = "-";
downButton.setAttribute("id", "downButton" + i)
downButton.addEventListener('click', incrementInput.bind(null, score, -1));
//populate data
parent.appendChild(base);
parent.appendChild(score);
parent.appendChild(upButton);
parent.appendChild(downButton);
}
input.value = "";
}
</script>
</body>
</html>
I will do that this way :
const
AllBases = document.querySelector('#bases')
, bt_Start = document.querySelector('#game-go')
, bt_newGame = document.querySelector('#new-game')
, playerCount = document.querySelector("#play-start > input")
;
playerCount.value = ''
playerCount.focus()
playerCount.oninput = () =>
{
playerCount.value.trim()
bt_Start.disabled = (playerCount.value === '' || isNaN(playerCount.value))
playerCount.value = (bt_Start.disabled) ? ''
: (playerCount.valueAsNumber > playerCount.max) ? playerCount.max
: (playerCount.valueAsNumber < playerCount.min) ? playerCount.min
: playerCount.value
}
bt_newGame.onclick = () =>
{
playerCount.value = ''
playerCount.disabled = false
bt_Start.disabled = true
bt_newGame.disabled = true
AllBases.innerHTML = ''
playerCount.focus()
}
bt_Start.onclick = () =>
{
playerCount.disabled = true
bt_Start.disabled = true
bt_newGame.disabled = false
for(let i = 0; i <= playerCount.valueAsNumber; i++)
{
let base = document.createElement('p')
base.countValue = 20 // create a counter property on <p>
base.innerHTML = `Base ${i+1} : <span>${base.countValue}</span> <button>+</button> <button>−</button>\n`
AllBases.appendChild(base)
}
}
AllBases.onclick = ({target}) =>
{
if (!target.matches('button')) return // verify clicked element
let countElm = target.closest('p')
if (target.textContent==='+') countElm.countValue++
else countElm.countValue--
countElm.querySelector('span').textContent = countElm.countValue
}
#bases p span {
display : inline-block;
width : 6em;
border-bottom : 2px solid aqua;
padding-right : .2em;
text-align : right;
margin : 0 .3em;
}
#bases p button {
width : 2em;
margin : 0 .1em;
cursor : pointer;
}
<hr>
<hl> Score Keeper </h1>
<hr>
<div id="play-start" >
<input type="number" placeholder="How many players?" min="2" max="4">
<button id="game-go" disabled> Enter </button>
<button id="new-game" disabled> new </button>
</div>
<hr>
<div id="bases"></div>
If it helps, I can add more explanations

How can I write an array values to different paragraphs in a html document using javascript/jquery?

Please, I want to print out the contents of an array to different blocks of paragraphs in HTML using javascript or jquery. I can console.log the problem but can write all individually to different paragraphs of the HTML document I need that to appear at.my source code screenshot in js
// Latest
$(document).each(function() {
var price = [];
var oldprice = [];
var discount;
var i;
$('.price').children('p').each(function() {
price.push(this.innerHTML);
});
$('.old-price').children('p').each(function() {
oldprice.push(this.innerHTML);
});
$(function(){
for(i=0;i <= ((oldprice.length)&&(price.length));i++) {
var mainprice = price[i].replace("₦",""); //new price
mainprice = parseFloat(mainprice.replace(",",""));
var oldmainprice = oldprice[i].replace("₦",""); //oldprice
oldmainprice = parseFloat(oldmainprice.replace(",",""));
var disc = oldmainprice - mainprice;
var pectDisc = (disc / oldmainprice) * 100;
pectDisc = parseInt(pectDisc);
// console.log("-" + pectDisc + "%");
var prices = [];
var offs = [];
prices.push(pectDisc);
for(var x in prices) {
if($(".off")) {
$(".off").text("-" + prices[x] + "%");
// console.log(prices[x]);
}
}
};//end of for loop
});
});
<div class="asses-product">
<div class="pd">
<div class="img"><img src="img/Products/laptop.png" alt="product-image"></div>
<div class="product-description">
<div class="product-name"><h4>Hp Laptop Envy 14</h4></div>
<div class="price"><p>₦ 256,000</p></div>
<div class="old-price"><p>₦ 300,000</p></div>
<div class="off"></div>
</div>
</div>
<div class="pd">
<div class="img"><img src="img/Products/printer.png" alt="product-image"></div>
<div class="product-description">
<div class="product-name"><h4>Hp printer series 10</h4></div>
<div class="price"><p>₦ 12,500</p></div>
<div class="old-price"><p>₦ 18,000</p></div>
<div class="off"></div>
</div>
</div>
</div>
You can do all that with this code:
$(".product-description").each(function () {
// Get price within this container, and remove all non-digits
let price = $(".price", this).text().replace(/\D/g, "");
let oldprice = $(".old-price", this).text().replace(/\D/g, "");
let disc = oldprice - price;
let pectDisc = Math.floor((disc / oldprice) * 100);
$(".off", this).text("-" + pectDisc + "%");
});
This will treat each block with class "product-description" one by one (since they don't effect each other's result). Within those blocks you can retrieve the elements you need by limiting the scope to this.
Digits can be extracted easily by removing anything that is not a digit. The regular expression \D matches any non-digit.
Don't use parseInt to remove decimals from a number. Use Math.floor instead, which avoids the unnecessary string-conversion that parseInt applies.
Some of the errors in your code:
The end-condition of the outer for loop is wrong:
i < ((oldprice.length)&&(price.length))
This should be:
i < oldprice.length && i < price.length
... and really, both lengths should be the same, so you could have simplified to:
i < oldprice.length
Another error is the inner for loop. It does not get to the right .off element. It always selects them all, and sets them all to the same text. Instead, your code should have retrieved the right instance among the many .off elements, and only set the text of that one.
You could have fixed that by replacing that inner loop with this code:
$(".off").eq(i).text("-" + prices[x] + "%");
But all in all, I think the approach I have taken at the start of my answer is better: instead of collecting the prices in an array, just deal with each section one by one.
The error is on your for loop condition.
Your array has 2 element but your condition has 3 loop. so change <= condition to <.
for(i=0;i < ((oldprice.length)&&(price.length));i++) {
see snippet:
// Latest
$(document).each(function() {
var price = [];
var oldprice = [];
var discount;
var i;
$('.price').children('p').each(function() {
price.push(this.innerHTML);
});
$('.old-price').children('p').each(function() {
oldprice.push(this.innerHTML);
});
$(function(){
for(i=0;i < ((oldprice.length)&&(price.length));i++) {
var mainprice = price[i].replace("₦",""); //new price
mainprice = parseFloat(mainprice.replace(",",""));
var oldmainprice = oldprice[i].replace("₦",""); //oldprice
oldmainprice = parseFloat(oldmainprice.replace(",",""));
var disc = oldmainprice - mainprice;
var pectDisc = (disc / oldmainprice) * 100;
pectDisc = parseInt(pectDisc);
// console.log("-" + pectDisc + "%");
var prices = [];
var offs = [];
prices.push(pectDisc);
for(var x in prices) {
if($(".off")) {
$(".off").text("-" + prices[x] + "%");
// console.log(prices[x]);
}
}
};//end of for loop
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="asses-product">
<div class="pd">
<div class="img"><img src="img/Products/laptop.png" alt="product-image"></div>
<div class="product-description">
<div class="product-name"><h4>Hp Laptop Envy 14</h4></div>
<div class="price"><p>₦ 256,000</p></div>
<div class="old-price"><p>₦ 300,000</p></div>
<div class="off"></div>
</div>
</div>
<div class="pd">
<div class="img"><img src="img/Products/printer.png" alt="product-image"></div>
<div class="product-description">
<div class="product-name"><h4>Hp printer series 10</h4></div>
<div class="price"><p>₦ 12,500</p></div>
<div class="old-price"><p>₦ 18,000</p></div>
<div class="off"></div>
</div>
</div>
</div>

how to make output text inside nested div with jquery

I have div inside div (nested div) and one button click and one textarea, when i click this button i want output that div in text,and add the text to Textarea
example
<div id="container">
<div class="nested">
<div id="1">
<div class="nested">
<div id="3">helpX</div>
<div id="4">helpY</div>
</div>
</div>
<div id="2">helpZ</div>
</div>
</div>
when i click my button i need the output like this =nested(=nested(helpX)(helpY))(helpZ)
my code is :
$('#BUTTONCLICK').click(function(){
$('#container').find("div").each( function(index) {
....
});
});
I hope you can help me. Thanks .
You have to set up some condition to check whether the child is a nested or child has nested children, or a simple div. So I use a recursive function to handle it:
$('#BUTTONCLICK').click(function(){
var findNest = function(ele) {
// To see if current item needs a nested prefix
var result = $(ele).hasClass("nested") ? '=nested(' : '';
$(ele).find(' > div').each(function(idx, item) {
var $item = $(item);
if ($item.hasClass("nested")) {
// If current cheked item is a nested item, nested it.
result += findNest($item);
} else if ($(item).find(".nested").length > 0) {
result += findNest(item);
} else {
// Current check item is a simple div, add it
result += '(' + $(item).text() + ')';
}
});
// Decide tail
var tail = $(ele).hasClass("nested") ? ')' : '';
return result + tail;
};
var $container = $('#container');
var result = findNest($container);
console.log(result);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="container">
<div class="nested">
<div id="1">
<div class="nested">
<div id="3">helpX</div>
<div id="4">helpY</div>
</div>
</div>
<div id="2">helpZ</div>
</div>
</div>
<div id="BUTTONCLICK">click</div>
If you want to give a level limit, the code can be changed to:
$('#BUTTONCLICK').click(function(){
// Inits
var LEVEL_LIMIT = 2;
var currentLevel = 0;
var findNest = function(ele) {
// Add one level at start.
++currentLevel;
// To see if current item needs a nested prefix
var result = $(ele).hasClass("nested") ? '=nested(' : '';
$(ele).find(' > div').each(function(idx, item) {
var $item = $(item);
var $nestChilds = $(item).find(".nested");
if (currentLevel <= LEVEL_LIMIT &&
($item.hasClass("nested") || $nestChilds.length > 0)) {
// If current cheked item is a nested item, or it has child that is nest, go into it.
result += findNest($item);
} else {
// Current check item is a simple div or level limit reached,
// simply add div texts...(May need other process of text now.)
result += '(' + $(item).text() + ')';
}
});
// Decrease Level by one before return.
--currentLevel;
// Decide tail
var tail = $(ele).hasClass("nested") ? ')' : '';
return result + tail;
};
var $container = $('#container');
var result = findNest($container);
console.log(result);
});
Try
$('#BUTTONCLICK').click(function(){
var text = '';
$('#container').find("div").each( function(index) {
text += $(this).text();
});
$("textarea").val(text);
});
$('#BUTTONCLICK').click(function(){
var findNest = function(ele) {
// To see if current item needs a nested prefix
var result = $(ele).hasClass("nested") ? '=nested(' : '';
$(ele).find(' > div').each(function(idx, item) {
var $item = $(item);
if ($item.hasClass("nested")) {
// If current cheked item is a nested item, nested it.
result += findNest($item);
} else if ($(item).find(".nested").length > 0) {
// For all .nested child from the item, do the findNest action
$(item).find(".nested").each(function(idx, item) {
result += findNest(item);
});
} else {
// Current check item is a simple div, add it
result += '(' + $(item).text() + ')';
}
});
// Decide tail
var tail = $(ele).hasClass("nested") ? ')' : '';
return result + tail;
};
var $container = $('#container');
var result = findNest($container);
console.log(result);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="container">
<div class="nested">
<div id="1">
<div class="nested">
<div id="3">helpX</div>
<div id="4">helpY</div>
</div>
</div>
<div id="2">helpZ</div>
</div>
</div>
<div id="BUTTONCLICK">click</div>

Why does my value keep returning as "NaN"?

Here is the link to the jsbin.
I was almost finished with my project (I thought I was) and then I tested it out. It is supposed to add buttons with the chosen title of the task and the number of points it awards. Every time the button is clicked the points would be added on to the "Points" section and every 500 points my "Level" would increase.
Upon finishing it, it worked. Then I went to clear the localStorage since that's what I used to save the information, but I wanted to start over. When I did that, the 'Points' section, or 'results' value, keeps returning as "NaN". The code is exactly the same as it was when it worked. Can someone please tell me how to fix this problem, thank you in advance.
Here is the code. (Used bootstrap for CSS)
HTML
<center>
<br>
<h2> Add task </h2>
<div class='well' style='width:500px' id="addc">
<div id="addc">
<input class='form-control' style='width:450px' id="btnName" type="text" placeholder="New Task" /><br>
<input class='form-control' style='width:450px' id="btnPoints" type="text" placeholder="Points" /><br>
<button id="addBtn">Add</button>
</div> </div>
<div class='well' style='width:230px' id="container">
</div>
<hr style="width:400px;">
<h3>Points </h3>
<div id="result">0</div>
</div>
<hr style="width:400px;">
<div style="width:400px;">
<h3>Level
<p id='lvl'>0</p>
</div>
<hr style="width:400px;">
</center>
JavaScript
var res = document.getElementById('result');
res.innerText = localStorage.getItem('myResult');
var level = document.getElementById('lvl');
level.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 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-danger';
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';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
function addToResult(pts) {
var result = document.getElementById('result');
result.innerText = parseInt(result.innerText) + parseInt(pts);
var lvl = 0;
var a = 100;
while (result.innerText > 5*a) {
lvl+=1;
a+=100;
}
document.getElementById('lvl').innerText = lvl;
var res = document.getElementById('result');
localStorage.setItem("myResult", res.innerText);
var level = document.getElementById('lvl');
localStorage.setItem("myLevel", level.textContent);
}
You were parsing result.innerText as a number, but its value, initially, was actually either NaN or nothing, both which end up being NaN. One fix is to just check if it parsed to a number, and if it didn't, fall back to 0.
I just basically changed that and removed some getElementByIds that, in my opinion, were redundant, check the addToResult function:
http://jsfiddle.net/owc26a0p/1/
function addToResult(pts) {
// NaN is falsy, so you can just use || to make a fallback to 0
var result = parseInt(resDiv.innerText, 10) || 0,
lvl = 0,
a = 100;
result = result + parseInt(pts, 10) || 0;
while (result > 5 * a) {
lvl += 1;
a += 100;
}
resDiv.innerText = result;
levelDiv.innerText = lvl;
localStorage.setItem("myResult", result);
localStorage.setItem("myLevel", levelDiv.textContent);
}
I ended up using jsFiddle since I couldn't always get jsBin to save my changes. Good luck.

Categories