changing forEach into for loop - javascript

Javascript beginner here, trying to learn by coding, at the moment i'm trying to learn 'forEach' and 'for', here i have a code where it is working with 'forEach' i'm trying to change it into 'for loop', like this(dont know if i'm doing right here ?) if possibly somebody could write separate 'for loops' for this ? would be good for new programmers.
for (var i = 0; i < arvvoja.length; i++) {
option.textContent += dataa[i][arvvoja] + " ";
});
without any success, here is my code :
let animals
let animalCols = ['Animal', 'Animal 2']
let peopleCols = ['Person', 'Person 2']
function myFunction() {
paivitys(animals, animalCols)
}
function paivitys(dataa, arvvoja) {
console.log(dataa);
//----
if (dataa.hasOwnProperty("animal")) {
document.getElementById("1name").innerHTML = dataa.animal;
} else {
document.getElementById("1name").innerHTML = dataa.person;
}
//----
if (dataa.hasOwnProperty("animal2")) {
document.getElementById("2name").innerHTML = dataa.animal2;
} else {
document.getElementById("2name").innerHTML = dataa.person2;
}
document.getElementById("1name1").innerHTML = arvvoja[0];
document.getElementById("2name1").innerHTML = arvvoja[1];
//-----
document.getElementById("id").innerHTML = dataa.id;
}
function paivitaselekt(dataa, arvvoja) {
for (var i = 0; i < dataa.length; i++) {
var valitse = document.getElementById("Select");
var option = document.createElement("option");
arvvoja.forEach((value) => {
option.textContent += dataa[i][value] + " ";
});
valitse.appendChild(option);
}
}
animals = {
"animal": "tiger",
"animal2": "lion",
"id": "54321",
"dole": {
"Key": "fhd699f"
}
}
paivitys(animals, animalCols);
let kokoarray;
people = [{
"person": "kaka",
"person2": "julle",
"id": "9874",
},
{
"person": "Ronaldo",
"person2": "jussi",
"id": "65555",
}
]
kokoarray = people;
paivitaselekt(kokoarray, ["person", "id"]);
document.getElementById("Select").addEventListener("change", function(event) {
const otettutunnsite = event.target.value.split(" ")[1];
const otettutieto = kokoarray.filter((dataa) => dataa.id === otettutunnsite)[0];
paivitys(otettutieto, peopleCols);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
integrity="sha384UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous"
/>
<style>
</style>
</head>
<body>
<div class="">
<table class="table ">
<thead>
<tr>
<th id="1name1" class="table-success">Animal</th>
<th id="2name1" class="table-success">Animal</th>
<th class="table-success">id</th>
</tr>
</thead>
<tbody>
<th id="1name"></th>
<th id="2name"></th>
<th id="id"></th>
</tbody>
</table>
<select id="Select" ></select>
<button onclick="myFunction()">backtozero</button>
</div> </body>
</html>

Use a different variable in the inner loop:
var i, j;
for (i = 0; i < dataa.length; i++) {
var valitse = document.getElementById("Select");
var option = document.createElement("option");
for (j = 0; j < arvvoja.length; j++) {
option.textContent += dataa[i][arvvoja[j]] + " ";
}
valitse.appendChild(option);
}

Related

creating a list of books in Javascript

I'm having a problem trying to sort the booklist I'm creating for an assignment. The titles of the books are supposed to move with the dates and be sorted from oldest to newest after clicking the button. However, I don't know why Don Quixote and Moby Dick don't appear after the button is clicked. Is there something that I am missing or I did wrong? Help is appreciated.
var names = new Array("To Kill a Mockingbird","Jaws","Don Quixote","Moby-Dick","Northern Lights");
var published = new Array("July 11, 1960", "February 1, 1974","July 11, 1615","October 18, 1851","November 12, 1995");
function display()
{
for(var i = 0; i < names.length; i++)
{
var temp = "cell" + i + "0";
document.getElementById(temp).innerHTML = names[i];
temp = "cell" + i + "1";
document.getElementById(temp).innerHTML = published[i];
}
}
function SortIt( )
{
var oldest = 0;
var index = 0;
var j = 0;
var k = 0;
var count = 0;
var temp = 0; var temp2 = "";
count = published.length;
count = names.length;
for (k =0; k <= (count -1); k++ )
{
oldest = Date.parse(published[k]);
index = k;
for (j = (k + 1); j <= (count-1); j++)
{
if (Date.parse(published[j]) < oldest )
{
oldest = Date.parse(published[j]);
index = j;
}
}
if(k != index)
{
temp = published[k];
published[k] = published[index];
published[index] = temp;
temp2 = names[k];
names[k] = index[k];
names[index] = temp2;
}
}
display();
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Program 9 - Selection Sort</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="Carbajal_Lab9.js"></script>
</head>
<body onload="display()">
<h1>Program 9 - Selection Sort</h1>
<table id ="workTable" border ="2">
<tr>
<td> <span id = "cell00"/> </td>
<td> <span id = "cell01"/> </td>
</tr>
<tr>
<td> <span id = "cell10"/> </td>
<td> <span id = "cell11"/> </td>
</tr>
<tr>
<td> <span id = "cell20"/> </td>
<td> <span id = "cell21"/> </td>
</tr>
<tr>
<td> <span id = "cell30"/> </td>
<td> <span id = "cell31"/> </td>
</tr>
<tr>
<td> <span id = "cell40"/> </td>
<td> <span id = "cell41"/> </td>
</tr>
</table>
<form>
<input type="button" value="Sort" onclick="SortIt()"/>
</form>
</body>
</html>
In
temp = published[k];
published[k] = published[index];
published[index] = temp;
temp2 = names[k];
names[k] = index[k];
names[index] = temp2;
you are setting names[k] as index[k], even though index is a int/counter.
What works for me is creating clones of published and names, so that when you are trying to put in a value from the old list, you can reference, for example, oldnames.
The variable count is also set as 2 different values in a row,. I have replaced this section to a call to Math.min, which picks the smallest of the 2 array lengths (Preventing invalid index queries )
Lastly I've saved you some html writing by having a loop in the javascript that creates the inital table
var names = new Array("To Kill a Mockingbird","Jaws","Don Quixote","Moby-Dick","Northern Lights");
var published = new Array("July 11, 1960", "February 1, 1974","July 11, 1615","October 18, 1851","November 12, 1995");
var count = Math.min(names.length,published.length);
function drawTable(){
for(var i = 0; i < count; i++)
{
document.getElementById('workTable').innerHTML+="<tr>"+
"<td> <span id=\"cell"+i+"0\""+"/></td>"+
"<td> <span id=\"cell"+i+"1\""+"/></td>"+
"</tr>"
}
}
function display()
{
for(var i = 0; i < count; i++)
{
var temp = "cell" + i + "0";
document.getElementById(temp).innerHTML = names[i];
temp = "cell" + i + "1";
document.getElementById(temp).innerHTML = published[i];
}
}
function SortIt( )
{
var oldPublished=published.slice();
var oldNames = names.slice();
var oldest = 0;
var index = 0;
var j = 0;
var k = 0;
var temp = 0; var temp2 = "";
for (k =0; k <= (count -1); k++ )
{
oldest = Date.parse(published[k]);
index = k;
for (j = (k + 1); j <= (count-1); j++)
{
if (Date.parse(published[j]) < oldest )
{
oldest = Date.parse(published[j]);
index = j;
}
}
if(k != index)
{
temp = published[k];
published[k] = oldPublished[index];
published[index] = oldPublished[k];
temp2 = names[k];
names[k] = oldNames[index];
names[index] = oldNames[k];
}
}
display();
}
drawTable();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Program 9 - Selection Sort</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="Carbajal_Lab9.js"></script>
</head>
<body onload="display()">
<h1>Program 9 - Selection Sort</h1>
<table id ="workTable" border ="2">
</table>
<form>
<input type="button" value="Sort" onclick="SortIt()"/>
</form>
</body>
</html>

replace the table data with the selected data(javascript)

javascript beginner here, trying to code and learn.
I have a table filled with data (fetch from url) and that data is
{
"france": "paris",
"finland": "helsinki",
"sweden": "stockholm",
"tajikistan": "dushanbe",
"uzbekistan ": "toshkent",
"china": "peking",
"dole": {
"Key": "fhd699f"
}
}
and under the table I have a select box (the data of it also fetched from url) its data is this
[
{"nimi": "tili","id": "48385","somewhere": "nassau","somewhere2": "bamako","somewhere3": "rabat","somewhere4": "baku"},
{"nimi": "tili","id": "789642","somewhere": "windhoek","somewhere2": "podgorica","somewhere3": "niamey","somewhere4": "islamabad"}
]
i want to replace the table data with the selected data ( i mean everything) even table's <th> also, for example table's <th> is 'france' and value is 'paris' but after replace table's <th> should be 'nimi' and value 'tili' according to select box data.
here is my code (as you can see 'tajikistan','uzbekistan','china' for some reason not going to their places in table):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<style>
</style>
</head>
<body>
<div class="container">
<table class="table ">
<thead>
<tr>
<th class="table-success">france</th>
<th class="table-success">finland</th>
<th class="table-success">sweden</th>
</tr>
</thead>
<tbody id="tiedot">
</tbody>
<thead>
<tr>
<th class="table-success">tajikistan</th>
<th class="table-success">uzbekistan</th>
<th class="table-success">china</th>
</tr>
</thead>
<tbody id="tiedot2">
</tbody>
</table>
<select id="valittu" name="name"></select>
</div>
<script>
fetch(
"https://tdejdjd***",
{
method: "GET",
headers: {
"x-api-key": "i****y"
}
}
)
.then((res) => {
res
.json()
.then((data) => {
tableupdating(data, ['france','finland','sweden','tajikistan','uzbekistan','china']);
})
.catch((err) => {
console.log("ERROR: " + err);
});
});
function tableupdating(data, values) {
const totable = document.getElementById("tiedot");
const totable2 = document.getElementById("tiedot2");
totable.innerHTML = "";
totable2.innerHTML = "";
var komb = "";
var komb2 = "";
komb += "<tr>";
komb2 += "<tr>";
values.forEach(value => {
komb += "<td>" + data[value] + "</td>";
})
values.forEach(value => {
komb2 += "<td>" + data[value] + "</td>";
})
totable.insertAdjacentHTML("beforeend", komb);
totable2.insertAdjacentHTML("beforeend", komb2);
}
let dataArray;
fetch(
"https://tdejdjd***",
{
method: "GET",
headers: {
"x-api-key": "i****y"
}
}
)
.then((res) => {
res.json().then((data) => {
dataArray = data;
updateSelect(data, ['nimi','id']);
});
});
function updateSelect(data, values) {
for (var i = 0; i < data.length; i++) {
var Valittu = document.getElementById("valittu");
var option = document.createElement("option");
values.forEach(value => {
option.textContent += data[i][value] + ' '
})
Valittu.appendChild(option);
}
}
document.getElementById("valittu").addEventListener("change", function (event) {
const chosenID = event.target.value.split(" ")[1];
const chosenData = dataArray.filter((data) => data.id === chosenID)[0];
tableupdating(chosenData, ['nimi', 'id', 'somewhere','somewhere2','somewhere3','somewhere4']);
});
</script>
</body>
</html>
as spoken in chat, here is new code, it is working but for some reason these three are in same line and not on their places : komb += "<td>"+tiedot.tajikistan+"</td>";
komb += "<td>"+tiedot.uzbekistan+"</td>";
komb += "<td>"+tiedot.china+"</td></tr>";
code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<style>
</style>
</head>
<body onload="fillTheBox();">
<div class="container">
<table class="table" id="myTable">
<thead>
<tr>
<th class="table-success">france</th>
<th class="table-success">finland</th>
<th class="table-success">sweden</th>
</tr>
</thead>
<tbody id="tiedot">
</tbody>
<thead>
<tr>
<th class="table-success">tajikistan</th>
<th class="table-success">uzbekistan</th>
<th class="table-success">china</th>
</tr>
</thead>
</table>
<select id="valittu" name="name" onchange="changed()"></select>
</div>
<script>
fetch("https://qj",
{
method: "GET",
headers: {
"x-api-key": ""
}
}
).then(res =>{
res.json().then(tiedot => {
console.log(tiedot);
var komb ="";
komb +="<tr>";
komb += "<td>"+tiedot.france+"</td>";
komb += "<td>"+tiedot.finland+"</td>";
komb += "<td>"+tiedot.sweden+"</td>";
komb += "<td>"+tiedot.tajikistan+"</td>";
komb += "<td>"+tiedot.uzbekistan+"</td>";
komb += "<td>"+tiedot.china+"</td></tr>";
document.getElementById("tiedot").insertAdjacentHTML("beforeend", komb );
}
)
})
var dataArray = [
{ "nimi": "tili", "id": "48385", "somewhere": "nassau", "somewhere2": "bamako", "somewhere3": "rabat", "somewhere4": "baku" },
{ "nimi": "tili", "id": "789642", "somewhere": "windhoek", "somewhere2": "podgorica", "somewhere3": "niamey", "somewhere4": "islamabad" }
]
function fillTheBox() {
var selectBox = document.getElementById("valittu");
var option = document.createElement("option");
option.value = dataArray[0];
option.text = dataArray[0].nimi+' '+dataArray[0].id;
selectBox.add(option);
var option1 = document.createElement("option");
option1.value = dataArray[1];
option1.text = dataArray[1].id;
selectBox.add(option1);
}
function changed() {
var e = document.getElementById("valittu");
var selectedObjectID = e.options[e.selectedIndex].text;
chosenData = dataArray.filter((data) => data.id === selectedObjectID)[0];
var myTable = document.getElementById("myTable");
myTable.innerHTML = "";
generateTable(myTable, chosenData);
}
function generateTable(table, data) {
let row1 = table.insertRow();
row1.className = "table-success";
let row2 = table.insertRow();
let row3 = table.insertRow();
row3.className = "table-success";
let row4 = table.insertRow();
var counter = 1;
for (key in data) {
if (counter<=3) {
let cell = row1.insertCell();
let text = document.createTextNode(key);
cell.appendChild(text);
let cell2 = row2.insertCell();
let text2 = document.createTextNode(data[key]);
cell2.appendChild(text2);
} else {
let cell = row3.insertCell();
let text = document.createTextNode(key);
cell.appendChild(text);
let cell2 = row4.insertCell();
let text2 = document.createTextNode(data[key]);
cell2.appendChild(text2);
}
counter++;
}
}
</script>
</body>
</html>
I created a basic demo to show the logic. Firs of all give an id to your table. And create a onChange event for your select box. In your event function edit your table content with innerHTML property. Just focus on change() and generateTable() functions in my code
<body onload="fillTheBox();">
<div class="container">
<table class="table" id="myTable">
<thead>
<tr>
<th class="table-success">france</th>
<th class="table-success">finland</th>
<th class="table-success">sweden</th>
</tr>
</thead>
<tbody id="tiedot">
</tbody>
<thead>
<tr>
<th class="table-success">tajikistan</th>
<th class="table-success">uzbekistan</th>
<th class="table-success">china</th>
</tr>
</thead>
</table>
<select id="valittu" name="name" onchange="changed()"></select>
</div>
<script>
var dataArray = [
{ "nimi": "tili", "id": "48385", "somewhere": "nassau", "somewhere2": "bamako", "somewhere3": "rabat", "somewhere4": "baku" },
{ "nimi": "tili", "id": "789642", "somewhere": "windhoek", "somewhere2": "podgorica", "somewhere3": "niamey", "somewhere4": "islamabad" }
]
function fillTheBox() {
var selectBox = document.getElementById("valittu");
var option = document.createElement("option");
option.value = dataArray[0];
option.text = dataArray[0].id;
selectBox.add(option);
var option1 = document.createElement("option");
option1.value = dataArray[1];
option1.text = dataArray[1].id;
selectBox.add(option1);
}
function changed() {
var e = document.getElementById("valittu");
var selectedObjectID = e.options[e.selectedIndex].text;
chosenData = dataArray.filter((data) => data.id === selectedObjectID)[0];
var myTable = document.getElementById("myTable");
myTable.innerHTML = "";
generateTable(myTable, chosenData);
}
function generateTable(table, data) {
let row1 = table.insertRow();
row1.className = "table-success";
let row2 = table.insertRow();
row2.className = "table-success";
let row3 = table.insertRow();
row3.className = "table-success";
let row4 = table.insertRow();
row4.className = "table-success";
var counter = 1;
for (key in data) {
if (counter<=3) {
let cell = row1.insertCell();
let text = document.createTextNode(key);
cell.appendChild(text);
let cell2 = row2.insertCell();
let text2 = document.createTextNode(data[key]);
cell2.appendChild(text2);
} else {
let cell = row3.insertCell();
let text = document.createTextNode(key);
cell.appendChild(text);
let cell2 = row4.insertCell();
let text2 = document.createTextNode(data[key]);
cell2.appendChild(text2);
}
counter++;
}
}
</script>
</body>
</html>
UPDATE:
To separate the fields mentioned in question add a <tr> element between them.
komb +="<tr>";
komb += "<td>"+tiedot.france+"</td>";
komb += "<td>"+tiedot.finland+"</td>";
komb += "<td>"+tiedot.sweden+"</td>";
komb +="</tr><tr>";
komb += "<td>"+tiedot.tajikistan+"</td>";
komb += "<td>"+tiedot.uzbekistan+"</td>";
komb += "<td>"+tiedot.china+"</td></tr>";

javascript loop array and object data in one table

I have array and object data i want to call those together.
var data = [
{"number": "PA1234","name": "John"},
{"number": "JM344","name": "jessi"},
{"number": "ML567","name": "Monty"}
];
var costing= {
"cost": 10,
"cost": 20,
"cost": 30,
};
Display Format in table
<pre>
<table>
<tr>
<td>number</td>
<td>name</td>
<td>cost</td>
</tr>
</table>
<pre>
I have done so far but don't know how to called the object costing
var records=$("<table/>").attr("id","tabs");
$("#table").append(records);
for(var j=0;j<data .length;j++)
{
var tr="<tr>";
var td1="<td>"+data [j]["number"]+"</td>";
var td2="<td>"+data [j]["name"]+"</td>";
$("#tabs").append(tr+td1+td2+td3);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<title>
</title>
<style>
#t, tr, th, td{
border: 1px solid black;
}
</style>
</head>
<body>
<table id="t" cellpadding="10">
<tr>
<th>
Number
</th>
<th>
Name
</th>
<th>
Cost
</th>
</tr>
</table>
</body>
<script>
var number = ['PA1234', 'JM344', 'ML567'], name = ['John', 'Jessi', 'Monty'], costing = [30, 30, 30];
for(var i=0;i<3;i++) {
$("#t").append('<tr><td>' + number[i] + '</td><td>' + name[i] + '</td><td>' + costing[i] + '</td></tr>');
}
</script>
</html>
This is what you want
Had to change some things with your second object, costing. I don't think you can have the same key names on different values, you wouldn't be able to iterate over them. Now you can do two approaches:
var data = [
{"number": "PA1234","name": "John"},
{"number": "JM344","name": "jessi"},
{"number": "ML567","name": "Monty"}
];
var costing = {
"cost0": 10,
"cost1": 20,
"cost2": 30,
};
document.addEventListener("DOMContentLoaded", () => {
const place = document.getElementById("place").firstElementChild
const table = document.createElement("table")
for(let i = 0; i < data.length; i++){
let tr = document.createElement("tr")
let tdNumber = document.createElement("td")
let tdName = document.createElement("td")
let tdCost = document.createElement("td")
tdNumber.innerText = data[i].number
tdName.innerText = data[i].name
tdCost.innerText = costing["cost"+i]
tr.appendChild(tdNumber)
tr.appendChild(tdName)
tr.appendChild(tdCost)
table.appendChild(tr)
}
place.appendChild(table)
})
However personally i would change your costing object to this:
var costing2 = [
10,20,30
]
And change the for loop to this:
for(let i = 0; i < data.length; i++){
let tr = document.createElement("tr")
let tdNumber = document.createElement("td")
let tdName = document.createElement("td")
let tdCost = document.createElement("td")
tdNumber.innerText = data[i].number
tdName.innerText = data[i].name
tdCost.innerText = costing2[i]
tr.appendChild(tdNumber)
tr.appendChild(tdName)
tr.appendChild(tdCost)
table.appendChild(tr)
}
Where place is the spot of the div tag in the html. Not the best solution but it works, putting down the html code aswell if you want that:
<html>
<head>
<script src="./file.js"></script>
</head>
<body>
<div id="place">
<pre>
</pre>
</div>
</body>
</html>

Choosing an item from HTML collection

I'm trying to select the elements(lis)that are pushed into my array(todos its a ul)..
when the function (nu) is called it creates a new li and stores it in an HTML Collection...
I want to be able to select those li for styling.
var input = document.querySelector("#input");
var todos = [];
var list = document.getElementById("list");
var lis = document.getElementsByTagName("li")
var btns = document.querySelectorAll("button")
function nu() {
input.addEventListener("change", function () {
todos.push(input.value)
list.innerHTML += "<li>" + input.value + "</li>"
input.value = ""
})
return list;
}
function alo() {
for (i = 0; i < todos.length; i++) {
lis.item(i).addEventListener("click", function () {
alert("alo")
})
}
}
function disp() {
todos.forEach(i => {
list.innerHTML += "<li>" + i + "</li>"
});
return list;
}
disp()
nu()
I tried to do this
function silly() {
for (i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function () {
alert("working")
})
}
}
still doesn't work :/..
here is my html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="new.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>New To-do!</title>
</head>
<body>
<div class="container">
<h1>MY TO-DO</h1>
<input type="type" placeholder="New TO-DO" id="input">
<ul id="list">
</ul>
</div>
<script src="todo.js" type="text/javascript"></script>
</body>
</html>
And this is the output, I want to style those todos.!
JSFiddle : https://jsfiddle.net/cytjae3z/
The function you created actually works, I think your problem comes from the fact that you weren't able to call it in the right place, that being in the input.addEventListener. Here is a working example :
var input = document.querySelector("#input");
var todos = [];
var list = document.getElementById("list");
var lis = document.getElementsByTagName("li")
var btns = document.querySelectorAll("button")
function nu() {
input.addEventListener("change", function() {
todos.push(input.value)
list.innerHTML += "<li>" + input.value + "</li>"
input.value = ""
silly()
})
return list;
}
function alo() {
for (i = 0; i < todos.length; i++) {
lis.item(i).addEventListener("click", function() {
alert("alo")
})
}
}
function disp() {
todos.forEach(i => {
list.innerHTML += "<li>" + i + "</li>"
});
return list;
}
function silly() {
for (i = 0; i < lis.length; i++) {
lis[i].addEventListener("click", function() {
this.style.backgroundColor = "#" + ((1 << 24) * Math.random() | 0).toString(16)
})
}
}
disp()
nu()
<div class="container">
<h1>MY TO-DO</h1>
<input type="type" placeholder="New TO-DO" id="input">
<ul id="list">
</ul>
</div>

How to use sort function and search function (regexp) together without strange errors?

In this prototype, I have "products" that are each individually stored in a div along with their price. I have added four buttons that sort the divs containing the products in alphabetical order (A-Z AND Z-A) as well as by price (lowest to highest and highest to lowest). These sorting functions work perfectly by themselves. I also have a search bar that acts as a search engine if you like an upon entering each character into the input field, will eliminate the products (div's) by name if they do not contain that letter(s). I have done this using a regular expression. This also worked by itself until I adapted it to try and work in conjunction with the sorting mechanisms.
Problem
I would like to be able to search for "products" using the search functionality to display the correct results regardless of what order the products have been sorted into.
Question
How is it possible to be able to display only the div's that contain the letter(s) searched for in the search bar regardless of the ordering (e.g. Z to A).
I think I ruined the search function itself by adding the index variable but you can't do list.name[i].match(res) can you? There is something wrong with the logic behind the search function. I believe the function that needs serious fixing is the searchProducts function.
The code AFTER I adapted the searchProducts function is below...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<div id="resultsSpan"></div>
<div id="product0" style="height:60px; width:60px; background-color:blue;"></div>
<div id="product1" style="height:60px; width:60px; background-color:blue;"></div>
<div id="product2" style="height:60px; width:60px; background-color:blue;"></div>
<div id="product3" style="height:60px; width:60px; background-color:blue;"></div>
<button onclick="sortprods()">
Sort A-Z
</button>
<button onclick="sortprods2()">
Sort Z-A
</button>
<button onclick="sortprods3()">
Price (low to high)
</button>
<button onclick="sortprods4()">
Price (high to low)
</button>
<input type="text" id="searchbar" onkeyup="searchProducts()"/>
</body>
</html>
<script>
var list = [
{name: "Apple", price: 31},
{name: "Banana", price: 22},
{name: "Orange", price: 46},
{name: "Strawberry", price:76}
];
list.sort(AtoZ);
for (var i = 0; i<list.length; i++) {
document.getElementById("product" + i).innerHTML = list[i].name + ", " + list[i].price;
}
function AtoZ(a,b) {
if (a.name < b.name)
return -1;
if (a.name > b.name)
return 1;
return 0;
}
function ZtoA(a,b) {
if (a.name < b.name)
return 1;
if (a.name > b.name)
return -1;
return 0;
}
function LowtoHigh(a,b) {
if (a.price < b.price)
return -1;
if (a.price > b.price)
return 1;
return 0;
}
function HightoLow(a,b) {
if (a.price < b.price)
return 1;
if (a.price > b.price)
return -1;
return 0;
}
function sortprods(){
list.sort(AtoZ);
currentSort = "AtoZ";
for (var i = 0; i < list.length; i++) {
document.getElementById("product" + i).innerHTML = list[i].name + ", " + list[i].price;
}
}
function sortprods2(){
list.sort(ZtoA);
currentSort = "ZtoA";
for (var j = 0; j < list.length; j++) {
document.getElementById("product" + j).innerHTML = list[j].name + ", " + list[j].price;
}
}
function sortprods3(){
currentSort = "LowtoHigh";
list.sort(LowtoHigh);
for (var k = 0; k < list.length; k++) {
document.getElementById("product" + k).innerHTML = list[k].name + ", " + list[k].price;
}
}
function sortprods4(){
currentSort = "HightoLow";
list.sort(HightoLow);
for (var l = 0; l < list.length; l++) {
document.getElementById("product" + l).innerHTML = list[l].name + ", " + list[l].price;
}
}
var input = "";
var index = [];
var currentSort = "AtoZ";
function searchProducts(){
input = document.getElementById("searchbar").value;
if(input == ""){
document.getElementById("product0").style.display = "block";
document.getElementById("product1").style.display = "block";
document.getElementById("product2").style.display = "block";
document.getElementById("product3").style.display = "block";
}else{
switch(currentSort){
case "AtoZ":
list.sort(AtoZ);
for(var a = 0; a < list.length; a++){
document.getElementById("product" + a).innerHTML = list[a].name + ", " + list[a].price;
index.push(list[a].name);
}
index.sort();
break;
case "ZtoA":
list.sort(ZtoA);
for(var b = 0; b < list.length; b++){
document.getElementById("product" + b).innerHTML = list[b].name + ", " + list[b].price;
index.push(list[b].name);
}
index.sort();
index.reverse();
break;
case "LowtoHigh":
list.sort(LowtoHigh);
for(var c = 0; c < list.length; c++){
index.push(list[c].price);
}
index.sort(function(a, b){return a-b});
break;
case "HightoLow":
list.sort(HightoLow);
for(var d = 0; d < list.length; d++){
index.push(list[d].price);
}
index.sort(function(a, b){return b-a});
break;
}
test = input;
re = new RegExp(test, 'gi');
for(var e=0; e<index.length; e++){
if(index[e].match(re)){
document.getElementById("product"+e).style.display = "block";
}else{
document.getElementById("product"+e).style.display = "none";
}
}
}
}
</script>
The code before I adapted the searchProducts function (THAT WORKED PERFECTLY BEFORE ADAPTION) is...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<input type="text" id="searchbar" onkeyup="searchProducts()"/>
<div id="demo"></div>
<div id="demo2">
<div id="product1" style="background-color:red; height:100px; width:100px; float:left">chocolate<br /><button onClick="grow()" id="button1">Show Info</button></div>
<div id="product2" style="background-color:blue; height:100px; width:100px; float:left">Mint</div>
<div id="product3" style="background-color:green; height:100px; width:100px; float:left">Caramel</div>
</div>
</body>
</html>
<script>
var index = ["Chocolate", "Mint", "Caramel"];
var input = "";
var currentLog = [];
function searchProducts(){
currentLog = [];
input = document.getElementById("searchbar").value;
/*function searchStringInArray(str, strArray){
for (var j = 0; j < strArray.length; j++) {
if (strArray[j].match(str)){
var temp = strArray.slice(j, (j + 1));
currentLog.push(temp);
console.log(j);
}
}
document.getElementById("demo").innerHTML = currentLog.join("<br />");
if(currentLog.length < 1){
document.getElementById("demo").innerHTML = "No results were found.";
}
}*/
test = input;
re = new RegExp(test, 'gi');
/*if(!index[0].match(re)){
document.getElementById("product1").style.display = "none";
}
if(!index[1].match(re)){
document.getElementById("product2").style.display = "none";
}
if(!index[2].match(re)){
document.getElementById("product3").style.display = "none";
}*/
for(var e=0; e<index.length; e++){
if(!index[e].match(re)){
document.getElementById("product"+(e+1)).style.display = "none";
}else{
document.getElementById("product"+(e+1)).style.display = "block";
}
}
if(document.getElementById("product1").style.display == "none" && document.getElementById("product2").style.display == "none" && document.getElementById("product3").style.display == "none"){
document.getElementById("demo").innerHTML = "no results";
}else{
document.getElementById("demo").innerHTML = "";
}
/*searchStringInArray(input, index);*/
}
function grow(){
if(document.getElementById('product1').style.height == "200px"){
document.getElementById('product1').style.height = '100px';
document.getElementById('button1').innerHTML = "Show Info";
}else{
document.getElementById('product1').style.height = "200px";
document.getElementById('button1').innerHTML = "Hide Info";
}
}
</script>
The issue is that when you sort your list when a filter was applied earlier, you only move the data, not the visibility of the containers of those data.
Instead you could re-execute the regex matching, every time you display the content according to the current sort order. That way you are sure the right data are visible at all times.
You have a lot of duplication in your code, with several places where you have the same loop, or code that only differs in one aspect. You should always try to "Don't Repeat Yourself" (DRY).
I would suggest to have one function for displaying content only. You could pass it the sort function to apply. Note that this means the HTML also changes where you have specified the event handlers. There are many other such simplifications, which are too many to mention all.
Check this snippet:
var list = [
{name: "Apple", price: 31},
{name: "Banana", price: 22},
{name: "Orange", price: 46},
{name: "Strawberry", price:76}
];
var currentRegex = /./; // any character matches
var currentSort = AtoZ;
// Call the function we have for applying the initial sort order and filter
searchProducts(document.getElementById('searchbar').value);
// Shorter ways to compare:
function AtoZ(a,b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; }
function ZtoA(a,b) { return AtoZ(b,a) }
function LowtoHigh(a,b) { return a.price - b.price }
function HightoLow(a,b) { return b.price - a.price }
// One function for all sort orders: pass sort order as function
function sortprods(sorter) {
var showCount = 0;
currentSort = sorter;
list.sort(currentSort);
for (var i = 0; i < list.length; i++) {
var product = document.getElementById("product" + i);
// use textContent, not innerHTML
product.textContent = list[i].name + ", " + list[i].price;
var show = !!list[i].name.match(currentRegex);
product.style.display = show ? "" : "none";
showCount += show;
}
document.getElementById('resultsSpan').textContent =
showCount ? '' : 'no results';
}
function searchProducts(input){
// Argument is value of input
// No need to `switch` on currentSort. Can do this with generic code.
// Deal with empty input by using all-matching `.` regexp.
// `g` not needed.
currentRegex = new RegExp(input.length ? input : '.', 'i');
sortprods(currentSort);
}
<div id="resultsSpan"></div>
<div id="product0" style="height:45px; width:60px; background-color:lightblue;"></div>
<div id="product1" style="height:45px; width:60px; background-color:lightblue;"></div>
<div id="product2" style="height:45px; width:60px; background-color:lightblue;"></div>
<div id="product3" style="height:45px; width:60px; background-color:lightblue;"></div>
<button onclick="sortprods(AtoZ)">Sort A-Z</button>
<button onclick="sortprods(ZtoA)">Sort Z-A</button>
<button onclick="sortprods(LowtoHigh)">Price (low to high)</button>
<button onclick="sortprods(HightoLow)">Price (high to low)</button>
<input type="text" id="searchbar" onkeyup="searchProducts(this.value)"/>
About the ternary operator:
You asked in comments about the ternary operator:
product.style.display = list[i].name.match(currentRegex) ? "" : "none";
The above is equivalent to this:
var temp;
if (list[i].name.match(currentRegex)) {
temp = "";
} else {
temp = "none";
}
product.style.display = temp;
... except that no temp variable is created of course.
The other occurrence:
currentRegex = new RegExp(input.length ? input : '.', 'i');
... is equivalent to:
var temp;
if (input.length) { // if length is defined and not 0
temp = input;
} else {
temp = ".";
}
currentRegex = new RegExp(temp, 'i');

Categories

Resources