I have been twisting my head around on this and I can't seem to fix it.
I have not coded much, but wanting to learn. However, I am trying to make a table in which when there is no input the entire table vanishes.
As of now I have managed to get it so that it starts as vanished, and that when information is inserted into the search box the non-relevant lines dissapear. However, when all text in the search box is removed the entire table is showing. I want the table to stay hidden when there is no text that matches.
Would love to get any feedback on what I am doing wrong here.
function performSearch() {
// Declare search string
var filter = searchBox.value.toUpperCase();
// Loop through first tbody's rows
for (var rowI = 0; rowI < trs.length; rowI++) {
// define the row's cells
var tds = trs[rowI].getElementsByTagName("td");
// hide the row
trs[rowI].style.display = "none";
// loop through row cells
for (var cellI = 0; cellI < tds.length; cellI++) {
// if there's a match
if (tds[cellI].innerHTML.toUpperCase().indexOf(filter) > -1)
{
// show the row
myTable.style.display = "table";
trs[rowI].style.display = "";
// skip to the next row
continue;
}
}
}
}
// declare elements
const searchBox = document.getElementById('searchBox');
const table = document.getElementById("myTable");
const trs = table.tBodies[0].getElementsByTagName("tr");
// add event listener to search box
searchBox.addEventListener('keyup', performSearch);
* {
box-sizing: border-box;
}
#searchBox {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 30%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
position: relative;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
#myTable {
border-collapse: collapse;
width: 80%;
border: 1px solid #ddd;
font-size: 18px;
position: relative;
left: 10%;
display: none;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
#Overskrift {
width: 100%;
text-align-last: center;
font-size: 40px;
}
<input class="form-control" type="text" id="searchBox" placeholder="Search ..." onkeyup="searchTableColumns()">
<table id="myTable">
<thead>
<tr class="header">
<th onclick="sortTable(0)" style="width:35%;">Fagnavn</th>
<th onclick="sortTable(1)" style="width:21%;">LK20</th>
<th onclick="sortTable(2)" style="width:21%;">LK06</th>
<th onclick="sortTable(3)" style="width:21%;">R94</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pika</td>
<td>Chu</td>
<td>Poke</td>
<td>Mon</td>
</tr>
<tr>
<td>Temporary</td>
<td>Text</td>
<td>Fields</td>
<td>Here</td>
</tr>
</tbody>
</table>
There is a simple solution for this. Just add a check to the end your performSearch function:
if (searchBox.value === ''){
table.style.display='none';
}
else {
table.style.display='table';
}
You can also check it here:
https://codepen.io/serazoltan/pen/dyZRprb
Related
.net mvc efcore, no angular, abp 5.3.1
Purpose: Dynamic search within a table.
Method: I create modal according to the tutorial (https://docs.abp.io/en/abp/latest/Tutorials/Part-3?UI=MVC&DB=EF). I add table, css and js codes into it. Myinput will filter the word entered in the textbox by searching in the 3rd column of the Mytables table. (https://www.w3schools.com/howto/howto_js_filter_table.asp)
Problem: There is no problem with tables and css, but js codes are not triggered in any way.
#page
#using xxx.Localization
#using xxx.xxx.Web.Pages.xxx
#using Microsoft.Extensions.Localization
#using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
#model xxxModalModel
#inject IStringLocalizer<xxxx> L
#{
Layout = null;
}
<style>
#myInput {
width: 100%; /* Full-width */
font-size: 10px; /* Increase font-size */
padding: 5px 5px 5px 5px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 5px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 10px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 5px; /* Add padding */
}
#myTable tr {
/* Add a bottom border to all table rows */
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
/* Add a grey background color to the table header and on hover */
background-color: #f1f1f1;
}
</style>
<form asp-page="/xxx/xxx">
<abp-modal>
<abp-modal-header title="#L["xxx"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<abp-table responsive-md="true" small="true" striped-rows="true" id="myTable" border-style="Bordered">
<thead>
<tr>
<th scope="Column">#</th>
<th scope="Column">1</th>
<th >2</th>
<th >3</th>
<th >4</th>
<th >5</th>
<th >6</th>
</tr>
</thead>
<tbody>
#{
var sutun = 1;
for (var i = 0; i < Model.xxx.Count; i++)
{
if (#Model.xxx[i].IsSelected)
{
var x= Model.xxx[i];
<tr>
<th scope="Row">#sutun</th>
<td>#Model.xxx[i].1</td>
<td>#Model.xxx[i].2</td>
<td>#Model.xxx[i].3</td>
<td>#Model.xxx[i].4</td>
<td>#Model.xxx[i].5</td>
<td>#Model.xxx[i].6</td>
</tr>
sutun +=1;
}
}
}
</tbody>
</abp-table>
</abp-modal-body>
<abp-modal-footer></abp-modal-footer>
</abp-modal>
</form>
<script>
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
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("td")[3];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.indexOf.toUpperCase(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
My Css code was working just fine, until I added my Javascript code, which works as a sorter for the table itself, the Javascript code seems to change my Css code (the green color when on hover on the first row and the last one) for the first row < tr > but not the last one.
In the code I used Css and Javascript comments to explain the origin of the problem and what could be fixed, I think it originates from the Javascript code. All I want is for the first row to be green when clicked on or hovered on and also the last one.
$(document).ready(function() {
$('th').each(function(col) {
$(this).hover(
function() {
$(this).addClass('focus');
},
function() {
$(this).removeClass('focus');
}
);
$(this).click(function() {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $('table').find('tbody >tr:has(td)').get();
arrData.sort(function(a, b) {
var val1 = $(a).children('td').eq(col).text().toUpperCase();
var val2 = $(b).children('td').eq(col).text().toUpperCase();
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else
return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
});
$.each(arrData, function(index, row) {
$('tbody').append(row);
});
});
});
});
* {
margin: 0;
padding: 0;
z-index: 0;
list-style: none;
box-sizing: border-box;
text-align: center: vertical-align: center;
transition: .4s;
}
body {
color: white;
margin: 0;
width: 100%;
background: #212121;
text-align: center: vertical-align: center;
height: 120em;
}
/* CSS OF TABLE */
table {
font-family: Arial, Helvetica, sans-serif;
width: 100%;
position: absolute;
top: 10em;
border-collapse: collapse;
text-align: center: z-index: 1000;
font-size: 0.8125em;
}
table td,
table th {
border: solid;
border-width: 0 .001em .001em .001em;
border-color: black;
padding: .1em .3em .1em .3em;
text-align: center;
}
table tr:nth-child(odd) {
background-color: #f6f6f8;
}
table tr:nth-child(even) {
background-color: #CACCD6;
}
/* THIS IS WHAT DOESN'T WORK */
table tr:first-child {
background-color: #0CDC80;
color: white;
}
/* AS WELL AS THIS */
table tr:last-child {
background-color: #DA0F3A;
color: white;
}
table tr:hover {
background-color: #676B77;
color: white;
font-weight: 900;
}
table th {
padding: .5em;
text-align: center;
background-color: #6C06D8;
color: #f6f6f8;
text-transform: uppercase;
font-weight: 900;
}
#supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
table tr:nth-child(odd) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .1);
}
table tr:nth-child(even) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .2);
}
/* THIS IS EXACTLY WHAT I NEED */
table tr:first-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(12, 220, 128, .6);
}
/* THIS IS ALREADY WORKING NO IDEA WHY */
table tr:last-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(218, 15, 58, .6);
}
table tr:hover {
background-color: rgba(0, 0, 0, .01);
font-weight: 900;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>HOMETOWN</th>
<th>SOCIALS</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td>$520</td>
<td>easy/medium</td>
<td>okay</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
</table>
It looks as though the javascript isn't affecting it (but I'll check this).
On a table the first row is the one containing the headings (i.e. the th tags). The css rule that's styling the th elements is overriding the table tr:first-child:hover rule because the th elements appear on top of the tr element. If you remove the table th rule, the change of colour on the top row works. If you want the row that has $520 in the first column to change colour on hover then use the nth-child(2) pseudo class.
The rules tagged 'THIS IS WHAT DOESN'T WORK' and 'AS WELL AS THIS' don't work because the nth-child(odd) and nth-child(even) rules appear after these two rules and in css the last rule 'wins'. If you move these rules after the nth-child(odd) and (even) rules then it works.
It's worthwhile reading up on specificity. There's a good article here and a good video on it by Kevin Powell here (Kevin's channel is brilliant btw and well worth a follow). But yeah, specificity is one of those things that drives developers mad (especially newbies)!
Hope this helps
P.S. there were a number of typos in your CSS too such as missing semicolons etc.
P.P.S my changes below:
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="jquery-3.6.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
z-index: 0;
list-style: none;
box-sizing: border-box;
text-align: center;
vertical-align: center;
transition: .4s;
}
body {
color: white;
margin: 0;
width: 100%;
background: #212121;
text-align: center;
vertical-align: center;
height: 120em;
}
/* CSS OF TABLE */
table {
font-family: Arial, Helvetica, sans-serif;
width: 100%;
position: absolute;
top: 10em;
border-collapse: collapse;
text-align: center;
z-index: 1000;
font-size: 0.8125em;
}
table td,
table th {
border: solid;
border-width: 0 .001em .001em .001em;
border-color: black;
padding: .1em .3em .1em .3em;
text-align: center;
}
table tr:nth-child(odd) {
background-color: #f6f6f8;
}
table tr:nth-child(even) {
background-color: #CACCD6;
}
table tr:hover {
background-color: #676B77;
color: white;
font-weight: 900;
}
table th {
padding: .5em;
text-align: center;
background-color: #6C06D8;
color: #f6f6f8;
text-transform: uppercase;
font-weight: 900;
}
#supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
table tr:nth-child(odd) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .1);
}
table tr:nth-child(even) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .2);
}
/* THIS IS WHAT DOESN'T WORK - moved this to below table:tr:nth*/
table tr:nth-child(2) {
background-color: #0CDC80;
color: white;
}
/* AS WELL AS THIS - moved this to below table:tr:nth */
table tr:last-child {
background-color: #DA0F3A;
color: white;
}
table tr:hover {
background-color: rgba(0, 0, 0, .01);
font-weight: 900;
}
/* THIS IS EXACTLY WHAT I NEED - changed this from first-child to nth-child(2)*/
table tr:nth-child(2):hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(12, 220, 128, .6);
}
/* THIS IS ALREADY WORKING NO IDEA WHY */
table tr:last-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(218, 15, 58, .6);
}
}
</style>
</head>
<body>
<table>
<tr>
<th>HOMETOWN</th>
<th>SOCIALS</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td>$520</td>
<td>easy/medium</td>
<td>okay</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
</table>
<script>
/* POSSIBLE ORIGIN OF PROBLEM */
$(document).ready(function () {
$('th').each(function (col) {
$(this).hover(
function () {
$(this).addClass('focus');
},
function () {
$(this).removeClass('focus');
}
);
$(this).click(function () {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $('table').find('tbody >tr:has(td)').get();
arrData.sort(function (a, b) {
var val1 = $(a).children('td').eq(col).text().toUpperCase();
var val2 = $(b).children('td').eq(col).text().toUpperCase();
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else
return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
});
$.each(arrData, function (index, row) {
$('tbody').append(row);
});
});
});
});
</script>
</body>
</html>
I've build a simple Expense Tracker that contains 3 inputs
Name input
Date input
Amount input
After the user fills these 3 inputs, they can click a button to add the expense into a table and store it there. If they want to remove an expense from the table, they can click the "REMOVE ENTRY" button.
If the table is empty, the "No expenses added yet!" tr element is shown. Once an expense gets added, the tr element with the message disappears. However, if I add an expense to the table and then remove it, the tr element with the message no longer appears. Is there any way how I can make it re-appear again?
let nameInput = document.querySelector(".name");
let dateInput = document.querySelector(".date");
let amountInput = document.querySelector(".amount");
let button = document.querySelector(".add-btn");
let ifEmpty = document.querySelector(".if-empty");
let table = document.querySelector("table");
button.addEventListener("click", function() {
ifEmpty.remove();
// CREATE THE EXPENSE
let holder = document.createElement("tr");
let row = document.createElement("td");
let btnRow = document.createElement("td");
let removeButton = document.createElement("button");
table.appendChild(holder);
holder.appendChild(row).textContent = nameInput.value;
holder.appendChild(row.cloneNode(true)).textContent = dateInput.value;
holder.appendChild(row.cloneNode(true)).textContent = amountInput.value;
holder.appendChild(btnRow);
btnRow.appendChild(removeButton).textContent = "REMOVE ENTRY";
// REMOVE THE EXPENSE
removeButton.addEventListener("click", function() {
holder.remove();
});
/* TRIED THIS TO MAKE THE ELEMENT RE-APPEAR IF THE TABLE IS EMPTY BUT
IT DIDN'T WORK */
if (!table.contains(holder)) {
table.appendChild(ifEmpty);
}
});
.container {
text-align: center;
}
h1 {
font-size: 3.5em;
}
h2 {
font-size: 2em;
margin-bottom: 0.5em;
color: green;
}
span {
font-size: 1.4em;
}
.date-amount-input {
margin-top: 0.5em;
}
input {
height: 28px;
}
.name {
padding-right: 5em;
}
.amount {
padding-right: 15.35em;
}
.amount-text {
margin-left: 0.4em;
}
.date {
padding-right: 18.8em;
}
.add-btn {
margin-top: 0.9em;
padding: 0.6em;
font-size: 1.1em;
background: green;
color: white;
border: none;
border-radius: 5px;
}
.add-btn:hover, .add-btn:focus {
cursor: pointer;
background: rgb(3, 177, 3);
}
table {
margin: 0 auto;
margin-top: 2em;
width: 50%;
height: 80px;
}
tr {
height: 40px;
}
table, th, td{
border: 1px solid rgba(0, 0, 0, 0.103);
border-collapse: collapse;
}
.empty-text {
font-size: 0.93em;
}
.if-empty {
background: rgba(0, 0, 0, 0.055);
}
<body>
<div class="container">
<h1>Expense Tracker</h1>
<h2>Add A New Item</h2>
<div class="name-input">
<span class="name-text">Name: </span>
<input type="text" class="name" placeholder="Where was the expense made" size="117">
</div>
<div class="date-amount-input">
<span>Date: </span>
<input class="date" type="date">
<span class="amount-text">Amount: </span>
<input class="amount" type="text">
</div>
<button class="add-btn">Add Expense</button>
<table>
<tr>
<th>Name</th>
<th>Date</th>
<th>Amount</th>
</tr>
<tr class="if-empty">
<td colspan = "4">
<span class="empty-text">No expenses added yet!</span>
</td>
</tr>
</table>
</div>
<script src="main.js"></script>
</body>
I am still a beginner in JS, so any tips will be aprecitated.
You do an ifEmpty.remove();, that actually removes the element. Once it is removed it is gone and you can't make it reappear without creating it again.
The easier solution may be to hide it instead of removing it.
You can use ifEmpty.style.display = "none" to hide it and ifEmpty.style.display = "table-row" to show it again
Show/hide can be done with pure CSS, display as table-row if it is the last <tr>. Make sure new rows are added inside the same <tbody>.
tr.if-empty {
background: rgba(0, 0, 0, 0.055);
display: none;
}
tr:last-child.if-empty {
display: table-row;
}
let nameInput = document.querySelector(".name");
let dateInput = document.querySelector(".date");
let amountInput = document.querySelector(".amount");
let button = document.querySelector(".add-btn");
let ifEmpty = document.querySelector(".if-empty");
let table = document.querySelector("table > tbody");
button.addEventListener("click", function() {
// CREATE THE EXPENSE
let holder = document.createElement("tr");
let row = document.createElement("td");
let btnRow = document.createElement("td");
let removeButton = document.createElement("button");
table.appendChild(holder);
holder.appendChild(row).textContent = nameInput.value;
holder.appendChild(row.cloneNode(true)).textContent = dateInput.value;
holder.appendChild(row.cloneNode(true)).textContent = amountInput.value;
holder.appendChild(btnRow);
btnRow.appendChild(removeButton).textContent = "REMOVE ENTRY";
// REMOVE THE EXPENSE
removeButton.addEventListener("click", function() {
holder.remove();
});
});
.container {
text-align: center;
}
h1 {
font-size: 3.5em;
}
h2 {
font-size: 2em;
margin-bottom: 0.5em;
color: green;
}
span {
font-size: 1.4em;
}
.date-amount-input {
margin-top: 0.5em;
}
input {
height: 28px;
}
.name {
padding-right: 5em;
}
.amount {
padding-right: 15.35em;
}
.amount-text {
margin-left: 0.4em;
}
.date {
padding-right: 18.8em;
}
.add-btn {
margin-top: 0.9em;
padding: 0.6em;
font-size: 1.1em;
background: green;
color: white;
border: none;
border-radius: 5px;
}
.add-btn:hover, .add-btn:focus {
cursor: pointer;
background: rgb(3, 177, 3);
}
table {
margin: 0 auto;
margin-top: 2em;
width: 50%;
height: 80px;
}
tr {
height: 40px;
}
table, th, td{
border: 1px solid rgba(0, 0, 0, 0.103);
border-collapse: collapse;
}
.empty-text {
font-size: 0.93em;
}
tr.if-empty {
background: rgba(0, 0, 0, 0.055);
display: none;
}
tr:last-child.if-empty {
display: table-row;
}
<body>
<div class="container">
<h1>Expense Tracker</h1>
<h2>Add A New Item</h2>
<div class="name-input">
<span class="name-text">Name: </span>
<input type="text" class="name" placeholder="Where was the expense made" size="117">
</div>
<div class="date-amount-input">
<span>Date: </span>
<input class="date" type="date">
<span class="amount-text">Amount: </span>
<input class="amount" type="text">
</div>
<button class="add-btn">Add Expense</button>
<table>
<tbody>
<tr>
<th>Name</th>
<th>Date</th>
<th>Amount</th>
</tr>
<tr class="if-empty">
<td colspan = "4">
<span class="empty-text">No expenses added yet!</span>
</td>
</tr>
</tbody>
</table>
</div>
<script src="main.js"></script>
</body>
Instead of deleting the element from page, you can simply hide it with CSS.
Add following class in CSS:
.hide{
display: none;
}
Now, create a function in JavaScript that checks if the table if Empty excluding header row and ifEmpty row:
let toggleIfEmpty = () => {
if(table.getElementsByTagName('tr').length <= 2){
ifEmpty.classList.remove("hide");
} else {
ifEmpty.classList.add("hide");
}
};
Call this function on eventListener:
removeButton.addEventListener("click", function() {
holder.remove();
toggleIfEmpty();
});
Then call the function again instead of appending the child element:
Do this: toggleIfEmpty();
Instead of:
if (!table.contains(holder)) {
table.appendChild(ifEmpty);
}
It will work.
Full updated JS for your reference:
let nameInput = document.querySelector(".name");
let dateInput = document.querySelector(".date");
let amountInput = document.querySelector(".amount");
let button = document.querySelector(".add-btn");
let ifEmpty = document.querySelector(".if-empty");
let table = document.querySelector("table");
let toggleIfEmpty = () => {
if(table.getElementsByTagName('tr').length <= 2){
ifEmpty.classList.remove("hide");
} else {
ifEmpty.classList.add("hide");
}
};
button.addEventListener("click", function() {
// CREATE THE EXPENSE
let holder = document.createElement("tr");
let row = document.createElement("td");
let btnRow = document.createElement("td");
let removeButton = document.createElement("button");
table.appendChild(holder);
holder.appendChild(row).textContent = nameInput.value;
holder.appendChild(row.cloneNode(true)).textContent = dateInput.value;
holder.appendChild(row.cloneNode(true)).textContent = amountInput.value;
holder.appendChild(btnRow);
btnRow.appendChild(removeButton).textContent = "REMOVE ENTRY";
// REMOVE THE EXPENSE
removeButton.addEventListener("click", function() {
holder.remove();
toggleIfEmpty();
});
/* TRIED THIS TO MAKE THE ELEMENT RE-APPEAR IF THE TABLE IS EMPTY BUT
IT DIDN'T WORK */
/* if (!table.contains(holder)) {
table.appendChild(ifEmpty);
} */
toggleIfEmpty();
});
You can do something like this, inside of the eventListener for the remove entry button you can check if the number of children elements inside the table is less than or equal to 1 (including the name date and amount element) in that case there will be no entries, and you can append the message.
In this solution, im creating a placeholder for the "no entries" message, and creating that everytime the message has to be appended, you could use the display property of an element to hide or show it accordingly instead of creating a new element for each session
let nameInput = document.querySelector(".name");
let dateInput = document.querySelector(".date");
let amountInput = document.querySelector(".amount");
let button = document.querySelector(".add-btn");
let ifEmpty = document.querySelector(".if-empty");
let table = document.querySelector("table");
const emptyMessage = ifEmpty;
button.addEventListener("click", function() {
ifEmpty.remove();
// CREATE THE EXPENSE
let holder = document.createElement("tr");
let row = document.createElement("td");
let btnRow = document.createElement("td");
let removeButton = document.createElement("button");
// REMOVE THE EXPENSE
removeButton.addEventListener("click", function() {
holder.remove();
if (table.children.length <= 1) table.appendChild(emptyMessage)
});
table.appendChild(holder);
holder.appendChild(row).textContent = nameInput.value;
holder.appendChild(row.cloneNode(true)).textContent = dateInput.value;
holder.appendChild(row.cloneNode(true)).textContent = amountInput.value;
holder.appendChild(btnRow);
btnRow.appendChild(removeButton).textContent = "REMOVE ENTRY";
// TRIED THIS BUT IT DIDN'T WORK
});
.container {
text-align: center;
}
h1 {
font-size: 3.5em;
}
h2 {
font-size: 2em;
margin-bottom: 0.5em;
color: green;
}
span {
font-size: 1.4em;
}
.date-amount-input {
margin-top: 0.5em;
}
input {
height: 28px;
}
.name {
padding-right: 5em;
}
.amount {
padding-right: 15.35em;
}
.amount-text {
margin-left: 0.4em;
}
.date {
padding-right: 18.8em;
}
.add-btn {
margin-top: 0.9em;
padding: 0.6em;
font-size: 1.1em;
background: green;
color: white;
border: none;
border-radius: 5px;
}
.add-btn:hover, .add-btn:focus {
cursor: pointer;
background: rgb(3, 177, 3);
}
table {
margin: 0 auto;
margin-top: 2em;
width: 50%;
height: 80px;
}
tr {
height: 40px;
}
table, th, td{
border: 1px solid rgba(0, 0, 0, 0.103);
border-collapse: collapse;
}
.empty-text {
font-size: 0.93em;
}
.if-empty {
background: rgba(0, 0, 0, 0.055);
}
<body>
<div class="container">
<h1>Expense Tracker</h1>
<h2>Add A New Item</h2>
<div class="name-input">
<span class="name-text">Name: </span>
<input type="text" class="name" placeholder="Where was the expense made" size="117">
</div>
<div class="date-amount-input">
<span>Date: </span>
<input class="date" type="date">
<span class="amount-text">Amount: </span>
<input class="amount" type="text">
</div>
<button class="add-btn">Add Expense</button>
<table>
<tr>
<th>Name</th>
<th>Date</th>
<th>Amount</th>
</tr>
<tr class="if-empty">
<td colspan = "4">
<span class="empty-text">No expenses added yet!</span>
</td>
</tr>
</table>
</div>
<script src="main.js"></script>
</body>
Using display property method
replace ifEmpty.remove() with ifEmpty.style.display = 'none to hide it and replace table.appendChild(emptyMessage) with ifEmpty.style.display = 'table-row to show it again
I am pretty new to Javascript and I am having troubles to implement a searchable method for the following treegrid.
Just by adding the method data-search="true" within the <table> variables doesn't seem to work as I expected. Only the parents can be searched, while the children are not found. Does this imply that I need to create a custom search function to return the children plus parent?
Seems like your estructure needs a little more order, I recommend you to create the full table with HTML and the Javascript function separatly:
For the html table I will give you an example like this one:
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
</table>
Then if you gonna add some CSS Style it could be something like this:
<style>
#myInput {
background-image: url('/css/searchicon.png'); /* Add a search icon to input */
background-position: 10px 12px; /* Position the search icon */
background-repeat: no-repeat; /* Do not repeat the icon image */
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 18px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 12px; /* Add padding */
}
#myTable tr {
/* Add a bottom border to all table rows */
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
/* Add a grey background color to the table header and on hover */
background-color: #f1f1f1;
}
</style>
And of course at the end of it you can add the Java script that is gonna do the job for you, in this case it will filter the first column, but you can change it and even make it search on all colums
<script>
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
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("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
I hope this actually help you! :)
I have one html page with some div and table inside div. Getting data by using XHTMLREQUEST. How can I make this to wrapper class so I can use it whenever I want in project with some id.
I can create div with id and use that particularturl for the loading data. How can I make it common so I can use it anywhere.
My htmlcode:
<html>
<head>
<style>
* {
box-sizing: border-box;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 30%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 30%;
height : 30%;
overflow-y:auto;
border: 1px solid #ddd;
font-size: 18px;
display: none;
margin-top:-12px;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
width : 10%;
}
#myTable tr {
border-bottom: 1px solid #ddd;
order-top: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
#myInput:focus + #myTable{
display: block;
}
#myTable:hover{
display: block;
}
</style>
</head>
<body>
<h2>My Customers</h2>
<input type="text" id="myInput" onkeyup="myFunction()" title="Type in a name">
<table id="myTable">
<tr class="header"></tr>
<tr><td>Germany</td></tr>
<tr><td>Sweden</td></tr>
<tr><td>UK</td></tr>
<tr><td>Germany</td></tr>
<tr><td>Canada</td></tr>
<tr><td>Italy</td></tr>
<tr><td>UK</td></tr>
<tr><td>France</td></tr>
</table>
<script>
function myFunction() {
var input, filter, table, tr, td, i;
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
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 = "";
} else {
tr[i].style.display = "none";
}
}
}
}
document.querySelectorAll('#myTable tr:not(.header)').forEach(function(_tr){
_tr.addEventListener('click',function(){
document.getElementById('myInput').value += " "+ this.getElementsByTagName('td')[0].textContent;
});
});
</script>
</body>
</html>
This is how I am loading the data.
function foo(callback) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "data.json",true);
httpRequest.onreadystatechange = function () {
if(httpRequest.readyState === XMLHttpRequest.DONE && httpRequest.status === 200) {
// trigger your callback function
callback(httpRequest.responseText);
}
};
httpRequest.send();
}
foo(function(data) {
var jsonc = JSON.parse(data);
var new_opt="";
for(i=0;i<jsonc.length;i++)
{
new_opt+='<option value="'+jsonc[i]['VALUE']+'">'+jsonc[i]['VALUE']+'</option>';
}
document.getElementById('choose').innerHTML =new_opt;
});
I know this code I can use only for this place. But I want same idea for another div also. I just wann pass some id and create the same div which I using here.
Can anybody help me in Javascript class which should be generic class.