I have used the following code that takes my array and converts it to a HTML table.
const MOUNTAINS = [
{name: "Kilimanjaro", height: 5895, place: "Tanzania"},
{name: "Everest", height: 8848, place: "Nepal"},
{name: "Mount Fuji", height: 3776, place: "Japan"},
{name: "Vaalserberg", height: 323, place: "Netherlands"},
{name: "Denali", height: 6168, place: "United States"},
{name: "Popocatepetl", height: 5465, place: "Mexico"},
{name: "Mont Blanc", height: 4808, place: "Italy/France"}
];
function buildTable(data) {
let table = document.createElement("table");
let fields = Object.keys(data[0]);
let headRow = document.createElement("tr");
fields.forEach(function(field) {
let headCell = document.createElement("th");
headCell.appendChild(document.createTextNode(field));
headRow.appendChild(headCell);
});
table.appendChild(headRow);
data.forEach(function(object) {
let row = document.createElement("tr");
fields.forEach(function(field) {
let cell = document.createElement("td");
cell.appendChild(document.createTextNode(object[field]));
if (typeof object[field] == "number") {
cell.style.textAlign = "right";
}
row.appendChild(cell);
});
table.appendChild(row);
});
return table;
}
document.querySelector("#mountains").appendChild(buildTable(MOUNTAINS));
I am now trying to make a filter/search function to this table. When a user types in "K", only mountains starting with the letter K should be displayed. I have tried the following:
function searchTable() {
var input, filter, table, tr, td, i;
input = document.getElementById(myInput);
filter = input.value.toUpperCase();
table = document.getElementsByTagName("table");
tr = tr.getElementsByTagName("tr");
for(i = 0; < tr.length; i++;){
td = tr[i].getElementsByTagName("td")[0];
if(td.innerHTML.toUpperCase().indexOf(filter)>-1){
tr[i].style.display=""
}else{
tr[i.style.display="none";]
}
}
}
When I link the list and use an input tag in my HTML document it does not work. I am very new to javascript and hope any of you can help me to where I go wrong or what I should do differently.
Thanks!
try following jquery. txtSearch is the ID of input text field
$("#txtSearch").on("keyup", function () {
$("#mountains .divnodata").remove();
var value = $(this).val().toLowerCase();
$("#mountains tr td:nth-of-type(1)").filter(function () {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) ==0);// >-1
});
if ($("#mountains tr:not(:first):visible").length == 0) {
$("#mountains").append("<tr class='divnodata'><td colspan='3'>No data</td></tr>");
}
});
Or try following Javascript
var bb = document.getElementById('txtSearch');
bb.addEventListener('keyup', function() {
var filter = this.value.toUpperCase();
var mm = document.getElementById('mountains');
var input = document.getElementById(txtSearch);
var tr = mm.getElementsByTagName("tr");
var td;var index=0;
for(i = 1; i< tr.length; i++){
index++;
td = tr[index].getElementsByTagName("td")[0];
if(td.innerHTML.toUpperCase().indexOf(filter)==0){
tr[index].style.display=""
}else{
tr[index].style.display="none";
}
}
});
Related
I have a table that is created by javascript when it obtains data from the data base, this is the function
function gotCData(snapshot){
snapshot.forEach(userSnapshot => {
var confirmed = userSnapshot.val().confirmed;
var date = userSnapshot.val().date;
var deaths = userSnapshot.val().deaths;
var recovered = userSnapshot.val().recovered;
//console.log(confirmed, date, deaths, recovered);
var local = k;
var csvDate = date;
var population = recovered;
var totalCases = confirmed;
var totalDeaths = deaths;
//console.log(location);
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
var td4 = document.createElement('td');
var td5 = document.createElement('td');
var tdLocal = document.createTextNode(local);
var tdPopulation = document.createTextNode(population);
var tdTotalCases = document.createTextNode(totalCases);
var tdTotalDeaths = document.createTextNode(totalDeaths);
var tdDate = document.createTextNode(csvDate);
td1.appendChild(tdLocal)
td2.appendChild(tdPopulation)
td3.appendChild(tdTotalCases)
td4.appendChild(tdTotalDeaths)
td5.appendChild(tdDate)
var tRow1 = document.getElementById("displayCorona").appendChild(td1);
var tRow2 = document.getElementById("displayCorona").appendChild(td2);
var tRow3 = document.getElementById("displayCorona").appendChild(td3);
var tRow4 = document.getElementById("displayCorona").appendChild(td4);
var tRow5 = document.getElementById("displayCorona").appendChild(td5);
//Writes the Table Row then the Divs after
document.getElementById("displayCorona").appendChild(tr, tRow1, tRow2, tRow3, tRow4, tRow5);
});
}
I have a search function :
function search(){
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("displayCorona");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td1")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
The tables are created when I loop through each node in a Firebase database. The search function is from W3Schools but im not sure why it is not searching the table that is created by the above function.
Here's some code for you to look at.
"use strict";
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onLoad, false);
function onLoad(evt)
{
var inputStr = "I have a table that is created by javascript when it obtains data from the data base, this is the function";
document.body.appendChild( makeTable(inputStr) );
byId('goBtn').addEventListener('click', onGoBtn, false);
}
function makeTable(input)
{
let tbl = newEl('table');
input = input.replace(',', '');
let words = input.split(' ');
let nWords = words.length;
let nRows = parseInt(nWords/5) + nWords%5;
for (var j=0; j<nRows; j++)
{
let tr = newEl('tr');
for (var col=0; col<5; col++)
{
let td = newEl('td');
td.textContent = words[j*5 + col];
tr.appendChild(td);
}
tbl.appendChild(tr);
}
return tbl;
}
function highlightContainingCells(input, highlightClassname)
{
let cells = document.querySelectorAll('td');
cells.forEach( cellFunc );
function cellFunc(curCell)
{
if (input == curCell.textContent)
curCell.classList.add(highlightClassname);
else
curCell.classList.remove(highlightClassname);
}
}
function onGoBtn(evt)
{
let str = byId('searchStr').value;
highlightContainingCells(str, "found");
}
td
{
color: #333;
background-color: #ddd;
}
td.found
{
color: #ddd;
background-color: #333;
}
<input id='searchStr' value='javascript'/><button id='goBtn'>SEARCH</button></br>
There were so many wrong things.
You had not specified what data type snapshot is. Is it array or something else? I assumed it to be array of JSON objects, where each object denotes a row in your table.
I did not understand the use of .val() method. I removed it completely.
The table being generates was not in correct format. You were appending tr to table. But instead of appending td to tr you were also appending them to table. I have corrected that also.
There was an undefined variable k which was being used to set local.
display:block style on tr was displaying table in a weird way once rows are eliminated. I changed it to display:table-row instead, which is ideal for table-rows
function gotCData(snapshot) {
snapshot.forEach(userSnapshot => {
var confirmed = userSnapshot.val().confirmed;
var date = userSnapshot.val().date;
var deaths = userSnapshot.val().deaths;
var recovered = userSnapshot.val().recovered;
var local = userSnapshot.local; // we will look at this later
// console.log(confirmed, date, deaths, recovered);
// var local = k;
var csvDate = date;
var population = recovered;
var totalCases = confirmed;
var totalDeaths = deaths;
//console.log(location);
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var td2 = document.createElement('td');
var td3 = document.createElement('td');
var td4 = document.createElement('td');
var td5 = document.createElement('td');
var tdLocal = document.createTextNode(local);
var tdPopulation = document.createTextNode(population);
var tdTotalCases = document.createTextNode(totalCases);
var tdTotalDeaths = document.createTextNode(totalDeaths);
var tdDate = document.createTextNode(csvDate);
td1.appendChild(tdLocal)
td2.appendChild(tdPopulation)
td3.appendChild(tdTotalCases)
td4.appendChild(tdTotalDeaths)
td5.appendChild(tdDate)
tr.appendChild(td1)
tr.appendChild(td2)
tr.appendChild(td3)
tr.appendChild(td4)
tr.appendChild(td5)
// Writes the Table Row then the Divs after
document.getElementById("displayCorona").appendChild(tr);
});
}
function search() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("displayCorona");
tr = table.querySelectorAll("tr:not(.table-head)");
// Loop through all table rows, and hide those who don't match the search query
var found
for (i = 0; i < tr.length; i++) {
tds = tr[i].getElementsByTagName("td")
if (tds) {
found = false
for (j = 0; j < tds.length && found == false; j++) {
td = tds[j];
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "table-row";
found = true
break
}
}
if (found == false) tr[i].style.display = "none";
}
}
}
// This is used for testing only
// window.onload = () => {
// snapshot = firebaseToArray(firebaseJSON)
// gotCData(snapshot)
// }
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
margin-top: 20px;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="myInput">
<button type="submit" onclick="search()">Search</button>
<table id="displayCorona">
<tr class="table-head">
<th>Location</th>
<th>Population</th>
<th>Total cases</th>
<th>Total deaths</th>
<th>Date</th>
</tr>
</table>
</body>
</html>
Some friendly advice:
I see you have extracted data from snapshot and assign them twice to variables, for say you first extract date from snapshot and then assign it to csvDate, while you could directly extract date to csvDate
You were creating text nodes for td, assigning them values and appending them to corresponding td node. You could directly insert data using innerHTML or innerText for example, td1.innerText = local. No need to create textNodes and append them!
It seems like you directly copy-pasted code for search function from w3schools. Please review such codes after using.
Use developer console to find common errors. Debugging your code can solves many common problems, so get familiar with it.
I have a filter function, based on this that hides table rows. I want to add the float values from the table if the row is not being hidden and then replace the original sum field below the table. So far I got the following, but for some reason it won't work and I can't figure out why:
function filter() {
var input, filter, table, tr, origresults, origsum, newresults, newsum, td, i;
input = document.getElementById("input");
filter = input.value.toUpperCase();
table = document.getElementById("list");
tr = table.getElementsByTagName("tr");
origresults = document.getElementById("results");
origsum = document.getElementById("sum");
newresults = 0;
newsum = 0.0;
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
newresults++;
newsum += parseFloat(td);
} else {
tr[i].style.display = "none";
}
}
}
origresults.innerHTML = newresults;
origsum.innerHTML = parseFloat(newsum).toFixed(2);
}
It always says NaN, but I can't figure out why.
newsum = parseFloat(newsum) + parseFloat(td); doesn't work either.
My mistake was to calculate with td instead of td.innerHTML. So the parseFloat function returned a NaN because td obviously contains the complete tag and not just it's content.
This works:
function filter() {
var input, filter, table, tr, origresults, origsum, newresults, newsum, td, i;
input = document.getElementById("input");
filter = input.value.toUpperCase();
table = document.getElementById("list");
tr = table.getElementsByTagName("tr");
origresults = document.getElementById("results");
origsum = document.getElementById("sum");
newresults = 0;
newsum = 0.0;
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
newresults++;
newsum += parseFloat(td.innerHTML);
} else {
tr[i].style.display = "none";
}
}
}
origresults.innerHTML = newresults;
origsum.innerHTML = parseFloat(newsum).toFixed(2);
}
I wanted to use the same javascript filter on the same page but with two or three different tables and different input field. Here below is the script I've been using to filter out dates on a table.
What if there are 2 or more tables?
function filterFunction() {
var input, filter, table, tr, td, i, totalViewable = 0;
input = document.getElementById("event_date_range");
filter = input.value.toUpperCase();
table = document.getElementById("dateTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
tds = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
totalViewable += parseFloat(tds.innerHTML);
document.getElementById("total_amount_td").innerHTML = "$" + totalViewable.toFixed(2);
} else {
tr[i].style.display = "none";
}
}
}
}
Table - dataTable
Input field - event_date_range
Output text - total_amount_td
Pass the table, input and total_amount_id as parameters to your filterFunction:
Something like:
function filterFunction(table, input, total_amount_id) {
var filter, tr, td, i, totalViewable = 0;
filter = input.value.toUpperCase();
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
tds = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
totalViewable += parseFloat(tds.innerHTML);
document.getElementById(total_amount_id).innerHTML = "$" + totalViewable.toFixed(2);
} else {
tr[i].style.display = "none";
}
}
}
}
And then call the function with different parameters:
var table1 = document.getElementById("dateTable");
var input1 = document.getElementById("event_date_range");
var total_amount_id1 = "total_amount_td";
filterFunction(table1, input1, total_amount_id1);
var table2 = document.getElementById("dateTable2");
var input2 = document.getElementById("event_date_range2");
var total_amount_id2 = "total_amount_td2";
filterFunction(table2, input2, total_amount_id2);
I was trying to use 2 different tables, different input field, and different text in a single script. I use this script below to pass those values on a function parameter to get those values. The problem is I am not getting the input.value but I can get the input1.value. I think the input1 is not going inside the filterFunction(input) above
<script type="text/javascript">
function filterFunction(table, input, total_amount_id) {
var filter, tr, td, i, totalViewable = 0;
console.log(input1.value);
console.log(input);
filter = input.value.toUpperCase();
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
tds = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
totalViewable += parseFloat(tds.innerHTML);
document.getElementById(total_amount_id).innerHTML = "$" + totalViewable.toFixed(2);
} else {
tr[i].style.display = "none";
}
}
}
}
var table1 = document.getElementById("dateTable");
var input1 = document.getElementById("event_date_range");
var total_amount_id1 = "total_amount_td";
filterFunction(table1, input1, total_amount_id1);
var table2 = document.getElementById("dateTable2");
var input2 = document.getElementById("event_date_range2");
var total_amount_id2 = "total_amount_td2";
filterFunction(table2, input2, total_amount_id2);
</script>
var input1 = document.getElementById("event_date_range");
In this expression you are placing value in input1.
so you cannot ge the {input} value.
I am building a table dynamically with JavaScript, and I need to nest another table which will be a jQuery datatable inside the first table which is HTML.
I have what I thought would work and after researching, I don't see why it isn't working. I am defining my first table, building out the header and then adding rows. Inside of a cell, I build the table that will be the datatable.
Using console.log, it looks to be built correctly, but it doesn't display correctly. Instead, it shows only the first table and then appears as if it is not in a table, but rather just haphazardly placed on the page. Here is my code. I would greatly appreciate it if someone will look at it and see if they see a problem with it.
By the way, I don't think it would make any difference, but my openDetailRow function is based on a click coming from a row in an existing datatable.
function openDetailRow() {
$("#gridTbl tr td:nth-child(1)").on("click",
function () {
var ndx = $(this).closest('tr').find('td:eq(0)').text();
var dataRow = reportApp.grid.fnGetData(this.parentNode);
addElements(dataRow);
});
}
function getDetails() {
$("#hdrTbl").dialog({
resizable: false,
modal: true,
title: "Order Details",
height: 250,
width: 700,
buttons: {
"Close": function () {
$(this).dialog('destroy');
$(this).remove();
$("#ordDiv").remove();
}
}
});
}
function buildHdrTable(dataRow){
var hdrDets = [];
hdrDets[0] = dataRow.ordnbr;
hdrDets[1] = dataRow.custordnbr;
hdrDets[2] = dataRow.carrier;
hdrDets[3] = dataRow.custid;
var rowDets = [];
dataRow.detail.forEach(
function (el) {
var rowAr = [];
rowAr[0] = el.invtid;
rowAr[1] = el.descr;
rowAr[2] = el.pcs;
rowAr[3] = el.status;
rowDets.push(rowAr);
});
hdrTbl = document.createElement('table');
hdrTbl.cellPadding = 5;
hdrTbl.style.width = '750px';
hdrTbl.style.display = 'none';
hdrTbl.setAttribute("id", "hdrTbl");
var hdrVals = ["Ord #", "Cust Ord #", "Ship Via", "Cust ID" ];
var tblHead = document.createElement('thead');
hdrTbl.appendChild(tblHead);
tblHeadRow = document.createElement("tr");
tblHead.appendChild(tblHeadRow);
for(var i =0; i < hdrVals.length; i++){
tblHeadRow.appendChild(document.createElement("th")).
appendChild(document.createTextNode(hdrVals[i]));
}
var hdrBody = document.createElement("tbody");
hdrTbl.appendChild(hdrBody);
var tr = hdrBody.insertRow();
var td1 = tr.insertCell();
var td2 = tr.insertCell();
var td3 = tr.insertCell();
var td4 = tr.insertCell();
td1.appendChild(document.createTextNode(hdrDets[0]));
td2.appendChild(document.createTextNode(hdrDets[1]));
td3.appendChild(document.createTextNode(hdrDets[2]));
td4.appendChild(document.createTextNode(hdrDets[3]));
var bdy = hdrBody.insertRow();
var bdyTbl = bdy.insertCell();
tbl = document.createElement('table');
tbl.style.width = '100%';
tbl.style.display = 'none';
//tbl.style.border = "1px solid black";
tbl.setAttribute("id", "ordertable");
var headVals = ["Inventory Number", "Description", "Number of Pieces", "Status"];
var thead = document.createElement('thead');
tbl.appendChild(thead);
var theadRow = document.createElement("tr");
thead.appendChild(theadRow);
for (var i = 0; i < headVals.length; i++) {
theadRow.appendChild(document.createElement("th"))
.appendChild(document.createTextNode(headVals[i]));
}
var tbody = document.createElement("tbody");
tbl.appendChild(tbody);
for (var i = 0; i < rowDets.length; i++) {
var tr = tbody.insertRow();
var td1 = tr.insertCell();
var td2 = tr.insertCell();
var td3 = tr.insertCell();
var td4 = tr.insertCell();
td1.appendChild(document.createTextNode(rowDets[i][0]));
td2.appendChild(document.createTextNode(rowDets[i][1]));
td3.appendChild(document.createTextNode(rowDets[i][2]));
td4.appendChild(document.createTextNode(rowDets[i][3]));
bdyTbl.appendChild(tbl);
}
return hdrTbl;
}
function addElements(dataRow) {
var body = document.body;
var hdrTbl = buildHdrTable(dataRow);
ordDiv = document.createElement("div");
ordDiv.appendChild(hdrTbl);
ordDiv.setAttribute("id", "ordDiv");
body.appendChild(ordDiv);
$("#ordertable").css('display', 'none');
$("#ordertable").dataTable(tbl);
getDetails();
console.log(hdrTbl);
}
The issue was caused because I was using display:none. Now here is the thing.. If you don't use that particular style attribute, then the table will show up on the page. However, since it is nested inside my first table, and the first table has the display:none style attribute already applied to it, then by applying it to the second table, it would not allow that table to be shown on page.
As for the skewed look, I had not set a colspan. So now, it is working perfectly. I commented out the display none and added this one line of code...
bdyTbl.setAttribute("colspan", 4);