i am trying to update first row width with JavaScript,
I have multiple tables
<table page="1">
<tbody>
<tr><td>aaaa</td><td>bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
....
</tbody>
</table>
<table page="2">
<tbody>
<tr><td>eeee</td><td>fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
....
</tbody>
</table>
and an array
var cw = ["100","500"];
i am trying to create a function that will change only the tds from first row inside each table, so the end result should be
<table page="1">
<tbody>
<tr><td style="width:100px;">aaaa</td><td style="width:500px;">bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
....
</tbody>
</table>
<table page="2">
<tbody>
<tr><td style="width:100px;">eeee</td><td style="width:500px;">fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
....
</tbody>
</table>
Since i only started using JavaScript i don't know best way to do things, yet, so i put this jsfiddle together from different examples, the problem is that i will have a lot of tables in one page (around 300) and i would like to know if this is the best way to do it:
var cw = ["100","500"];
var i,j,col;
var tables = document.getElementsByTagName("table");
for(i = 0;i<tables.length;i++) {
for ( j = 0, col; col = tables[i].rows[0].cells[j]; j++) {
col.style.width = cw[j]+'px';
}
}
i am afraid that 2 loops will make the browser unresponsive or slow, so can this be done safer with JavaScript or jquery?
Also i need this to work on IE, Chrome and Firefox
Thanks
Here is an example of how it should work
var size = ["100px", "500px"];
var tr = document.querySelectorAll('tbody tr:first-child');
for (i = 0; i < tr.length; i++) {
tr[i].firstElementChild.style.width = size[0];
tr[i].querySelector('td:nth-child(2)').style.width = size[1];
}
td {
background: yellow;
}
// Background for showing purpose only!
<table page="1">
<tbody>
<tr><td>aaaa</td><td>bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
</tbody>
</table>
<table page="2">
<tbody>
<tr><td>eeee</td><td>fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
</tbody>
</table>
Enjoy!
I'm not sure you'll be able to get away from using two loops. One to go through each table and find the first row and the second to apply the widths to each td. Here's my jQuery version:
function assignWidths(arr){
$('table').each(function(){
var firstRowTds = $(this).find('tr').eq(0).children('td');
firstRowTds.each(function(i){
$(this).css('width', arr[i] + 'px');
});
});
}
Related
I have an output.php. It creates an html table with 3 columns: Question number, Correct Answer, Student Answer. Works just as I want it to.
Now what I would like is to paint the cells with incorrect student answers red. I think Javascript is the best way to do this, rather than php.
Looking at other answers here, I was hoping this might do the job, but, alas ...
Can you please help me get this working?
<script type="text/javascript" >
function paint_cells() {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
</script>
You code working good! I think your problem occurs that your js run before the dom already loaded. You have multiple opportunities to fix this. 1) you can add your script to the bottom inside the body tag. 2) work with onload event. https://developer.mozilla.org/de/docs/Web/API/GlobalEventHandlers/onload
Note Maybe you forgot to call the function? paint_cells()
function paint_cells() {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
}
paint_cells();
<table border="1">
<thead>
<tr>
<th>Question</th>
<th>Correct Answer</th>
<th>Students Answer</th>
</tr>
</thead>
<tbody>
<tr>
<td>abc</td>
<td>right</td>
<td>false</td>
</tr>
<tr>
<td>abc</td>
<td>right</td>
<td>right</td>
</tr>
<tr>
<td>abc</td>
<td>right</td>
<td>false</td>
</tr>
</tbody>
</table>
I think you need to wait for page DOM loaded, try below. And it also depends on how and when the table in your page is generated, if it doesn't work, please provide more details.
<script type="text/javascript" >
window.addEventListener('DOMContentLoaded', (event) => {
var tds = document.querySelectorAll('tbody td'), i;
for(i = 0; i < tds.length; i += 3) {
if(tds[i+1].textContent != tds[i+2].textContent){
tds[i+2].bgColor = "red";
}
}
});
</script>
I am using a JavaScript snippet to show a responsive table, setting the headers on mobile via attributes. This works, but, if I use a second table with the same class, it goes all wrong on mobile (please resize your screen to see this); the headers of.
What am I doing wrong here and how can I fix this?
This is the HTML:
<table class="test">
<thead>
<tr>
<th>Bla</th>
<th>Bla</th>
<th>Bla</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bla</td>
<td>Blabla</td>
<td>Blablabla</td>
</tr>
</tbody>
</table>
<table class="test">
<thead>
<tr>
<th>Not</th>
<th>Not</th>
</tr>
</thead>
<tbody>
<tr>
<td>Twatwa</td>
<td>Twatwa</td>
</tr>
</tbody>
</table>
http://codepen.io/anon/pen/QbJqVv
Edit: after the new answer, it does show table headers on the second table now, but not the correct ones. It just puts the table headers of the first table, into the second.
As I wrote in the comments, you need to handle each table separately. For .querySelectorAll('.test th') will simply give you all th elements, irregardless of which table they belong to.
Here's a quick example of how this could be done.
// for each .test
[].forEach.call(document.querySelectorAll('.test'), function (table) {
// get header contents
var headers = [].map.call(table.querySelectorAll('th'), function (header) {
return header.textContent.replace(/\r?\n|\r/, '');
});
// for each row in tbody
[].forEach.call(table.querySelectorAll('tbody tr'), function (row) {
// for each cell
[].forEach.call(row.cells, function (cell, headerIndex) {
// apply the attribute
cell.setAttribute('data-th', headers[headerIndex]);
});
});
});
demo: http://codepen.io/anon/pen/NqEXqe
First of all, your HTML is invalid, as you are not closing any of your elements (<tr><td></td></tr> etc) - but that's another issue. Please practice good HTML standards.
You are not using querySelectorAll when selecting your table bodies, so you're only setting the attribute in the first one found.
This revised snippet should achieve what you are trying to do.
var headertext = [],
headers = document.querySelectorAll(".test th"),
tablerows = document.querySelectorAll(".test th"),
tablebody = document.querySelectorAll(".test tbody");
for(var i = 0; i < headers.length; i++) {
var current = headers[i];
headertext.push(current.textContent.replace(/\r?\n|\r/,""));
}
for (var tb = 0; tb < tablebody.length; tb++) {
for (var i = 0, row; row = tablebody[tb].rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
col.setAttribute("data-th", headertext[j]);
}
}
}
I am trying to delete multiple columns from html table using javascript.
The logic it is using is that it searches in top row for tag "" and then deletes that column.
The problem is if only one cell in top row is having '', then it deletes that columns fine, but if there are multiple columns it throws error.
Here is my code
<!DOCTYPE html>
<html>
<body>
<table style="width:100%" border='1' id='Just_for_california'>
<tr>
<td><span></span></td>
<td>S</td>
<td><span></span></td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
<script>
var dataTable_length = document.getElementById('Just_for_california').rows[0].cells.length;
var count_rows = document.getElementById('Just_for_california').rows.length;
var column_array = [];
for(var i=0; i<dataTable_length; i++)
{
var str = document.getElementById("Just_for_california").rows[0].cells[i].innerHTML;
if(str.search("<span></span>") != -1)
{
column_array.push(i);
}
}
var len = column_array.length;
for(var i=count_rows-1 ; i>=0;i--)
{
rows_number = document.getElementById('Just_for_california').rows[i];
console.log("row_number:"+i);
for(var j=0; j<len;j++)
{
rows_number.deleteCell(column_array[j]);
}
}
</script>
</html>
It happens because you calculate indexes incorrectly when you delete cells. I refactored you code (making it clearer) and it seems to work now:
var table = document.getElementById('Just_for_california'),
rows = table.rows;
for (var i = 0; i < rows[0].cells.length; i++) {
var str = rows[0].cells[i].innerHTML;
if (str.search("<span></span>") != -1) {
for (var j = 0; j < rows.length; j++) {
rows[j].deleteCell(i);
}
}
}
The problem is that you are trying to remove cells "horizontally" in the row. So say you want to delete cells at indexes 1 and 3 and there are 4 columns in the table. When you delete the first cell 1 it works fine. However then you move to the right and try to remove cell at index 3. This fails because since you have already removed cell 1, there is no cell with index 3 anymore. The maximum index now is 2. Hence the error.
In my improved code I'm removing columns "vertically", so such an issue can't happen.
Demo: http://jsfiddle.net/t2q60aag/
Imagine I have a table of data in HTML and each of the rows have, say, one of three possible classes: RowA, RowB, and RowC; which represent the information in the rows. (For example, Small, Medium, and Large cars).
Above the table, I have 3 checkboxes: "Show Small Cars", "Show Medium Cars", "Show Large Cars".
If the user deselects "Show Small Cars", then the rows containing small cars should disappear.
This is how I would do it:
function showHideRows(classToShowOrHide, checkBoxSender)
{
var tableObj = document.getElementById("myDataTable");
for (i = 0; i < tableObj.childNodes.length; i++)
if (tableObj.childNodes[i].className == classToShowOrHide)
tableObj.childNodes[i].style.display = checkBoxSender.checked ? "visible" : "none";
}
Is there a better way? For example, can I modify the css class using javascript to include/exclude a display: none?
I'm not using jQuery.
If you define your markup/styles as this:
<table class="showSmallCars showMediumCars">
<tr class="smallCar">...<tr>
<tr class="mediumCar">...<tr>
</table>
CSS:
table tr { display:none; }
table.showSmallCars tr.smallCar { display:table-row; }
table.showMediumCars tr.mediumCar { display:table-row; }
then it is enough for you to modify class attribute on table to present records of groups you need:
Thus <table class="showSmallCars showMediumCars"> will show smalls an mediums
and <table class="showSmallCars showMediumCars showLargeCars"> will show all of them.
And no need to scan all rows in script.
jQuery is a cleaner way to do it; go to http://www.jquery.com and follow the instructions there to start using it, then your function becaomse
function showHideRows(classToShowOrHide, checkBoxSender)
{
$('.' + classToShowOrHide, '#myDataTable').each(function(){
$(this).css('display', ((checkBoxSender.checked) ? 'visible' : 'none'));
});
}
If you want to do it in vanilla JS, something like this should be about right. Probably a gremlin in the following code somewhere, I don't do much vanilla JS any more :) jQuery is that good.
window.onload=function(){
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
}
function showHideRows(classToShowOrHide, checkBoxSender)
{
for (i = 0; i < document.getElementsByClassName(classToShowOrHide); i++)
document.getElementsByClassName(classToShowOrHide)[i].style.display = checkBoxSender.checked ? "visible" : "none";
}
Really, the basics of showing and hiding rows can be done very cleanly in CSS. Javascript is only required to tell the surrounding table what type it should show - and that's just a matter of setting a class name.
If this is your HTML:
<table>
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Price</td>
</tr>
<tbody>
<tr class="rowA">
<td>Falcon</td>
<td>Large</td>
<td>$160.00</td>
</tr>
<tr class="rowA">
<td>Commodore</td>
<td>Large</td>
<td>$160.00</td>
</tr>
<tr class="rowB">
<td>Camry</td>
<td>Medium</td>
<td>$110.00</td>
</tr>
<tr class="rowB">
<td>Lancer</td>
<td>Medium</td>
<td>$105.00</td>
</tr>
<tr class="rowC">
<td>Prius</td>
<td>Small</td>
<td>$75.00</td>
</tr>
<tr class="rowC">
<td>Civic</td>
<td>Small</td>
<td>$80.00</td>
</tr>
</tbody>
</thead>
</table>
Use this CSS:
/* The rows to show */
table.showTypeA .rowA,
table.showTypeB .rowB,
table.showTypeC .rowC {
display: table-row;
}
/* Then, hide the other types */
table.showTypeA .rowB,
table.showTypeA .rowC,
table.showTypeB .rowA,
table.showTypeB .rowC,
table.showTypeC .rowA,
table.showTypeC .rowB {
display: none;
}
All you need to do with javascript is set a class on the table of 'showTypeA', 'showTypeB', 'showTypeC', and the browser will take care of the rest.
I know you asked for JavaScript, but you could do it failry easy with jQuery.
Like:
http://jsfiddle.net/XJRVt/17/
You would proberbly also need to do a check on page load :)
I have a table that is a history of a mysql record.
I want to add a button that will highlight the changes.
<table>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
In this example the 600 would be highlighted as it was 300 and is now 600.
UPDATE: Thanks, I should have said there would be more than 2 rows. could be upto 20 rows
This jsFiddle shows an example that will iterate over a table of any size and highlight the cells that have changed from the previous row.
$(function() {
var $rows = $("tr");
for (oldIndex = 0; oldIndex < $rows.length-1; oldIndex++) {
var newIndex = oldIndex + 1;
var $oldCols = $("td", $rows[oldIndex]);
var $newCols = $("td", $rows[newIndex]);
for (col = 0; col < $oldCols.length; col++) {
var $newCol = $($newCols[col]);
if ($($oldCols[col]).html() != $newCol.html()) {
$newCol.addClass("highlight");
}
}
}
});
Your solution should go along these lines. Assuming set1 and set2 are id's of two trs here is a sample code (not tested).
var s1 = $('tr#set1 td');
var s2 = $('tr#set2 td');
var l = $('tr#set1 td').length;
for(var i =0; i<l i++){
if(s1.eq(i).text() != s2.eq(i)){
$(s2.eq(i)).highlight();
}
}
$('table tr.new td').each(function(i){
//First TR td, Previous Rows
td = $(this);
check = $('table tr.prev td:eq('+i+')');
if(td[0].innerText != check[0].innerText)
{
check.addClass('Changed');
}
})
This should do it but you need to add 2 classes:
<table>
<tr class="new">
<td>150</td>
<td>200</td>
<td>300</td>
</tr>
<tr class="prev">
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
Demo: http://jsfiddle.net/hjXZd/1/
Hope this helps.
I advise you to do an attr for each TD and place the mysql id in there so that you will only compare the rows that are the same in the DB, otherwise if your first list has more items then the second list the results will be corrupt.
Assuming your table has the id results, here is a solution:
var topRow = $('table#results tr:eq(0)');
var bottomRow = $('table#results tr:eq(1)');
topRow.find('td').each(function(index,item){
var shadow = bottomRow.find('td:eq('+index+')');
if($(item).contents().text()!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
Update: this solution compares the top row with all following ones:
$('table#results tr:eq(0) td').each(function(index,item){
var orig = $(item).contents().text();
$('table#results tr:gt(0)').find('td:eq('+index+')').each(function(index2,item2){
var shadow = $(item2);
if(orig!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
});
Using Jquery .live you can handle multiple elements.
See here
http://api.jquery.com/live/
You have to give ids for the changed values.. which can be inside divs.
Hope td also may work
On button click using this .live you can chnage style of div
like highlighting.
Use addClass function os jquery itslef or you can add css using jquery add