Restructure tables with media queries - javascript

I have a table with four columns and two rows, as follows:
<table>
<tr>
<td> A </td>
<td> B </td>
<td> C </td>
<td> D </td>
</tr>
<tr>
<td> E </td>
<td> F </td>
<td> G </td>
<td> H </td>
</tr>
</table>
Using a media query, such as #media (max-width: 800px), I want to restructure this table to instead have two columns and four rows, e.g:
<table>
<tr>
<td> A </td>
<td> B </td>
</tr>
<tr>
<td> C </td>
<td> D </td>
</tr>
<tr>
<td> E </td>
<td> F </td>
</tr>
<tr>
<td> G </td>
<td> H </td>
</tr>
</table>
Is this possible? Solutions in JavaScript are also welcome if, which I assume to be the case, this cannot be done with mere CSS.

Pure CSS
Changing the appearance using floats and nth-child.
td { float:left; display:inline-block; }
td:nth-child(3) {
clear:both;
}
https://jsfiddle.net/hks5d6th/2/
JavaScript
Looping through all applicable columns and use the modulus operator to determine where to split out into new rows.
var table = document.getElementsByTagName('table')[0],
columns = Array.prototype.slice.call(document.getElementsByTagName('td')),
newTable = document.createElement('table'), html;
columns.forEach(function(next, idx) {
if (idx % 2 === 0 || idx === 0) {
html += '<tr>' + next.outerHTML;
return;
}
html += next.outerHTML + '</tr>';
});
newTable.innerHTML = html;
table.replaceWith(newTable);
https://jsfiddle.net/hks5d6th/1/

Related

Total sum of a filtered table using vanilla JS

The only consideration for this question is, at the moment, I'm not using jQuery. Here's the code:
//I think here is where the problem relies, in the function I'm using to calculate the sum of the values under 'Valor' column:
var t1 = document.getElementById("emp-table");
getSum();
function getSum() {
var sumVal = 0;
for(var i = 1; i < t1.rows.length; i++){
sumVal = sumVal + parseInt(t1.rows[i].cells[6].innerHTML);
document.getElementById("sumV").innerHTML = "Sum Value = "+sumVal;
}
};
function getUniqueValuesFromColumn() {
var unique_col_values_dict = {}
allFilters = document.querySelectorAll(".table-filter")
allFilters.forEach((filter_i) => {
col_index = filter_i.parentElement.getAttribute("col-index");
const rows = document.querySelectorAll("#emp-table > tbody > tr")
rows.forEach((row) => {
cell_value = row.querySelector("td:nth-child("+col_index+")").innerHTML;
if (col_index in unique_col_values_dict) {
if (unique_col_values_dict[col_index].includes(cell_value)) {
//console.log("already exists");
} else {
unique_col_values_dict[col_index].push(cell_value)
}
} else {
unique_col_values_dict[col_index] = new Array(cell_value)
}
});
});
updateSelectOptions(unique_col_values_dict)
};
function updateSelectOptions(unique_col_values_dict) {
allFilters = document.querySelectorAll(".table-filter")
allFilters.forEach((filter_i) => {
col_index = filter_i.parentElement.getAttribute('col-index')
unique_col_values_dict[col_index].forEach((i) => {
filter_i.innerHTML = filter_i.innerHTML + `\n<option value="${i}">${i}</option>`
});
});
};
function filter_rows() {
allFilters = document.querySelectorAll(".table-filter")
var filter_value_dict = {}
allFilters.forEach((filter_i) => {
col_index = filter_i.parentElement.getAttribute('col-index')
value = filter_i.value
if (value != "all") {
filter_value_dict[col_index] = value;
}
});
var col_cell_value_dict = {};
const rows = document.querySelectorAll("#emp-table tbody tr");
rows.forEach((row) => {
var display_row = true;
allFilters.forEach((filter_i) => {
col_index = filter_i.parentElement.getAttribute('col-index')
col_cell_value_dict[col_index] = row.querySelector("td:nth-child(" + col_index+ ")").innerHTML
})
for (var col_i in filter_value_dict) {
filter_value = filter_value_dict[col_i]
row_cell_value = col_cell_value_dict[col_i]
if (row_cell_value.indexOf(filter_value) == -1 && filter_value != "all") {
display_row = false;
break;
}
}
if (display_row == true) {
row.style.display = "table-row"
} else {
row.style.display = "none"
}
})
};
//And finally, the 'onload' part to update the content:
window.onload = () => {
console.log(document.querySelector("#emp-table > tbody > tr:nth-child(1) > td:nth-child(2) ").innerHTML);
};
getUniqueValuesFromColumn()
<body>
<div class="container">
<div class="card">
<div class="card-header">
Lista Pagos
</div>
<div class="card-body">
<table id="emp-table" class="table">
<thead>
<tr>
<th>id</th>
<th col-index = 2>Persona
<select class="table-filter" onchange="filter_rows()">
<option value="all"></option>
</select>
</th>
<th col-index = 3>Servicio
<select class="table-filter" onchange="filter_rows()">
<option value="all"></option>
</select>
</th>
<th col-index = 4>Año
<select class="table-filter" onchange="filter_rows()">
<option value="all"></option>
</select>
</th>
<th col-index = 5>Mes
<select class="table-filter" onchange="filter_rows()">
<option value="all"></option>
</select>
</th>
<th>id Recibo</th>
<th>Valor</th>
</tr>
</thead>
<tbody>
<tr>
<td> 33 </td>
<td> David Camacho </td>
<td> Gas </td>
<td> 2022 </td>
<td> 4 </td>
<td> 7 </td>
<td> 10000 </td>
</tr>
<tr>
<td> 32 </td>
<td> Héctor Camacho </td>
<td> Gas </td>
<td> 2022 </td>
<td> 4 </td>
<td> 7 </td>
<td> 15075 </td>
</tr>
<tr>
<td> 30 </td>
<td> Héctor Camacho </td>
<td> Seguro exequial </td>
<td> 2022 </td>
<td> 4 </td>
<td> 6 </td>
<td> 11100 </td>
</tr>
<tr>
<td> 29 </td>
<td> María Camacho </td>
<td> Seguro exequial </td>
<td> 2022 </td>
<td> 4 </td>
<td> 6 </td>
<td> 11100 </td>
</tr>
<tr>
<td> 28 </td>
<td> Mateo León </td>
<td> Internet </td>
<td> 2022 </td>
<td> 4 </td>
<td> 1 </td>
<td> 20000 </td>
</tr>
<tr>
<td> 27 </td>
<td> David Camacho </td>
<td> Internet </td>
<td> 2022 </td>
<td> 4 </td>
<td> 1 </td>
<td> 11600 </td>
</tr>
<tr>
<td> 24 </td>
<td> Alba Camacho </td>
<td> Internet </td>
<td> 2022 </td>
<td> 4 </td>
<td> 1 </td>
<td> 11600 </td>
</tr>
<tr>
<td> 23 </td>
<td> María Camacho </td>
<td> Internet </td>
<td> 2022 </td>
<td> 4 </td>
<td> 1 </td>
<td> 11600 </td>
</tr>
</tbody>
</table>
</div>
</div>
<p id="sumV"></p>
<br/>
<br/>
</div>
</body>
So, at the moment, whenever I load the page, the <span> tag already has the total amount if we consider all rows. But, whenever I filter the table, the value there doesn't change. At first, I tried to do it with a button using onclick, but every time I clicked it, it changed from the total value to 'undefined'. That's why I removed that button, and I'm considering to update the content in the <span> tag with the onload segment of my code, but I've been unable to achieve it so far.
Any help is greatly appreciated, cheers!
You could replace your getSum function with the following
function getSum() {
const rows = [...document.querySelectorAll('#emp-table tr').values()];
const visibleRows = rows.filter(row => {
return row.style.display !== 'none';
});
let sumVal = 0;
for (let visibleRow of visibleRows){
sumVal += parseInt(visibleRow.cells[6].innerHTML);
}
document.getElementById("sumV").innerHTML = "Sum Value = " + sumVal;
};
Basically you first filter the rows based on their display value to get just the visibleRows and then sum up the values.

Compare two cells in a html table and highlight row if different

I have an HTML table (tree table precisely but it doesn't matter) and it has several columns. For each row, it is very important that the values in one of the columns should be higher than the other column. If that is not the case then I'd like to highlight that entire row. How do I do that?
My HTML code looks like this:
<table id="stepstats-list-exp">
<thead>
<tr>
<th> name </th>
<th> elp_01 </th>
<th> elp_20 </th>
<th> scal </th>
</tr>
</thead>
<tbody>
<tr data-tt-id=864845 data-tt-parent-id=>
<td> 'Init' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864846 data-tt-parent-id=864845>
<td> 'Update' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864847 data-tt-parent-id=>
<td> 'Load' </td>
<td class="elp_01"> 32 </td>
<td class="elp_20"> 31 </td>
<td class="scal"> 1.03 </td>
</tr>
</tbody>
</table>
In all my test cases, elp_20 should always be smaller than elp_01. If not, the entire row needs to be highlighted. For that purpose, I have this jQuery code that doesn't seem to be working. For each tr row, I'm checking each td column and comparing values.
<script type="text/javascript">
/* Highlight row if elp_20 > elp_01 */
$(document).ready(function () {
$("#stepstats-list-exp tr").each(function () {
$(this).find('td').each(function(){
if (parseInt($(".elp_20").text(), 10) < parseInt($(".elp_01").text(), 10)) {
$(this).parent("tr").css('background-color', 'crimson');
$(this).parent("tr").css('font-weight','bold');
$(this).parent("tr").css('color','white');
}
});
});
});
</script>
This working snippet accesses the table rows as an html collection that can be looped through to compare the values represented by the contents of the second and third cell of each row. An inline style attribute it used to highlight the row (alternative styling could be made by adding or toggling class names if something more complex is needed)
let tableRows = document.getElementById("stepstats-list-exp").getElementsByTagName('tr');
for (let i=0; i<tableRows.length; i++)
if (Number(tableRows[i].children[2].innerText) >= Number(tableRows[i].children[1].innerText)) {
tableRows[i].setAttribute("style", "background: yellow");
}
<table id="stepstats-list-exp">
<thead>
<tr>
<th> name </th>
<th> elp_01 </th>
<th> elp_20 </th>
<th> scal </th>
</tr>
</thead>
<tbody>
<tr data-tt-id=864845 data-tt-parent-id=>
<td> 'Init' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864846 data-tt-parent-id=864845>
<td> 'Update' </td>
<td class="elp_01"> 0 </td>
<td class="elp_20"> 0 </td>
<td class="scal"> 0.00 </td>
</tr>
<tr data-tt-id=864847 data-tt-parent-id=>
<td> 'Load' </td>
<td class="elp_01"> 32 </td>
<td class="elp_20"> 31 </td>
<td class="scal"> 1.03 </td>
</tr>
</tbody>
</table>
You can just iterate through the classes, add them to a variable and iterate with a for loop, if you need to iterate one elp_01 to all elp_20 just map it.
Here's an example:
let firstColumn = document.getElementsByClassName('elp_01').innerText
let secondColumn = document.getElementsByClassName('elp_20').innerText
for (let i = 0; i < firstColumn.length; i ++) {
if (firstColumn[i] > secondColumn[i]) {
// Something - maybe add a class in css to color the row and add it to the element
}
else {
// Something else
}
}

How to Get text from table cell

This is what i have right now:
This is the table:
<table border='1'>
<tr>
<td>
Employee Code
</td>
<td>
FirstName
</td>
<td>
LastName
</td>
<td>
Address
</td>
</tr>
<tr class='display' onclick='hello();' >
<td id='trId1'>
E100
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
<tr class='display' onclick='hello();' >
<td id='trId1'>
E200
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
-----> etc...
</table>
This is the javascipt
<script>
function hello(){
var r = document.getElementById("trId1").innerHTML;
alert(r);
}
</script>
The JavaScript gets E100 when its the first row is clicked which is correct but when E200 row is clicked it still shows E100, how would i get E200 and so on when there is more data? Is there a javascript only solution
To start, you can't have two Id's on the page that are the same as that is invalid HTML5 and will cause errors in some browsers. The reason why you're getting what you're getting is because when looking for an ID, most browsers only look for one occurrence of an ID (because that is precisely what valid HTML is, 1 unique id per page). So to fix up your HTML code and you may also want to have a header for your table:
<table border='1'>
<thead>
<tr>
<th>
Employee Code
</th>
<th>
FirstName
</th>
<th>
LastName
</th>
<th>
Address
</th>
</tr>
</thead>
<tbody>
<tr class='display' onclick='hello(1);' >
<td class='trId1'>
E100
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
<tr class='display' onclick='hello(2);' >
<td class='trId1'>
E200
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
-----> etc...
</tbody>
</table>
Your best bet is to getElementsByClassName function and traverse the array to the one you want. (general change, code) Assuming you can't use JQuery at all for some reason:
<script>
function hello(rowClickedNumber){
var RowClicked = document.getElementsByClassName("trId1");
var r = RowClicked[0].innerHTML;
alert(r); //E100
var r = RowClicked[1].innerHTML;
alert(r); //E200
var r = RowClicked[rowClickedNumber].innerHTML;
alert(r);
}
</script>
However, an even simpler solution would be to use JQuery and would limit browser inconsistencies. After the document loads:
$(body).on("click", "tr", function(){
var getData =$(this).children(".trId1").getHTML();
console.log(getData);
});
Note: this is to allow when you inevitably add more items to the table (hence the reason why the code to get a child element of a row).
*EDIT: added the note
**EDIT: fixed the spelling and grammer
* EDIT: fixed the javascript function.
I have a solution for this. Please check the code and fiddle link below. Let me know if you have any question.
Fiddle
HTML:
<table border='1'>
<tr>
<td>
Employee Code
</td>
<td>
FirstName
</td>
<td>
LastName
</td>
<td>
Address
</td>
</tr>
<tr class='display' onclick='hello(this);' >
<td class='trId1'>
E100
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
<tr class='display' onclick='hello(this);' >
<td class='trId1'>
E200
</td>
<td>
Alex
</td>
<td>
Stone
</td>
<td>
33 Wave Place
</td>
</tr>
</table>
JavaScript:
function hello(obj){
alert(obj.childNodes[1].innerText); //The first child being a text node.
}

How to concat a number with "Kg" using Jquery. I want to concat the TotalWeight field with unit "Kg"

**HTML Snippet**
<table id="mytable">
#foreach (var item in Model) {
<tr class="item">
<td>
#Html.DisplayFor(modelItem => item.OrderId)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustomerId)
</td>
<td>
#Html.DisplayFor(modelItem => item.OrderDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.OrderQty)
</td>
<td class="Weight">
#Html.DisplayFor(ModelItem => item.TotalWeight, new { id="TotalWeight"})
</td>
<td>
#Html.DisplayFor(modelItem => item.LimeType.LimeTypeName)
</td>
</tr>
</table>
<script type="text/javascript">
$(document).ready(function () {
$("tr.item").each(function () {
var weight = $(this).find(td[5].val());
var unit = "Kg";
var value = weight + unit;
$("#TotalWeight").val(value);
});
});
</script>
}
html as in markup
<tbody>
<tr>
<tr class="item">
<td> 1 </td>
<td> C001 </td>
<td> 7/26/2013 12:00:00 AM </td>
<td> 100.00 </td>
<td class="Weight"> 5000.00 </td>
<td> Hydrated Lime Powder </td>
<td> Order Pending </td>
<td>
</tr>
</tbody>
I want to add Kg to my TotalWeight value. My code is not working. It shows the value in
Quantity1 as undefined. How can one access the table in jQuery?
i forgot to define weight, but still the code is not working, i have posted the html markup
$(document).ready(function () {
$("tr.item").each(function () {
var weight = $(this).find('td.Weight').text(); // you left out the quotes and the closing paran
var unit = "Kg";
$("#TotalWeight").text(weight + unit);
});
});
jsFiddle DEMO
You should probably actually calculate the sum in Scala (it looks you're using Scala) instead. Also your loop closes the <table> tag after every model and your <tr> tag is never closed. You also have one ModelItem that should probably be modelItem like in other places.

Jquery delete table duplicates with some twist

In simple form my html table is such:
Article | description | links | price
<table>
<tr>
<td>
</td>
OC 90
<td>
ololooo
</td>
<td>
</td>
<td>
123
</td>
</tr>
<tr>
<td>
OC90
</td>
<td>
some other ololo
</td>
<td>
link
</td>
<td>
123
</td>
</tr>
<tr>
<td>
OC 90
</td>
<td>
other other oloooloo
</td>
<td>
</td>
<td>
321
</td>
</tr>
</table>
But how can i do, that i delete from my table duplicates, but!!! only if first column (also make it uppercase and delete freespaces when check) and last td (so article and price are same), but main trouble is to left in table such row, which in third column has link's...
After that my table must look:
<table>
<tr>
<td>
OC90
</td>
<td>
some other ololo
</td>
<td>
link
</td>
<td>
123
</td>
</tr>
<tr>
<td>
OC 90
</td>
<td>
other other oloooloo
</td>
<td>
</td>
<td>
321
</td>
</tr>
</table>
I have tried something like this:
var seen = {};
$('table tr').each(function() {
var tr = $(this).clone();
if(tr.not(':input')){ //tried for input, is not strange)
tr.find("td:eq(2)").remove();
tr.find("td:eq(3)").remove();
// tr.find("td:eq(2)").remove();
var txt = tr.text().toLowerCase().replace(/\s+/g, '');;
if (seen[txt])
$(this).remove();
else
seen[txt] = true;
}
}
});
but this doesn't help's me....
also full-version table is here:
http://jsfiddle.net/STrm5/1/
Please help me to delete duplicates from table....
Try with this :
var seen = {};
$('#table tr').each(function () {
var tr = $(this).clone();
if (tr.not(':input')) {
tr.find("td:eq(1)").remove();
tr.find("td:eq(1)").remove();
var txt = tr.text().toLowerCase().replace(/\s+/g, '');
if (seen[txt]) $(this).remove();
else seen[txt] = true;
}
});
Sample

Categories

Resources