Infinite scroll on table with merged cells (defined colspan/rowspan) - javascript

How can I implement the infinite scroll on a table with the merged cells?
I want to implement pivot grid with lots of data to be processed. The difficulty is drawing only visible parts of headers (+ scrolling buffer).
Possible solutions:
Without smooth scrolling, discretely, redraw all table header. (I would like smoothness)
Implement the div-table and organize creating and deleting items on scroll event. (Could not find an example of a dynamic div-table with the merged cells)
Implement the table header from the sequence of tables, that created and removed as necessary. (delete borders, share labels between the nearby tables)
Example:
var xHeaderWrapperEl = document.querySelector(".header-wrapper");
var xHeaderTableEl = document.querySelector(".header-table");
xHeaderWrapperEl.addEventListener("scroll", function () {
if (xHeaderWrapperEl.scrollLeft >= xHeaderTableEl.offsetWidth - xHeaderWrapperEl.offsetWidth){
console.log("scroll next page");
} else if (xHeaderWrapperEl.scrollLeft <= 0) {
console.log("scroll prev page");
} else {
console.log("scroll");
}
});
.header-wrapper {
overflow-x: scroll;
width: 250px;
height: auto;
display: flex;
//flex-flow: row nowrap;
}
<body>
<div class="header-wrapper">
<!-- 1st block -->
<table class="header-table" border="1">
<tr>
<td colspan="10"><div>0x1</div></td>
</tr>
<tr>
<td colspan="2"><div>1x1</div></td>
<td colspan="8" rowspan="2"><div>1x2</div></td>
</tr>
<tr>
<td colspan="2"><div>2x1</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
<!-- 2nd block -->
<table class="header-table" border="1">
<tr>
<td colspan="4"><div>0x1</div></td>
<td colspan="6"><div>0x2</div></td>
</tr>
<tr>
<td colspan="4" rowspan="2"><div>1x1</div></td>
<td colspan="6"><div>1x2</div></td>
</tr>
<tr>
<td colspan="6"><div>2x1</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
<!-- 3rd block -->
<table class="header-table" border="1">
<tr>
<td colspan="2"><div>0x1</div></td>
<td colspan="6"><div>0x2</div></td>
<td colspan="2"><div>0x3</div></td>
</tr>
<tr>
<td colspan="2"><div>1x1</div></td>
<td colspan="2"><div>1x2</div></td>
<td colspan="2"><div>1x3</div></td>
<td colspan="2"><div>1x4</div></td>
<td colspan="2"><div>1x5</div></td>
</tr>
<tr>
<td colspan="2"><div>2x1</div></td>
<td colspan="2"><div>2x2</div></td>
<td colspan="2"><div>2x3</div></td>
<td colspan="2"><div>2x4</div></td>
<td colspan="2"><div>2x5</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
</div>
</body>
Take note flexbox...

I am assuming that you will have 1mln columns table according to your answer.
It is not realistic to have such a table continuously scrollable.
It will take forever to scroll/find/consume information from there.
Therefore you have to have some pagination / filtering mechanism there.
And with the pagination your problem is less severe. Split it in partial table blocks wrapped in scrollable page container. So you will have scrollable pages similar to gmail's message list - paginated yet scrollable.

Related

How to get td innerHTML per row and then set div css per row based on this value

I have a table as per the below and I want to use javascript or Jquery to get the value from the middle cell of each row. I then want to see the width of a div (id="myprogres") in the last cell to match the percentage that we just got.
My problems that I know of are
my td tags don't have an id or anything unique to identify them by. So identifying the 3rd td on each row isn't as simple as getElementById
I want to get the value on each row, and then set the corresponding myprogress width based upon that value.
myprogress is not a unique id, it's the same id per row.
This is a simplified version of the table so I appreciate the full css isn't there.
<table>
<tr>
<td>Hard drive</td>
<td>Usage</td>
<td>25</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
<tr>
<td>Memory</td>
<td>Usage</td>
<td>50</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
<tr>
<td>Brain Power</td>
<td>Usage</td>
<td>75</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
</table>
My td tags don't have an id or anything unique to identify them by.
This isn't a problem as you can loop over the progress bars directly.
I want to get the value on each row, and then set the corresponding myprogress width based upon that value.
As above, you can loop over the progress bars and use DOM traversal methods to get the related value from the previous td cell to set as the width of the bar. Specifically the closest() and prev() methods.
myprogress is not a unique id, it's the same id per row.
This is invalid HTML and needs to be fixed. Use a class instead.
With all that said, try this:
$('.myprogress').css('width', function() {
return $(this).closest('td').prev().text() + '%';
});
table {
width: 100%;
}
table td {
width: 25%;
}
.myprogress {
height: 20px;
background-color: #C00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table>
<tr>
<td>Hard drive</td>
<td>Usage</td>
<td>25</td>
<td><div class="myprogress"></div></td>
</tr>
<tr>
<td>Memory</td>
<td>Usage</td>
<td>50</td>
<td><div class="myprogress"></div></td>
</tr>
<tr>
<td>Brain Power</td>
<td>Usage</td>
<td>75</td>
<td><div class="myprogress"></div></td>
</tr>
</table>
First find all the divs in 4th td of the table
var divs = $("tr td:nth-child(4) div");
run a loop to set the width of the div and get the value from the 3rd td
for(var i=0;i<divs.length;i++) {
$(divs[i]).css({'width': $(divs[i]).parent().prev('td').text() + '%'});
}
Using pure Vanilla JS, you can achieve the result without jquery, with the help of querySelector() method..
const table = document.querySelector('table');
const row = table.querySelectorAll('tr');
row.forEach((tr,i) => {
const width = tr.querySelectorAll("tr td:nth-of-type(3)")[0].textContent;
const progress = tr.querySelectorAll("tr td:nth-of-type(4)")[0];
progress.querySelector('div').style.width = `${width}%`;
})
table td {
width: 10%;
}
#myprogress {
height: 20px;
background-color: green;
}
<table>
<tr>
<td>Hard drive</td>
<td>Usage</td>
<td>25</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
<tr>
<td>Memory</td>
<td>Usage</td>
<td>50</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
<tr>
<td>Brain Power</td>
<td>Usage</td>
<td>75</td>
<td>
<div style="width:100%">
<div id="myprogress"></div>
</div>
</td>
</tr>
</table>

JQuery sum rows with unique id elements

I'm looking for a way to display the sum of all the input elements (quantity and amount) respectively in the last 2 cells of each line.
Every element in this table has a unique id. Each input element has an id that contains information about the row it appears in :
var trRows = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
trRows.forEach(function(trRow) {
var $sumQuantity = 0;
var $sumAmount = 0;
$(this).find('#tr' + trRow + 'input[id *= "qty"]').each(function() {
$sumQuantity += +$(this).text() || 0;
});
$(this).find('#tr' + trRow + 'input[id *= "amount"]').each(function() {
$sumAmount += +$(this).text() || 0;
});
$('#sumQtyTR' + trRows, this).html($sumQuantity);
$('#sumAmountTR' + trRows, this).html($sumAmount);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr id='tr2'>
<td id='td2_65'><span id='span_i2qty_65'><input id='input_i2qty_65' class='editbox'></span>
</td>
<td id='td2_65'><span id='span_i2amount_65'><input id='input_i2amount_65' class='editbox'></span>
</td>
<td id='td2_66'><span id='span_i2qty_66'><input id='input_i2qty_66' class='editbox'></span>
</td>
<td id='td2_66'><span id='span_i2amount_66'><input id='input_i2amount_66' class='editbox'></span>
</td>
<td id='sumQtyTR2'></td>
<td id='sumAmountTR2'></td>
</tr>
<tr id='tr3'>
<td id='td3_65'><span id='span_i3qty_65'><input id='input_i3qty_65' class='editbox'></span>
</td>
<td id='td3_65'><span id='span_i3amount_65'><input id='input_i3amount_65' class='editbox'></span>
</td>
<td id='td3_66'><span id='span_i3qty_66'><input id='input_i3qty_66' class='editbox'></span>
</td>
<td id='td3_66'><span id='span_i3amount_66'><input id='input_i3amount_66' class='editbox'></span>
</td>
<td id='sumQtyTR3'></td>
<td id='sumAmountTR3'></td>
</tr>
<!-- More rows -->
</table>
I can't figure out why sums are not displayed. Selectors ? Thanks
Recommendations
Within your code there are a few points of interest that may be worth consideration to reduce the clutter:
IDs are intended to be unique. There should never be a time where an ID is used in more than one place in an HTML document. In places where you think two or more elements might share an id, you should use a class instead
Unless you are using jQuery elsewhere, you should know that jQuery is not necessary. It does provide several advantages (including cross-browser compliance), but you should consider using native JavaScript and a packager that will add the necessary polyfills
Examples
The examples below are intended to be close in structure/design to the original source code in the OP for learning purposes; however, it should be noted that there are many ways to optimize to improve performance and readability.
One major point worth mentioning is in the logic flow. The structure in these examples are inefficient, since every time an input is updated it is looping over and recalculating sums for all of the rows. This could be improved by only calculating and updating the sum of the altered row. Additionally, holding an array of interested rows (e.g., row_ids) could be better improved with more semantic HTML and the use of classes (if needing to be selective).
There are some other major changes made to both the jQuery and ES6+ example below. Most notably is the onChange event handler. The code in the OP iterated over each ID immediately on page load, but never again. There needed to be a hook into some event that would be called when the input box was modified; thus the onChange or onBlur event is necessary in order to re-calculate the values.
jQuery Example
Given these two recommendations, I've made some substantial changes to your HTML and JavaScript, which include but are not limited to:
removed unnecessary IDs and added respective classes
use reduce for sum calculation
jQuery(document).ready(function($) {
let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
function changeEventHandler() {
$.each(row_ids, function(ndx, row_id) {
const $row = $('#' + row_id)
if (!$row.length)
return;
const quantity = $row.find('input.quantity').get().reduce(function(acc, input) {
acc += parseFloat(input.value) || 0;
return acc
}, 0)
const amount = $row.find('input.amount').get().reduce(function(acc, input) {
acc += parseFloat(input.value) || 0;
return acc
}, 0)
$row.find('.sum.quantity').text(quantity)
$row.find('.sum.amount').text(amount)
});
}
$(document).on('change', 'input', changeEventHandler)
})
.sum { background: #eee; }
th,td {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
table { width: 100%; }
input { width: 40%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Fill in each input with a number (watch sums auto-update):
<table>
<thead>
<tr>
<th>QTY 1</th>
<th>AMT 1</th>
<th>QTY 2</th>
<th>AMT 2</th>
<th>SUM QTY</th>
<th>SUM AMT</th>
</tr>
</thead>
<tbody>
<tr id='tr2'>
<!-- td: use class and not id -->
<!-- remove unnecessary classes -->
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<tr id='tr3'>
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<!-- More rows -->
</tbody>
</table>
ES6+ Example
Given the two recommendations, I've made some substantial changes to your HTML and JavaScript, which include but are not limited to:
removed unnecessary IDs and added respective classes
removed unnecessary jQuery code (used native event handling)
use reduce for sum calculation
use arrow functions for simplified syntax
Note: as mentioned prior, the code may not work in all browsers (all versions and variations), but should work in most of the newer browsers. The snippet will work in most (if not all) because it is configured to use babel
function changeEventHandler() {
let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
// could iterate over the rows:
// document.querySelectorAll(selector)
// where selector is 'tr' or '[id^="tr"]'
row_ids.forEach(row_id => {
const row = document.querySelector(`#${row_id}`)
if (row == null)
return;
const qty_el = row.querySelectorAll('input.quantity')
const quantity = [...qty_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)
const amt_el = row.querySelectorAll('input.amount')
const amount = [...amt_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)
row.querySelector('.sum.quantity').textContent = quantity
row.querySelector('.sum.amount').textContent = amount
});
}
window.setTimeout(function() {
document.querySelectorAll('input').forEach(() => this.onchange = changeEventHandler)
},0);
.sum { background: #eee; }
th,td {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
table { width: 100%; }
input { width: 40%; }
Fill in each input with a number (watch sums auto-update):
<table>
<thead>
<tr>
<th>QTY 1</th>
<th>AMT 1</th>
<th>QTY 2</th>
<th>AMT 2</th>
<th>SUM QTY</th>
<th>SUM AMT</th>
</tr>
</thead>
<tbody>
<tr id='tr2'>
<!-- td: use class and not id -->
<!-- remove unnecessary classes -->
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<tr id='tr3'>
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<!-- More rows -->
</tbody>
</table>

jQuery or JS transformation of dynamic HTML table

I need to find a TABLE within a DIV tag and perform modifications on the header. The available reporting tool does not allow to identify the generated table but allows script and DIV insertion.
Consider the table below where the header is the first line:
<div id="ScrollHeader">
<table>
<tr>
<td>Browser</td>
<td>Visits</td>
<td>Pages/Visit</td>
<td>Avg. Time on Site</td>
<td>% New Visits</td>
<td>Bounce Rate</td>
<td>Avg. Time on Site</td>
<td>% New Visits</td>
<td>Bounce Rate</td>
</tr>
<tr>
<td>Firefox first</td>
<td>1,990</td>
<td>3.11</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
</tr>
<tr>
<td>Firefox</td>
<td>1,990</td>
<td>3.11</td>
<td>00:04:22 test test test</td>
<td>70.00%</td>
<td>32.61%</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
</tr>
</table>
</div>
I need a JavaScript or jQuery code to transform the table to the following:
<div id="ScrollHeader">
<table>
<thead>
<tr>
<th>Browser</th>
<th>Visits</th>
<th>Pages/Visit</th>
<th>Avg. Time on Site</th>
<th>% New Visits</th>
<th>Bounce Rate</th>
<th>Avg. Time on Site</th>
<th>% New Visits</th>
<th>Bounce Rate</th>
</tr>
</thead>
<tr>
<td>Firefox first</td>
<td class="numeric">1,990</td>
<td class="numeric">3.11</td>
<td class="numeric">00:04:22</td>
<td class="numeric">70.00%</td>
<td class="numeric">32.61%</td>
<td class="numeric">00:04:22</td>
<td class="numeric">70.00%</td>
<td class="numeric">32.61%</td>
</tr>
</table>
</div>
The code needs to identify the table within <div id="ScrollHeader">, insert THEAD before the first TR, change the TD to TH in the first line and close it with </thead>.
I have tried using $("div p[id^='ScrollHeader']").length to find the DIV and $("tr:first") to perform <table>.prepend(document.createElement('thead')); without success.
Try this:
$('#ScrollHeader table tr:eq(0)').wrap('<thead />');
$('#ScrollHeader table tr:eq(0) td').each(function () {
$('#ScrollHeader table tr:eq(0)').append($('<th />').html($(this).html()));
$(this).remove();
});
$('#ScrollHeader tr:first')
.wrap('<thead />')
.children().each(function(){
text = $(this).text();
$(this).replaceWith('<th>'+text+'</th>');
});
$('#ScrollHeader thead').insertBefore('#ScrollHeader tbody');
you can see it working here

Get the closest class from a list jquery

It's hard to explain, so I created an example:
jsfiddle
My idea is to change the color of each column when the respective input is in action...
If anyone has a better idea to do this - please let me know!
When I focus the input, I need the current class of the column.
first column input, get the class of the RED column
and the second one, get the class of the BLUE column
and so go's on...
Because if I get the class, then I can manipulate anything with this class.
the code is here:
$(".inputTest").focusin(function(){
var class = $(this).closest('.tableList')
.children().children().children('.auxClass')
.attr('class')
.split(' ')[0];
alert(class);
});
This is the main code, I try alot of stuffs to get, but nothing.
Thanks
First I'd add an outer table to split the page in a left and a right hand side. That way, the inputs below the red border and the inputs below the blue border each have their own table.
Then you can search for the first td below the closest table:
$(".inputTest").focusin(function(){
var class = $(this).closest('table').find('td:eq(0)').attr('class');
alert(class);
});
Click for working jsfiddle example.
Try this:
$(".inputTest").focus(function(){
var class = $(this).closest('table').parent().attr('class');
alert(class);
});
Edit: Oh, i just realised your inputs are not inside your tables, i think you're gonna have a hard time matching them up to the table/column they're under then. You'd need to add a common attribute to identify them by.
As mentioned in other answers your inputs are not actually in the same "columns" as your red/blue bordered tables, but you can make it so they are using the <col> element on the main table, then using the index value you can match your inputs to their column
Working Example
HTML - the only addition is the two <col> elements at the start
<table width="100%" border="1" class='tableList'>
<col span="2" class="left">
<col span="2" class="right">
<tr>
<td class="101 auxClass" width="261px" colspan="2" style="border: solid red;">
<table border="1" cellspacing="1" cellpadding="1" width="100%" height="70px">
<tbody>
<tr>
<td colspan="2">Something</td>
</tr>
<tr>
<td width="78px">Something 2</td>
<td>Total</td>
</tr>
</tbody>
</table>
</td>
<td class="102" width="261px" colspan="2" style="border: solid blue;">
<table border="1" cellspacing="1" cellpadding="1" width="100%" height="70px">
<tbody>
<tr>
<td colspan="2">
Something 3
</td>
</tr>
<tr>
<td width="78px">Something 4</td>
<td width="75px">Total 2</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
</tr>
<tr>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
</tr>
<tr>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
<td>Result</td>
<td><input type="text" class="inputTest"/></td>
</tr>
</table>
CSS:
col.current {background: #eee;}
jQuery
$(".inputTest").focusin(function(){
var colidx = $(this).closest('td').index();
if (colidx == 1) {
$("col").removeClass('current');
$("col.left").addClass('current');
} else if (colidx == 3) {
$("col").removeClass('current');
$("col.right").addClass('current');
}
});
Your main table is actually 4 columns, and you need to split it into two halfs of two columns each with the input being in the second column of each half
The jQuery is finding the index of the parent td of the input - there are four columns in the main table so the index of a td will either be 0,1,2 or 3 - and the input is either going to be in cell index 1 or cell index 3. When it finds out which one it add a class to the relevant col element to which you can add a background highlight..
Note though that the CSS you can apply to a col element is limited, see: http://www.quirksmode.org/css/columns.html , for the options so it would depend what you want to do
however I think from this you could probably target td index 0 & 1, or td index 2 & 3 if needed

Manipulating <td>'s within different <tr>'s

I'm wondering if the following can be done.
I have a list of 'expenses' that I'm displaying in a table. 4 columns - amount, date, where, and what.
I was thinking I'd like to make each clickable via jQuery which would expand that particular expense, inline, to show a more detailed description.
What I'm trying to do is, on click, replace the contents of the 'tr' with a single 'td' that would contain the extended info. Problem is that 'td' only expands to about a quarter of the table. Is there any way of making it extend to the whole row, while maintaining the widths of the other 'td's in the other rows?
Here's what I would do. Working Demo.
<table id="expenses">
<thead>
<tr>
<td>Amount</td>
<td>Date</td>
<td>Where</td>
<td>What</td>
</tr>
</thead>
<tbody>
<tr class='expense' id='expense-1'>
<td>$5.99</td>
<td>4/2/2009</td>
<td>Taco Bell</td>
<td>Chalupa</td>
</tr>
<tr class='details' id='details-1'>
<td colspan='4'>
It was yummy and delicious
</td>
</tr>
<tr class='expense' id='expense-2'>
<td>$4.99</td>
<td>4/3/2009</td>
<td>Burger King</td>
<td>Whopper</td>
</tr>
<tr class='details' id='details-2'>
<td colspan='4'>
The king of burgers, indeed!
</td>
</tr>
<tr class='expense' id='expense-3'>
<td>$25.99</td>
<td>4/6/2009</td>
<td>Olive Garden</td>
<td>Chicken Alfredo</td>
</tr>
<tr class='details' id='details-3'>
<td colspan='4'>
I love me some italian food!
</td>
</tr>
</tbody>
</table>
With styles like these:
#expenses tr.expense {
cursor: pointer;
}
#expenses tr.details {
display: none;
}
And then have Javascript that looks like this:
$(function() {
$('tr.expense', '#expenses').click(function() {
var id = $(this).attr('id').split('-').pop();
var details = $('#details-'+id);
if(details.is(':visible')) {
details.hide();
} else {
details.show();
}
});
});
That should do it.
<td colspan="4"> ?

Categories

Resources