function addSelected(id) {
var feedFound = false;
var selList = [] ;
for (var i = 0; i < vm.feeds.length; i++) {
if (vm.feeds[i].id == id) {
if (vm.rationList.length > 0) {
for (var j = 0; j < vm.rationList.length; j++) {
if (vm.feeds[i].id == vm.rationList[j].id) {
feedFound = true;
break;
}
}
}
if (!feedFound) {
selList.push(vm.feeds[i]);
vm.feeds[i] = vm.feeds.filter(function(item) {
return item.id === vm.feeds[i].id;
});
}
feedFound = false;
}
}
var li = [];
angular.copy(selList, li);
for (var i = 0; i < li.length; i++) {
vm.rationList.push(li[i]);
}
vm.rationListSafe = vm.rationList;
}
This is how i add elements from one list to another with filtering. The problem is, for each filtered element, I get back an empty array. Is there anyway I can solve this?
If you are looking for only one item in your array, use find() instead of filter()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
PS: find may return null so you should always null-check
Example:
const foundItem = vm.feeds.find(function(item) {
return item.id === vm.feeds[i].id;
});
if (foundItem) {
vm.feeds[i] = foundItem
}
Here are the relevant bits of the client-side code:
function simpsonsShow(forest) {
alert(document.getElementById("simpsons"));
var ind = simpsonsIndex(forest).toFixed(2); // simpsonsIndex is a function not shown here
document.getElementById("simpsons").innerHTML = "";
document.getElementById("simpsons").innerHTML =
document.getElementById("simpsons").innerHTML + ind;
}
document.addEventListener("DOMContentLoaded", function () {
document.querySelector("div#intro button").addEventListener("click", function clicked() {
document.getElementById("intro").style.display = "none";
document.getElementById("sim").style.display = "block";
document.getElementById("simpsons").style.display = "block";
let content = document.getElementById("inputForest").value;
let forest = forestGenerate(content);
const ind = simpsonsShow(forest);
let button = document.createElement("button");
button.appendChild(document.createTextNode("generate"));
button.addEventListener("click", function () {
forest = forestGenerate(content);
simpsonsShow(forest);
});
document.getElementById("sim").appendChild(button);
});
});
When that simpsonsShow function is ran a second time, all of a sudden document.getElementById("simpsons") becomes null even though upon first try, it's a proper HTML Div Element.
Here are the relevant parts of the HTML:
<head>
<script src="sim.js"></script>
</head>
<body>
<div id="content">
<div id="intro">
</div>
<div id="sim" class="hidden">
<h2>the current Simpson's Index is:
</h2>
<div id="simpsons">
</div>
</div>
</div><!--close id="content"-->
</body>
</html>
I've added the code snippet: The website works by pressing generate, then continually pressing generate. The error pops up once you press generate a 2nd time
function forestGenerate(content) {
const forest = [];
if (content.length === 0) {
const possible = ["", "🌲", "🌳", "🌴", "🌵", "🌶", "🌷", "🌸", "🌹", "🌺", "🌻", "🌼", "🌽", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃"];
for (let i = 0; i < 8; i++) {
let text = '';
for (let i = 0; i < 8; i++) {
text += possible[Math.floor(Math.random() * possible.length)];
}
forest.push(text);
}
}
else {
const possible = [...content, ""];
for (let i = 0; i < 8; i++) {
let text = '';
for (let i = 0; i < 8; i++) {
text += possible[Math.floor(Math.random() * possible.length)];
}
forest.push(text);
}
}
for (let i = 0; i < forest.length; i++) {
let row = document.createElement("div");
let newContent = document.createTextNode(forest[i]);
row.appendChild(newContent);
row.addEventListener("click", function () {
row.style.backgroundColor = "grey";
row.setAttribute("pinned", "yes");
});
document.getElementById("sim").appendChild(row);
}
return forest;
}
function simpsonsShow(forest) {
const simpsonsIndex = forest =>
1 - Object.entries(
[...forest.join("")].reduce(
(counts, emoji) => ({ ...counts, [emoji]: (counts[emoji] || 0) + 1 }),
{}
)
).reduce(([top, bottom], [species, count]) => [top + (count * (count - 1)), bottom + count], [0, 0])
.reduce((sumLilN, bigN) => sumLilN / (bigN * (bigN - 1)))
alert(document.getElementById("simpsons"));
var ind = simpsonsIndex(forest).toFixed(2);
document.getElementById("simpsons").innerHTML = "";
document.getElementById("simpsons").innerHTML = document.getElementById("simpsons").innerHTML + ind;
}
document.addEventListener("DOMContentLoaded", function () {
let element = document.getElementById("sim");
element.classList.add("hidden");
let element1 = document.getElementById("pushtray");
element1.classList.add("hidden");
document.querySelector("div#intro button").addEventListener("click", function clicked() {
document.getElementById("intro").style.display = "none";
document.getElementById("sim").style.display = "block";
document.getElementById("simpsons").style.display = "block";
let content = document.getElementById("inputForest").value;
let forest = forestGenerate(content);
const ind = simpsonsShow(forest);
if (ind <= .7) {
let over = document.createElement("div");
let newContent = document.createTextNode("WARNING: Simpson's Index Dropped To" + simpsonsIndex);
over.appendChild(newContent);
document.getElementById("pushtray").appendChild(over);
document.getElementById("pushtray").style.zIndex = "100";
document.getElementById("pushtray").style.right = "50px";
document.getElementById("pushtray").style.position = "fixed";
document.getElementById("pushtray").style.display = "block";
}
let button = document.createElement("button");
button.appendChild(document.createTextNode("generate"));
button.addEventListener("click", function () {
const curr = document.getElementById("sim").querySelectorAll("div");
for (let i = 0; i < curr.length; i++) {
if (!curr[i].hasAttribute("pinned")) {
document.getElementById("sim").removeChild(curr[i]);
}
}
document.getElementById("sim").removeChild(button);
forest = forestGenerate(content);
simpsonsShow(forest);
document.getElementById("sim").appendChild(button);
});
document.getElementById("sim").appendChild(button);
});
});
<!doctype html>
<html>
<head>
<title>FOREST SIMULATOR</title>
<script src="sim.js"></script>
<link rel="stylesheet" href="base.css" type="text/css" media="screen" title="no title" charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Lato|Playfair+Display" rel="stylesheet" >
</head>
<link href="https://fonts.googleapis.com/css?family=Lato|Playfair+Display" rel="stylesheet">
<body>
<div id="content">
<h1>FOREST SIMULATOR</h1>
<style>
.hidden{
display:none;
}
</style>
<div id="intro">
starting forest (leave empty to randomize):
<br />
<textarea id="inputForest" name="inputForest" cols="16" rows="8"></textarea>
<br />
<button>generate</button>
</div>
<div id="sim" class="hidden">
<h2>the current Simpson's Index is:
</h2>
<div id="simpsons">
</div>
</div>
<div id="pushtray" class="overlay">
</div>
</div><!--close id="content"-->
</body>
</html>
#simpsons is a child of #sim. The problem is in this code here:
const curr = document.getElementById("sim").querySelectorAll("div");
for (let i = 0; i < curr.length; i++) {
if (!curr[i].hasAttribute("pinned")) {
document.getElementById("sim").removeChild(curr[i]);
}
}
It effectively removes all div children of #sim which don't have a pinned attribute. Try removing only divs after the first index, thereby keeping #simpsons (which is the first div inside #sim):
for (let i = 1; i < curr.length; i++) {
function forestGenerate(content) {
const forest = [];
if (content.length === 0) {
const possible = ["", "🌲", "🌳", "🌴", "🌵", "🌶", "🌷", "🌸", "🌹", "🌺", "🌻", "🌼", "🌽", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃"];
for (let i = 0; i < 8; i++) {
let text = '';
for (let i = 0; i < 8; i++) {
text += possible[Math.floor(Math.random() * possible.length)];
}
forest.push(text);
}
} else {
const possible = [...content, ""];
for (let i = 0; i < 8; i++) {
let text = '';
for (let i = 0; i < 8; i++) {
text += possible[Math.floor(Math.random() * possible.length)];
}
forest.push(text);
}
}
for (let i = 0; i < forest.length; i++) {
let row = document.createElement("div");
let newContent = document.createTextNode(forest[i]);
row.appendChild(newContent);
row.addEventListener("click", function() {
row.style.backgroundColor = "grey";
row.setAttribute("pinned", "yes");
});
document.getElementById("sim").appendChild(row);
}
return forest;
}
function simpsonsShow(forest) {
const simpsonsIndex = forest =>
1 - Object.entries(
[...forest.join("")].reduce(
(counts, emoji) => ({ ...counts,
[emoji]: (counts[emoji] || 0) + 1
}), {}
)
).reduce(([top, bottom], [species, count]) => [top + (count * (count - 1)), bottom + count], [0, 0])
.reduce((sumLilN, bigN) => sumLilN / (bigN * (bigN - 1)))
var ind = simpsonsIndex(forest).toFixed(2);
document.getElementById("simpsons").innerHTML = "";
document.getElementById("simpsons").innerHTML = document.getElementById("simpsons").innerHTML + ind;
}
document.addEventListener("DOMContentLoaded", function() {
let element = document.getElementById("sim");
element.classList.add("hidden");
let element1 = document.getElementById("pushtray");
element1.classList.add("hidden");
document.querySelector("div#intro button").addEventListener("click", function clicked() {
document.getElementById("intro").style.display = "none";
document.getElementById("sim").style.display = "block";
document.getElementById("simpsons").style.display = "block";
let content = document.getElementById("inputForest").value;
let forest = forestGenerate(content);
const ind = simpsonsShow(forest);
if (ind <= .7) {
let over = document.createElement("div");
let newContent = document.createTextNode("WARNING: Simpson's Index Dropped To" + simpsonsIndex);
over.appendChild(newContent);
document.getElementById("pushtray").appendChild(over);
document.getElementById("pushtray").style.zIndex = "100";
document.getElementById("pushtray").style.right = "50px";
document.getElementById("pushtray").style.position = "fixed";
document.getElementById("pushtray").style.display = "block";
}
let button = document.createElement("button");
button.appendChild(document.createTextNode("generate"));
button.addEventListener("click", function() {
const curr = document.getElementById("sim").querySelectorAll("div");
for (let i = 1; i < curr.length; i++) {
if (!curr[i].hasAttribute("pinned")) {
document.getElementById("sim").removeChild(curr[i]);
}
}
document.getElementById("sim").removeChild(button);
forest = forestGenerate(content);
simpsonsShow(forest);
document.getElementById("sim").appendChild(button);
});
document.getElementById("sim").appendChild(button);
});
});
.hidden {
display: none;
}
<div id="content">
<h1>FOREST SIMULATOR</h1>
<div id="intro">
starting forest (leave empty to randomize):
<br />
<textarea id="inputForest" name="inputForest" cols="16" rows="8"></textarea>
<br />
<button>generate</button>
</div>
<div id="sim" class="hidden">
<h2>the current Simpson's Index is:
</h2>
<div id="simpsons">
</div>
</div>
<div id="pushtray" class="overlay">
</div>
</div>
The code gets the values of the input and sends it to the textarea, but when you add more than one title the values are repeated in the result of the titles, for example, the DESCRIPTIONS of title 1 are the same as in title 2, why does this happen? and how to make it work without changing the purpose?
Run the code in codepen.io or jsfiddle.net
This is what happens:
This is what should happen:
function result() {
var inp2 = document.getElementsByName("inp2");
var titu = document.getElementsByName("titu");
var res = document.getElementById("result");
res.value = "";
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
for (var j = 0; j < inp2.length; j++) {
if (inp2[j].value.trim() != '') {
res.value += `<li>${inp2[j].value.trim()}</li>\n`;
}
}
}
}
}else {
console.log("test")
res.value += `<ul>\n`;
for (var l = 0; l < inp2.length; l++) {
if (inp2[l].value.trim() != '') {
res.value += `<li>${inp2[l].value.trim()}</li>\n`;
}
}
}
};
// -----------------------------------------
if (document.getElementById("add2")) {
let cont2 = 1;
document.getElementById("add2").onclick = function clone2() {
let container2 = document.getElementById("output2");
let tempLinha2 = document.querySelector('#template2');
let clone2 = document.importNode(tempLinha2.content, true);
const label2 = clone2.querySelector("label");
label2.htmlFor = cont2;
clone2.querySelector("input").className = cont2;
container2.appendChild(clone2);
cont2++;
};
document.getElementById("del2").onclick = function del2() {
document.querySelector('#output2 #linha2:last-child').remove();
};
}
// ---------------------------------------
if (document.getElementById("addtit")) {
let cont3 = 1;
document.getElementById("addtit").onclick = function clone3() {
let container3 = document.getElementById("output2");
let tempLinha3 = document.querySelector('#template3');
let clone3 = document.importNode(tempLinha3.content, true);
const label3 = clone3.querySelector("label");
label3.htmlFor = cont3;
clone3.querySelector("input").className = cont3;
container3.appendChild(clone3);
cont3++;
document.getElementById('add2').id = 'add3';
document.getElementById('del2').id = 'del3';
};
document.getElementById("deltit").onclick = function deltit() {
document.querySelector('#output2 #alg:last-child').remove();
document.getElementById('add3').id = 'add2';
document.getElementById('del3').id = 'del2';
};
}
// -----------------------------------------
if (document.getElementById("add3")) {
let cont4 = 1;
document.getElementById("add3").onclick = function clone4() {
let container4 = document.getElementById("output3");
let tempLinha4 = document.querySelector('#template2');
let clone4 = document.importNode(tempLinha4.content, true);
const label4 = clone4.querySelector("label");
label4.htmlFor = cont4;
clone4.querySelector("input").className = cont4;
container4.appendChild(clone4);
cont4++;
};
document.getElementById("del3").onclick = function del4() {
document.querySelector('#output3 #linha2:last-child').remove();
};
}
<div class="container">
<button id="addtit">+ TITLE</button>
<button id="deltit">- TITLE</button>
<button id="add2">+ DESCRIPTION</button>
<button id="del2">- DESCRIPTION</button>
<div id="output2"></div>
<div class='botoes'>
<button onclick="result()" id='done'>DONE</button>
</div>
<div class="header"><span class="title">RESULT</span>
</div>
<div class="linha"><textarea id="result"></textarea>
</div>
</div>
<!-- template 2 -->
<template id="template2">
<div class="linha" id="linha2"><div class="coluna1"><label for="0">DESCRIPTION:</label></div><div class="coluna2"><input name="inp2" class="0" type="text"/></div>
</div>
</template>
<!-- template 3 -->
<template id="template3">
<div id="alg">
<div class="linha"><div class="coluna1"><label for="0">TITLE:</label></div><div class="coluna2"><input name="titu" class="0" type="text"/></div>
</div>
<div class="linha" id="linha3"><div class="coluna1"><label for="0">DESCRIPTION:</label></div><div class="coluna2"><input name="inp2" class="0" type="text"/></div>
</div>
<div id="output3"></div>
</div>
</template>
Ok. it's because this part of code in function result:
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
for (var j = 0; j < inp2.length; j++) {
if (inp2[j].value.trim() != '') {
res.value += `<li>${inp2[j].value.trim()}</li>\n`;
}
}
}
}
}
your titles have the same names : 'titu' , and your descriptions have same names : 'inp2', and you have two nested loops, for each title, loop on description, and it results as you see.
it's better to change your code and make different names and ids
by the way. if you persist to do not change your code, you should use one loop for both of them, like this code
if (titu[0]) {
for (var k = 0; k < titu.length; k++) {
if (titu[k].value.trim() != '') {
res.value += `<div>
<span>${titu[k].value.trim()}</span>
</div>
<ul>\n`;
if (inp2[k].value.trim() != '') {
res.value += `<li>${inp2[k].value.trim()}</li>\n`;
}
}
}
}
UPDATE
for the case of more description for each title, you have to change the code of onClick methods of Title+ and Description+, the added title and all of its description must have same parent, and after doing that, it's possible to solve the problem like this . (assuming the parent that I already have said has class name 'parent')
function result() {
var parents = document.querySelectorAll(".parent")
parents.forEach(function(parent){
var title = parent.querySelector("titu");
var descriptions = parent.querySelectorAll("inp2");
var res = document.getElementById("result");
if (title.value.trim() != '') {
res.value += `<div>
<span>${title.value.trim()}</span>
</div>
<ul>\n`;
}
descriptions.forEach(function(inp2){
if (inp2.value.trim() != '') {
res.value += `<li>${inp2.value.trim()}</li>\n`;
}
});
});
}
notice that this code could work after modifying Title+ and Description+ events and add same parent with class name parent to title and descriptions inputs
I created the Product and Store classes, implemented the functions of adding, removing, counting and sorting.
After that, I displayed it all with the help of the HTML table.
Now I need to add to the UI sort by price.
I can sort only once when creating an array. But I do not know how to hang an event that would respond to changing the table and sort it by clicking on the heading of the "Price" column.
<div id="_shop">
<form id="addForm">
<label for="_add_name">Name </label><input id="_add_name"><br/><br/>
<label for="_price">Price </label><input id="_price"><br/><br/>
<label for="_count">Count </label><input id="_count"><br/><br/>
<input type="button" id="btnAdd" value="Add"><br/><br/>
</form>
<form id="removeForm">
<label for="_del_name">Enter Name </label><input id="_del_name"><br/><br/>
<input type="button" id="btnDlt" value="Delete"><br/><br/>
</form>
<table id="shopTable">
<thead>
<th>Name:</th>
<th>Price:</th>
<th>Count:</th>
</thead>
</table>
class Product{
constructor(name, price, count){
this.name = name;
this.price = price;
this.count = count;
}
static get SORT_ORDER_ASC(){
return 0;
}
static get SORT_ORDER_DESC(){
return 1;
}
}
class Shop{
constructor(){
this.products = [];
}
addProduct (product) {
this.products.push(product);
};
deleteProductByName (productName) {
for (let i = 0; i < this.products.length; i++) {
if (this.products[i].name === productName) {
this.products.splice(i, 1);
}
}
};
get totalProductsPrice () {
let totalCost = 0;
for (let i = 0; i < this.products.length; i++) {
totalCost += this.products[i].count * this.products[i].price;
}
return totalCost;
};
sortProductsByPrice (sortOrder) {
let rows = document.querySelectorAll("#shopTable .data");
for(let i = 0; i < rows.length; i++)
{
//this.products[i].name = rows.item(i).toString();
console.log(this.products[i].name);
}
if(sortOrder === 0) {
this.products.sort();
this.products.map(t => t.name + " " + t.price).join("\n");
}
else if(sortOrder === 1) {
this.products.sort();
this.products.reverse();
this.products.map(t => t.name + " " + t.price).join("\n");
}
else {
console.log("The parameter is incorrect");
}
};
show() {
let rows = document.querySelectorAll("#shopTable .data");
let tp = document.querySelectorAll("#totalPrice .data");
for (let i = rows.length - 1; i >= 0; i--) {
let e = rows.item(i);
e.parentNode.removeChild(e);
}
if(document.getElementById("totalPrice") !== null){
document.getElementById("totalPrice").remove();
}
//tp.parentNode.removeChild(tp);
let table = document.getElementById("shopTable");
for (let i = 0; i < this.products.length; i++) {
table.innerHTML += `<tbody id="tbProducts"><tr class="data">
<td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td>
</tr></tbody>`;
}
table.innerHTML += `<tfoot><tr><td id="totalPrice">Total price: ${shop.totalProductsPrice}</td></tr></tfoot>`;
}
}
let shop = new Shop();
shop.addProduct(new Product("product1", 200, 10));
shop.addProduct(new Product("product2", 500, 1));
shop.addProduct(new Product("product3", 1000, 1));
shop.show();
let btnAdd = document.getElementById("btnAdd");
btnAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(document.getElementById('_add_name').value,
parseInt(document.getElementById('_price').value),
parseInt(document.getElementById('_count').value)));
//let tmpTotalPrice =
document.getElementById("totalPrice").innerHTML = shop.totalProductsPrice;
shop.show();
}, false);
let btnDlt = document.getElementById("btnDlt");
btnDlt.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(document.getElementById('_del_name').value);
shop.show();
}, false);
Unless I misunderstand your question you can give your th an id and add an event listener just as you did for the buttons:
<th id="priceHeader">Price:</th>
let priceHeader = document.getElementById("priceHeader");
btnDlt.addEventListener('click', (e) => {
//do your sorting here
});
Edit:
I made a jsFiddle where I fixed your sort function and added a resort function to your shop class, check if it's what you wanted:
http://jsfiddle.net/2mza4710/24/
new resort function:
resort(){
let sortOrder = this.currentSortOrder === Product.SORT_ORDER_ASC ? Product.SORT_ORDER_DESC : Product.SORT_ORDER_ASC;
this.currentSortOrder = sortOrder;
this.sortProductsByPrice(sortOrder);
this.show();
}
change in your sortProductsByPrice function:
if(sortOrder === 0) {
this.products.sort(function(a, b){return a.price - b.price});
}
else if(sortOrder === 1) {
this.products.sort(function(a, b){return b.price - a.price});
}
I want to delete after clicking the product button, but it does not work properly I do not know why. It does not remove the correct object from the table
document.addEventListener('click', function(e) {
if (e.target.id === 'removeItem') {
var divWithItem = document.getElementsByClassName('containerBasket__allProducts__product');
// Pobieram name itemu
var nameItem = e.target.parentElement.parentElement.getAttribute('name');
var thisItemDiv = e.target.parentElement.parentElement;
var thisItem = JSON.parse(products[nameItem]);
products.splice(thisItem, 1);
localStorage.setItem('product', JSON.stringify(products));
thisItemDiv.remove();
for (var i = 0; i < products.length; i++) {
for (var j = 0; j < divWithItem.length; j++) {
divWithItem[j].setAttribute('name', [j]);
}
}
console.log(products);
}
});
Before looping
After looping
Why does a div with the same name?