I have a site where I can enter the amount of an item, it will then take that input value and return the result on the page. I am then trying to get the results of all the items and return a grand total.
The issue is when I a loop to do this it will only add the first one.
I created a fiddle: https://jsfiddle.net/rc1mgLj5/4/
I am using querySelectorAll and using the length of all the classNames for the result of the first return.
Then looping them after parsing them to a number from text.
But at the moment it is only doing the first calculation. If I delete the for loop the first part works correctly again.
So since its only doing the first calculation for the first item, I get NaN for the second because it does not have a number to parse.
const total = document.querySelectorAll(".tot");
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll(".qty-item");
const cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll(".error");
cal.addEventListener("mouseover", function(e) {
console.log(total);
for (var i = 0; i < price.length; i++) {
let xPrice = price[i].innerHTML.split("$");
let parsePrice = parseFloat(xPrice[1]);
if (textval[i].value === "" || isNaN(textval[i].value)) {
setMessage("Please enter a number", "red");
} else {
let x = parseFloat(textval[i].value);
let y = parsePrice;
let z = x * y;
total[i].innerText = z.toFixed(2);
total[i].innerText = z;
for (i = 0; i < total.length; i++) {
let j = parseFloat(total[i].innerHTML);
console.log(j);
}
}
}
});
HTML:
<body>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 1</span>
</div>
<div>
<span class="cost">$100.00</span>
</div>
<div id="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<br><br>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 2</span>
</div>
<div>
<span class="cost">$50.00</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<div class="calc-button">
<button id="calc">Calculate Prices</button>
</div>
</body>
You are nesting two fors using the same i variable as index:
cal.addEventListener('mouseover', function(e) {
console.log('total', total);
for (var i = 0; i < price.length; i++) {
//...
for (i = 0; i < total.length; i++) { // <== uses "i" again
let j = parseFloat(total[ii].innerHTML);
console.log(j);
}
}
}
});
Just replace that second for's variable with another name. Example:
for (let k = 0; k < total.length; k++) {
let j = parseFloat(total[k].innerHTML);
console.log(j);
}
Demo: https://jsfiddle.net/acdcjunior/gpLvszx3/
It seems you are using the same variable "i" for both loops and i is being reset in the second loop to 3 and hence the main loop runs only once. So i removed the following code and calculated the total outside main loop. seems to be working fine now. https://jsfiddle.net/uxr7ac9k/7/
total[i].innerText = z;
for (i=0;i < total.length; i++){
let j = parseFloat(total[i].innerHTML);
console.log(j);
}
Related
I'm currently working on an e-commerce site and I'm stuck on the search page, especially when filtering the products.
**
This is the HTML code for the product card:**
<div class="product-seller-item" data-brand="Louis Vuitton" data-category="Helmets">
<div class="product-page-seller-item-header">
<img src="/Images/user.png" alt="User profile image">
<p>citygirl1996</p>
</div>
<img class="product-page-seller-item-body-image" src="/Images/Products/product1.png" alt="">
<div class="product-page-seller-item-footer">
<div class="product-page-seller-item-footer-flex">
<p>£15.00</p>
</div>
<p class="product-page-seller-item-footer-description">Juicy Couture</p>
</div>
</div>
And this is the code for the checkbox:
<label class="container">Helmets
<input type="checkbox" value="Helmets">
<span class="checkmark"></span>
</label>
<label class="container">Louis Vuitton
<input type="checkbox" value="Louis Vuitton">
<span class="checkmark"></span>
</label>
And this is the code for JavaScript:
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
const products = document.querySelectorAll('.product-seller-item');
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function () {
for (let j = 0; j < products.length; j++) {
let productVisible = false;
for (let k = 0; k < checkboxes.length; k++) {
if (checkboxes[k].checked && products[j].dataset.category === checkboxes[k].value) {
productVisible = true;
break;
} else if (checkboxes[k].checked && products[j].dataset.brand
&& products[j].dataset.brand === checkboxes[k].parentElement.textContent.trim()) {
productVisible = true;
break;
}
}
if (productVisible) {
products[j].style.display = 'block';
} else {
products[j].style.display = 'none';
}
}
});
}
The problem is as follows, when I select the Helmets category, it shows me all of them, everything works perfectly, but when I select the brand, it doesn't hide the product that doesn't match.
If the products have a category you can use filtermethod, that will return you a new array with the elements that have this conditions. For example:
const products = document.querySelectorAll('.products'):
const categories = document.querySelectorAll('input[type=checkbox]');
const filteredProducts
= products.filter(product => product.category == categories.checked);
Good, I have a form which is loaded by 2 iterations, one to load activities and another iteration that is within months, the problem I have is that when entering text in the input text the value in the other text is doubled input The activities come from the database, and the months that will take a start date and an end date, those months should be assigned an amount. So the problem is that these quantities are doubled, making it impossible to enter data correctly.
This is my code in sandbox
https://codesandbox.io/embed/inspiring-proskuriakova-nb0bk?fontsize=14&hidenavigation=1&theme=dark
<template>
<div class="content">
<div v-for="(act, index) in actividades" :key="index">
<div class="row">
<div class="col-12 mt-3">
<b>Actividad {{act.codigo}}</b>
<div class="row" v-for="(pro, index2) in act.programaticas" :key="index2">
<div class="col-4">
<br>
{{pro.mes}}
</div>
<div class="col-8">
Cantidad
<input type="number" required class="form-control" v-model="pro.cantidad">
</div>
</div>
</div>
</div>
<hr>
</div>
export default {
data () {
return {
proyecto:{},
actividades:[],
programaticas:[],
programatica:{mes:'',cantidad:''},
}
},
created() {
this.fetch();
},
methods:{
async fetch()
{
const proyecto = await
Repository.show('proyectos',this.$route.params.proyecto_id);
this.proyecto = proyecto.data;
const actividades=await
Repository.show('actividades',this.$route.params.objetivo_id);
if(actividades.data.length!=0)
{
this.actividades = actividades.data;
}
this.obtenerMeses();
},
obtenerMeses()
{
var monthNames = [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ];
var datFrom = new Date(this.proyecto.fecha_inicio);
var datTo = new Date(this.proyecto.fecha_fin);
var fromYear = datFrom.getFullYear();
var toYear = datTo.getFullYear();
var diffYear = (12 * (toYear - fromYear)) + datTo.getMonth();
for (var i = datFrom.getMonth(); i <= diffYear; i++) {
this.programatica.mes=monthNames[i%12] + " " + Math.floor(fromYear+(i/12));
this.programaticas.push(this.programatica);
this.programatica={mes:'',cantidad:''};
}
for(var i2 = 0; i2 < this.actividades.length; i2++)
{
this.actividades[i2].programaticas=this.programaticas;
}
}
}
}
The problem is:
for(var i2 = 0; i2 < this.actividades.length; i2++)
{
this.actividades[i2].programaticas=this.programaticas;
}
You declare for each item the reference to the same array: this.programaticas. You must create the copy for each item. For example:
for(var i2 = 0; i2 < this.actividades.length; i2++)
{
this.actividades[i2].programaticas=JSON.parse(JSON.strigify(this.programaticas));
}
or better
for(var i2 = 0; i2 < this.actividades.length; i2++)
{
var list = []
for (var i = datFrom.getMonth(); i <= diffYear; i++) {
list.push({
mes: monthNames[i%12] + " " + Math.floor(fromYear+(i/12)),
cantidad:''
});
}
this.actividades[i2].programaticas = list;
}
or change the concept, like one structure for inputs, other for labels
In order to animate images in - I need to add many divs using Javascript over the image where at present the markup is
<div class="js-img-in">
<figure><img src="test.jpg"></figure>
</div>
To eventually compile to
<div class="js-img-in">
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<figure><img src="test.jpg"></figure>
</div>
My code at the moment returns appendChild is not a function.
const imageAnimIn = () => {
const images = document.querySelectorAll(".js-img-in");
for (var x = 0; x < 5; x++) {
var imageOverDivs = document.createElement('div');
imageOverDivs.className = "js-anim-img-in";
images.appendChild(imageOverDivs);
}
}
This error took me to this S.O article. createTextNode here, however, will not help me as I am adding an element node, not text.
Will querySelectorAll not work in this instance?
You want querySelector(), not querySelectorAll(). Then you want Node.insertBefore(), and pass in the figure element as the second argument.
const imageAnimIn = () => {
const image = document.querySelector(".js-img-in")
const fig = document.querySelector(".js-img-in > figure")
for (var x = 0; x < 5; x++) {
var imageOverDivs = document.createElement('div');
imageOverDivs.className = "js-anim-img-in";
image.insertBefore(imageOverDivs, fig)
}
}
imageAnimIn()
.js-anim-img-in::after{
content: "New Div"
}
<div class="js-img-in">
<figure><img src="http://placekitten.com/100/100"></figure>
</div>
<!--<div class="js-img-in">
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<div class="js-anim-img-in"></div>
<figure><img src="test.jpg"></figure>
</div>-->
Did you mean to loop through images.length, and use the image position? Because the result of document.querySelectorAll is a NodeList, not just a single node.
const imageAnimIn = () => {
const images = document.querySelectorAll(".js-img-in");
for (var x = 0; x < images.length; x++) { // Loop through each result
for (var _ = 0; _ < 5; _++) { // Updated to disregard variable
var imageOverDivs = document.createElement('div');
imageOverDivs.className = "js-anim-img-in";
images[x].appendChild(imageOverDivs); // Added [x]
}
}
}
<head>
<title> Pascal’s Triangle </title>
</head>
<body>
<header>
<div id="strong"> Pascal’s Triangle </div>
</header>
<div class="container">
<div>
<span id="enter"> Please enter any number: </span><input id="number" /> <br id="screen"/>
<button id="button" onclick="createPascalTriangle()"> Check »</button>
</div> <br/>
</div>
<div id="show"> </div>
<footer>
<div> ©Technical Challenge </div>
<footer>
<script>
function createPascalTriangle () {
var pascalTriangle = [];
var numRows = document.getElementById("number").value;
for (var i = 0; i < numRows; i++) {
pascalTriangle[i] = new Array(i+1);
for (var j = 0; j < i+1; j++) {
if (j === 0 || j === i) {
pascalTriangle[i][j] = 1;
} else {
pascalTriangle[i][j] = pascalTriangle[i-1][j-1] + pascalTriangle[i-1][j];
}
}
}
return pascalTriangle;
pascal = JSON.Stringify(pascalTriangle);
document.getElementById("show").innerHTML = pascal;
}
</script>
</body>
Pascal Triangle array not displaying in expected 'div'
How do i display these array of Pascal Triangle in HTML?
Here is my code. The 'div 'is not displaying anything
i tried the innerHTML property. the pascalTriangle output is an Array. But i'm unable to display the output in html
The problem might be:
its JSON.stringify (capitalization)
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
You are doing actions after your function returns a value. The function stops being executed as soon as the return statement is reached. You should write at the end of the function:
pascal = JSON.stringify(pascalTriangle);
document.getElementById("show").innerHTML = pascal;
return pascalTriangle;
Let's say I have the following input field:
<input id="inputField" type="number" value="">
and some divs such as:
<div id="1000"></div>
<div id="1200"></div>
<div id="1500"></div>
<div id="1900"></div>
...
When the user enters a number in the input field, I want my code to go to the nearest div id to that number.
e.g: If user enters 1300 then show div with id = "1200".
What's the most efficient way to implement that in javascript considering there will be a large number of divs?
Right now I'm doing:
<script>
function myFunction()
{
var x = document.getElementById("inputField").value;
if(x >= 1750 && x <= 1900)
{
window.location.hash = '#1800';
}
}
</script>
One way is to wrap all your divs with number ids in another div if you can (and give it some id, say 'numbers'); this allows you to find all the divs in your javascript file.
Javascript:
// Get all the divs with numbers, if they are children of div, id="numbers"
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
// Append the integer of the id of every child to an array
array.push(parseInt(children[i].id));
}
// However you are getting your input number goes here
let number = 1300 // Replace
currentNumber = array[0]
for (const value of array){
if (Math.abs(number - value) < Math.abs(number - currentNumber)){
currentNumber = value;
}
}
// You say you want your code to go to the nearest div,
// I don't know what you mean by go to, but here is the div of the closest number
let target = document.getElementById(currentNumber.toString());
Let me know if there's more I can add to help.
Demo
function closestNum() {
let children = document.getElementById('numbers').children;
let array = [];
for (i = 0; i < children.length; i++) {
array.push(parseInt(children[i].id));
}
let number = document.getElementById('inputnum').value;
currentNumber = array[0]
for (const value of array) {
if (Math.abs(number - value) < Math.abs(number - currentNumber)) {
currentNumber = value;
}
}
let target = document.getElementById(currentNumber.toString());
document.getElementById('target').innerHTML = target.innerHTML;
}
<div id="numbers">
<div id="1000">1000</div>
<div id="2000">2000</div>
<div id="3000">3000</div>
<div id="4000">4000</div>
<div id="5000">5000</div>
</div>
<br />
<input type="text" id="inputnum" placeholder="Input Number" onchange="closestNum()" />
<br />
<br /> Target:
<div id="target"></div>
With some optimization this shall be ok-
var element;
document.addEventListener("change",
function(evt){
if(element && element.classList){
element.classList.remove("selected", false);
element.classList.add("unselected", true);
}
var listOfDivs =
document.querySelectorAll(".unselected");
var val = evt.target.value;
var leastAbs=listOfDivs[0].id;
for(let anIndex=0, len=listOfDivs.length;anIndex<len;anIndex++){
if(Math.abs(listOfDivs[anIndex].id-val)<leastAbs){
leastAbs = Math.abs(listOfDivs[anIndex].id-val);
element = listOfDivs[anIndex];
}
}
element.classList.remove("unselected");
element.classList.add("selected");
});
.selected{
background-color:red;
}
.unselected{
background-color:yellow;
}
.unselected, .selected{
width:100%;
height:50px;
}
<input id="inputField" type="number" value="">
<div id="1000" class='unselected'>1</div>
<div id="1200" class='unselected'>2</div>
<div id="1500" class='unselected'>3</div>
<div id="1900" class='unselected'>4</div>
This may work for you. Loops through each div and compared it to your inputted ID. Tracks closest one, hides all divs, then displays the closest.
document.getElementById("inputField").addEventListener("change", function(){
var divs = document.getElementsByTagName("div");
var closestDiv = -1;
var inputId = document.getElementById("inputField").value;
for(var i=0; i<divs.length; i++)
{
if(Math.abs(inputId - closestDiv) > Math.abs(inputId - divs[i].id) || closestDiv == -1)
{
closestDiv = divs[i].id;
for (var x = 0; x < divs.length; x++) {
divs[x].style.display = 'none';
}
divs[i].style.display = "block";
}
}
});
See it Live: jsfiddle.net