i have HTML table, how to do row span on specific columns using j-query. i want to row span on specific columns as can be seen in fiddle demo
here is Demo
after HTML Result should be using jquery
Below is HTML.
<p>Before</p>
<table width="200" border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>4</td>
<td>1</td>
<td>1</td>
<td>5</td>
</tr>
<tr>
<td>1</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>3</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>1</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
</tr>
<tr>
<td>13</td>
<td>131</td>
<td>4155</td>
<td>464</td>
<td>46</td>
</tr>
</table>
<p>After Sholud be using jquery (dynamically)</p>
<table width="200" border="1">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td rowspan="2">1</td>
<td>4</td>
<td rowspan="2">1</td>
<td rowspan="2">1</td> <td>5</td>
</tr>
<tr>
<td>5</td>
<td>3</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>1</td>
<td>6</td>
<td>7</td>
</tr>
<tr>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
</tr>
<tr>
<td>13</td>
<td>131</td>
<td>4155</td>
<td>464</td>
<td>46</td>
</tr>
</table>
i try this,but it does not work
groupTable($('#gvSearchRecord tr:has(td)'), 2,2);
$('#gvSearchRecord .deleted').remove();
function groupTable($rows, startIndex, total) {
if (total === 0) {
return;
}
var i, currentIndex = startIndex, count = 1, lst = [];
var tds = $rows.find('td:eq(' + currentIndex + ')');
var ctrl = $(tds[0]);
lst.push($rows[0]);
for (i = 1; i <= tds.length; i++) {
if (ctrl.text() == $(tds[i]).text()) {
count++;
$(tds[i]).addClass('deleted');
lst.push($rows[i]);
}
else {
if (count > 1) {
ctrl.attr('rowspan', count);
groupTable($(lst), startIndex + 1, total - 1)
}
count = 1;
lst = [];
ctrl = $(tds[i]);
lst.push($rows[i]);
}
}
}
I've updated your JSFiddle example:
http://jsfiddle.net/bn9m1p6k/6/
I've removed the list parameter and put the rowspan parameter in a data-attribute.
When the rowspan is directly applied, the table is changed and the following checks aren't correct.
Both the delete and rowspan are applied after all cells have been traversed.
This is the full code:
groupTable($('#gvSearchRecord tr:has(td)'), 0,5);
$('#gvSearchRecord .deleted').remove();
$('#gvSearchRecord td[data-rowspan]').each(function(){
$(this).attr('rowspan', $(this).attr('data-rowspan'));
});
function groupTable($rows, startIndex, total) {
if (total === 0) {
return;
}
var i, currentIndex = startIndex, count = 1, lst = [];
var tds = $rows.find('td:eq(' + currentIndex + ')');
var ctrl = $(tds[0]);
for (i = 1; i < tds.length; i++) {
if (ctrl.text() == $(tds[i]).text()) {
count++;
$(tds[i]).addClass('deleted');
}
else {
if (count > 1) {
ctrl.attr('data-rowspan', count);
}
count = 1;
//lst = [];
ctrl = $(tds[i]);
//lst.push($rows[i]);
}
}
groupTable($rows, startIndex + 1, total - 1);
}
DEMO FIDDLE
The easiest way i found was to create a 2D array and then traverse it in reverse. This was the case, as rowspan works by pushing itself down, and if you remove a matching element from below, you then have trouble matching to the element above it when more than 2 are on top of one another.
There are assumptions that both your code and mine are making:
There is no header table row (can be fixed by changing the initial processArray element assignment selectors
No cells have colspan (if this is not the case, i will happily re-examine my code)
JS
var processArray = [];
// make things easier to traverse in reverse by first creating a 2D array of the table
$('#before tr').each(function(i){
var processRow = [];
$(this).find('td').each(function(){
processRow.push($(this));
});
processArray.push(processRow);
});
function computeDuplicates(){
// we are starting at the last row and working up to row 2
// we dont need to look at the first row, as we're looking at it from the row below
for(var x = processArray.length - 1; x > 0 ; x--){
for(var y = 0; y < processArray[x].length; y++){
if(processArray[x][y].text() == processArray[x-1][y].text()){ //if the cell above has the same text as the current cell
var currentRowSpan = processArray[x][y].attr('rowspan'); // get the current cell rowspan
if(typeof currentRowSpan == "undefined"){ // no rowspan found on current cell
currentRowSpan = 2; // set default of 2
}else{
currentRowSpan = parseInt(currentRowSpan, 10) + 1; // increase by 1
}
// apply currentRowSpan to above cell and delete current cell
processArray[x-1][y].attr('rowspan', currentRowSpan);
processArray[x][y].remove();
}
}
}
processArray = []; // remove from memory
}
computeDuplicates();
Related
My html page contains ajax, which helps to create a table dynamically.
<title>Clients</title>
</head>
<body>
<table style="width:100%" id="clients_data">
<caption>Clients</caption>
<tr>
<th>Clients</th>
<th>Number of Sites</th>
<th>Reset the Processing</th>
</tr>
</table>
<script>
var myTable;
$(document).ready(function () {
loadCustomers();
});
function loadCustomers() {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/cache/getCustomers',
dataType: 'json',
success: function(data) {
var rows = [];
$.each(data,function(id,value) {
rows.push('<tr><td><a href="clientSiteInfo.html?client='+id+'">'+id+'</td><td>'+value+'</td><td><button type="button" onclick="reset(\''+id+'\')">Reset</td></tr>');
});
$('#clients_data').append(rows.join(''));
}
});
};
</script>
</body>
</html>
At runtime, i may have 100s of rows populated in the table. How can I add pagination ,sorting fro this table using jquery?
Here is a very basic example using jQuery each(), index(), toggle(), and an Anonymous function. I'm leveraging HTML 5 data-* attributes to keep track of my position and set the number of items to increase/decrease.
You can use plugins or write your own code to make pagination as simple or complex as you would like. Although I would strongly suggest using AJAX to populate your results, as loading 1000's of results to hide/show could potentially slow down a system.
/* Variable Defaults */
var total = $('tbody > tr').length;
var position = $('tbody').data('position');
var jump = $('tbody').data('jump');
var paginate = function(position, jump) {
/* Show Default Items */
$('tbody > tr').each(function() {
/* Variable Defaults */
var index = $(this).index();
/* Condition */
var condition = (index >= position) && (index < position + jump);
/* Hide/Show Item */
$(this).toggle(condition);
/* Set Disabled Status */
$('.less').prop('disabled', (position - jump) < 0);
$('.more').prop('disabled', (position + jump) >= total);
});
};
/* Set Default Text */
$('.count').text(jump);
/* Init Paginate */
paginate(position, jump);
/* Bind Click Events to "Less" and "More" Button */
$('.less, .more').on('click', function() {
/* Decrease/Increase Position */
position = $(this).hasClass('less') ? $('tbody').data('position') - jump : $('tbody').data('position') + jump;
/* Paginate */
paginate(position, jump);
/* Update Position */
$('tbody').data('position', position);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Email</td>
</tr>
</thead>
<tbody data-position="0" data-jump="2">
<tr>
<td>1</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>2</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>3</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>4</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>5</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>6</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>7</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>8</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>9</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
<tr>
<td>10</td>
<td>Test McTester</td>
<td>test#gmail.com</td>
</tr>
</tbody>
</table>
<button class="less">Back <span class="count">0</span></button>
<button class="more">Forwards <span class="count">0</span></button>
You can use Datatables for your purpose :
https://datatables.net/examples/basic_init/alt_pagination.html
You can also use Tablesorter :
http://tablesorter.com/docs/
I have a table for example:
head1 head2 head3
x 1 BLA
y 2 BLA
z 3 BLA
I want to be able to do Group by function liek SQL:
select count(head2) , head3
group by head3
And the output will be something like:
3 BLA
iv'e been told that i able to do this only on the server side but I want to do that on the client side.
the table is in format of HTML
<table>
<thead>
<tr>
<th>head1</th>
<th>head2</th>
<th>head3</th>
</tr>
</thead>
<tbody>
<tr>
<td>x</td>
<td>1</td>
<td>BLA</td>
</tr>
<tr>
<td>y</td>
<td>2</td>
<td>BLA</td>
</tr>
<tr>
<td>z</td>
<td>3</td>
<td>BLA</td>
</tr>
</tbody>
</table>
So just for fun...
function countByGroup(data, val)
{
var i, count = 0;
for (i=0; i<data.length; i++)
{
if (val === data[i].head3)
{
count++;
}
}
return count;
}
var payload = [
{
head1: "x",
head2: 1,
head3: "BLA"
},
{
head1: "y",
head2: 2,
head3: "BLA"
},
{
head1: "z",
head2: 3,
head3: "THER"
}
];
window.alert(countByGroup(payload, "BLA") + " BLA");
window.alert(countByGroup(payload, "THER") + " THER");
Fiddleige.
There's no, nice, LINQ-like or SQL-like way of doing it. If you want to be able to change column name, we can do that too, but, again, it depends on what your data looks like on the client.
If you wanted to know more than one val type each time, you'd want to edit the function to check for more than one count at a time, otherwise you're looping needlessly.
And, again, please be careful sorting tens of thousands of rows of data if it's tied to your UI at all.
OK!
I watched #ruffin answer and I just changed it a little for my own case:
<table>
<thead>
<tr>
<th>head1</th>
<th>head2</th>
<th>head3</th>
</tr>
</thead>
<tbody>
<tr class="trtest">
<td>x</td>
<td>1</td>
<td>BLA</td>
</tr>
<tr class="trtest">
<td>y</td>
<td>2</td>
<td>BLA</td>
</tr>
<tr class="trtest">
<td>z</td>
<td>3</td>
<td>THER</td>
</tr>
</tbody>
</table>
<script>
var payload = [];
function countByGroup(data, val)
{
var i, count = 0;
for (i=0; i<data.length; i++)
{
if (val === data[i].head3)
{
count++;
}
}
return count;
}
for(i = 0 ; i < document.getElementsByClassName('trtest').length ; i++)
{
var obj = new Object();
obj.head1 = document.getElementsByClassName('trtest')[i].getElementsByTagName('td')[0].innerHTML;
obj.head2 = document.getElementsByClassName('trtest')[i].getElementsByTagName('td')[1].innerHTML;
obj.head3 = document.getElementsByClassName('trtest')[i].getElementsByTagName('td')[2].innerHTML;
payload.push(obj)
}
window.alert(countByGroup(payload, "BLA") + " BLA");
window.alert(countByGroup(payload, "THER") + " THER");
</script>
this worked for me very good for this current case.
Thank you all!
I'm trying to move cell values within a three by three table. But I am moving one cell at a time with the click of a button. Is this possible with jQuery or JS? I have the following table:
[1][2][3]
[4][5][6]
[7][8][9]
and I want to click a button to move right like so:
[4][1][2]
[7][5][3]
[8][9][6]
and so on..
this is my HTML:
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr><tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr><tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
<button id="moveStuff">Move!</button>
This is so hacky and I don't necessarily advise it, but it should give you a place to start out from. Basically what you can do is create a function that grabs all the tds and based on their index value, rearrange them. Every time the function is called, it recreates the cells variable, meaning it will always start out fresh with the correct index values associated with the correct cells.
Source: http://jsfiddle.net/9nfvc/
Demo: http://jsfiddle.net/9nfvc/show
HTML
<table id="rotation">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr><tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr><tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
<button id="moveStuff">Move!</button>
javascript
document.getElementById('moveStuff').onclick = (function(){
var cells = document.getElementById('rotation').getElementsByTagName('td');
var rows = document.getElementById('rotation').getElementsByTagName('tr');
rows[2].appendChild(cells[5].parentNode.removeChild(cells[5]));
rows[1].appendChild(cells[2].parentNode.removeChild(cells[2]));
rows[1].insertBefore(cells[5].parentNode.removeChild(cells[5]), cells[3]);
rows[0].insertBefore(cells[2].parentNode.removeChild(cells[2]), cells[0]);
});
EDIT
I like this way better.
Source: http://jsfiddle.net/ZquQL/
Demo: http://jsfiddle.net/ZquQL/show
javascript
document.getElementById('moveStuff').onclick = (function(){
var parent = document.getElementById('rotation');
var cells = [];
var rows = parent.getElementsByTagName('tr');
var patern = [3,0,1,6,4,2,7,8,5];
for (var i = 0; i < rows.length; i++) {
while(rows[i].firstChild) {
var node = rows[i].removeChild(rows[i].firstChild)
if(node.nodeType === document.ELEMENT_NODE) cells.push(node);
}
}
row = -1;
for(i in cells) {
if(i%3 === 0) row++;
rows[row].appendChild(cells[patern[i]]);
}
});
html JS FIDDLE HERE
See first example home,Scripts,Snippet. if Script Parent is 1 it should under home tr,if Snippet parent id is 6 it is under the Script menu
<table id="sort-table">
<tbody>
<tr>
<th>Id</th>
<th>Parent</th>
<th>Title</th>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>home</td>
</tr>
<tr>
<td>2</td>
<td>0</td>
<td>Code</td>
</tr>
<tr>
<td>3</td>
<td>0</td>
<td>Contact</td>
</tr>
<tr>
<td>4</td>
<td>10</td>
<td>PHP</td>
</tr>
<tr>
<td>5</td>
<td>2</td>
<td>CSS</td>
</tr>
<tr>
<td>6</td>
<td>1</td>
<td>Scripts</td>
</tr>
<tr>
<td>8</td>
<td>4</td>
<td>Archive</td>
</tr>
<tr>
<td>9</td>
<td>6</td>
<td>Snippet</td>
</tr>
<tr>
<td>10</td>
<td>0</td>
<td>samitha</td>
</tr>
<tr>
<td>7</td>
<td>4</td>
<td>help</td>
</tr>
</tbody>
</table>
<span></span>
<br>
<button class="sort-table asc">sort</button>
jquery
$('.sort-table').click(function (e) {
var table = $("table tbody");
table.find('tr').each(function () {
var $tds = $(this).find('td'),
id = $tds.eq(0).text(),
parent = $tds.eq(1).text(),
title = $tds.eq(2).text();
if (parent === 0) {
}
});
});
output
Id Parent Title
1 0 home
2 0 Code
3 0 Contact
4 10 PHP
5 2 CSS
6 1 Scripts
8 4 Archive
9 6 Snippet
10 0 samitha
7 4 help
I want to sort it like bellow
2nd table
Id Parent Title
1 0 home
6 1 Scripts
9 6 Snippet
2 0 Code
5 2 CSS
3 0 Contact
10 0 samitha
4 10 PHP
8 4 Archive
7 4 help
I want if the parent Id is the id of menu it need to be sort like above 2nd table.I did something with and i need to go though on this ?
As there is no apparent system to sort by, I guess you have to define something yourself :
$('.sort-table').click(function (e) {
var sort = [1,6,9,2,5,3,10,4,8,7],
table = $("table tbody"),
tr = table.find('tr');
$.each(sort, function(_,index) {
tr.filter(function() {
return parseInt($('td:first', this).text(), 10) == index;
}).appendTo(table);
});
});
FIDDLE
EDIT:
I think maybe I get it, but I probably don't?
If you are trying to add each TR element after the TR element that has the ID of the given parent element in the current TR etc... ???
Anyway, try this :
$('.sort-table').click(function (e) {
var table = $("table tbody"),
tr = table.find('tr');
$.each(tr, function(_,el) {
var par = parseInt($(el).find('td').eq(1).text(), 10);
if (par !== 0) {
var par_el = tr.find('td:first').filter(function() {
return parseInt($(this).text(),10) == par;
}).closest('tr');
par_el.after(el);
}
});
});
FIDDLE
http://jsfiddle.net/9sKwJ/66/
tr.spacer { height: 40px; }
$.tablesorter.addWidget({
id: 'spacer',
format: function(table) {
var c = table.config,
$t = $(table),
$r = $t.find('tbody').find('tr'),
i, l, last, col, rows, spacers = [];
if (c.sortList && c.sortList[0]) {
$t.find('tr.spacer').removeClass('spacer');
col = c.sortList[0][0]; // first sorted column
rows = table.config.cache.normalized;
last = rows[0][col]; // text from first row
l = rows.length;
for (i=0; i < l; i++) {
// if text from row doesn't match last row,
// save it to add a spacer
if (rows[i][col] !== last) {
spacers.push(i-1);
last = rows[i][col];
}
}
// add spacer class to the appropriate rows
for (i=0; i<spacers.length; i++){
$r.eq(spacers[i]).addClass('spacer');
}
}
}
});
$('table').tablesorter({
widgets : ['spacer']
});
<table id="test">
<thead>
<tr>
<th>Name</th>
<th>Number</th>
<th>Another Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test4</td>
<td>4</td>
<td>Hello4</td>
</tr>
<tr>
<td colspan="3">Test4</td>
</tr>
<tr>
<td>Test3</td>
<td>3</td>
<td>Hello3</td>
</tr>
<tr>
<td colspan="3">Test3</td>
</tr>
<tr>
<td>Test2</td>
<td>2</td>
<td>Hello2</td>
</tr>
<tr>
<td colspan="3">Test2</td>
</tr>
<tr>
<td>Test1</td>
<td>1</td>
<td>Hello1</td>
</tr>
<tr>
<td colspan="3">Test1</td>
</tr>
</tbody>
</table>
This sorts just the way I want it if you sort it by the first column, but the other two columns don't maintain the same paired 'tr' sort im looking for.
Any help on this?
Use the expand-child class name on each duplicated row:
<tr>
<td>Test3</td>
<td>3</td>
<td>Hello3</td>
</tr>
<tr class="expand-child">
<td colspan="3">Test3</td>
</tr>
It's defined by the cssChildRow option:
$('table').tablesorter({
cssChildRow: "expand-child"
});
Here is a demo of it in action.