Finding the matching value in an HTML table and highlighting it - javascript

I need your help.
Because of the way my data will be structured. I need to create some sort of a function that will allow a user to input the record number from column 1 into the input box "record". Then at the click of a button, the code will find the exact matching value from column 1 in my data table and select the row using the existing code to highlight it. I can't seem to be able to put together some sort of logic as to how to make this work.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#data tr.normal td {
color: #235A81;
background-color: white;
}
#data tr.highlighted td {
color: #FFFFFF;
background-color: #235A81;
}
</style>
<script type='text/javascript'>
function test() {
var table = document.getElementById("data");
var thead = table.getElementsByTagName("thead")[0];
var tbody = table.getElementsByTagName("tbody")[0];
var ishigh
tbody.onclick = function (e) {
e = e || window.event;
var td = e.target || e.srcElement
var row = td.parentNode;
if (ishigh&&ishigh!=row){
ishigh.className='';
}
row.className = row.className==="highlighted" ? "" : "highlighted";
ishigh=row;
}
document.onkeydown = function(e){
e = e || event;
var code = e.keyCode, rowslim = table.rows.length - 2, newhigh;
if(code === 38){ //up arraow
newhigh = rowindex(ishigh) - 2;
if(!ishigh || newhigh < 0){return GoTo('data', rowslim);}
return GoTo('data', newhigh);
} else if (code === 40){ //down arrow
newhigh = rowindex(ishigh);
if(!ishigh || newhigh > rowslim){return GoTo('data', 0);}
return GoTo('data', newhigh);
}
}
function GoTo(id,nu){
var obj=document.getElementById(id),
trs=obj.getElementsByTagName('TR');
nu = nu + 1;
if (trs[nu]){
if (ishigh&&ishigh!=trs[nu]){
ishigh.className='';
}
trs[nu].className = trs[nu].className=="highlighted" ? "" : "highlighted";
ishigh=trs[nu];
}
}
function rowindex(row){
var rows = table.rows, i = rows.length;
while(--i > -1){
if(rows[i] === row){return i;}
}
}
}//end of nested function
</script>
</head>
<body onload="test()">
<table style="cursor: default;" id="data" cellspacing="1" border="1">
<thead>
<tr>
<th>Record #</th>
<th>first name</th>
<th>last name</th>
<th>age</th>
<th>total</th>
<th>discount</th>
<th>diff</th>
</tr>
</thead>
<tbody>
<tr>
<td>5</td>
<td>peter</td>
<td>parker</td>
<td>28</td>
<td>9.99</td>
<td>20.3%</td>
<td>+3</td>
</tr>
<tr>
<td>3</td>
<td>john</td>
<td>hood</td>
<td>33</td>
<td>19.99</td>
<td>25.1%</td>
<td>-7</td>
</tr>
<tr>
<td>1</td>
<td>clark</td>
<td>kent</td>
<td>18</td>
<td>15.89</td>
<td>44.2%</td>
<td>-15</td>
</tr>
<tr>
<td>4</td>
<td>bruce</td>
<td>almighty</td>
<td>45</td>
<td>153.19</td>
<td>44%</td>
<td>+19</td>
</tr>
<tr>
<td>2</td>
<td>benjamin</td>
<td>evans</td>
<td>56</td>
<td>153.19</td>
<td>23%</td>
<td>+9</td>
</tr>
</tbody>
</table>
<br>
Example: type the record's number in the input box and then select it:
<input type="text" id="record" />
</body>
</html>

I'm still having trouble getting the big picture of what you're trying to do, but I wrote a function to grab the tr whose first td contains the record.
function findTrForRecord(record) {
var nodelist = document.getElementById('data').getElementsByTagName('tr');
for (var i = 0; i < nodelist.length; i++) {
var tr = nodelist.item(i);
var tds = tr.getElementsByTagName('td');
if (tds.length > 0 && tds[0].innerHTML.trim() == record)
return tr;
}
}
From there, you can highlight it or do whatever you want.
/**
* unhighlights previous row and highlights new row
* that matches the record
*/
button.onclick = function () {
var trs = document.getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++)
if (trs[i].className.indexOf('highlighted') > 0) {
trs[i].className.replace('highlighted','');
break;
}
var record = document.getElementById('record').value;
var tr = findTrForRecord(record);
tr.className += ' highlighted';
}

I edited your html file you provided. Check this out. http://pastebin.com/Wz0EdBMV

Related

count duplicate value from table column using jquery or javascript and pass to rowspan

I want to count duplicate value from table column and pass to rowspan using javascript or jQuery.
$(document).ready(function(){
var myarry =[];
var el = {};
$("tbody tr").each(function() {
var row = $(this).nextAll();
var first = row.find('td').eq(0).text();
var second =row.find('td').eq(1).text();
var third = row.find('td').eq(2).text();
if(el[first + second + third]) {
myarry.push(el);
}else {
var c = (parseInt(myarry.length) + parseInt(1));
console.log(c);
row.find('td').eq(3).attr("rowspan",2);
el[first + second + third] = 1;
myarry =[];
}
});
});
here what i want in actual
you can do this by using selectors
$('#tableId tbody tr td:nth-child(1)');
$(document).ready(function(){
var counts={},valuesArray=[];
$('#tableId tbody tr td:nth-child(1)').each( function(){
//add item to array
var colValue=$(this).text();
if($.inArray(colValue,valuesArray)==-1){
counts[colValue]=1;
valuesArray.push(colValue);
}
else{
var oldCount=counts[colValue];
counts[colValue]= ++oldCount;
}
});
valuesArray=[];
$('#tableId tbody tr td:nth-child(4)').each( function(){
var currentObj=$(this);
if(currentObj.length>0){
$('#tableId tbody tr td:nth-child(1)').each( function(){
var colValue=$(this).text();
debugger;
if($.inArray(colValue,valuesArray)==-1){
var rowspanValue=counts[colValue];
if( currentObj.attr("rowspan")==undefined)
{
currentObj.attr("rowspan",rowspanValue);
currentObj.text(rowspanValue);
valuesArray.push(colValue);
}
}
})
}
});
});
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<table id='tableId'>
<thead>
<tr>
<th>VISA</th>
<th>Country</th>
<th>Category</th>
<th>Total VISA</th>
</tr>
</thead>
<tbody>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
<td></td>
</tr>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
</tr>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
<td></td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
</tbody>
</table>
</body>
</html>
Here is an example using jQuery and I will give an explanation below it:
$(document).ready(function() {
let tr = $('tr');
let vals = [];
tr.each(function() {
let td = $(this).find('td');
td.each(function() {
let val = $(this).text();
if(isNaN(val)) {
return;
}
else {
let obj = _.find(vals, elt => elt.number === val);
if(obj) {
obj.count += 1;
}
else {
vals.push({
number: val,
count: 1
});
}
}
});
});
let finalArr = [];
vals.forEach(function(elt) {
let count = elt.count;
let num = elt.number;
$('tr').each(function() {
let td = $(this).find('td');
td.each(function() {
let val = $(this).text();
if($.inArray(val, finalArr) === -1 && !isNaN(val) && !$(this).hasClass('added') && val === elt.number) {
finalArr.push(val);
$(this).parent('tr').append(`<td class='added' rowspan=${count}>${count}</td>`);
}
else {
return;
}
});
});
});
});
We can first create an array of unique values that are within each table data. If there is a unique value, we will add it to the vals array which will store objects representing the number that is unique and the "count" which is the number of times it occurs. If we see that number again during iteration, we will add to the count. After we are done iterating through each row we create a final array. We then iterate through our vals and retrieve the number of times it occurs and store it in the "count" variable. We then iterate through each table row and table data element again, and if the number is unique, we add that count the current count to parent element of the array we are currently doing iteration on if it is equal to the current number we are operating on in the vals array that stores the objects we created earlier. Lastly, we simply append a table data element to the parent table row of the element we are working with a rowspan that is equal to our count, and we can insert the value for how many times that number occurs. Of course, if you don't want to insert a value, you can simply keep the inner text of the table data element blank.
Here is mine
var startIndex = 0;
var lastValue;
var rows = $('tbody > tr');
$.each(rows, function(currentIndex, row){
var cells = row.cells
var value = cells[0].textContent + cells[1].textContent + cells[2].textContent;
if(!lastValue)
lastValue = value;
if(value != lastValue){
$(rows[startIndex]).append('<td rowspan='+ (currentIndex - startIndex ) +' >'+ (currentIndex - startIndex) +'</td>')
startIndex = currentIndex
lastValue = value
}
if (currentIndex == rows.length -1){
$(rows[startIndex]).append('<td rowspan='+ (currentIndex - startIndex + 1 ) +' >'+ (currentIndex - startIndex + 1) +'</td>')
}
})
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<table id='tableId'>
<thead>
<tr>
<th>VISA</th>
<th>Country</th>
<th>Category</th>
<th>Total VISA</th>
</tr>
</thead>
<tbody>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
</tr>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
</tr>
<tr>
<td>123456</td>
<td>abcc</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
<tr>
<td>8787</td>
<td>ddd</td>
<td>Plumber</td>
</tr>
</tbody>
</table>
here is the result of dynamic group data row count.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> -->
<script src = "https://code.jquery.com/jquery-1.10.2.js"></script>
<script src = "https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/jquery.validate.js"></script>
</head>
<body>
<table id="tbl1" border="1px">
<tr><th>visa no </th>
<th>country</th>
<th>category</th>
</tr>
<!-- 1st -->
<tr><td>123456</td>
<td>pakistan</td>
<td>plumber</td></tr>
<!-- 2n -->
<tr><td>123456</td>
<td>pakistan</td>
<td>plumber</td></tr>
<!-- 3rd -->
<tr><td>123456</td>
<td>pakistan</td>
<td>plumber</td></tr>
<!-- 4 -->
<tr><td>123456</td>
<td>pakistan</td>
<td>plumber</td></tr>
<!-- 5 -->
<tr><td>654321</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 6 -->
<tr><td>654321</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 7 -->
<tr><td>654321</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 8 -->
<tr><td>654321</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 9 -->
<tr><td>654321</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 10-->
<tr><td>6543217</td>
<td>india</td>
<td>plumber</td></tr>
<!-- 11-->
<tr><td>6543217</td>
<td>india</td>
<td>plumber</td></tr>
<tr><td>1234d563</td>
<td>pakistan</td>
<td>plumber</td></tr>
<tr><td>1234d563</td>
<td>pakistan</td>
<td>plumber</td></tr>
<tr><td>1234d563</td>
<td>pakistans</td>
<td>plumber3</td></tr>
</table>
</body>
</html>
<script>
$(document).ready(function(){
var id = 0;
var id2 =0;
var id3 =0;
var counts=0;
var myarry =[];
var el = {};
var valCell=0;
/*var first = $('#tbl1 td:first-child');
var second = $('#tbl1 td:nth-child(2)');
var third = $('#tbl1 td:nth-child(3)');
modifyTableRowspan(first);
modifyTableRowspan(second);
modifyTableRowspan(third);*/
$("tbody tr").each(function() {
// get row
var rows = $(this);
var row = $(this).next();
// get first and second td
var first = row.find('td:first-child').text();
var second = row.find('td:nth-child(2)').text();
var third = row.find('td:nth-child(3)').text();
//if exists, remove the tr
if(el[first + second + third]) {
myarry.push(el);
// $(this).remove(); wait
}
else {
var c = (myarry.length) + 1;
//$('#tbl1 tr').eq(0).append("<td rowspan='"+c+"'>some new data</td>");
console.log(c);
if(id2 == 0)
{
//alert('zero:'+id);
//rows.append("<td rowspan='"+id+"'>some new data</td>");
if(id2==0){
$('#tbl1 tr').eq(id).append("<td rowspan='"+c+"'>Via</td>");
}else{
$('#tbl1 tr').eq(id).append("<td rowspan='"+c+"'>some new data "+c+"</td>");
id2=1;
}
id = c;
id2=c;
}
else {
//rows.append("<td rowspan='"+c+"'>some new data</td>");
$('#tbl1 tr').eq(id).append("<td rowspan='"+c+"'>some new data "+c+"</td>");
id = id + c;
}
el[first + second + third] = 1;
myarry =[];
}
});
id=0;
});
function modifyTableRowspan(column) {
var prevText = "";
var counter = 0;
column.each(function (index) {
var textValue = $(this).text();
if (index === 0) {
prevText = textValue;
}
if (textValue !== prevText || index === column.length - 1) {
var first = index - counter;
if (index === column.length - 1) {
counter = counter + 1;
}
column.eq(first).attr('rowspan', counter);
if (index === column.length - 1)
{
for (var j = index; j > first; j--) {
column.eq(j).remove();
}
}
else {
for (var i = index - 1; i > first; i--) {
column.eq(i).remove();
}
}
prevText = textValue;
counter = 0;
}
counter++;
});
}
</script>

JavaScript logic error

I am trying to get JavaScript to generate a table with data from an array for me however when I run this code it enters the same data twice. Does anyone know what mistake I am making?
The HTML:
<body>
<div class="container">
<h1 class="page-header">Bookings</h1>
<table id="bookTable" class="table table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Second Name</th>
<th>Email</th>
<th>From</th>
<th>To</th>
</tr>
<tr>
<td type="text" id="firstName"></td>
<td type="text" id="secondName"></td>
<td type="text" id="email"></td>
<td type="text"id="dateFrom"></td>
<td type="text"id="dateTo"></td>
</tr>
</thead>
</table>
</div>
The JavaScript is using a guide I found that I have adapted. In reality, the array comes from a python file that is fed in as a variable when Flask displays the template. I have used the same data that python prints out when looking at the contents of the variable that is passed.
<script>
var listOfBookings = [John`Doe`jd#gmail.com`03/01/2018`18/01/2018`John`Doe`jd#gmail.com`26/12/2017`27/12/2017]
var array = listOfBookings.split("`");
var count = 1
for (var i = 0; i < array.length; i++){
if (1%(i+1) == 0){
var firstName = array[i];
}
if (2%(i+1) == 0){
var secondName = array[i];
}
if (3%(i+1) == 0){
var email = array[i];
}
if (4%(i+1) == 0){
var dateFrom = array[i];
}
if (5%(i+1) == 0){
var dateTo = array[i];
}
// Addapted from http://talkerscode.com/webtricks/add-edit-and-
delete-rows-from-table-dynamically-using-javascript.php
if(count%5 == 0){
var table=document.getElementById("bookTable");
var table_len=(table.rows.length)-1;
var row = table.insertRow(table_len).outerHTML="<tr
id='row"+table_len+"'><td id='date_row"+table_len+"'>"+firstName+"</td><td
id='name_row"+table_len+"'>"+secondName+"</td><td
id='country_row"+table_len+"'>"+email+"</td><td
id='country_row"+table_len+"'>"+dateFrom+"</td><td
id='country_row"+table_len+"'>"+dateTo+"</td></tr>";
}
count += 1
}
</script>
Your code seems overly complicated. Here's a working example of how you might do it: (Note: I've added a tbody to your table, rather than have all these rows inserted into the thead)
var listOfBookings = "John`Doe`jd#gmail.com`03/01/2018`18/01/2018`John`Doe`jd#gmail.com`26/12/2017`27/12/2017";
var array = listOfBookings.split("`");
var count = 1;
var table = document.getElementById("bookTable").getElementsByTagName('tbody')[0];
var row = table.insertRow(-1); //appends initial row
row.id = "row_" + (count)
for (var i = 0; i < array.length; i++) {
if (i % 5 == 0 && i > 0) {
row = table.insertRow(-1); //appends a row
row.id = "row_" + (++count)
}
var cell = row.insertCell(-1); //appends a cell
var text = document.createTextNode(array[i]); //create the textNode
cell.appendChild(text); //fill the cell with the text
//(you could also set the cell id and other attributes at this point too)
}
<div class="container">
<h1 class="page-header">Bookings</h1>
<table id="bookTable" class="table table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Second Name</th>
<th>Email</th>
<th>From</th>
<th>To</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
Your array seems to have 10 values and from all your if statements none of them will have their condition equal true when i is bigger then 4.
All the variables (firstName, secondName, email, dataFrom, dateTo) will have the same value when count is 10 as they had when it was 5
You could do something like this:
var array = ["John","Doe","jd#gmail.com","03/01/2018","18/01/2018","John","Doe","jd#gmail.com","26/12/2017","27/12/2017"];
var table=document.getElementById("bookTable");
for (var i = 0; array.length % 5 === 0 && i < array.length;){
var firstName = array[i++];
var secondName = array[i++];
var email = array[i++];
var dateFrom = array[i++];
var dateTo = array[i++];
var table_len = (table.rows.length)-1;
var row = table.insertRow(table_len).outerHTML="<tr id='row"+table_len+"'><td id='date_row"+table_len+"'>"+firstName+"</td><td id='name_row"+table_len+"'>"+secondName+"</td><td id='country_row"+table_len+"'>"+email+"</td><td id='country_row"+table_len+"'>"+dateFrom+"</td><td id='country_row"+table_len+"'>"+dateTo+"</td></tr>";
}
<body>
<div class="container">
<h1 class="page-header">Bookings</h1>
<table id="bookTable" class="table table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Second Name</th>
<th>Email</th>
<th>From</th>
<th>To</th>
</tr>
<tr>
<td type="text" id="firstName"></td>
<td type="text" id="secondName"></td>
<td type="text" id="email"></td>
<td type="text"id="dateFrom"></td>
<td type="text"id="dateTo"></td>
</tr>
</thead>
</table>
</div>

Remove extra cell spaces

I have a script below:
var cells = [].slice.call(document.querySelectorAll("#myTable td"));
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
cells.forEach(function(cell) {
if (!search.value.trim()) {
cell.style.background = "white";
cell.style.display = 'table-cell';
} else if (cell.textContent.toLowerCase().indexOf(search.value.toLowerCase()) == 0) {
cell.style.background = 'yellow';
cell.style.display = "table-cell";
} else {
cell.style.background = "white";
cell.style.display = 'none';
}
});
});
<input id='myInput' type='text'>
<table id='myTable'>
<tr>
<td>a</td>
<td>ab</td>
<td>abs</td>
<td>ador</td>
<td>turous</td>
<td>acac</td>
<td>accle</td>
</tr>
<tr>
<td>ed</td>
<td>aced</td>
<td>ate</td>
<td>acg</td>
<td>aci</td>
<td>atic</td>
<td>ive</td>
</tr>
<tr>
<td>l</td>
<td>pt</td>
<td>able</td>
<td>ad</td>
<td>adoent</td>
<td>ble</td>
<td>d</td>
</tr>
<tr>
<td>ed</td>
<td>a</td>
<td>aate</td>
<td>a</td>
<td>aavating</td>
<td>aive</td>
<td>a</td>
</tr>
<tr>
<td>d</td>
<td>ng</td>
<td>eable</td>
<td></td>
<td>alarmed</td>
<td>ming</td>
<td>t</td>
</tr>
<tr>
<td>ted</td>
<td>ae</td>
<td>all</td>
<td>agjhistic</td>
<td>akjhkjg</td>
<td>hjious</td>
<td>ample</td>
</tr>
<tr>
<td>hjbsed</td>
<td>ahkjng</td>
<td>anhjkd</td>
<td>ahjhnt</td>
<td>ahjkjc</td>
<td>a</td>
<td>hjhed</td>
</tr>
<tr>
<td>aghjed</td>
<td>hjjal</td>
<td>ghjmher</td>
<td>amjhkiue</td>
<td>ahkjus</td>
<td>any</td>
<td>ahmkjehensive</td>
</tr>
<tr>
<td>ajhjkjiate</td>
<td>ahkjpt</td>
<td>arctic</td>
<td>arid</td>
<td>aromatic</td>
<td>artistic</td>
<td>ashamed</td>
</tr>
<tr>
<td>assured</td>
<td>astonishing</td>
<td>athletic</td>
<td>attached</td>
<td>attentive</td>
<td>atkjkjactive</td>
<td>ahghbtere</td>
</tr>
<tr>
<td>bhkuhish</td>
<td>hkjh</td>
<td>bhkre</td>
<td>barren</td>
<td>basic</td>
</tr>
<tr>
<td>befsgdfgful</td>
<td>bdsfsdfed</td>
<td>dsfsdfved</td>
<td>bedsfsfcial</td>
<td>better</td>
<td>best</td>
<td>bdfsfitched</td>
</tr>
</table>
I use this script for searching text with an HTML table. It have more than 500 cells like 100 rows and 5 columns etc. This script works well for finding text within a short table but when I search anything it also display gap of rows and columns, if i have a long table which has more than 500 cells.
Here I tried to used regular expressions like \s and /g but it doesn't work, may be I insert them on wrong place. Also I tried to change cell.style.display = "table-cell"; with many other style but doesn't work.
Can any one properly guide me what and where I have to put exactly to get output properly without rows/columns gap if i have more than 500 cells and what that mean with syntax description.
Try this! =)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text" class="input"/>
<div class="print"></div>
<script>
var data = ['food', 'bar', 'google']; // your data
var fx = function(text) {
var print = function(list,s) {
var table = $('<table/>').css('width','100%');
var x = 0;
while (list[x]) {
var tr = $('<tr/>');
while (list[x] && x < 5) {
var td = $('<td/>').text(list[x])
if(s == list[x]){
td.css('background','red');
}
tr.append(td);
x++;
}
table.append(tr);
}
$('.print').html(table);
}
if (typeof text === "undefined") {
print(data, '');
} else {
var find = [];
for (var i = 0; data[i]; i++) {
if (data[i].toLowerCase().indexOf(text.toLowerCase()) == 0) find[find.length] = data[i];
}
print(find,text);
}
}
$(function() {
$('.input').keyup(function() {
fx($(this).val());
});
fx();
});
</script>

Javascript - how to toggle all next singlings until class found

I have the table below which hides all the child rows by default.
I'd like to toggle all child rows right underneath the corresponding clicked root row. That is, the n .child rows next to the clicked .root. How can I do this in pure Javascript?
.hidden {
display:none;
}
<table>
<tr>
<td>Root</td>
</tr>
<tr class="hidden">
<td>Child 1</td>
</tr>
<tr class="hidden">
<td>Child 2</td>
</tr>
<tr class="hidden">
<td>Child 3</td>
</tr>
<tr class="hidden">
<td>Child 4</td>
</tr>
<tr>
<td>Root</td>
</tr>
<tr class="hidden">
<td>Child 1</td>
</tr>
<tr class="hidden">
<td>Child 2</td>
</tr>
</table>
If, what you want to do is to remove the hidden classname from all the rows after the clicked one until you get to a row that is not hidden, then you can do this:
function func(root) {
var row = root.parentNode.parentNode;
row = nextElement(row, "tr");
while (row && row.className === "hidden") {
row.className = "";
row = nextElement(row, "tr");
}
}
function nextElement(start, tag) {
tag = tag.toUpperCase();
start = start.nextSibling;
while (start) {
if (start.tagName === tag) {
return start;
} else {
start = start.nextSibling;
}
}
return start;
}
Working demo: http://jsfiddle.net/jfriend00/dvg6j9or/
Here's another version that works off the array of rows and uses a parent search to find the right level of the table:
function func(root) {
var table = findParentTag(root, "table");
var currentRow = findParentTag(root, "tr");
var rows = Array.prototype.slice.call(table.querySelectorAll("tr"));
var currentIndex = rows.indexOf(currentRow) + 1;
// now traverse rows until you find one that is different than the starting row
for (; currentIndex < rows.length; ++currentIndex) {
if (rows[currentIndex].className.indexOf("hidden") !== -1) {
rows[currentIndex].className = "";
} else {
break;
}
}
}
function findParentTag(start, tag) {
tag = tag.toUpperCase();
while (start && start.tagName !== tag) {
start = start.parentNode;
}
return start;
}
Working demo: http://jsfiddle.net/jfriend00/hut56fLg/

Pure Javascript: onClick toggle rows/ image: Firefox/Chrome - works: IE - does not work

Got some great help from Zeb Rawnsley (you rock!) on resolving the preceding question to my current issue.
Working with some code to allow subordinate rows to be hidden via a collapsible link behind an image. This works perfectly fine in Firefox and Chrome but the image does not alternate after the first iteration in IE (IE 8 specifically my company's standard).
The section of interest is here (I think):
var closedImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png\" border=\"0\" height=\"50\">";
var openImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png\" border=\"0\" height=\"50\">";
and possibly here (but I don't think so):
lnk.innerHTML =(lnk.innerHTML == openImgHTML)?closedImgHTML:openImgHTML;
This CodePen is for the working version (Firefox/Chrome):
http://codepen.io/anon/pen/yjLvh
This is the HTML for the working version:
<html>
<head>
<style type="text/css">
table { empty-cells: show; }
cell {font-family:'Calibri';font-size:11.0pt;color: #000000;}
TD{font-family: Calibri; font-size: 10.5pt;}
TH{font-family: Calibri; font-size: 10.5pt; }
</style>
</head>
<body>
<SCRIPT type=text/javascript>
var tbl;
var toggleimage=new Array("http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png","http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png")
var closedImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png\" border=\"0\" height=\"50\">";
var openImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png\" border=\"0\" height=\"50\">";
function trim(str){
return str.replace(/^\s*|\s*$/g,"");
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function toggleSection(lnk){
var td = lnk.parentNode;
var table = getParent(td,'TABLE');
var len = table.rows.length;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;
var rowHead=table.rows[rowIndex].cells[1].innerHTML;
lnk.innerHTML =(lnk.innerHTML == openImgHTML)?closedImgHTML:openImgHTML;
vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';
for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
table.rows[i].cells[1].style.visibility="hidden";
}
}
}
function toggleRows(){
tables =document.getElementsByTagName("table");
for(i =0; i<tables.length;i++){
if(tables[i].className.indexOf("expandable") != -1)
tbl =tables[i];
}
if(typeof tbl=='undefined'){
alert("Could not find a table of expandable class");
return;
}
//assume the first row is headings and the first column is empty
var len = tbl.rows.length;
var link =''+closedImgHTML+'';
var rowHead = tbl.rows[1].cells[1].innerHTML;
for (j=1; j<len;j++){
//check the value in each row of column 2
var m = tbl.rows[j].cells[1].innerHTML;
if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
// tbl.rows[j].cells[0].style.textAlign="center";
tbl.rows[j].style.background = "#FFFFFF";
}
else
tbl.rows[j].style.display = "none";
}
}
var oldEvt = window.onload;
var preload_image_1=new Image()
var preload_image_2=new Image()
preload_image_1.src=toggleimage[0]
preload_image_2.src=toggleimage[1]
var i_image=0
function testloading() {
isloaded=true
}
function toggle() {
if (isloaded) {
document.togglepicture.src=toggleimage[i_image]
}
i_image++
if (i_image>1) {i_image=0}
}
window.onload = function() { if (oldEvt) oldEvt(); toggleRows(); testloading();}
</SCRIPT>
<TABLE class=expandable width="400px" border="1" cellspacing="0" frame="box" rules="all" >
<THEAD>
<TR>
<TH bgColor="#E6E4D4"> </TH>
<TH bgColor="#E6E4D4" align="left">Manager</TH>
<TH bgColor="#E6E4D4" align="left">Sales Rep</TH>
<TH bgColor="#E6E4D4" align="left">Amount </TH></TR>
</THEAD>
<TBODY>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD><i>Georgia District Reps</i></TD>
<TD>500000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Rex Smtih</TD>
<TD>350000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Alex Anderson</TD>
<TD>150000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD><i>Texas District Reps</i></TD>
<TD>630000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Bill Smith</TD>
<TD>410000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Simon Wilkes</TD>
<TD>220000</TD></TR>
</TBODY></font></TABLE>
<br>
<br>
</body>
</html>
The prior set of code without the images (using text for open/close) worked fine in all browsers.
Not sure if there is an image syntax issue in IE or something else. It most certainly is focused on the images since, well, it works fine without images.
Here is the CodePen for the version (text based) working in IE (and others).
http://codepen.io/anon/pen/morpF
Here is the HTML for the "ALL" browser version"
<html>
<head>
<style type="text/css">
table { empty-cells: show; }
cell {font-family:'Calibri';font-size:11.0pt;color: #000000;}
TD{font-family: Calibri; font-size: 10.5pt;}
TH{font-family: Calibri; font-size: 10.5pt; }
</style>
</head>
<body>
<SCRIPT type=text/javascript>
var tbl;
function trim(str){
return str.replace(/^\s*|\s*$/g,"");
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function toggleSection(lnk){
var td = lnk.parentNode;
var table = getParent(td,'TABLE');
var len = table.rows.length;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;
var rowHead=table.rows[rowIndex].cells[1].innerHTML;
lnk.innerHTML =(lnk.innerHTML == "+")?"--":"+";
vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';
for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
table.rows[i].cells[1].style.visibility="hidden";
}
}
}
function toggleRows(){
tables =document.getElementsByTagName("table");
for(i =0; i<tables.length;i++){
if(tables[i].className.indexOf("expandable") != -1)
tbl =tables[i];
}
if(typeof tbl=='undefined'){
alert("Could not find a table of expandable class");
return;
}
//assume the first row is headings and the first column is empty
var len = tbl.rows.length;
var link ='+';
var rowHead = tbl.rows[1].cells[1].innerHTML;
for (j=1; j<len;j++){
//check the value in each row of column 2
var m = tbl.rows[j].cells[1].innerHTML;
if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
// tbl.rows[j].cells[0].style.textAlign="center";
tbl.rows[j].style.background = "#FFFFFF";
}
else
tbl.rows[j].style.display = "none";
}
}
var oldEvt = window.onload;
window.onload = function() { if (oldEvt) oldEvt(); toggleRows();}
</SCRIPT>
<TABLE class=expandable width="400px" border="1" cellspacing="0" frame="box" rules="all" >
<THEAD>
<TR>
<TH width="10%" bgColor="#E6E4D4"> </TH>
<TH bgColor="#E6E4D4" align="left">Manager</TH>
<TH bgColor="#E6E4D4" align="left">Sales Rep</TH>
<TH bgColor="#E6E4D4" align="left">Amount </TH></TR></THEAD>
<TBODY>
<TR class="cell">
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>&nbsp</TD>
<TD>500000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Rex Smtih</TD>
<TD>350000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Alex Anderson</TD>
<TD>150000</TD></TR>
<TR>
<TD> </TD>
<TD>William Jones</TD>
<TD> </TD>
<TD>620000</TD></TR>
<TR>
<TD> </TD>
<TD>William Jones</TD>
<TD>Bill Smith</TD>
<TD>410000</TD></TR>
<TR>
<TD> </TD>
<TD>William Jones</TD>
<TD>Simon Wilkes</TD>
<TD>220000</TD></TR>
</TBODY></font></TABLE></body>
</html>
Thanks!
Different browsers serialize the DOM differently. Running your code in IE10 gives me this:
foo.innerHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png\" border=\"0\" height=\"50\">";
foo.innerHTML; // <img name="togglepicture" height="50" src="http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png" border="0">
IE rearranged the attributes, so you no longer have the same string.
Instead of getting the HTML inside the link element, get the image itself and look at its src property.

Categories

Resources