Move Array value to another specific array - javascript

Hi i have this code below that consists of 2 list Total fruits and random fruits for my current codes i'm able to click on the values of Random fruits and send that array value to the green fruits array and vice versa. What im trying to accomplish is to use my fruits array key value [type] to map where the value in random fruit array should go. is there any easy way to accomplish this? Any help would be greatly appreciated!
var red = {};
var green = {};
var random = {};
var fruits = [];
var fruits1 = {["fruit"]:"Apple", ["type"]:"1"}
var fruits2 = {["fruit"]:"Tomato", ["type"]:"1"}
var fruits3 = {["fruit"]:"Lime", ["type"]:"2"}
var fruits4 = {["fruit"]:"Guava", ["type"]:"2"}
fruits.push(fruits1,fruits2,fruits3,fruits4);
var randomFruits = fruits.filter(x => x.fruit).map(x => x.fruit);
var key = "Red Fruits";
red[key] = ['Apple', 'Cherry', 'Strawberry','Pomegranate','Rassberry'];
var key2 = "Green Fruits";
green[key2] = ['Watermelon', 'Durian', 'Avacado','Lime','Honeydew'];
var key3 = "Random Fruits";
random[key3] = randomFruits;
function redraw() {
var combineString = '';
$.each(red[key], function(index) {
combineString += ('<div class="pilldiv redpill class">' + red[key][index] + '</div>');
});
$('.combineclass').html(combineString);
$.each(green[key2], function(index) {
combineString += ('<div class="pilldiv greenpill class">' + green[key2][index] + '</div>');
});
$('.combineclass').html(combineString);
var randomString = '';
$.each(random[key3], function(index) {
randomString += ('<div class="pilldiv randompill class">' + random[key3][index] + '</div>');
});
$('.randomclass').html(randomString);
}
function listener() {
$(document).ready(function() {
$(document).on("click", "#randomid div", function() {
data = this.innerHTML;
k1 = Object.keys(random).find(k => random[k].indexOf(data) >= 0)
index = random[k1].indexOf(data);
random[k1].splice(index, 1);
green[key2].push(data);
$(".total_count_Green_Fruits").html(key2 + ': ' + green[key2].length);
var element = $(this).detach();
$('#combineid').prepend('<div class="new-green-fruit pilldiv class ">' + element.html() + '</div>');
});
});
$('body').on('click', 'div.new-green-fruit', function() {
data2 = this.innerHTML;
k2 = Object.keys(green).find(k => green[k].indexOf(data2) >= 0)
index2 = green[k2].indexOf(data2);
green[k2].splice(index2, 1);
random[key3].push(data2);
$(this).detach();
var element2 = $(this).detach();
$('#randomid').prepend('<div class="pilldiv randompill class" >' + element2.html() + '</div>');
});
}
redraw();
listener();
.pilldiv {
padding: 8px 15px;
text-align: center;
font-size: 15px;
border-radius: 25px;
color: Black;
margin: 2px;
}
.randompill:after{
content: "\002B";
float: left;
width:16px;
}
.new-green-fruit:after{
content: "\292B";
float: left;
width:16px;
}
.redpill {
background-color: Pink;
cursor:default;
}
.greenpill {
background-color: SpringGreen;
cursor:default;
}
.randompill {
background-color: LightBlue;
cursor:pointer;
}
.class {
font-family: Open Sans;
}
.center {
display: flex;
justify-content: center;
}
.wrappingflexbox {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.top {
margin-bottom: 20px
}
h3{
font-weight: normal;
}
.panel {
display: table;
height: 100%;
width: 60%;
background-color:white;
border: 1px solid black;
margin-left: auto;
margin-right: auto;
}
.new-green-fruit{
background-color: LightBlue;
cursor:pointer;
}
.top{
margin-bottom:30px;
}
<!DOCTYPE html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="//#" />
</head>
<body>
<div class="panel">
<div style="float:left;width:calc(50% - 5px);">
<h3 class="class center">Total Fruits</h3>
<div id="combineid" class="combineclass wrappingflexbox top"></div>
</div>
<div style="float:right;width:calc(50% - 5px)">
<h3 class="class center">Random Fruits</h3>
<div id="randomid" class="randomclass wrappingflexbox top"></div>
</div>
</div>
</body>
</html>

You should apply some check like
if type == 1
prepend
else if type == 2
append
Just update your function as below
$(document).ready(function() {
$(document).on("click", "#randomid div", function() {
data = this.innerHTML;
k1 = Object.keys(random).find(k => random[k].indexOf(data) >= 0)
index = random[k1].indexOf(data);
random[k1].splice(index, 1);
let fromrandom = fruits.find(k => k.fruit == data);
if(fromrandom.type == 1) {
green[key2].push(data);
$(".total_count_Green_Fruits").html(key2 + ': ' + green[key2].length);
var element = $(this).detach();
$('#combineid').prepend('<div class="new-green-fruit pilldiv class ">' + element.html() + '</div>');
}
else if(fromrandom.type == 2) {
red[key].push(data);
$(".total_count_Red_Fruits").html(key + ': ' + red[key].length);
var element = $(this).detach();
$('#combineid').append('<div class="new-green-fruit pilldiv class ">' + element.html() + '</div>');
}
console.log(JSON.stringify(red)+" "+ JSON.stringify(green)+" "+JSON.stringify(fromrandom));
});
});

Related

how do I add the image to my cart using javascript (Front-End Only)?

I have a working cart but would like to add the image of my product as well as the title and price but not really sure how to do it. Everything I tried so far has just broken the code. Any help would be much appreciated. Below is my single product page with my cart and my javascript file. Im only looking for front-end help here as I havent gotten round to the back end yet
var shoppingCart = (function() {
cart = [];
function Item(name, image, price, count) {
this.name = name;
this.image = image;
this.price = price;
this.count = count;
}
function saveCart() {
sessionStorage.setItem('shoppingCart', JSON.stringify(cart));
}
function loadCart() {
cart = JSON.parse(sessionStorage.getItem('shoppingCart'));
}
if (sessionStorage.getItem("shoppingCart") != null) {
loadCart();
}
var obj = {};
obj.addItemToCart = function(name, image, price, count) {
for (var item in cart) {
if (cart[item].name === name) {
cart[item].count++;
saveCart();
return;
}
}
var item = new Item(name, price, count);
cart.push(item);
saveCart();
}
obj.setCountForItem = function(name, count) {
for (var i in cart) {
if (cart[i].name === name) {
cart[i].count = count;
break;
}
}
};
obj.removeItemFromCart = function(name) {
for (var item in cart) {
if (cart[item].name === name) {
cart[item].count--;
if (cart[item].count === 0) {
cart.splice(item, 1);
}
break;
}
}
saveCart();
}
obj.removeItemFromCartAll = function(name) {
for (var item in cart) {
if (cart[item].name === name) {
cart.splice(item, 1);
break;
}
}
saveCart();
}
obj.clearCart = function() {
cart = [];
saveCart();
}
obj.totalCount = function() {
var totalCount = 0;
for (var item in cart) {
totalCount += cart[item].count;
}
return totalCount;
}
obj.totalCart = function() {
var totalCart = 0;
for (var item in cart) {
totalCart += cart[item].price * cart[item].count;
}
return Number(totalCart.toFixed(2));
}
obj.listCart = function() {
var cartCopy = [];
for (i in cart) {
item = cart[i];
itemCopy = {};
for (p in item) {
itemCopy[p] = item[p];
}
itemCopy.total = Number(item.price * item.count).toFixed(2);
cartCopy.push(itemCopy)
}
return cartCopy;
}
return obj;
})();
$('.add-to-cart').click(function(event) {
event.preventDefault();
var name = $(this).data('name');
var price = Number($(this).data('price'));
shoppingCart.addItemToCart(name, price, 1);
displayCart();
});
$('.clear-cart').click(function() {
shoppingCart.clearCart();
displayCart();
});
function displayCart() {
var cartArray = shoppingCart.listCart();
var output = "";
for (var i in cartArray) {
output += "<tr>" +
"<td>" + cartArray[i].name + "</td>" +
"<td>(" + cartArray[i].price + ")</td>" +
"<td><div class='input-group'><button class='minus-item input-group-addon btn
btn - primary ' data-name=" + cartArray[i].name + ">-</button>" +
"<input type='number' class='item-count form-control' data-name='" +
cartArray[i].name + "' value='" + cartArray[i].count + "'>" +
"<button class='plus-item btn btn-primary input-group-addon' data-name=" +
cartArray[i].name + ">+</button></div></td>" +
"<td><button class='delete-item btn btn-danger' data-name=" + cartArray[i].name +
">X</button></td>" +
" = " +
"<td>" + cartArray[i].total + "</td>" +
"</tr>";
}
$('.show-cart').html(output);
$('.total-cart').html(shoppingCart.totalCart());
$('.total-count').html(shoppingCart.totalCount());
}
$('.show-cart').on("click", ".delete-item", function(event) {
var name = $(this).data('name')
shoppingCart.removeItemFromCartAll(name);
displayCart();
})
$('.show-cart').on("click", ".minus-item", function(event) {
var name = $(this).data('name')
shoppingCart.removeItemFromCart(name);
displayCart();
})
$('.show-cart').on("click", ".plus-item", function(event) {
var name = $(this).data('name')
shoppingCart.addItemToCart(name);
displayCart();
})
$('.show-cart').on("change", ".item-count", function(event) {
var name = $(this).data('name');
var count = Number($(this).val());
shoppingCart.setCountForItem(name, count);
displayCart();
});
displayCart();
and my single product page
<!DOCTYPE html>
<html>
<body>
<head>
<script src="https://code.jquery.com/
jquery-3.1.1.slim.min.js" i.ntegrity="sha384A7FZj7v+d/sdmMqp/
nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n"
crossorigin="anonymous"></script>
<script>
function openNav() {
document.getElementById("mySidepanel").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidepanel").style.width = "0";
}
</script>
<style>
body {
padding-top: 80px;
}
img {
border-radius: 20%;
}
.sidepanel {
width: 350px;
position: fixed;
z-index: 1;
top: 0;
right: 0;
background-color: white;
overflow-x: hidden;
transition: 0.5s;
padding-top: 100px;
}
.sidepanel a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidepanel a:hover {
color: #f1f1f1;
}
.sidepanel .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
}
.openbtn {
font-size: 20px;
cursor: pointer;
background-color: #111;
color: white;
padding: 10px 15px;
border: none;
}
.openbtn:hover {
background-color: #444;
}
.show-cart li {
display: flex;
}
.card {
margin-bottom: 20px;
}
.card-price {
font-weight: bold;
text-align: center;
}
.gallery-hightlight {
width: 80%;
height: 50%;
}
.image-preview {
display: flex;
display: width:: 100%;
}
.image-preview img {
flex-grow: 1;
height: 200px;
opacity: 0.5;
transition: opacity 0.4s ease;
cursor: pointer;
}
img.image-active {
opacity: 1;
}
<body>
<head>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-
A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script>
function openNav() {
document.getElementById("mySidepanel").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidepanel").style.width = "0";
}
</script>
<nav class="navbar-buttons">
<div class="row">
<div class="col">
<button class="openbtn" onclick="openNav()" data-toggle="modal" data- target="#cart">Cart (<span class="total-count"></span>)</button><button class="clear-cart btn btn-danger">Clear Cart</button></div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col">
<div class="card" style="width: 650px; text-align: center;">
<img class="gallery-hightlight" src="/Volumes/Untitled/coding/images/bowie-
big.jpeg" width="500px" alt="David Bowie Pop Art">
<div class="image-preview">
<img src="/volumes/Untitled/coding/images/bowie-small.jpeg" class="image-active" width="250px" alt="" />
<img src="/volumes/Untitled/coding/images/bowie2-small.jpeg" width="250px" alt="" />
</div>
<div class="card-block">
<h4 class="card-title">Original David Bowie Mug Shot Mixed Media Framed Artwork</h4>
<p class="card-text">Original David Bowie Mug Shot Mixed Media Framed Artwork floral painting on wooden canvas with an original pop art style David Bowie Mugshot on top painting is framed with a red baroque style frame including the words deadly flowers bloom
around frame</p>
<p class="card-price">Price: £200</p>
<a href="#" data-name="Bowie Art" data-image="/volumes/Untitled/coding/images/Boy-
small.jpeg" data-price="200" class="add-to-cart btn btn-primary">Add to cart</a>
</div>
</div>
</div>
</div>
<div id="mySidepanel" class="sidepanel">
x
<div class="modal fade" id="cart" tabindex="-1" role="dialog" aria- labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Cart</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<table class="show-cart table">
</table>
<div>Total price: £<span class="total-cart"></span></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data- dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Order now</button>
</div>
</div>
</div>
</div>
<!--
<script src="./shop.js"></script>
<script src="imageGallery.js"></script>
-->
</body>

What am I doing wrong in scoping my function?

In this test case, I am using append.child with plain JavaScript to add 3 kinds of divs (blue, red, green) to a parent multiple times according to their corresponding button onclicks, then I am adding another child inside the added div with another button (innerButton).
My issue is that, the onclick function which is assigned to the innerbutton and is nested within the initial function, listens only to the very first appended div, and it adds the input (which is supposed to be added to the div I'm clicking on) to the last append element of its 'kind'.
I am doing something wrong with my scoping but I can't see it.
I just started studying JavaScript, so I am not familiar yet with libraries, jQuery etc.
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var blue = document.createElement("div");
blue.id = "blueDiv";
blue.innerHTML = "<input id=blueInput><button id=innerButtonBlue onclick=addInputs()>ADD INPUTS</button>";
addTo.appendChild(blue);
document.getElementById("innerButtonBlue").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
blue.appendChild(newInput);
}
countBlue++;
}
function addRed() {
var addTo = document.getElementById('div1')
var red = document.createElement("div");
red.id = "redDiv";
red.innerHTML = "<input id=redInput><button id=innerButtonRed>ADD INPUTS</button>";
addTo.appendChild(red);
document.getElementById("innerButtonRed").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
red.appendChild(newInput);
}
countRed++;
}
function addGreen() {
var addTo = document.getElementById('div1')
var green = document.createElement("div");
green.id = "greenDiv";
green.innerHTML = "<input id=greenInput><button id=innerButtonGreen>ADD INPUTS</button>";
addTo.appendChild(green)
document.getElementById("innerButtonGreen").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input id="newInput" placeholder="NEW">';
green.appendChild(newInput);
}
countGreen++;
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
#blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
#redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
#greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
#innerButtonRed {
position: relative;
float: right;
}
#innerButtonBlue {
position: relative;
float: right;
}
#innerButtonGreen {
position: relative;
float: right;
}
#newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
#redInput {
background: red;
}
#blueInput {
background: blue;
}
#greenInput {
background: green;
}
<html>
<body>
<script src="test.js"></script>
<link rel="stylesheet" type="text/css" href="test.css">
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
</body>
</html>
The first thing you need to know is that, although you can technically add the same id to multiple elements, it is bad practice to do so. The id of an element should be unique. If you need to apply the same style or target multiple elements with your code you should use class instead of id.
I think that's what is causing issues in your code.
Second, since you say you are learning, i think it would be good if you tried to make a single function to add the elements since the code is repeated in all of the three functions, except for the color.
Try making the function accept the color as a variable so you can reuse it for the three colors. Imagine if it was a hundred colors.
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countBlue++; //set the counter to one so ids don't start at zero
div.id = `blueDiv-${countBlue}`; //creates a unique id depending on the counter
div.classList = "blueDiv";
div.innerHTML = `<input id="blueInput-${countBlue}" class="blueInput"><button id="innerButtonBlue-${countBlue}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonBlue-${countBlue}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-blue-${countBlue}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function addRed() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countRed++
div.id = `redDiv-${countRed}`;
div.classList = "redDiv";
div.innerHTML = `<input id="redInput-${countRed}" class="redInput"><button id="innerButtonRed-${countRed}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonRed-${countRed}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-red-${countRed}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function addGreen() {
var addTo = document.getElementById('div1')
var div = document.createElement("div");
countGreen++
div.id = `greenDiv-${countGreen}`;
div.classList = "greenDiv";
div.innerHTML = `<input id="greenInput-${countGreen}" class="greenInput"><button id="innerButtonGreen-${countGreen}" onclick="addInputs">ADD INPUTS</button>`;
addTo.appendChild(div);
document.getElementById(`innerButtonGreen-${countGreen}`).onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = `<input id="newInput-green-${countGreen}" class="newInput" placeholder="NEW">`;
div.appendChild(newInput);
}
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
.blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
.innerButtonRed {
position: relative;
float: right;
}
.innerButtonBlue {
position: relative;
float: right;
}
.innerButtonGreen {
position: relative;
float: right;
}
.newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
.redInput {
background: red;
}
.blueInput {
background: blue;
}
.greenInput {
background: green;
}
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
IDs need to be unique in the whole document. Don't use IDs for this, you can just use a class. But even with a class how is the code supposed to know which element it should look for since there will be more than one existing with the class? The solution is to search only inside the element that you just created (e.g. blue.querySelector('.someClass') to search for the first element with class someClass inside the blue element).
I changed your code to use classes everywhere:
var countBlue = 0;
var countRed = 0;
var countGreen = 0;
function addBlue() {
var addTo = document.getElementById('div1')
var blue = document.createElement("div");
blue.className = "blueDiv";
blue.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(blue);
blue.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
blue.appendChild(newInput);
}
countBlue++;
}
function addRed() {
var addTo = document.getElementById('div1')
var red = document.createElement("div");
red.className = "redDiv";
red.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(red);
red.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
red.appendChild(newInput);
}
countRed++;
}
function addGreen() {
var addTo = document.getElementById('div1')
var green = document.createElement("div");
green.className = "greenDiv";
green.innerHTML = "<input class='firstInput'><button class='innerButton'>ADD INPUTS</button>";
addTo.appendChild(green)
green.querySelector(".innerButton").onclick = function() {
var newInput = document.createElement("div");
newInput.innerHTML = '<input class="newInput" placeholder="NEW">';
green.appendChild(newInput);
}
countGreen++;
}
function displayCounters() {
alert("Blue divs amount : " + parseInt(countBlue) + "\n" + " Red divs amount : " + parseInt(countRed) + "\n" + " Green divs amount : " + parseInt(countGreen) + "\n" + "\n" + " All together is : " + (parseInt(countBlue) + parseInt(countRed) + parseInt(countGreen)))
}
button {
margin-bottom: 10px;
}
.blueDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.redDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
.greenDiv {
margin-top: 10px;
margin-bottom: 10px;
width: 300px;
}
input {
text-align: center;
}
.redDiv .innerButton {
position: relative;
float: right;
}
.blueDiv .innerButton {
position: relative;
float: right;
}
.greenDiv .innerButton {
position: relative;
float: right;
}
.newInput {
margin-top: 2px;
width: 162px;
height: 23px;
}
.redDiv .firstInput {
background: red;
}
.blueDiv .firstInput {
background: blue;
}
.greenDiv .firstInput {
background: green;
}
body {
height: 800px; /* Just for visibility here in Stack Overflow */
}
<html>
<body>
<script src="test.js"></script>
<link rel="stylesheet" type="text/css" href="test.css">
<button onclick="addBlue()">BLUE</button>
<button onclick="addRed()">RED</button>
<button onclick="addGreen()">GREEN</button>
<button onclick="displayCounters()">COUNTERS</button>
<div id="div1"></div>
</body>
</html>
There is a lot more that could be improved of course - the code duplication could be removed, a generalized function for all three types (red/green/blue) can be created that is differentiated just by an attribute on the button for example - but that's beyond the scope of this answer.

Loop through array in JSON

I have created a loop to cycle through the information in an API with this endpoint:
That returns data in this format (reduced in order to simplify):
{
"query": "allah",
"total_count": 3394,
"took": 153,
"current_page": 1,
"total_pages": 170,
"per_page": 20,
"results": [
{
"id": 664,
"verse_number": 171,
"chapter_id": 4,
"verse_key": "4:171",
"text_madani": "يَا أَهْلَ الْكِتَابِ لَا تَغْلُوا فِي دِينِكُمْ وَلَا تَقُولُوا عَلَى اللَّهِ إِلَّا الْحَقَّ ۚ إِنَّمَا الْمَسِيحُ عِيسَى ابْنُ مَرْيَمَ رَسُولُ اللَّهِ وَكَلِمَتُهُ أَلْقَاهَا إِلَىٰ مَرْيَمَ وَرُوحٌ مِّنْهُ ۖ فَآمِنُوا بِاللَّهِ وَرُسُلِهِ ۖ وَلَا تَقُولُوا ثَلَاثَةٌ ۚ انتَهُوا خَيْرًا لَّكُمْ ۚ إِنَّمَا اللَّهُ إِلَٰهٌ وَاحِدٌ ۖ سُبْحَانَهُ أَن يَكُونَ لَهُ وَلَدٌ ۘ لَّهُ مَا فِي السَّمَاوَاتِ وَمَا فِي الْأَرْضِ ۗ وَكَفَىٰ بِاللَّهِ وَكِيلًا",
"words": [
{
"id": 82924,
"position": 1,
"text_madani": "يَا أَهْلَ",
"text_indopak": null,
"text_simple": "يا اهل",
"verse_key": "4:171",
"class_name": "p105",
"line_number": 1,
"page_number": 105,
"code": "ﭑ",
"code_v3": "ﭑ",
"char_type": "word",
"audio": {
"url": "//verses.quran.com/wbw/004_171_001.mp3"
},
"translation": {
"id": 72752,
"language_name": "english",
"text": "O People",
"resource_name": null,
"resource_id": 59
},
"transliteration": {
"id": 72752,
"language_name": "english",
"text": "O People",
"resource_name": null,
"resource_id": 59
},
"highlight": null
}
],
"translations": [
{
"resource_name": "Abdullah Muhammad Basmeih",
"text": "dan janganlah kamu mengatakan sesuatu terhadap <em class=\"hlt1\">Allah</em> melainkan yang benar; sesungguhnya Al Masih Isa",
"id": 217603,
"language_name": "malay",
"resource_id": 39
}
]
}
]
}
It goes through the array of results and displays each one in an <li> tag. Then it goes through the translations. The following snippet displays only the first element of array, I want to include a new list inside my list item (right after the verse key) with all the translations inside more <li> tags. Is there any way to do this?
The snippet:
$.getJSON(url, function (data) {
count = data.total_count;
took = data.took;
results = data.results;
var li = '';
results = data.results;
var li = '';
for (const x of results) {
li +=
'<li>' +
x.text_madani +
'<br><span class="surah">' +
x.translations[0].text +' - '+ x.translations[0].resource_name+
'</span><br> <span class="surah">' +
x.verse_key +
'</span><br></li>';
}
document.getElementById('demo').innerHTML = li;
document.getElementById('Results').innerHTML =
'Results: ' + count + '';
document.getElementById('Time').innerHTML =
'Took: ' + took + ' milliseconds to load ' + count + ' results';
})
here's all the code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
<script
type="text/javascript"
src="https://code.jquery.com/jquery-2.1.1.min.js"
></script>
<link
href="https://fonts.googleapis.com/css?family=Google+Sans+Display:wght#300;400;700;800;900&display=swap"
rel="stylesheet"
/>
</head>
<body>
<style>
body {
font-family: 'Google Sans Display', sans-serif;
}
em{
font-weight:900;
font-style: normal;
}
li {
font-size: 20px;
margin-bottom: 4vh;
font-weight: 400;
}
.content {
margin-left: 20vw;
margin-right: 20vw;
text-align: justify;
}
:root {
--primary: #23adad;
--greyLight: #23adade1;
--greyLight-2: #cbe0dd;
--greyDark: #2d4848;
}
ul {
list-style-type: none;
}
.items-list {
max-width: 90vw;
margin: 2rem;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 3rem;
justify-content: center;
align-content: center;
}
#media only screen and (max-width: 600px) {
.items-list {
grid-template-columns: repeat(2, 1fr);
}
}
.item {
width: 10rem;
height: 10rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: var(--greyDark);
cursor: pointer;
}
.item span {
background: #ffffff;
box-shadow: 0 0.8rem 2rem rgba(90, 97, 129, 0.05);
border-radius: 0.6rem;
padding: 2rem;
font-size: 3rem;
transition: all 0.3s ease;
}
.item:hover span {
transform: scale(1.2);
color: var(--primary);
}
.item p {
font-size: 1.2rem;
margin-top: 1rem;
color: var(--greyLight);
}
.page {
display: flex;
justify-content: center;
align-items: center;
height: 5rem;
margin: 3rem;
border-radius: 0.6rem;
background: #ffffff;
box-shadow: 0 0.8rem 2rem rgba(90, 97, 129, 0.05);
}
.page__numbers, .page__btn, .page__dots {
display: flex;
justify-content: center;
align-items: center;
margin: 0.8rem;
font-size: 1.4rem;
cursor: pointer;
}
.page__dots {
width: 2.6rem;
height: 2.6rem;
color: var(--greyLight);
cursor: initial;
}
.page__numbers {
width: 2.6rem;
height: 2.6rem;
border-radius: 0.4rem;
}
.page__numbers:hover {
color: var(--primary);
}
.page__numbers.active {
color: #ffffff;
background: var(--primary);
font-weight: 600;
border: 1px solid var(--primary);
}
.page__btn {
color: var(--greyLight);
pointer-events: none;
}
.page__btn.active {
color: var(--greyDark);
pointer-events: initial;
}
.page__btn.active:hover {
color: var(--primary);
}
</style>
<div class="content">
<h3 id="Results"></h3>
<h3 id="Time"></h3>
<h6 id="demo"></h6>
</div>
<div id="app" class="container">
<ul class="page">
<li class="page__btn"><span class="material-icons">chevron_left</span></li>
<li class="page__numbers"> 1</li>
<li class="page__numbers active">2</li>
<li class="page__numbers">3</li>
<li class="page__numbers">4</li>
<li class="page__numbers">5</li>
<li class="page__numbers">6</li>
<li class="page__dots">...</li>
<li class="page__numbers"> 10</li>
<li class="page__btn"><span class="material-icons">chevron_right</span></li>
</ul>
</div>
<script>
window.onload = function () {
var search = prompt('search');
var arText;
var enText;
var surah;
var ayahNumber;
var surahAndAyah;
$(document).ready(function () {
getQuote();
$('#shuffle').on('click', getQuote);
$('#tweet').click(function () {
var tweetLink = '' + '"' + enText + '" QS' + surahAndAyah;
window.open(tweetLink);
});
});
function getQuote() {
var ayah = Math.floor(Math.random() * 6236) + 1;
var url =
'http://api.quran.com:3000/api/v3/search?q= ' +
search +
' &size=20&page=0&language=en';
arText;
enText;
surah;
ayahNumber;
surahAndAyah;
$.getJSON(url, function (data) {
count = data.total_count;
took = data.took;
results = data.results;
var li = '';
results = data.results;
var li = '';
for (const x of results) {
li +=
'<li>' +
x.text_madani +
'<br><span class="surah">' +
x.translations[0].text +' - '+ x.translations[0].resource_name+
'</span><br> <span class="surah">' +
x.verse_key +
'</span><br></li>';
}
document.getElementById('demo').innerHTML = li;
document.getElementById('Results').innerHTML =
'Results: ' + count + '';
document.getElementById('Time').innerHTML =
'Took: ' + took + ' milliseconds to load ' + count + ' results';
})
.done(function () {
console.log('second success');
})
.fail(function (jqXHR, textStatus, errorThrown) {
//alert("You're offline! " + textStatus);
})
.always(function () {
console.log('complete');
});
}
};
</script>
</body>
</html>
You can achieve that by looping through both the results and translations keys, something like this:
$.getJSON(url, function (data) {
count = data.total_count;
took = data.took;
results = data.results;
var li = '';
results = data.results;
for (const x of results) {
li += '<li>' + x.text_madani + '<br>' +
'<span class="surah">' + x.verse_key + '</span><ul>'
for (const y of x.translations) {
li += '<li><span class="surah">' +
y.text +' - '+ y.resource_name+
'</span></li>';
}
li += '</ul></li>';
}
document.getElementById('demo').innerHTML = li;
document.getElementById('Results').innerHTML =
'Results: ' + count + '';
document.getElementById('Time').innerHTML =
'Took: ' + took + ' milliseconds to load ' + count + ' results';
})
Please keep in mind that this might mess with your HTML if your data is not sanitized or if it's not using some kind of abstraction to generate the HTML.
Creating HTML using a string concatenated from results from a API is not encouraged.
you can create a new ul element and use insertAdjacentHTML('beforeend', str) in order to append the text as HTML element.
function printTranslations(translations) {
var ul = '<ul>';
for (const text of translations) {
ul +=
'<li><span class="surah">' +
text.text + ' - ' + text.resource_name +
'</span></li>';
}
return ul + '</ul>';
}
function (data) {
count = data.total_count;
took = data.took;
results = data.results;
var ul = document.createElement('ul');
results = data.results;
for (const x of results) {
ul.insertAdjacentHTML('beforeend',
'<li>' +
x.text_madani +
'<br><span class="surah">' +
printTranslations(x.translations) +
'<span class="surah">' +
x.verse_key +
'</span><br></li>');
}
document.getElementById('demo').appendChild(ul);
document.getElementById('Results').innerHTML = 'Results: ' + count + '';
document.getElementById('Time').innerHTML =
'Took: ' + took + ' milliseconds to load ' + count + ' results';
}

How do i keep a set of elements wrapped in a div inline?

https://jsfiddle.net//2L4t9saq/61/ is my code
this is the output of one line of iterations
<span class="inline"><div class="pixels" x="1" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="2" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="3" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="4" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="5" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="6" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="7" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="8" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="9" y="1" style="background-color: red; width: 10px; height: 10px;"></div><div class="pixels" x="10" y="1" style="background-color: red; width: 10px; height: 10px;"></div></span>
this creates 10 divs with width/height of 10px with the background color red, all 10 divs are wrapped in the span with class inline. this process is then repeated 10 times to create the 10*10 array.
this can be configured, currently all that can be configured are the width and height of the array, and the width and height of each individual pixel
currently it is just a vertical 100 block line of red squares.
how would i make all element wrapped in classinline stay inline? as to turn it from a 1*100 line to a 10*10 square
thanks in advance
/*
$("#body").append(
"<div x='1'></div>"
);
$("div[x=1]").css("background-color","red")
$("div[x=1]").css("width","16")
$("div[x=1]").css("height","16")
*/
var createGrid = function(dimx, dimy, pixx, pixy) {
for (var n = 1; n < dimy + 1; n++) {
var str = "<div class='inline'>"
for (var i = 1; i < dimx + 1; i++) {
var opentag = "<div class='pixels' x='"
var midtag = "' y='"
var endtag = "'></div>"
str = str + opentag + i + midtag + n + endtag
}
str = str + "</div>"
$("#main").append(str)
}
$(".pixels").css("background-color", "red")
$(".pixels").css("width", pixx)
$(".pixels").css("height", pixy)
};
createGrid(10, 10, 10, 10)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div canvas="canvas" id="main">
</div>
span should be inside the div and make them inline-block to be able to specify width/height
var createGrid = function(dimx,dimy,pixx,pixy){
for(var n = 1; n <dimy+1; n++){
var str = "<div>"
for(var i=1;i<dimx+1;i++){
var opentag = "<span class='pixels' x='"
var midtag = "' y='"
var endtag = "'></span>"
str = str+opentag+i+midtag+n+endtag
}
str=str+"</div>"
$("#main").append(str)
}
$(".pixels").css("background-color","red")
$(".pixels").css("width",pixx)
$(".pixels").css("height",pixy)
};
createGrid(10,10,10,10)
#main {
font-size:0; /* To fix white-space issue*/
}
.pixels {
display:inline-block;
border:1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div canvas="canvas" id="main">
</div>
Add display: flex on canvas div.
And no need of making the inline element as span, make it a div instead.
/*
$("#body").append(
"<div x='1'></div>"
);
$("div[x=1]").css("background-color","red")
$("div[x=1]").css("width","16")
$("div[x=1]").css("height","16")
*/
var createGrid = function(dimx, dimy, pixx, pixy) {
for (var n = 1; n < dimy + 1; n++) {
var str = "<div class='inline'>"
for (var i = 1; i < dimx + 1; i++) {
var opentag = "<div class='pixels' x='"
var midtag = "' y='"
var endtag = "'></div>"
str = str + opentag + i + midtag + n + endtag
}
str = str + "</div>"
$("#main").append(str)
}
$(".pixels").css("background-color", "red")
$(".pixels").css("width", pixx)
$(".pixels").css("height", pixy)
};
createGrid(10, 10, 10, 10)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div canvas="canvas" id="main" style="display: flex;">
</div>
The parent element should be display: block and the inner elements could be display: inline-block for them to display in a grid-like manner. Changing only the CSS:
var createGrid = function(dimx, dimy, pixx, pixy) {
for (var n = 1; n < dimy + 1; n++) {
var str = "<span class='inline'>"
for (var i = 1; i < dimx + 1; i++) {
var opentag = "<div class='pixels' x='"
var midtag = "' y='"
var endtag = "'></div>"
str = str + opentag + i + midtag + n + endtag
}
str = str + "</span>"
$("#main").append(str)
}
$(".pixels").css("background-color", "red")
$(".pixels").css("width", pixx)
$(".pixels").css("height", pixy)
};
createGrid(10, 10, 10, 10)
.inline {
display: block;
height: 10px;
}
.pixels {
display: inline-block
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div canvas="canvas" id="main">
</div>
But it would be better to put spans inside divs, not the other way around (divs are display: block by default):
var createGrid = function(dimx, dimy, pixx, pixy) {
for (var n = 1; n < dimy + 1; n++) {
var str = "<div>"
for (var i = 1; i < dimx + 1; i++) {
var opentag = "<span class='pixels' x='"
var midtag = "' y='"
var endtag = "'></span>"
str = str + opentag + i + midtag + n + endtag
}
str = str + "</div>"
$("#main").append(str)
}
$(".pixels").css("background-color", "red")
$(".pixels").css("width", pixx)
$(".pixels").css("height", pixy)
};
createGrid(10, 10, 10, 10)
.pixels {
display: inline-block
}
#main > div {
height: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div canvas="canvas" id="main">
</div>

Dynamically add values to form with javascript or jquery

I have created a calculator I use for counting carbs for my 7 y/o type 1 diabetic but as I add more values into my array the page is getting too long.
I'm looking for a way to start with a single select for the food name then select the weight and it calculates the carbs. Then have a button to dynamically add another row to the form in order to select a new food item and calculate the results of any further additions.
This is my functional code base:
<html><head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
#container{width: 200px; margin: 0 auto;}
label { font-size:20px; display: inline-block; width: 45%; text-align: right;}
input[type="text"][disabled] {width: 12%; background-color: white; color: black; font-weight: bolder;}
input[type="button"] {}
select {width: 15%}
</style></head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [['Banana',0.1428571429], ['Blackberry',0.1], ['Blueberry',0.1418918919], ['Carrots',0.09836065574], ['Cantaloupe',0.08], ['Cherry Tomato',0.05882352941], ['Cucumber',0.03653846154], ['Green apple',0.1373626374], ['Honeydew',0.09], ['Pear',0.15], ['Raspberry',0.12], ['Plum',0.11], ['Strawberry',0.075], ['Watermelon',0.075]];
function reset(){
var t=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
document.calc.elements[v].value=0;
}
}
function calculate(){
var t=0;
var tt=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
var a = "answer"+i;
if(isNaN(parseInt(document.calc.elements[v].value))) {
//document.calc.elements[a].value="";
} else {
tt=(parseInt(document.calc.elements[v].value))* myArray[i][1];
document.calc.elements[a].value=tt.toFixed(1);
t+=tt;
}
}
document.calc.answerTot.value=(t).toFixed(1)
}
document.write("<form name=\"calc\" action=\"post\">");
for (var i=0; i<myArray.length; i++) {
var vv = "val"+i;
var aa = "answer"+i;
document.write("<label>"+myArray[i][0]+":</label> <select name=\""+ vv +"\" onchange=\"calculate()\" >");
for (var j=0; j<301; j++) {
document.write("<option value=" +j+ ">" +j+ "</option>");
}
document.write("</select><input type=text name=" +aa+ " size=5 placeholder=\"Carbs\" disabled><br>");
}
document.write("<br><label for=\"answerTot\">Total carbs: </label> <input type=text name=answerTot size=5 disabled></br></br> <div style=\"text-align:center\"> <input type=button value=Calculate onClick=\"calculate()\"></br></br><input type=button value=Reset onClick=\"reset()\"></div>");
</script></body></html>
Hello there and welcome to StackOverflow!
Your code required a bit of rework and questions like that (more like a task than a question) aren't usually very successful around here.
Having said that, I wrote something that will hopefully help you, the nice thing about it being that if you want to add new types of food you'll only need to add them in the array and the js will take care of it.
Careful with the approximation to 1 digit though, you might lose some carbs in the calculation. Also, please check your carbs, see if I haven't modified anything by mistake.
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = "";
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) > 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inp = document.createElement("input");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
entry.appendChild(sel);
entry.appendChild(inp);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
* {
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 140px;
height: 20px;
margin: 5px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 240px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
<form name="calc" action="post" id="calculatorForm">
</form>
<div style="text-align:center" class="control">
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
If anyone wants to see the result, this is what I ended up with. I added a couple event listeners and made the weight value a select rather than an input. Thanks again #Paul for the assistance this is exactly what I was trying to accomplish!
<html>
<head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
{
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 145px;
height: 20px;
margin: 2px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 50px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
</style>
</head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = 0;
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) >= 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inpu = document.createElement("select");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
inpu.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
for (var j=0; j<301; j++){
inpu.options[inpu.options.length]=new Option(j,j)
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
inpu.addEventListener("change", function() {
calculate();
})
sel.addEventListener("change", function() {
calculate();
})
entry.appendChild(sel);
entry.appendChild(inpu);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
</script>
<form name="calc" action="post" id="calculatorForm"></form>
<div style="text-align:center" class="control"><br>
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
</body></html>
Here is a small application I came up with that could also suit your needs.
It consists of five files that should be located in the same directory.
Best of health for your child!
Features include:
adding and removing of new food types
adding and removing food to/from multiple lists
changing, increasing and decreasing count of fooditems in lists
manage (add,remove,rename) multiple lists
save and load data in your browser locally
export and import data through a text area to save your data externally.
layout support for both big screen and handheld devices
myCarbCalculator.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Carb Calculator</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="myCarbCalculator.css"></link>
<link rel="stylesheet" media="screen" href="myCarbCalculator-Screen.css"></link>
<link rel="stylesheet" media="handheld" href="myCarbCalculator-Handheld.css"></link>
<script type="text/javascript" src="myCarbCalculator.js"></script>
</head>
<body onload="init();">
<div id="root">
<div id="header">
<button id="btnSaveSettings">save Settings</button>
<button id="btnLoadSettings">load Settings</button>
<button id="btnImportSettings">import Settings</button>
<button id="btnExportSettings">export Settings</button>
<button id="btnResetSettings">reset Settings</button>
</div>
<div id="center">
<div id="content-main">
<div id="c_foodSelector">
<label for="selFoodSelector">select a type of food</label>
<select id="selFoodSelector"></select>
<button id="btnAddSelectedFoodToList">Add Food to List</button>
</div>
<div id="c_foodTable">
<div id="c_foodTableOptions">
<input id="p_foodTableName" value="Your List of Food Items"/>
<button id="btnRenameFoodTable">rename List</button>
<button id="btnNewFoodTable">new List</button>
</div>
<table id="foodTable" class="fill-width"></table>
</div>
</div>
<div id="content-additional">
<div id="c_results">
<label for="inputResultCarbs">Carbs Total</label>
<input id="inputResultCarbs" readonly="readonly"/>
</div/>
<div id="c_foodTableSelection">
<table id="foodTableSelection" class="fill-width"></table>
</div>
<div id="c_output">
<h3>Import/Export</h3>
<textarea id="p_output" class="fill-width"></textarea>
</div/>
</div>
</div>
<div id="footer">
<label for="p_newFoodName">Food Name</label><input id="p_newFoodName"/>
<label for="p_newFoodCarbs">Carb Value</label><input id="p_newFoodCarbs"/>
<button id="btnNewFood">add a new type of food</button>
<button id="btnDeleteSelectedFood">delete Selected type of food</button>
</div>
</div>
</body>
</html>
myCarbCalculator.js
var SAVEID = 'carbCalculatorSettings';
function MyCarbCalculator(){
var self = this;
this.settings = null;
this.initSettings = function(){
self.settings = {
'activeFoodList' : 'default',
'foodData' : {},
'foodList' : {
'default' : {
'label' : 'Your List of Food Items',
'list' : {},
'dateCreated' : '',
'dateChanged' : '',
'notes' : 'This is the default Food List'
}
}
};
};
this.clearContents = function(element){
while (element.firstChild) {
element.removeChild(element.firstChild);
}
};
this.formatDate = function(timestamp){
if(timestamp != ""){
var date = new Date(timestamp);
var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
];
var day = date.getDate();
var monthIndex = date.getMonth();
var year = date.getFullYear();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
return day + ' ' + monthNames[monthIndex] + ' ' + year + ' ' + hours + ':'+ minutes + ':'+ seconds;
}
return "---";
};
//////////////////////////////////////////////////////////////////
// Load and Save Data
//////////////////////////////////////////////////////////////////
this.resetSettings = function(){
self.initSettings();
self.updateView();
};
this.saveSettings = function(){
localStorage.setItem(SAVEID,JSON.stringify(self.settings));
};
this.loadSettings = function(){
var saveData = localStorage.getItem(SAVEID);
if(saveData != null && saveData.length > 0){
self.settings = JSON.parse(localStorage.getItem(SAVEID));
self.updateView();
}
else{
self.initSettings();
}
};
this.importSettings = function(){
localStorage.setItem(SAVEID,document.getElementById('p_output').value);
self.loadSettings();
};
this.exportSettings = function(){
document.getElementById('p_output').value = localStorage.getItem(SAVEID);
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.updateView = function(){
self.updateFoodSelector();
self.updateFoodTable();
self.updateFoodTableSelection();
self.updateResult();
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.newFood = function(){
var name = document.getElementById('p_newFoodName').value;
var carbs = document.getElementById('p_newFoodCarbs').value;
var id = Date.now();
self.settings.foodData[id] = {'name':name,'carbs':carbs};
self.updateFoodSelector();
};
this.removeSelectedFoodData = function(){
var foodSelector = document.getElementById('selFoodSelector');
var foodDataId = foodSelector.options[foodSelector.selectedIndex].value;
delete self.settings.foodData[foodDataId];
self.updateFoodSelector();
}
this.updateFoodSelector = function(){
var foodSelector = document.getElementById('selFoodSelector');
self.clearContents(foodSelector);
for(id in self.settings.foodData){
var food = self.settings.foodData[id];
var item = document.createElement("option");
item.value = id;
item.innerHTML = food.name + " (" + food.carbs + ")";
foodSelector.appendChild(item);
}
};
//////////////////////////////////////////////////////////////////
// Manage current Food Table
//////////////////////////////////////////////////////////////////
this.addSelectedFoodToTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var foodSelector = document.getElementById('selFoodSelector');
var selectedFoodId = foodSelector.options[foodSelector.selectedIndex].value;
var foodData = self.settings.foodData[selectedFoodId];
var foodItem = {'name':foodData.name,'carbs':foodData.carbs,'count':1};
foodList.list[Date.now()] = foodItem;
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodCount = function(id,value){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
foodList.list[id].count = value;
foodList.dateChanged = Date.now();
self.updateView();
};
this.removeFoodItem = function(id){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
delete foodList.list[id];
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
// update the List Name
var foodTableNameElement = document.getElementById('p_foodTableName');
foodTableNameElement.value = foodList.label;
// update the List itself
var foodTable = document.getElementById('foodTable');
self.clearContents(foodTable);
// create the Table Header
var row = document.createElement("tr");
foodTable.innerHTML =
"<tr><th>Name</th><th>Carbs/unit</th><th></th><th>Count</th><th></th></tr>";
for(id in foodList.list){
// create a table structure
var row = document.createElement("tr");
var elm1 = document.createElement("td");
var elm2 = document.createElement("td");
var elm3 = document.createElement("td");
var elm4 = document.createElement("td");
var elm5 = document.createElement("td");
var elm6 = document.createElement("td");
row.appendChild(elm1);
row.appendChild(elm2);
row.appendChild(elm3);
row.appendChild(elm4);
row.appendChild(elm5);
row.appendChild(elm6);
foodTable.appendChild(row);
// create input fields
var food = foodList.list[id];
var inputFoodId = document.createElement("input");
inputFoodId.id = "food-id-" + id;
inputFoodId.type = "hidden";
inputFoodId.value = id;
var inputFoodName = document.createElement("input");
inputFoodName.id = "food-name-" + id;
inputFoodName.setAttribute("readonly","readonly");
inputFoodName.value = food.name;
var inputFoodCarbs = document.createElement("input");
inputFoodCarbs.id = "food-carbs-" + id;
inputFoodCarbs.setAttribute("readonly","readonly");
inputFoodCarbs.style.width = "3em";
inputFoodCarbs.value = food.carbs;
var inputFoodCount = document.createElement("input");
inputFoodCount.id = "food-count-" + id;
inputFoodCount.setAttribute("data-id",id);
inputFoodCount.style.width = "3em";
inputFoodCount.value = food.count;
inputFoodCount.addEventListener("change",function(event){
var inputFoodCount = event.currentTarget;
var id = inputFoodCount.getAttribute("data-id");
var count = inputFoodCount.value;
self.updateFoodCount(id,count);
});
var btnDeleteFoodItem = document.createElement("button");
btnDeleteFoodItem.innerHTML = "remove";
btnDeleteFoodItem.setAttribute("data-id",id);
btnDeleteFoodItem.addEventListener("click",function(event){
var btnDeleteFoodItem = event.currentTarget;
var id = btnDeleteFoodItem.getAttribute("data-id");
self.removeFoodItem(id);
});
var btnCountUp = document.createElement("button");
btnCountUp.innerHTML = "+";
btnCountUp.setAttribute("data-id",id);
btnCountUp.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = ++ inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
var btnCountDown = document.createElement("button");
btnCountDown.innerHTML = "-";
btnCountDown.setAttribute("data-id",id);
btnCountDown.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = -- inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
// append input fields to the table row
elm1.appendChild(inputFoodId); // this one is invisible anyway
elm1.appendChild(inputFoodName);
elm2.appendChild(inputFoodCarbs);
elm3.appendChild(btnCountDown);
elm4.appendChild(inputFoodCount);
elm5.appendChild(btnCountUp);
elm6.appendChild(btnDeleteFoodItem);
}
};
//////////////////////////////////////////////////////////////////
// Calculate Results
//////////////////////////////////////////////////////////////////
this.calculateCarbsForList = function(listId){
var foodListData = self.settings.foodList[listId].list;
var total = 0;
for(id in foodListData){
var item = foodListData[id];
total = total + (item.carbs * item.count);
}
return total;
};
this.updateResult = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var inputResultCarbs = document.getElementById("inputResultCarbs");
inputResultCarbs.value = self.calculateCarbsForList(activeFoodListId);
};
//////////////////////////////////////////////////////////////////
// Food Table Handling
//////////////////////////////////////////////////////////////////
this.renameFoodTable = function(){
var activeTableId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeTableId];
var newName = document.getElementById('p_foodTableName').value;
foodList.label = newName;
foodList.dateChanged = Date.now();
self.updateView();
};
this.newFoodTable = function(){
var newTableName = document.getElementById('p_foodTableName').value;
var date = Date.now();
self.settings.foodList[date] = {
'label' : newTableName,
'list' : {},
'dateCreated' : date,
'dateChanged' : date,
'notes' : ''
}
self.settings.activeFoodList = date;
self.updateView();
};
this.updateFoodTableSelection = function(){
var foodTableSelection = document.getElementById('foodTableSelection');
self.clearContents(foodTableSelection);
var foodTableLists = self.settings.foodList;
foodTableSelection.innerHTML =
"<tr><th>Name</th><th>last Change</th><th>Carbs</th><th></th><th></th></tr>";
for(var tableId in foodTableLists){
var foodTable = foodTableLists[tableId];
var row = document.createElement("tr");
if(tableId == self.settings.activeFoodList){
row.classList.add("active");
}
var cell1 = document.createElement("td");
var cell2 = document.createElement("td");
var cell3 = document.createElement("td");
var cell4 = document.createElement("td");
var cell5 = document.createElement("td");
cell1.innerHTML = foodTable.label;
cell1.style.cursor = "help";
cell1.title = foodTable.notes;
cell2.innerHTML = self.formatDate(foodTable.dateChanged);
cell2.title = "created: " + self.formatDate(foodTable.dateCreated);
cell3.innerHTML = self.calculateCarbsForList(tableId);
var btnSelectFoodTable = document.createElement("button");
if(tableId == self.settings.activeFoodList)btnSelectFoodTable.disabled = 'disabled';
btnSelectFoodTable.innerHTML = "select";
btnSelectFoodTable.setAttribute("data-tableId",tableId);
btnSelectFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
self.settings.activeFoodList = button.getAttribute("data-tableId");
self.updateView();
});
cell4.appendChild(btnSelectFoodTable);
var btnDeleteFoodTable = document.createElement("button");
if(tableId == 'default')btnDeleteFoodTable.disabled = 'disabled';
btnDeleteFoodTable.innerHTML = "delete";
btnDeleteFoodTable.setAttribute("data-tableId",tableId);
btnDeleteFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
var tableId = button.getAttribute("data-tableId");
if(self.settings.activeFoodList = tableId){
self.settings.activeFoodList = "default";
};
delete self.settings.foodList[tableId];
self.updateView();
});
cell5.appendChild(btnDeleteFoodTable);
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
row.appendChild(cell5);
foodTableSelection.appendChild(row);
}
};
//////////////////////////////////////////////////////////////////
// Add global Events
//////////////////////////////////////////////////////////////////
document.getElementById("btnNewFood").addEventListener("click",this.newFood);
document.getElementById("btnSaveSettings").addEventListener("click",this.saveSettings);
document.getElementById("btnLoadSettings").addEventListener("click",this.loadSettings);
document.getElementById("btnResetSettings").addEventListener("click",this.resetSettings);
document.getElementById("btnImportSettings").addEventListener("click",this.importSettings);
document.getElementById("btnExportSettings").addEventListener("click",this.exportSettings);
document.getElementById("btnDeleteSelectedFood").addEventListener("click",this.removeSelectedFoodData);
document.getElementById("btnAddSelectedFoodToList").addEventListener("click",this.addSelectedFoodToTable);
document.getElementById("btnRenameFoodTable").addEventListener("click",this.renameFoodTable);
document.getElementById("btnNewFoodTable").addEventListener("click",this.newFoodTable);
//////////////////////////////////////////////////////////////////
// Initialize the Data on screen
//////////////////////////////////////////////////////////////////
self.loadSettings();
}
function init(){
var carCalculator = new MyCarbCalculator();
}
myCarbCalculator.css
body,html{
height:100%;
}
/* dont show borders on input fields if read only */
input:-moz-read-only {
border : none;
}
input:read-only {
border : none;
}
/* spacing elements out */
th{
text-align:left;
}
label,input,button,select{
white-space:nowrap;
margin-right: 1em;
}
button{
height:2.5em;
}
#c_results,#c_foodSelector,#c_output,#footer,#header{
padding:1em;
}
/* make result stand out */
#c_results #inputResultCarbs{
font-size: 2em;
color: #882222;
width:4em;
}
#c_results label[for="inputResultCarbs"]{
font-size: 1em;
padding-top:1em;
}
.fill-width{
width:100%;
}
table#foodTableSelection > tr.active{
background-color:yellow;
}
myCarbCalculator-Screen.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:row;
border-bottom: 1px solid black;
}
#footer{
display:flex;
flex-direction.row;
border-top: 1px solid black;
}
#center{
flex: 1 0;
display:flex;
flex-direction:row;
}
#content-main{
flex: 1 0 auto;
display:flex;
flex-direction: column;
}
#c_foodSelector{
border-bottom: 1px solid black;
}
#c_foodTable{
}
#content-additional{
flex: 0 1 30%;
display:flex;
flex-direction: column;
border-left: 1px solid black;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
myCarbCalculator-Handheld.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 3;
}
#footer{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 2;
}
#center{
flex: 1 0;
display:flex;
flex-direction:column;
order: 1;
}
#content-main{
display:flex;
flex-direction: column;
}
#c_foodSelector{
display:flex;
flex-direction:column;
border-bottom: 1px solid black;
}
#c_foodTable{
border-bottom: 1px solid black;
}
#content-additional{
display:flex;
flex-direction: column;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
/*******************************************
ADDITONAL STYLES ONLY FOR HANDHELD LAYOUT
*******************************************/
/* spacing out vertically */
label,input,button,select{
margin-bottom: 0.5em;
}
input[id^="food-name"]{
width:4em;
}
#header:before,#footer:before{
text-align:center;
font-size:1em;
font-weight:bold;
margin-bottom:0.5em;
}
#header:before{
content:'Options';
}
#footer:before{
content:'Foodtypes';
}
Technical Notes:
I am using pure Javascript and css. Some styles might not be compatible with older browsers like Internet Explorer prior to Edge.
Saving of data is handled through the browsers local storage.
Import and Export is handled through plain text in "Javascript Object Notation" (JSON).
The Application itself is written as a Javascript Class e.g. Function named MyCarbCalculator which is created and initialized through the bodies onload event and an init() function.
With this example application I'm trying to show how to use Javascript in a structured (pseudo object oriented) way and the power and flexibility of event listeners and unnamed functions e.g. the use of functions as parameters.
Also I am using CSS media descriptors to create a flexible layout that can be customized for both handheld devices and big screens. This is mostly done through the "flexbox" style which allows for very fluid layouts and offers great control over the positioning of elements.

Categories