How to get array property values in a generated number input field - javascript

CODEPEN: https://codepen.io/3lly/pen/LYNzJwP
I have an array of objects:
let product = [
{omschrijving:"Brood", waarde:1, aantal:3, total:0},
{omschrijving:"Brocolli", waarde:0.99, aantal:2, total:0},
{omschrijving:"Krentenbollen", waarde:1.20, aantal:4, total:0},
{omschrijving:"Noten", waarde:2.99, aantal:2, total:0}
]
And I generate a table, I added an extra column with a number input field. I want the property of aantal set in the value of the number input field.
With these loops (I did the loop again because a scoping issue?) I get the last value only in ALL of the fields. So they all fill in 2.
var elements = table.getElementsByTagName('input');
for(let j=0;j<elements.length;j++) {
for(let i=0;i<product.length;i++) {
let = elements[j].value = product[i].aantal;
}
}
The expected output is in the first input field it would be 3, the next, 2,4,2
I will also put the snippet here so you can see the result.( I know it is a mess right now)
UPDATE , I did get it finally, it took me hours I dont even really completely understand. But I gave a rowID with the generation of the row and compare it to that. I tried so many things. I have a lot to do on this code. Now to make it increment etc. etc.
Now my problem is that I cannot increment and update the value of products.aantal This so it can calculate the total. If I can get that to work I can fix the rest.
It somehow does not see the products.value in the loop of EentjeMeer Function.
Because that loop worked before I wanted to do the same loop but now of course just increment the "aantal" column. My head hurts :/ been at it for many hours today.
I added this, but I will update my snippet:
var elements = table.getElementsByTagName('input');
schaap = [];
for(let j=0;j<elements.length;j++) {
inputID++;
//console.log("de input ID" + inputID);
//product.push({input: elements[j]});
//console.log(schaap);
for(let i=0;i<product.length;i++) {
if ( rowID != inputID) {
rowID++
//schaap.push({aantal: product[i].aantal});
console.log( "inputID " + inputID + " en de ROW ID " + rowID);
//console.log(schaap);
//index = product.findIndex(x => x.aantal[i] === elements[i]);
if (rowID = product[i].aantal) {
//index = product.findIndex(x => x.aantal === elements.input);
elements[i].value = product[i].aantal;
//console.log("index" + index);
}
}
}
}
Thats what I added. Here below this was the code of my original questions:
let myTable = document.querySelector('#table');
let rowID = 0;
let inputID = 0;
//Array met objecten erin {} staat voor een object
let product = [
{omschrijving:"Brood", waarde:1, aantal:3, total:0},
{omschrijving:"Brocolli", waarde:0.99, aantal:2, total:0},
{omschrijving:"Krentenbollen", waarde:1.20, aantal:4, total:0},
{omschrijving:"Noten", waarde:2.99, aantal:2, total:0}
]
///Update totals
for(let i=0;i<product.length;i++)
{
product[i].total = product[i].waarde*product[i].aantal;
}
const total = product.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0)
uitslag = total.toFixed(2);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + uitslag;
////Table
let headers = ['Name', 'Prijs', 'Aantal', 'Totaal', 'Aanpassen'];
let table = document.createElement('table');
let headerRow = document.createElement('tr');
headers.forEach(headerText => {
let header = document.createElement('th');
let textNode = document.createTextNode(headerText);
header.appendChild(textNode);
headerRow.appendChild(header);
});
table.appendChild(headerRow);
///////////td is column
product.forEach(emp => {
let row = document.createElement('tr');
Object.values(emp).forEach(text => {
//console.log("row" + rowID);
let cell = document.createElement('td');
let textNode = document.createTextNode(text);
cell.appendChild(textNode);
row.appendChild(cell);
})
input = document.createElement('input');
cell = document.createElement('td');
input.type = 'number';
//input.value
input.addEventListener('click', eentjeMeer() );
cell.appendChild(input);
row.appendChild(cell);
/*
let input = document.createElement('input');
input.type = "step";
table.appendChild(input);
*/
table.appendChild(row);
});
myTable.appendChild(table);
/////////////////////
/////////////////INPUTS AANPASSEN MET WAARDE VAN ARRAY////////////////////////////
var elements = table.getElementsByTagName('input'); //misschien mot ik het in een array droppen
for(let j=0;j<elements.length;j++) {
inputID++;
//console.log("de input ID" + inputID);
//product.push({input: elements[j]});
//console.log(schaap);
for(let i=0;i<product.length;i++) {
if ( rowID != inputID) {
rowID++
//schaap.push({aantal: product[i].aantal});
console.log( "inputID " + inputID + " en de ROW ID " + rowID);
//console.log(schaap);
//index = product.findIndex(x => x.aantal[i] === elements[i]);
if (rowID = product[i].aantal) { //hier GAAT IETS GOED ALS laatst op 22:22 HIJ DOET DE LAATSTE NIET WHY???
//index = product.findIndex(x => x.aantal === elements.input);
elements[i].value = product[i].aantal;
//console.log("index" + index);
}
}
}
}
//product[i].total = product[i].waarde*product[i].aantal;
///////////////////////////////////////////////////
for(let j=0;j<product.length;j++) {
//let row = document.createElement('tr');
}
function updateTable() {
test = [];
b1 = document.getElementById('naam').value;
b2 = document.getElementById('prijs').value;
b3 = document.getElementById('qty').value;
test.push({omschrijving:b1, waarde:b2, aantal:b3, total:0});
for(let i=0;i<test.length;i++)
{
test[i].total = test[i].waarde*test[i].aantal;
}
test.forEach(emp => {
let row = document.createElement('tr');
Object.values(emp).forEach(text => {
let cell = document.createElement('td');
let textNode = document.createTextNode(text);
cell.appendChild(textNode);
row.appendChild(cell);
})
table.appendChild(row);
});
myTable.appendChild(table);
//console.log(product);
/////////////////////////totaal na update WORDT AFGEROND DOOR PARSEINT?!?!?!
const total0 = test.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0)
console.log("total0 = " + total0);
yo = total0.toFixed(2);
yo1 = Number.parseInt(yo) + Number.parseInt(uitslag);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + yo1;
console.log(yo);
}
function eentjeMeer(){
var elements = table.getElementsByTagName('input'); //misschien mot ik het in een array droppen
for(let j=0;j<elements.length;j++) {
inputID++;
//console.log("de input ID" + inputID);
//product.push({input: elements[j]});
//console.log(schaap);
for(let i=0;i<product.length;i++) {
if ( rowID != inputID) {
rowID++
//schaap.push({aantal: product[i].aantal});
//console.log(schaap);
//index = product.findIndex(x => x.aantal[i] === elements[i]);
if (rowID = product[i].aantal) {
console.log(product[i].aantal); //het doet het wel nu....iets met inputID denk ik
objIndex = product.findIndex((obj => obj.aantal == rowID));
//product[i].aantal.name = elements[i].value;
testje = product[i].aantal;
//elements[i].value = inputID;
//inputID = product[i].aantal;
//product[i].aantal = elements[i].value;
//console.log(elements[i].value);
//console.log(product);
//console.log("index" + index);
}
}
}
}
};
body {
text-align: center;
}
div {
display: inline-block;
}
button {
display: inline-block;
padding: 10px 20px;
}
#table {
display: block;
margin-top: 20px;
}
th, td {
border: 1px solid black;
padding: 5px;
}
#totaal {
border: 2px solid black;
background-color: skyblue;
padding: 5px;
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style.css">
<title>Boodschappenlijst</title>
</head>
<body>
<h1> Boodschappenlijst </h1>
<div id="container"></div>
<div>
<div id="table"></div>
</div>
<p>Naam</p>
<input type="text" name="item" id="naam" /><br />
<p>Aantal</p>
<input type="text" name="quantity" id="qty" /><br />
<p>Prijs</p>
<input type="text" name="price" id="prijs" /><br/><br />
<input type="button" value="Add Product" onclick="updateTable()" id="add"><br /><br />
<div id="totaal"></div>
<script src="script.js"></script>
</body>
</html>

Related

Display slider when you hover over array elements and give value to the array elements

I have done the part where you have to generate the array elements when you enter them from textbox, what I struggle with now is to display a slider on hover over each array element and give the array element a value, also what I struggle with is to delete each generated array element individually, my delete function deletes the entire array on click not just the single element I click.
Here is how it should look like:
enter image description here
Here is my code so far:
let names = [];
let nameInput = document.getElementById("name");
let messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
clearAndShow();
}
function remove()
{
var element = document.getElementById("display");
element.parentNode.removeChild(element);
}
function clearAndShow () {
let printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.style.borderStyle = "solid"
_span.style.borderColor = "blue"
_span.style.width = '50px'
_span.style.marginLeft = "5px"
_span.appendChild(document.createTextNode(element))
messageBox.appendChild(_span)
printd +="''" + element + "''" + "," + " ";
document.getElementById("labelprint").innerHTML=(printd)
}
})
}
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
<div class="container">
<form>
<h1>Enter Search</h1>
<input id="name" type="text" />
<input type="button" value="Search" onclick="insert()" />
</form>
<br/>
<div onclick="remove(this)" id="display"></div>
<br/>
<label >You have Selected: </label>
<h3 id="labelprint"></h3>
</div>
I am not being rude I just got confused on how you stated your message but what I think you are saying is to do this:
var names = [];
var nameInput = document.getElementById("name");
var messageBox = document.getElementById("display");
function insert ( ) {
names.push( nameInput.value );
// add value to array val: names[names.length - 1] = PutValueHere
clearAndShow();
}
function remove(this){
document.getElementById("display").parentNode.firstChild.remove(); // If you want it to remove the last child with the id 'display' then do .parentNode.lastChild.remove()
//if you are trying to remove the last val in the array do this: names.splice(names.length-1,1) for the first do this names.splice(0,1)
}
function clearAndShow () {
var printd=""
nameInput.value = "";
messageBox.innerHTML = "";
names.forEach(function(element){
if(element != ''){
var _span = document.createElement('span');
_span.id = '_spanId'
$('_spanId').css('border-style',solid');
$('_spanId').css('border-color',blue');
$('_spanId').css('width',50+'px');
$('_spanId').css('margin-left',5+'px');
_span[0].appendChild(document.createTextNode(element))
messageBox[0].appendChild(_span)
printd += "''" + element + "'', ";
document.getElementById("labelprint").innerHTML = printd
}
})
}
I have tried to implement something that i hope it's close to what are you looking for:
HTML:
<div class="container">
<form>
<h1>Add new slider</h1>
<input id="sliderName" type="text" />
<input type="button" value="Add" onclick="insertSlider()" />
</form>
<div id="display"></div>
</div>
CSS:
h3 {
color: rgb(0, 174, 255);
}
.container {
border: solid 2px;
display: block;
margin-left: 200px;
margin-right: 200px;
margin-top: 50px;
}
JS:
let messageBox = document.getElementById("display");
function deleteFn(id) {
const element = document.getElementById(id)
if(element) element.outerHTML="";
}
function onChangeSlideId(id){
const elementSlide = document.getElementById('slider-'+id+'')
if(elementSlide){
const value = elementSlide.value
const elementSlideText = document.getElementById('slider-value-'+id+'')
elementSlideText.innerText = '('+value+')'
}
}
function insertSlider(){
const name = document.getElementById("sliderName")
const nameValue = name.value
const newLabel = document.createElement('label')
newLabel.setAttribute('for',nameValue)
newLabel.innerText = nameValue
const newSlider = document.createElement('input')
newSlider.setAttribute('id','slider-'+nameValue+'')
newSlider.setAttribute('type','range')
newSlider.setAttribute('name',nameValue)
newSlider.setAttribute('onchange','onChangeSlideId("'+nameValue+'")')
const sliderValue = document.createElement('span')
sliderValue.setAttribute('id','slider-value-'+nameValue+'')
sliderValue.innerText = '('+newSlider.value+')'
const newContainer = document.createElement('div')
newContainer.setAttribute('id',nameValue)
newContainer.setAttribute('style','display: grid')
newContainer.appendChild(newSlider)
newContainer.appendChild(newLabel)
newContainer.appendChild(sliderValue)
const newDeleteButton = document.createElement('input')
newDeleteButton.setAttribute('type', 'button')
newDeleteButton.setAttribute('value', 'Delete ' + nameValue + '')
newDeleteButton.setAttribute('onclick', 'deleteFn("'+nameValue+'")')
newContainer.appendChild(newDeleteButton)
messageBox.appendChild(newContainer)
}
You can try it by yourself in this codepen

Generated row of table event listener not working instantly

I have a table like this :
I have added an event listener assetTableEvent() to each text box in the table. My issue is when I add new row to the table, i also add the corresponding event listener to it assetTableEvent(), but the total value does not pop while entering value, it shows only when next row has values entered.
function assetTableEvent() {
let total = 0;
for (var k = 0; k < document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
I even tried calling assetTableEvent() every time there is a change, but it just does not work. Can somebody help me in Javascript how to make dynamically added rows correspond to event listener like above rows.
HTML for Asset table:
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>
And add row event listener :
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
Trying to use incremental IDs is more work than it is worth, especially when you start removing rows.
I suggest you use classes instead and delegate the event listener to the table itself. When an input event occurs you get the closest row and query for the elements within that row for the row total, then query all of the rows totals for the master total
Basic example with functional add row
const table = document.querySelector('#myTable'),
cloneRow = table.rows[0].cloneNode(true);
table.addEventListener('input',(e) => {
if (e.target.matches('.qty, .price')) {
const row = e.target.closest('tr'),
price = row.querySelector('.price').valueAsNumber || 0,
qty = row.querySelector('.qty').valueAsNumber || 0;
row.querySelector('.amt').value = qty * price;
setTotalAmt()
}
});
document.querySelector('#add-row').addEventListener('click', (e) => {
table.appendChild(cloneRow.cloneNode(true))
});
function setTotalAmt() {
const sum = [...table.querySelectorAll('.amt')].reduce((a, el) => a + (+el.value || 0), 0)
document.querySelector('#total').value = sum;
}
<button id="add-row">
Add Row
</button>
Total:<input id="total" />
<table id="myTable">
<tr>
<td>Qty:
<input type="number" class="qty" value="0" />
</td>
<td>Price:
<input type="number" class="price" value="0" />
</td>
<td>Amt:
<input class="amt" readonly value="0" />
</td>
</tr>
</table>
#charlietfl 's solition is more elegant but if you wonder what is the problem in your code, you should change the < to <= in k < document.getElementById("assetTable").rows.length; part
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
Here is the working example:
document.getElementById("addRow").addEventListener("click", function () {
var table = document.getElementById("assetTable");
var row = table.insertRow();
for (let j = 0; j < 4; j++) {
var tb = document.createElement("INPUT");
var value = "", idNum = "";
if (j == 0) {
tb.setAttribute("type", "text");
tb.value = value;
}
else {
tb.setAttribute("type", "number");
}
//Setting textbox id
switch (j) {
case 0:
idNum = "a";
break;
case 1:
idNum = "v";
break;
case 2:
idNum = "o";
break;
case 3:
idNum = "t";
break;
}
tb.id = idNum + (table.rows.length);
if (tb.id.includes('t')) {
tb.setAttribute("readOnly", "true");
}
tb.classList.add("assetTBox");
let cell = row.insertCell(j);
tb.addEventListener("input", assetTableEvent, false);
cell.appendChild(tb);
}
});
function assetTableEvent() {
let total = 0;
for (var k = 0; k <= document.getElementById("assetTable").rows.length; k++) {
var a = document.getElementById("v" + k);
var o = document.getElementById("o" + k);
var t = document.getElementById("t" + k);
if (a == null || o == null) {
continue;
}
if (a.value.length > 0 && o.value.length > 0) {
t.value = Number.parseInt(a.value - o.value);
total = (Number.parseInt(t.value) + Number.parseInt(total));
document.getElementById("totalAssets").value = Number.parseInt(total);
}
}
}
<div id="calcContainer">
<div id = "headingText" >
Child Maintenance Calculator
</div>
<div id="startPage">
<button id="startBtn">Start</button>
</div>
<div id="asset">
<table id="assetTable">
<tr>
<th>Asset</th>
<th>Value</th>
<th>Own</th>
<th>Total</th>
</tr>
</table>
<div id="totalAssetsDiv">
<Label for ="totalAssets">Total Assets</Label>
<input type="number" id = "totalAssets" readonly="true">
<br>
</div>
<div id ="rowOps">
<br> <button id="addRow" class = "addDel">Add Row</button>
<button id="removeRow" class = "addDel1">Delete Row</button><br>
</div>
</div>

I cannot update the totals in my dynamic Table (it shows undefined for the new added input)

When I add a new item to my grocery list, and then if I change the number value in the table of the new item. It will give NaN (Not a number) After going with some console.logs trough my code I find out that if I log in eentjeMeer function (which is the function called when I click the number value)
that products[i].waarde they are all defined except the new added item, it is undefined.
but inputs[i].value they are also all defined plus the new added item. So the calculation cannot be made. And then it will result in the total column to NaN as you can see.
Why does it get undefined ? Why does it not see it ? Why does it get NaN ?
For clarification aantal=Quantity and prijs=Value, I want it to calculate the total. Which it does correctly when I add a new item. But not when I want to change the value of the new item in the table.
(It works for the original items in the array)
Code Snippet here:
const myTable = document.getElementById('table')
let products = [
{ omschrijving: "Brood" , waarde: 1 , aantal:3 , total: 0},
{ omschrijving: "Brocolli" , waarde: 0.99 , aantal: 2 , total: 0},
{ omschrijving: "Krentenbollen" , waarde: 1.20 , aantal: 4 , total: 0},
{ omschrijving: "Noten" , waarde: 2.99 , aantal: 2 , total: 0}
]
///Update totals in tabel
TabelTotals();
function TabelTotals() {
for (let i = 0; i < products.length; i++) {
products[i].total = products[i].waarde * products[i].aantal;
}
}
Alles();
function Alles(){
//Totaal alle producten
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
}
////Table /////Headers
const headerTexts = ['Name', 'Prijs', 'Aantal', 'Totaal'];
const t = document.createElement('table');
t.appendChild(document.createElement('thead'));
t.querySelector('thead').appendChild(document.createElement('tr'));
for (var i = 0; i < headerTexts.length; i++) {
const heading = document.createElement('td');
heading.textContent = headerTexts[i];
t.querySelector('thead tr').appendChild(heading);
}
document.getElementById('table').appendChild(t);
//Rows
for (var i = 0; i < products.length; i++) {
var s = products[i];
var r = document.createElement('tr');
r.dataset.productID = s.id; //ff beter kijken wat dit is, dit is wel cool.
r.id = s.omschrijving + "--row";
var omschrijvingCell = document.createElement('td');
omschrijvingCell.textContent = s.omschrijving;
omschrijvingCell.classList.add('omschrijving');
omschrijvingCell.dataset.productID = s.id;
var prijsCell = document.createElement('td');
prijsCell.textContent = s.waarde;
prijsCell.classList.add('prijs')
prijsCell.dataset.productID = s.id;
var aantalCell = document.createElement('input');
aantalCell.type = "number"
aantalCell.defaultValue = s.aantal;
aantalCell.addEventListener("change", eentjeMeer);
aantalCell.classList.add('aantal')
aantalCell.dataset.productID = s.id;
var totaalCell = document.createElement('td');
totaalCell.textContent = s.total;
totaalCell.classList.add('total')
totaalCell.dataset.productID = s.id;
r.appendChild(omschrijvingCell);
r.appendChild(prijsCell);
r.appendChild(aantalCell);
r.appendChild(totaalCell);
t.appendChild(r);
}
/////Functions//////
function getNewInput() {
const naamValue = document.getElementById('naam').value;
const waardeValue = parseFloat(document.getElementById('prijs').value);
const qtyValue = parseFloat(document.getElementById('qty').value);
return [{ omschrijving: naamValue , waarde: waardeValue , aantal: qtyValue , total: waardeValue * qtyValue }]
}
function eentjeMeer() {
const inputs = document.getElementsByClassName('aantal');
uitKomst = myTable.getElementsByClassName("total");
for (let i = 0; i < products.length; i++) {
uitKomst[i].innerHTML = inputs[i].value * products[i].waarde;
console.log(products[i].waarde);
}
//Totaal alle producten
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
}
function updateTable() {
const newInput = getNewInput();
products.push(newInput);
for (var i = 0; i < newInput.length; i++) {
var s = newInput[i];
var r = document.createElement('tr');
r.dataset.productID = s.id; //ff beter kijken wat dit is, dit is wel cool.
r.id = s.omschrijving + "--row"; //ff checken hoe dat gaat --row geef dus IDS mee
var omschrijvingCell = document.createElement('td');
omschrijvingCell.textContent = s.omschrijving;
omschrijvingCell.classList.add('omschrijving');
omschrijvingCell.dataset.productID = s.id;
var prijsCell = document.createElement('td');
//prijsCell.type = "number"
prijsCell.textContent = s.waarde;
prijsCell.classList.add('prijs');
prijsCell.dataset.productID = s.id;
var aantalCell = document.createElement('input');
aantalCell.type = "number"
aantalCell.defaultValue = s.aantal;
aantalCell.addEventListener("change", eentjeMeer);
aantalCell.classList.add('aantal');
aantalCell.dataset.productID = s.id;
var totaalCell = document.createElement('td');
totaalCell.textContent = s.total;
totaalCell.classList.add('total');
totaalCell.dataset.productID = s.id;
r.appendChild(omschrijvingCell);
r.appendChild(prijsCell);
r.appendChild(aantalCell);
r.appendChild(totaalCell);
t.appendChild(r);
console.log(products[4]); // het word geen string zie ik hier.
}
};
function CalculateTot() {
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
// allTotal.splice(0,1, total.toFixed(2));
// document.getElementById('totaal').innerHTML = "Totaal bedrag " + allTotal;
}
//Vraag , in for loops altijd var ?
body {
text-align: center;
}
div {
display: inline-block;
}
button {
display: inline-block;
padding: 10px 20px;
}
#table {
display: block;
margin-top: 20px;
}
th, td , input {
border: 1px solid black;
padding: 5px;
}
#totaal {
border: 2px solid black;
background-color: skyblue;
padding: 5px;
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style.css">
<title>Boodschappenlijst</title>
</head>
<body>
<h1> Boodschappenlijst </h1>
<div id="container"></div>
<div>
<div id="table"></div>
</div>
<p>Naam</p>
<input type="text" name="item" id="naam" /><br />
<p>Aantal</p>
<input type="text" name="quantity" id="qty" /><br />
<p>Prijs</p>
<input type="text" name="price" id="prijs" /><br/><br />
<input type="button" value="Add Product" onclick="updateTable()" id="add"><br /><br />
<div id="totaal"></div>
<script src="script.js"></script>
</body>
</html>
The problem is in your getNewInput() function. You return an array, while you should return an object. Change this:
return [{ omschrijving: naamValue , waarde: waardeValue , aantal: qtyValue , total: waardeValue * qtyValue }]
to this:
return { omschrijving: naamValue , waarde: waardeValue , aantal: qtyValue , total: waardeValue * qtyValue }
And accordingly, modify the updateTable() function by removing the for-loop.
And everything will work fine:
const myTable = document.getElementById('table')
let products = [
{ omschrijving: "Brood" , waarde: 1 , aantal:3 , total: 0},
{ omschrijving: "Brocolli" , waarde: 0.99 , aantal: 2 , total: 0},
{ omschrijving: "Krentenbollen" , waarde: 1.20 , aantal: 4 , total: 0},
{ omschrijving: "Noten" , waarde: 2.99 , aantal: 2 , total: 0}
]
///Update totals in tabel
TabelTotals();
function TabelTotals() {
for (let i = 0; i < products.length; i++) {
products[i].total = products[i].waarde * products[i].aantal;
}
}
Alles();
function Alles(){
//Totaal alle producten
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
}
////Table /////Headers
const headerTexts = ['Name', 'Prijs', 'Aantal', 'Totaal'];
const t = document.createElement('table');
t.appendChild(document.createElement('thead'));
t.querySelector('thead').appendChild(document.createElement('tr'));
for (var i = 0; i < headerTexts.length; i++) {
const heading = document.createElement('td');
heading.textContent = headerTexts[i];
t.querySelector('thead tr').appendChild(heading);
}
document.getElementById('table').appendChild(t);
//Rows
for (var i = 0; i < products.length; i++) {
var s = products[i];
var r = document.createElement('tr');
r.dataset.productID = s.id; //ff beter kijken wat dit is, dit is wel cool.
r.id = s.omschrijving + "--row";
var omschrijvingCell = document.createElement('td');
omschrijvingCell.textContent = s.omschrijving;
omschrijvingCell.classList.add('omschrijving');
omschrijvingCell.dataset.productID = s.id;
var prijsCell = document.createElement('td');
prijsCell.textContent = s.waarde;
prijsCell.classList.add('prijs')
prijsCell.dataset.productID = s.id;
var aantalCell = document.createElement('input');
aantalCell.type = "number"
aantalCell.defaultValue = s.aantal;
aantalCell.addEventListener("change", eentjeMeer);
aantalCell.classList.add('aantal')
aantalCell.dataset.productID = s.id;
var totaalCell = document.createElement('td');
totaalCell.textContent = s.total;
totaalCell.classList.add('total')
totaalCell.dataset.productID = s.id;
r.appendChild(omschrijvingCell);
r.appendChild(prijsCell);
r.appendChild(aantalCell);
r.appendChild(totaalCell);
t.appendChild(r);
}
/////Functions//////
function getNewInput() {
const naamValue = document.getElementById('naam').value;
const waardeValue = parseFloat(document.getElementById('prijs').value);
const qtyValue = parseFloat(document.getElementById('qty').value);
return { omschrijving: naamValue , waarde: waardeValue , aantal: qtyValue , total: waardeValue * qtyValue }
}
function eentjeMeer() {
const inputs = document.getElementsByClassName('aantal');
uitKomst = myTable.getElementsByClassName("total");
for (let i = 0; i < products.length; i++) {
uitKomst[i].innerHTML = inputs[i].value * products[i].waarde;
console.log(products[i].waarde);
}
//Totaal alle producten
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
}
function updateTable() {
const newInput = getNewInput();
products.push(newInput);
var s = newInput;
var r = document.createElement('tr');
r.dataset.productID = s.id; //ff beter kijken wat dit is, dit is wel cool.
r.id = s.omschrijving + "--row"; //ff checken hoe dat gaat --row geef dus IDS mee
var omschrijvingCell = document.createElement('td');
omschrijvingCell.textContent = s.omschrijving;
omschrijvingCell.classList.add('omschrijving');
omschrijvingCell.dataset.productID = s.id;
var prijsCell = document.createElement('td');
//prijsCell.type = "number"
prijsCell.textContent = s.waarde;
prijsCell.classList.add('prijs');
prijsCell.dataset.productID = s.id;
var aantalCell = document.createElement('input');
aantalCell.type = "number"
aantalCell.defaultValue = s.aantal;
aantalCell.addEventListener("change", eentjeMeer);
aantalCell.classList.add('aantal');
aantalCell.dataset.productID = s.id;
var totaalCell = document.createElement('td');
totaalCell.textContent = s.total;
totaalCell.classList.add('total');
totaalCell.dataset.productID = s.id;
r.appendChild(omschrijvingCell);
r.appendChild(prijsCell);
r.appendChild(aantalCell);
r.appendChild(totaalCell);
t.appendChild(r);
console.log(products[4]); // het word geen string zie ik hier.
};
function CalculateTot() {
const total = products.reduce((currentTotal, productCal) => {
return productCal.total + currentTotal
}, 0);
document.getElementById('totaal').innerHTML = "Totaal bedrag " + total.toFixed(2);
// allTotal.splice(0,1, total.toFixed(2));
// document.getElementById('totaal').innerHTML = "Totaal bedrag " + allTotal;
}
//Vraag , in for loops altijd var ?
body {
text-align: center;
}
div {
display: inline-block;
}
button {
display: inline-block;
padding: 10px 20px;
}
#table {
display: block;
margin-top: 20px;
}
th, td , input {
border: 1px solid black;
padding: 5px;
}
#totaal {
border: 2px solid black;
background-color: skyblue;
padding: 5px;
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style.css">
<title>Boodschappenlijst</title>
</head>
<body>
<h1> Boodschappenlijst </h1>
<div id="container"></div>
<div>
<div id="table"></div>
</div>
<p>Naam</p>
<input type="text" name="item" id="naam" /><br />
<p>Aantal</p>
<input type="text" name="quantity" id="qty" /><br />
<p>Prijs</p>
<input type="text" name="price" id="prijs" /><br/><br />
<input type="button" value="Add Product" onclick="updateTable()" id="add"><br /><br />
<div id="totaal"></div>
<script src="script.js"></script>
</body>
</html>

HTML Table search on each column Individually using JavaScript

I have a table with 5 columns. the following code will filter the data on basis of all columns. I want to filter the data for each column. for ex: if there are 10 columns then 10 search fields and Also how can I make HTML part Dynamic so that I don't have to add one more search text field whenever a new column is added.
<input id="myInput" type="text" />
<script>
function filterTable(event) {
var filter = event.target.value.toUpperCase();
var rows = document.querySelector("#myTable tbody").rows;
for (var i = 1; i < rows.length; i++) {
var Col1 = rows[i].cells[0].textContent.toUpperCase();
var Col2 = rows[i].cells[1].textContent.toUpperCase();
var Col3 = rows[i].cells[2].textContent.toUpperCase();
var Col4 = rows[i].cells[3].textContent.toUpperCase();
var Col5 = rows[i].cells[4].textContent.toUpperCase();
if (Col1.indexOf(filter) > -1 || Col2.indexOf(filter) > -1 || Col3.indexOf(filter) > -1
|| Col4.indexOf(filter) > -1 || Col5.indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
document.querySelector(''#myInput'').addEventListener(''keyup'', filterTable, false);
</script>
I want to have this kind of functionality:
You can loop over the rows and then the columns. The Array.from method allows you to cast an element list to an array so that you can iterate over the children with Array.prototype.forEach.
All you need to do is have a show initialized to true for each row. Then if any DOES NOT column meets the filter criteria, you set show to false. After looping through all columns you display the row based on the final value of show.
Edit: Make sure you are using a browser that supports ES6+. There is a polyfill available for Array.from on the MDN site.
function filterTable(event) {
let filter = event.target.value.trim().toLowerCase();
let rows = document.querySelector('#myTable tbody').rows;
for (let i = 0; i < rows.length; i++) {
let row = rows[i], show = false;
if (filter.length > 0) {
for (let j = 0; j < row.children.length; j++) {
let col = row.children[j], text = col.textContent.toLowerCase();
if (text.indexOf(filter) > -1) {
show = true;
continue;
}
}
} else {
show = true;
}
// Avoid using 'row.styledisplay' - https://stackoverflow.com/a/28028656/1762224
// Avoid using 'row.visibility' - rows do not collapse
toggleClass(row, 'hidden-row', !show);
}
}
function toggleClass(el, className, state) {
if (el.classList) el.classList.toggle(className, state);
else {
var classes = el.className.split(' ');
var existingIndex = classes.indexOf(className);
if (state === undefined) {
if (existingIndex > -1) classes.splice(existingIndex, 1)
else classes.push(existingIndex);
} else {
if (!state) classes.splice(existingIndex, 1)
else classes.push(existingIndex);
}
el.className = classes.join(' ');
}
}
document.querySelector('#myInput').addEventListener('keyup', filterTable, false);
body {
padding: 8px;
}
.field label {
font-weight: bold;
margin-right: 0.25em;
}
#myTable {
margin-top: 0.667em;
width: 100%;
}
#myTable th {
text-transform: capitalize;
}
.hidden-row {
display: none;
}
<link href="https://unpkg.com/purecss#1.0.0/build/pure-min.css" rel="stylesheet" />
<div class="field"><label for="myInput">Filter:</label><input id="myInput" type="text" /></div>
<table id="myTable" class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>name</th>
<th>drink</th>
<th>pizza</th>
<th>movie</th>
</tr>
</thead>
<tbody>
<tr>
<td>Homer</td>
<td>Squishie</td>
<td>Magheritta</td>
<td>The Avengers</td>
</tr>
<tr>
<td>Marge</td>
<td>Squishie</td>
<td>Magheritta</td>
<td>The Avengers</td>
</tr>
<tr>
<td>Bart</td>
<td>Squishie</td>
<td>Pepperoni</td>
<td>Black Dynamite</td>
</tr>
<tr>
<td>Lisa</td>
<td>Buzz Cola</td>
<td>Pepperoni</td>
<td>Iron Man</td>
</tr>
<tr>
<td>Maggie</td>
<td>Duff Beer</td>
<td>Magheritta</td>
<td>The Avengers</td>
</tr>
<tr>
<td>Kent</td>
<td>Duff Beer</td>
<td>Hawaiian</td>
<td>The Avengers</td>
</tr>
</tbody>
</table>
Search fields example
populateTable(document.getElementById('simpsons'), getData());
function dataFields(data) {
return data.reduce((r, x) => Object.keys(x).reduce((s, k) => s.indexOf(k) === -1 ? s.concat(k) : s, r), []);
}
/* Can be useful if working with raw JSON data */
function searchCriteria(fields) {
return Array.from(fields).reduce((o, field) => {
return Object.assign(o, { [field.getAttribute('placeholder')] : field.value });
}, {});
}
function onFilter(e) {
let table = e.target.parentElement.parentElement.parentElement.parentElement;
let fields = table.querySelectorAll('thead tr th input');
let criteria = searchCriteria(fields); // Unused, but useful if filtering bindable data
let searchText = Array.from(fields).map(field => field.value.trim());
Array.from(table.querySelectorAll('tbody tr')).forEach(row => {
let hideRow = false;
Array.from(row.children).forEach((col, index) => {
var value = col.innerHTML.trim().toLowerCase();
var search = searchText[index].toLowerCase();
if (search.length > 0) {
if (!value.startsWith(search)) { /* or value.indexOf(search) === -1 */
hideRow = true;
return;
}
}
});
row.classList.toggle('hidden-row', hideRow);
});
}
function populateTable(table, data) {
let fields = dataFields(data);
let thead = document.createElement('THEAD');
let tr = document.createElement('TR');
fields.forEach(field => {
let th = document.createElement('TH');
th.innerHTML = field;
tr.appendChild(th);
});
thead.appendChild(tr);
let tbody = document.createElement('TBODY');
tr = document.createElement('TR');
fields.forEach(field => {
let th = document.createElement('TH');
let input = document.createElement('INPUT');
input.setAttribute('placeholder', field);
input.addEventListener('keyup', onFilter);
th.append(input);
tr.appendChild(th);
});
thead.appendChild(tr);
data.forEach(record => {
let tr = document.createElement('TR');
fields.forEach(field => {
let td = document.createElement('TD');
td.innerHTML = record[field];
tr.appendChild(td);
});
tbody.append(tr);
});
table.appendChild(thead);
table.appendChild(tbody);
}
function getData() {
return [{
"name": "Homer",
"drink": "Squishie",
"pizza": "Magheritta",
"movie": "The Avengers"
}, {
"name": "Marge",
"drink": "Squishie",
"pizza": "Magheritta",
"movie": "The Avengers"
}, {
"name": "Bart",
"drink": "Squishie",
"pizza": "Pepperoni",
"movie": "Black Dynamite"
}, {
"name": "Lisa",
"drink": "Buzz Cola",
"pizza": "Pepperoni",
"movie": "Iron Man"
}, {
"name": "Maggie",
"drink": "Duff Beer",
"pizza": "Magheritta",
"movie": "The Avengers"
}, {
"name": "Kent",
"drink": "Duff Beer",
"pizza": "Hawaiian",
"movie": "The Avengers"
}];
}
table {
border-collapse: collapse;
width: 100%;
}
table thead tr th {
text-transform: capitalize;
}
table thead tr:last-child {
background: #eaeaea;
border-bottom: 4px double #cbcbcb;
}
table thead tr th input {
width: 100%;
}
table tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
table tbody tr.hidden-row {
display: none;
}
<link href="https://unpkg.com/purecss#1.0.0/build/pure-min.css" rel="stylesheet" />
<table id="simpsons" class="pure-table pure-table-horizontal"></table>
Browser Compatibility
function onFilter(e) {
var table = e.target.parentElement.parentElement.parentElement.parentElement;
console.log(table);
var fields = table.querySelectorAll('thead tr th input');
console.log(fields);
var searchText = Array.from(fields).map(function (field) {
return field.value.trim();
});
console.log(searchText);
Array.from(table.querySelectorAll('tbody tr')).forEach(function (row) {
var hideRow = false;
Array.from(row.children).forEach(function (col, index) {
var value = col.innerHTML.trim().toLowerCase();
console.log(value);
var search = searchText[index].toLowerCase();
console.log(search);
if (search.length > 0) {
if (value.indexOf(search) === -1) {
hideRow = true;
return;
}
}
});
row.classList.toggle('hidden-row', hideRow);
});
}
All you have to do is iterate the .cells array with a for loop:
For this example, I used a variable to determine if the row should be shown.
function filterTable(event) {
var filter = event.target.value.toUpperCase();
var rows = document.querySelector("#myTable tbody").rows;
for (var i = 1; i < rows.length; i++) {
// Placeholder to indicate if a row matches the given query.
var shouldShowRow = false;
// Loop over all the cells in this row.
for (var k = 0; k < rows[i].cells.length) {
// Check to see if this cell in this row matches the query.
if (rows[i].cells[k].textContent.toUpperCase().indexOf(filter) > -1) {
// Yes, this cell matches, therefore this entire row matches.
// Flip the show row boolean to indicate that we need to show.
shouldShowRow = true;
// Because this cell matches, we do not need to check any more cells.
break;
}
}
// Change the display on the row if we need to.
if (shouldShowRow) {
rows[i].style.display = "";
} else rows[i].style.display = "none";
}
}
You can use array.
First map col to an array colArr and than using some you can match you can match filter content with content of cols .
for (var i = 1; i < rows.length; i++) {
let colArr = new Array(5).fill(0).map((e,index)=> rows[i].cells[index].textContent.toUpperCase();)
if (colArr.some(e=> e.indexOf(filter) > -1 ) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
})
}

jQuery, count child and display result on hover

I realise an alphabetic search of products. At the click on letter, all products begining by the letter is displaying.
But i would diplay it at the top of the letter and hide before.
Did i have to used functions hover() and append() ans how ?
that's my code :
_alphabets.hover(function(){
var _letter = $x(this), _text = $x(this).text(), _count = 0;
_contentRows.removeClass("lignetrouve");
_contentRows.each(function(i) {
var _cellText = $x(this).children('td').eq(0).text();
if ( RegExp('^' + _text).test(_cellText) ) {
_count += 1;
list = $x(this).addClass("lignetrouve");
}
}); /*end _contentRows.each(function(i) */
//we count number of child
_nblignes = $x('.lignetrouve').length;
//display
$x('.compteur').append(_nblignes);
})
Thanks.
I found :
_alphabets = $x('.alphabet > a');
_contentRows = $x('#produits-table tbody tr');
_alphabets.click(function() {
var _letter = $x(this), _text = $x(this).text(), _count = 0;
//Ajout de la class active a la lettre plutot qu'a l'alphabet entier
_alphabets.removeClass("active");
_letter.addClass("active");
_contentRows.removeClass("lignetrouve");
if (($x('#noproduct').length == 0) && ($x('.lignetrouve').length == 0)) {
$x('tbody').append('<tr id="noproduct"><td>Aucun produit</td></tr>');
};
_contentRows.hide();
_contentRows.each(function(i) {
//Affectation de la variable celltext qui contient le contenu
var _cellText = $x(this).children('td').eq(0).text();
//Si le debut commence comme la lettre selectionnée
if ( RegExp('^' + _text).test(_cellText) ) {
_count += 1;
list = $x(this).fadeIn(400);
list.addClass("lignetrouve");
$x('#noproduct').remove();
}
_nblignes = $x('.lignetrouve').length;
$x(this).attr('data-title',_nblignes);
}); /*end _contentRows.each(function(i) */
}); /*end _alphabets.click(function() */
_alphabets.hover(function(){
_contentRows.removeClass("lignetrouve");
var _letter = $x(this), _text = $x(this).text(), _count = 0;
_contentRows.each(function(i) {
var _cellText = $x(this).children('td').eq(0).text();
if ( RegExp('^' + _text).test(_cellText) ) {
_count += 1;
//on ajoute une class pour le calcul
list = $x(this).addClass("lignetrouve");
}
}); /*end _contentRows.each(function(i) */
_nblignes = $x('.lignetrouve').length;
$x(this).attr('data-title',_nblignes);
}); /*end _alphabets.hover(function() */
Jsfiddle

Categories

Resources