How to make table jQuery pagination logic - javascript

I am trying to make a jQuery "plugin" to paginate records on a table. According to my own question I tried to make manually.
Also, I am trying to figure out how to display the page numbers correlatively according to the buttonSize.
$(document).ready(function() {
$('#tabla').pagination({
pageSize: 1,
buttonSize: 5,
target: '#paginacion',
template: `<nav class="text-center" aria-label="Page navigation">
<ul class="pagination" id="paginacion">
</ul>
</nav>`
});
});
$.fn.extend({
pagination: function($options) {
$el = this;
buttons = $options.buttonSize || 5;
htmlElement = $($options.template);
target = $(htmlElement).find($options.target);
rows = $($el).find('tbody tr');
initialPage = 1;
pagesAmount = Math.ceil(rows.length / $options.pageSize);
pages = [];
while(rows.length > 0) {
let page = rows.splice(0, $options.pageSize);
pages.push(page);
}
window.pages = pages;
window.currentPage = initialPage;
for(i=0; i<pagesAmount; i++) {
paginationHTML = `<li><a data-page="${i}" href="#">${i+1}</a></li>`;
target.append(paginationHTML);
}
$el.append(htmlElement);
$el.find('tbody').html(pages[window.currentPage-1]);
let scriptCode = `$('${$options.target} a').on('click', function() {` + "\n\t" +
`window.currentPage = $(this).attr('data-page'); ` + "\n\t" +
`$('#${$el.attr('id')} tbody').html(window.pages[window.currentPage]); ` + "\n" +
`$(this).parent().parent().find('li').each(function(item) { $(this).removeClass('active'); })` + "\n" +
`$(this).parent().addClass('active')` + "\n" +
`});` + "\n"
$('body').append($('<script>').html(scriptCode));
}
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tabla" class="table table-striped table-bordered">
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Column1: Row 1</td>
<td>Column2: Row 1</td>
<td>Column3: Row 1</td>
<td>Column4: Row 1</td>
</tr>
<tr>
<td>Column1: Row 2</td>
<td>Column2: Row 2</td>
<td>Column3: Row 2</td>
<td>Column4: Row 2</td>
</tr>
<tr>
<td>Column1: Row 3</td>
<td>Column2: Row 3</td>
<td>Column3: Row 3</td>
<td>Column4: Row 3</td>
</tr>
<tr>
<td>Column1: Row 4</td>
<td>Column2: Row 4</td>
<td>Column3: Row 4</td>
<td>Column4: Row 4</td>
</tr>
<tr>
<td>Column1: Row 5</td>
<td>Column2: Row 5</td>
<td>Column3: Row 5</td>
<td>Column4: Row 5</td>
</tr>
<tr>
<td>Column1: Row 6</td>
<td>Column2: Row 6</td>
<td>Column3: Row 6</td>
<td>Column4: Row 6</td>
</tr>
<tr>
<td>Column1: Row 7</td>
<td>Column2: Row 7</td>
<td>Column3: Row 7</td>
<td>Column4: Row 7</td>
</tr>
<tr>
<td>Column1: Row 8</td>
<td>Column2: Row 8</td>
<td>Column3: Row 8</td>
<td>Column4: Row 8</td>
</tr>
</tbody>
</table>
I didn't use ES6 functions since our system is Microsoft based and it won't work on IE.
I am not sure how to adjust the button size so if I have two hundred rows it won't display two hundred pages.
Any suggestions?

Related

How to get the cell element that is spanning another cell element in a table using JavaScript

We have a table:
<table>
<tbody>
<tr>
<td>Column 1</td>
<td colspan="3">Column 2</td>
<td>Column 3</td>
<td colspan="99999">Column 4</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td id="target">C</td>
<td>D</td>
<td>E</td>
<td>F</td>
</tr>
</tbody>
</table>
Using JavaScript or jQuery, how would we able to get the column element (or its index) of the first row that is spanning the cell with id "target"? I don't really want to use any box positioning method (is: getBoundingClientRect()) technique.
In this example, the associated cell element that is spanning "target" is the cell with text "Column 2".
Here is a solution for the case, that the second row also has colspans and there is no third row:
Iterate over the cells of the second row with a for loop and count their colspans until you find your target cell (if there is no colspan defined it is automatically '1'). Then iterate over the cells of the first row and count their colspans until the count is equal or bigger then the count of the second row. In that case you have found the desired head cell.
Working example:
const head_cells = document.querySelectorAll('#head-row td');
const target_cells = document.querySelectorAll('#target-row td');
let head_position = 0;
let target_position = 0;
for (i = 0; i < target_cells.length; i++) {
target_position += target_cells[i].colSpan;
if (target_cells[i].id === 'target') {
for (k = 0; k < head_cells.length; k++) {
head_position += head_cells[k].colSpan;
if (head_position >= target_position) {
console.log(head_cells[k].textContent);
break;
}
}
break;
}
}
<table>
<tbody>
<tr id="head-row">
<td>Column 1</td>
<td colspan="4">Column 2</td>
<td>Column 3</td>
<td colspan="99999">Column 4</td>
</tr>
<tr id="target-row">
<td>A</td>
<td colspan="2">B</td>
<td id="target">C</td>
<td>D</td>
<td>E</td>
<td>F</td>
</tr>
</tbody>
</table>
<script>
function findHeader(cell) {
let count = cell.cellIndex + 1; // 3
for(let header of headers.cells) {
const colspan = +header.getAttribute('colspan') || 1;
count -= colspan;
if (count<1) return alert(header.textContent);
}
}
</script>
<table border=1>
<tbody>
<tr id="headers">
<td>Column 1</td>
<td colspan="3">Column 2</td>
<td>Column 3</td>
<td colspan="99999">Column 4</td>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td onclick="findHeader(this)">Click</td>
<td>D</td>
<td>E</td>
<td>F</td>
</tr>
</tbody>
</table>

How to filter getElement based on CSS property in JS or jQuery

The following code gets all the tr tags in #mytable:
table = document.getElementById("myTable");
trs = table.getElementsByTagName("tr");
But if we want to get only tr tags whose display is not none, what should I do?
Thanks.
Not the best solution, but you can do this...
let tableRows = $("#my-table tr");
tableRows.map((i, obj)=>{
if($(obj).attr('style') != 'display: none;'){
// whatever you want to do here...
console.log(obj);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<table id="my-table">
<tbody>
<tr>
<td>data 1</td>
<td>data 2</td>
</tr>
<tr style="display: none;">
<td>data 3</td>
<td>data 4</td>
</tr>
<tr>
<td>data 5</td>
<td>data 6</td>
</tr>
<tr style="display: none;">
<td>data 7</td>
<td>data 8</td>
</tr>
<tr>
<td>data 9</td>
<td>data 10</td>
</tr>
</tbody>
</table>
You can use the :visible selector which is a jquery extension (https://api.jquery.com/visible-selector/) that allows seelction of elements based on display visibility.
In the following snippet - there are 3 tr's but the middle one is hidden with display:none. The console log targets the visible tr's and logs the number (2);
$(document).ready(function(){
const totalRows = $('#myTable tr');
const visibleRows = totalRows.filter(':visible');
console.log('total rows: '+ totalRows.length); // gives 3
console.log('visible rows: '+ visibleRows.length); // gives 2 - since one tr is hidden
})
.second-row {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
<tbody>
<tr class="first-row">
<td>row 1</td>
<td>row 1</td>
<td>row 1</td>
</tr>
<tr class="second-row">
<td>row 2</td>
<td>row 2</td>
<td>row 2</td>
</tr>
<tr class="third-row">
<td>row 3</td>
<td>row 3</td>
<td>row 3</td>
</tr>
</tbody>
</table>
Simple solution with VanillaJS
var elems = document.querySelectorAll('tr');
var noneElems = [];
elems.forEach(function (element) {
if (window.getComputedStyle(element).display == 'none') {
noneElems.push(element);
}
});
console.log( { noneElems } );
<table id="mytable">
<tr>
<td>Block</td>
<td>1</td>
</tr>
<tr style="display:none">
<td>None</td>
<td>1</td>
</tr>
<tr>
<td>Block</td>
<td>2</td>
</tr>
<tr style="display:none">
<td>None</td>
<td>2</td>
</tr>
</table>

How can i append table (tr th: even and tr td:even and th:odd and td:odd) to a new table

Firstly, sorry English is not my first language.
*(Even and Odd is based on the index)
I would like to achieve this table in mobile view.
What i have tried
<table class="table">
<tbody>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
</tbody>
<tbody>
<tr>
<th>Content 3 Head</th>
<th>Content 4 Head</th>
</tr>
<tr>
<td>Content 3</td>
<td>Content 4</td>
</tr>
</tbody>
</table>
var mobileTable = ""
$("table tbody th:even").each(function(i) {
var tdval = $(this).html();
console.log(thval);
mobileTable =+ "<th>" + $('table tr td:odd') + tdval +'</th>';
});
$('table:first-child').empty();
$('.table-mobile').append(mobileTable);
var x = $("#table").find("th,td");
var i = $("#table").find("tr").length;
var j = x.length/i;
//console.log(i , j);
var newT= $("<table>").appendTo("body");
for (j1=0; j1<j;j1++){
//var temp = $("<tr>").appendTo(newT);
for(var i1=0;i1<i; i1++){
var temp = $("<tr>").appendTo(newT);
temp.append($(x[j1 *4+i1%2 *2+i1/2]).clone());
var temp2 = $("<tr>").appendTo(newT);
temp2.append($(x[j1 *4+i1%2 *2+i1/2+2]).clone());
//console.log(j1 *4,i1%2 *2,i1/2);
}
}
$("#table").remove();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="table">
<tbody>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
</tbody>
<tbody>
<tr>
<th>Content 3 Head</th>
<th>Content 4 Head</th>
</tr>
<tr>
<td>Content 3</td>
<td>Content 4</td>
</tr>
</tbody>
</table>
Create an array
Give seperate rows to each th and tds
Add each th to array in positions like: 0,2,4,6 (index*2)
Add each td to Array in positions like: 1,3,5,7 (((index+1)*2)-1)
Add array to mobile table using append.
Your final array becomes:
[0] = th1
[1] = td1
[2] = th2
[3] = td2
...
var tarr = [];
$("table tr:even *").each(function(i) {
tarr[(i*2)]="<tr><th>"+$(this).html()+"</th></tr>";
});
$("table tr:odd *").each(function(i) {
tarr[((i+1)*2)-1]="<tr><td>"+$(this).html()+"</td></tr>";
});
console.log(tarr);
$('table').empty();
$('.table-mobile').append(tarr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table">
<tbody>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
</tr>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
</tbody>
<tbody>
<tr>
<th>Content 3 Head</th>
<th>Content 4 Head</th>
</tr>
<tr>
<td>Content 3</td>
<td>Content 4</td>
</tr>
</tbody>
</table>
<table class="table-mobile"></table>
This is amendment made.
var mobileTable = ""
$("table tbody th").each(function(i) {
var thval = $(this).html();
var tdval = $('table tr td').html(); // How can i loop this through
mobileTable += "<tr><td>" + thval +'</td></tr><tr><td>'+ tdval + '</td><tr>';
});
$('table:first-child').empty();
$('.table-mobile').append(mobileTable);
Result (Triggered by jQuery)

Append tbody td to th based on similar index

i'm trying to append tbody td with the similar to thead th with the similar index.
$("table").find("th").each(function(i, e) {
console.log(i, e)
$(this).attr('head-index', i)
});
$("table").find("td").each(function(i, e) {
console.log(i, e)
$(this).attr('row-index', i)
});
var tableTH = $("table > thead > tr > th");
var tableTR = $("table > tbody > tr > td");
if ($(tableTH).attr == $(tableTR).attr) {
} else {
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table table-hover">
<thead>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 4</td>
<td>Content 5</td>
</tr>
<tr>
<td>Content 7</td>
<td>Content 8</td>
</tr>
</tbody>
</table>
This function will be triggered in mobile view only.
End Result expected.
enter image description here
*Edited(What is there's more TR)
You can use .each() to loop over the headers, and an attribute selector to select get the row with the same index.
$("table").find("th").each(function(i, e) {
$(this).attr('head-index', i)
});
$("table").find("td").each(function(i, e) {
$(this).attr('row-index', i)
});
var tableTH = $("table > thead > tr > th");
var tableTR = $("table > tbody > tr > td");
tableTH.each(function() {
var index = $(this).attr("head-index");
var row = tableTR.filter(`[row-index=${index}]`);
$(this).after(row);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table table-hover">
<thead>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
<th>Content 3 Head</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
<td>Content 3</td>
</tr>
</tbody>
</table>
I used .after() rather than .append(). You can't append a <td> inside a <th>, they both have to be children of <tr>.
Is this you are trying to achieve?
$(function(){
var th = $("table > thead > tr > th");
var td = $("table > tbody > tr > td");
$('thead tr').each(function(th_index,th_item) {
var index = $(th_item).attr("data-th-index");
var row = $('tbody tr[data-td-index="'+index+'"]');
row.each(function(td_index,td_item){
$(th_item).after(td_item);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table table-hover">
<thead>
<tr data-th-index="1">
<th>Content 1 Head</th>
</tr>
<tr data-th-index="2">
<th >Content 2 Head</th>
</tr>
<tr data-th-index="3">
<th >Content 3 Head</th>
</tr>
</thead>
<tbody>
<tr data-td-index="1">
<td >Content 1</td>
</tr>
<tr data-td-index="2">
<td >Content 2</td>
</tr>
<tr data-td-index="3">
<td >Content 3</td>
</tr>
<tr data-td-index="1">
<td >Content 5</td>
</tr>
<tr data-td-index="2">
<td >Content 6</td>
</tr>
<tr data-td-index="3">
<td >Content 7</td>
</tr>
</tbody>
</table>
Use $.each on all TDs
If index is even number then add first th(Head 1)
If index is odd number then add second th(Head 2)
Append string and create new table
var new_table_string="";
$.each($("table tbody tr td"), function (index,value){
console.log(value);
var tdval= $(this).html()
new_table_string += "<tr><th>" + $("table thead tr th").eq(index%2).html() + "</th></tr><tr><td>" + tdval + "</td></tr>";
});
//$("table").empty();
$(".table2").append(new_table_string);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Before:
<table class="table table-hover" border="1">
<thead>
<tr>
<th>Content 1 Head</th>
<th>Content 2 Head</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
</tr>
<tr>
<td>Content 3</td>
<td>Content 4</td>
</tr>
<tr>
<td>Content 5</td>
<td>Content 6</td>
</tr>
<tr>
<td>Content 7</td>
<td>Content 8</td>
</tr>
</tbody>
</table>
After:
<table class="table2" border="1"></table>

Show and hide subrows using jQuery

I'm trying to use jQuery for solving the following problem. Currently I don't have any useful code for posting here.
Initially only the Master Rows (class term1_master and term2_master) should be visible.
By pressing the "Show" link the correlating group of rows should toogle the visibility (e. g. pressing Show button in tr-class term1_master should show all tr-elements owning class term1).
The number of blocks is not fix, there can also appear term3_master, term4_master ... with their sub items.
This is my sample HTML code:
<table>
<tr class="term1_master">
<td>Master Row 1</td>
<td>Show</td>
</tr>
<tr class="term1">
<td>Sub Row 1</td>
<td>Example</td>
</tr>
<tr class="term1">
<td>Sub Row 2</td>
<td>Example</td>
</tr>
<tr class="term1">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
<tr class="term2_master">
<td>Master Row 2</td>
<td>Show</td>
</tr>
<tr class="term2">
<td>Sub Row 1</td>
<td>Example</td>
</tr>
<tr class="term2">
<td>Sub Row 2</td>
<td>Example</td>
</tr>
<tr class="term2">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
</table>
Thanks a lot for helping me!
You don't have to use separate classes, at all, all master rows can have one .master class. Then you can use great nextUntil() method to get what you want:
$('a').click(function(e) {
e.preventDefault();
if($(this).text()=='Show') {
$(this).closest('.master').nextUntil('.master').show();
$(this).text('Hide');
}
else {
$(this).closest('.master').nextUntil('.master').hide();
$(this).text('Show');
}
});
Demo:
$('a').click(function(e) {
e.preventDefault();
if($(this).text()=='Show') {
$(this).closest('.master').nextUntil('.master').show();
$(this).text('Hide');
}
else {
$(this).closest('.master').nextUntil('.master').hide();
$(this).text('Show');
}
});
tr {
display:none;
}
tr.master {
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr class="master">
<td>Master Row 1</td>
<td>Show</td>
</tr><tr class="term1">
<td>Sub Row 1</td>
<td>Example</td>
</tr><tr class="term1">
<td>Sub Row 2</td>
<td>Example</td>
</tr><tr class="term1">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
<tr class="master">
<td>Master Row 2</td>
<td>Show</td>
</tr><tr class="term2">
<td>Sub Row 1</td>
<td>Example</td>
</tr><tr class="term2">
<td>Sub Row 2</td>
<td>Example</td>
</tr><tr class="term2">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
<tr class="master">
<td>Master Row 3</td>
<td>Show</td>
</tr><tr class="term3">
<td>Sub Row 1</td>
<td>Example</td>
</tr><tr class="term3">
<td>Sub Row 2</td>
<td>Example</td>
</tr><tr class="term3">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
</table>
You could use following logic inside relevant click handler to show only specific targeted follow row, depending relevant class:
$(function() { // ready handler
$('table a').on('click', function(e) {
e.preventDefault();
var $tr = $(this).closest('tr');
var trClass = $tr.attr('class').split('_').shift();
$tr.nextAll('.' + trClass).show();
})
});
-jsFiddle-
The following should work for the current HTML and appending term3_master, term4_master ... with their sub items.
$(function() {
$('tr').not('[class$="_master"]').hide();
$('table a').on('click', function(e) {
e.preventDefault();
if($(this).text() === "Show") {
$(this).text("Hide");
var $tr = $(this).closest('tr');
var trClass = $tr.attr('class').split('_').shift();
$tr.nextAll('.' + trClass).show();
} else {
$(this).text("Show")
var $tr = $(this).closest('tr');
var trClass = $tr.attr('class').split('_').shift();
$tr.nextAll('.' + trClass).hide();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr class="term1_master">
<td>Master Row 1</td>
<td>Show</td>
</tr><tr class="term1">
<td>Sub Row 1</td>
<td>Example</td>
</tr><tr class="term1">
<td>Sub Row 2</td>
<td>Example</td>
</tr><tr class="term1">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
<tr class="term2_master">
<td>Master Row 2</td>
<td>Show</td>
</tr><tr class="term2">
<td>Sub Row 1</td>
<td>Example</td>
</tr><tr class="term2">
<td>Sub Row 2</td>
<td>Example</td>
</tr><tr class="term2">
<td>Sub Row 3</td>
<td>Example</td>
</tr>
</table>

Categories

Resources