I have a problem with table on HTML using django ,
i want to Hightlight the row where clicked on and get it's index
HTML CODE:
<table class="table table-striped table-sm" id="tab1" >
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Nº</th>
<th scope="col">Header</th>
<th scope="col">Header</th>
<th scope="col">Header</th>
<th scope="col">Header</th>
</tr>
</thead>
<tbody class="post">
{% for post in posts %}
<tr>
<td><input type="checkbox"></td>
<td><b><count> </count></b></td>
<td>{{ post.head1 }}</td>
<td>{{ post.head2 }}</td>
<td>{{ post.head3 }}</td>
<td>{{ post.head4 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Part of style sheet using counter:
body {
counter-reset: section;
}
count::before {
counter-increment: section;
content: " " counter(section) " ";
}
I try to use javascript code from many blog but not work.
I can't use getelementbyid because i can't create dynamic IDs for all rows
You can use JavaScript to add an event listener to the table rows, and then use the this keyword to reference the row that was clicked on. You can then add a class to that row to highlight it and get its index. Here is an example of how you could do this:
var tableRows = document.querySelectorAll("#tab1 tbody tr");
for (var i = 0; i < tableRows.length; i++) {
tableRows[i].addEventListener("click", function() {
var current = document.getElementsByClassName("highlight");
if (current.length > 0) {
current[0].className = current[0].className.replace(" highlight", "");
}
this.className += " highlight";
console.log(this.rowIndex);
});
}
This will add an event listener to each row in the table, and when a row is clicked, it will add a class called "highlight" to the row, and log the index of the row to the console.
You can also use the querySelectorAll method to select all rows and add a click event listener to them.
const rows = document.querySelectorAll("#tab1 tbody tr")
rows.forEach(row => {
row.addEventListener("click", e => {
rows.forEach(row => row.classList.remove("highlight"))
e.currentTarget.classList.add("highlight")
console.log(row.rowIndex + 1)
})
});
This will add a click event listener to each row and remove the highlight class from all the rows and then add it to the one that was clicked on and then log the row index to the console.
You can also use jQuery, it's simple and effective too.
$("#tab1 tbody tr").click(function() {
$("#tab1 tbody tr").removeClass("highlight");
$(this).addClass("highlight");
console.log($(this).index() + 1);
});
Related
I have a table that I'm manipulating through a static js file. I made a filter to show only the lines that contain the values typed in the input. For that, I add the 'hidden' class to those that don't contain the value typed in the input. However, when I go to inspect, only the first line is configured with the "hidden" class. How do I do it for all the other lines that don't contain the values typed in the input?
The code:
HTML:
<div class="container">
<hr>
<form class="form-search">
<input class="form-control" id="form-control" type="text" name="fitrar" placeholder="Buscar Registros"
autocomplete="off" autofocus />
Limpar
</form>
</hr>
<table class="table table-dark">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">CNPJ</th>
<th scope="col">CPF</th>
<th scope="col">Nome</th>
</tr>
</thead>
<tbody>
{% for registro in registros %}
<tr>
<td scope="row">{{ registro.id }}</td>
<td scope="row">{{ registro.cnpj }}</td>
<td scope="row">{{ registro.cpf }}</td>
<td scope="row">{{ registro.nome }}</td>
</tr>
JS:
const inputSearchRegistros = document.querySelector('.form-search input')
const tableRegistros = document.querySelector('.table tbody tr')
inputSearchRegistros.addEventListener('input', event => {
const inputValue = event.target.value.trim()
Array.from(tableRegistros.children)
.filter(regs => !regs.textContent.includes(inputValue))
.forEach(regs => {
regs.classList.add('hidden')
})
})
Result:
<tr>
<td scope="row" class="hidden">1</td>
<td scope="row" class="hidden">31024483000198</td>
<td scope="row" class="hidden">86520083534</td>
<td scope="row" class="hidden">Adriana teste esteves</td>
</tr>
<tr>
<td scope="row">2</td>
<td scope="row">31024483000198</td>
<td scope="row">86520083534</td>
<td scope="row">Adriana teste esteves</td>
</tr>
They are the same values, but only the first line receives the hidden class
I would like all lines that do not have the values typed in the input to receive the hidden class.
querySelector only returns the first element that matches the selector even if there is more than one match. You want to use querySelectorAll like this
const tableRegistros = document.querySelectorAll('.table tbody tr')
You'll then have to loop through the results like in ryan's answer or select the td elements and loop through those like this depending on what your trying to accomplish
const tableRegistros = document.querySelectorAll('.table tbody tr td')
inputSearchRegistros.addEventListener('input', event => {
const inputValue = event.target.value.trim()
Array.from(tableRegistros)
.filter(regs => !regs.textContent.includes(inputValue))
.forEach(regs => {
regs.classList.add('hidden')
})
})
Two problems:
You are using document.querySelector, which will only select the first row. You want to use document.querySelectorAll
You are iterating over the table cells using Array.from(tableRegistros.children).
// this only selects the first row
const tableRegistros = document.querySelector('.table tbody tr');
// this is a bunch of td elements
Array.from(tableRegistros.children)
Instead, you want to iterate over all of the rows, and then all of the cells in each row:
// use querySelectorAll to select all rows
const tableRegistros = document.querySelectorAll('.table tbody tr');
// Iterate each row
tableRegistros.forEach(row => {
// Then search all of the cells for the content
const containsText = Array.from(row.children).some(cell => cell.textContent.includes(inputValue));
if (!containsText) {
row.classList.add('hidden');
} else {
row.classList.remove('hidden');
}
});
I want to filter a table's display from a database based on the selected value.
I want to display table rows when the 7th cell index of each row is less than Selected value, by comparing the integer/string value.
I found lots of examples of matching or containing criteria, but I couldn't figure out Less Than or Greater than, currently my code displays table but not working properly.
I am happy to accept jQuery if it works too.
<table id="carTable" class="table table-striped">
<thead>
<tr class="header">
<th>ID</th>
<th>Make</th>
<th>Model</th>
<th>Type</th>
<th>Seats</th>
<th>Color</th>
<th>Location</th>
<th>Price/Day
<select id='filterText' style='display:inline-block' onchange='filterPrice()'>
<option value="all" selected>All</option>
<option value='69'> < 69 </option>
<option value='100'> < 100 </option>
<option value='200'> < 200 </option>
<option value='500'> < 500 </option>
</select>
</th>
</tr>
</thead>
<tbody id="carsTable">
{%for car in cars%}
<tr>
<td>{{ car[0] }}</td>
<td>{{ car[1] }}</td>
<td>{{ car[2] }}</td>
<td>{{ car[3] }}</td>
<td>{{ car[4] }}</td>
<td>{{ car[5] }}</td>
<td>{{ car[6] }}</td>
<td>{{ car[7] }}</td>
</tr>
{%endfor%}
</tbody>
</table>
My function looks like this
function filterPrice() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("filterText");
filter = input.value;
table = document.getElementById("carTable");
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")[7];
if (td) {
cellValue = td.innerHTML;
if (cellValue <= filter) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
enter image description here
Fixed by convert to integers first then compare, thanks to #isherwood
function filterPrice() {
// Declare variables
var input, filter, table, tr, td, i, cellValue;
input = document.getElementById("filterText");
filter = parseInt(input.value);
table = document.getElementById("carTable");
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")[7];
if (td) {
cellValue = parseInt(td.innerHTML);
if (cellValue <= filter) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
I have a table that should eventually have 5 columns which I want to be able to sort though only the value of one column, "Name". This is what my function looks like so far:
function RenderResultsByName() {
//Declaration of variables
var nameInput, nameFilter, ul, li, a, i;
//Set the variables accorging to matching id's
//Name
nameInput = document.getElementById('nameInput');
nameFilter = nameInput.value.toUpperCase();
ul = document.getElementById("UL");
li = document.getElementsByTagName('tr');
console.log(li[0]);
//Loop trough items and hide those who don't match the query-->
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("td")[0];
if (a.innerHTML.toUpperCase().indexOf(nameFilter) > -1) {
li[i].style.display = "";
}
else {
li[i].style.display = "none";
}
}
}
The HTML looks like this
<div class="row">
<div class="col-md-3">
<label>Namn: </label><br />
<input type="text" id="nameInput" onkeyup="RenderResultsByName()" placeholder="Sök efter namn..." /> <br /> <br />
</div>
</div>
<br /><br />
<table id="UL" class="table table-bordered">
<tr>
<th>Name</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.visitor.FullName</td>
</tr>
}
</table>
I tried to apply a class "tdOfName" on all the 's in the Name column, but after that the sort stopped working because the a variable became undefined.
How would you solve this?
First, two things for your HTML code:
First a piece of advice, add thead and tbody to your tables to simplify jquery row selectors (and is a good practice, anyway).
You're creating 5 columns in the head row but only one in the rest. You have to add the rest or set a colspan.
<table id="UL" class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
</tr>
<thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>#item.visitor.FullName</td><td></td><td></td><td></td><td></td>
</tr>
}
<tbody>
</table>
Then, you say sort but your function is trying to show/hide rows attending at the input of the value. I can't see any sign of sorting. In case what you want is show/hide rows that has the input value in the first column, you can simplify it with this...
jQuery.expr[':'].icontains = function(a, i, m) {
return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
$('input#nameInput').on('keyup',function() {
$('table#UL tbody tr').hide().filter(':has(td:first:icontains('+this.value+'))').show();
});
Here you have an fiddle example... https://fiddle.jshell.net/rigobauer/4rzf4wt7/
Is this what you're looking for?
I hope it helps.
In my app I used to have a page with >1000 rows that was getting ridiculous. The underlying data was highly structured, so that page now loads a table with all of the parent data. Each parent row has a button that when clicked, creates a child row in the table and then loads in HTML (a table of all of the children).
I'm using #Mottie's fork of Tablesorter, and his demo shows that this should work; that when you sort the parent columns, the child tables stay with the parent. But that's not working properly for me, and I can't figure out why.
(For background, I'm using Jinja2 for templating, which is why you see some of the syntax in the HTML below.)
Can anyone help me figure out what's going wrong?
Here's the JS of the parent table:
<script type="text/javascript">
$(function(){
$.tablesorter.themes.bootstrap = {
table : 'table table-condensed table-bordered table-striped table-hover',
caption : 'caption',
header : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css)
iconSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted
iconSortAsc : 'glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort
iconSortDesc : 'glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort
};
$("#seedcohorts").tablesorter({
theme: 'bootstrap',
sortList:[[3,0]],
sortInitialOrder: 'asc',
headerTemplate : '{content} {icon}',
widgets : [ "uitheme", "zebra" ],
widgetOptions : {
zebra : ["even", "odd"],
},
dateFormat: 'mm/yyyy',
selectorHeaders: '> thead > tr > th',
});
});
$(document).ready(function(){
$('#seedcohorts').on('click', ".toggleCohort", function () {
var thisRow = $(this).parents('tr.adder');
var hasNextRow = thisRow.next('tr.added').length;
if (hasNextRow) {
thisRow.next('tr.added').remove();
} else {
var parent = $(this).parents('tr.adder'), id = parent.attr('id');
$.get('/myurl?cohortid='+id, function(html) {
parent.after('<tr class="added tablesorter-childRow"><td colspan="7" >'+html+'</td></tr>');
});
}
});
$(document).on('click','a.collapsed', function () {
var id = this.id;
$(this).addClass('expanded');
$(this).removeClass('collapsed');
$('a#'+id+' button').html('<i class="fa fa-minus" aria-hidden="true"></i>');
});
$(document).on('click','a.expanded', function () {
var id = this.id;
$(this).addClass('collapsed');
$(this).removeClass('expanded');
$('a#'+id+' button').html('<i class="fa fa-plus" aria-hidden="true"></i>');
});
});
</script>
Here's the HTML of the parent table:
<div class="table-responsive">
<table id="seedcohorts" class="tablesorter table table-striped table-bordered table-condensed table-hover" >
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Name</th>
<th scope="col">Location</th>
<th scope="col">Date</th>
<th scope="col">Number</th>
<th scope="col">Dollar data</th>
<th scope="col">Dollar data 2</th>
</tr>
</thead>
<tbody>
{% for entry in cohortlist %}
<tr class="adder" id="{{entry.key().id()}}">
<td>
<a href="javascript:void(0)" id="{{entry.key().id()}}" class="toggleCohort collapsed">
<button class="btn btn-xs disabled"><i class="fa fa-plus" aria-hidden="true"></i></button>
</a>
</td>
<td>{{ entry.name }}</td>
<td>{{ entry.loc_city}}, {{entry.loc_country}}</td>
<td>{{ entry.cohort_date.month }}/{{ entry.cohort_date.year }}</td>
<td>{{ entry.num_cos }}</td>
<td>${{ entry.total_value|newnumber }}</td>
<td>${{ entry.total_funding|newnumber }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
Here's the JS of the child table:
<script type="text/javascript">
$(function(){
$.tablesorter.themes.bootstrap = {
table : 'table table-condensed table-bordered table-striped table-hover',
caption : 'caption',
header : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css)
iconSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted
iconSortAsc : 'glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort
iconSortDesc : 'glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort
};
$("#mytable-{{cohort.key().id()}}").tablesorter({
theme: 'bootstrap',
sortList:[[5,1]],
sortInitialOrder: 'desc',
headerTemplate : '{content} {icon}',
widgets : [ "uitheme", "zebra" ],
widgetOptions : {
zebra : ["even", "odd"],
},
dateFormat: 'mm/yyyy',
selectorHeaders: '> thead > tr > th',
});
});
</script>
Here's the HTML of the child table:
<table id="mytable-{{cohort.key().id()}}" class="tablesorter-child table table-striped table-bordered table-condensed" >
<thead>
<tr>
<th scope="col">Status</th>
<th scope="col">Company</th>
<th scope="col">Details</th>
<th scope="col">Dollar value</th>
<th scope="col"></th>
<th scope="col">Dollar value 2</th>
</tr>
</thead>
<tbody>
{% for entry in listofcohortcompanies %}
<tr>
<td></td>
<td>{{ entry.name }}</td>
<td>{{ entry.website }}</td>
<td>${{ entry.exit_value|newnumber }}</td>
<td></td>
<td>${{ entry.total_funding|newnumber }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I have been working on your code, and what I would do, is to iterate over the tables finding the id's that are open, store them in an array, and removing those "tabledsorter-childRow", after doing that what I did was to iterate over the ids array and just click again those ones that where open, here is my code:
/* Function for leaving the array with only unique id's */
function unique(array) {
return $.grep(array, function(el, index) {
return index === $.inArray(el, array);
});
}
/* Find all id's of tablesorters that are open and store them in the variable "arrayIds" */
var arrayIds = [];
$('.tablesorter-childRow').each(function(item){
arrayIds.push($(this).find('table').attr('id').split('-')[1]);
//Here we remove the tables
$(this).remove();
});
//Here we leave the array with only unique id's in case more than one is selected
arrayIds = unique(arrayIds);
//Lastly, we cycle through the id's, and also through each button so that we can click it again.
var i;
for (i = 0; i < arrayIds.length; ++i) {
$('#seedcohorts a#'+arrayIds[i]).each(function(){
$(this).click();
$(this).find('i').removeClass('fa-plus').addClass('fa-minus');
});
}
This code has to go at the end of the code when the user hits the sorting column.
Let me know how it goes, hope this helps,
Leo.
Have you tried something different from this?
$.get('/myurl?cohortid='+id, function(html) {
parent.after('<tr class="added tablesorter-childRow"><td colspan="7" >'+html+'</td></tr>');
});
I think you could be forcing the element appending to the table and the library could not recognise that row. Could you try appending the html at the same row than the parent?
$.get('/myurl?cohortid='+id, function(html) {
parent.append('<div class="added">'+html+'</div>');
});
I want to get the entire column of a table header.
For example, I want to select the table header "Address" to hide the address column, and select the "Phone" header to show the correspondent column.
<table>
<thead>
<tr>
<th id="name">Name</th>
<th id="address">Address</th>
<th id="address" class='hidden'>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td class='hidden'>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td class='hidden'>3456</td>
</tr>
</tbody>
I want to do something like http://www.google.com/finance?q=apl (see the related companies table) (click the "add or remove columns" link)
Something like this would work -
$('th').click(function() {
var index = $(this).index()+1;
$('table td:nth-child(' + index + '),table th:nth-child(' + index + ')').hide()
});
The code above will hide the relevant column if you click on the header, the logic could be changed to suit your requirements though.
Demo - http://jsfiddle.net/LUDWQ/
With a couple simple modifications to your HTML, I'd do something like the following (framework-less JS):
HTML:
<input class="chk" type="checkbox" checked="checked" data-index="0">Name</input>
<input class="chk" type="checkbox" checked="checked" data-index="1">Address</input>
<input class="chk" type="checkbox" checked="checked" data-index="2">Phone</input>
<table id="tbl">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td>3456</td>
</tr>
</tbody>
Javascript:
var cb = document.getElementsByClassName("chk");
var cbsz = cb.length;
for(var n = 0; n < cbsz ; ++n) {
cb[n].onclick = function(e) {
var idx = e.target.getAttribute("data-index");
toggleColumn(idx);
}
}
function toggleColumn(idx) {
var tbl = document.getElementById("tbl");
var rows = tbl.getElementsByTagName("tr");
var sz = rows.length;
for(var n = 0; n < sz; ++n) {
var el = n == 0 ? rows[n].getElementsByTagName("th")[idx] : rows[n].getElementsByTagName("td")[idx];
el.style.display = el.style.display === "none" ? "table-cell" : "none";
}
}
http://jsfiddle.net/dbrecht/YqUNz/1/
I added the checkboxes as it doesn't make sense to bind the click to the column headers as you won't be able to toggle the visibility, only hide them.
You can do something with CSS, like:
<html>
<head>
<style>
.c1 .c1, .c2 .c2, .c3 .c3{
display:none;
}
</style>
</head>
<body>
<table class="c2 c3">
<thead>
<tr>
<th id="name" class="c1">Name</th>
<th id="address" class="c2">Address</th>
<th id="phone" class="c3">Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td class="c1">Freddy</td>
<td class="c2">Nightmare Street</td>
<td class="c3">123</td>
</tr>
<tr>
<td class="c1">Luis</td>
<td class="c2">Lost Street</td>
<td class="c3">3456</td>
</tr>
</tbody>
</table>
</body>
</html>
To hide a column, you add with Javascript the corresponding class to the table. Here c2 and c3 are hidden.
You could add dynamically the .c1, .c2,... in a style tag, or define a maximum number.
The easiest way to do this would be to add a class to each td that matches the class of the header. When you click the , it checks the class, then hides every td with that class. Since only the s in that column would hide that class, it would effectively hide the column.
<table>
<thead>
<th>Name</th>
<th>Address</th>
</thead>
<tbody>
<tr>
<td class="Name">Joe</td>
<td class="Address">123 Main St.
</tbody>
</table>
And the script something like:
$('th').click( function() {
var col = $(this).html(); // Get the content of the <th>
$('.'+col).hide(); // Hide everything with a class that matches the col value.
});
Something like that, anyway. That's probably more verbose than it needs to be, but it should demonstrate the principle.
Another way would be to simply count how many columns over the in question is, and then loop through each row and hide the td that is also that many columns over. For instance, if you want to hide the Address column and it is column #3 (index 2), then you would loop through each row and hide the third (index 2).
Good luck..
Simulating the Google Finance show/hide columns functionality:
http://jsfiddle.net/b9chris/HvA4s/
$('#edit').click(function() {
var headers = $('#table th').map(function() {
var th = $(this);
return {
text: th.text(),
shown: th.css('display') != 'none'
};
});
var h = ['<div id=tableEditor><button id=done>Done</button><table><thead><tr>'];
$.each(headers, function() {
h.push('<th><input type=checkbox',
(this.shown ? ' checked ' : ' '),
'/> ',
this.text,
'</th>');
});
h.push('</tr></thead></table></div>');
$('body').append(h.join(''));
$('#done').click(function() {
var showHeaders = $('#tableEditor input').map(function() { return this.checked; });
$.each(showHeaders, function(i, show) {
var cssIndex = i + 1;
var tags = $('#table th:nth-child(' + cssIndex + '), #table td:nth-child(' + cssIndex + ')');
if (show)
tags.show();
else
tags.hide();
});
$('#tableEditor').remove();
return false;
});
return false;
});
jQuery('thead td').click( function () {
var th_index = jQuery(this).index();
jQuery('#my_table tbody tr').each(
function(index) {
jQuery(this).children('td:eq(' + th_index + ');').each(
function(index) {
// do stuff here
}
);
}
);
});
here's a working fiddle of this behaviour:
http://jsfiddle.net/tycRW/
of course, hiding the column with out hiding the header for it will have some strange results.