I am trying to put images in a table. I have that working, if you click, you cycle through the available options. However, the counter is not cell related, it is a global counter. Is there a way to make a local variable, to keep track of where that individual cell is in the array?
I have tried making a local variable, only to a single cell, but it wasn't working.
Here is the related function in js:
var i = 1;
var table = document.getElementsByTagName('table')[0];
var def = ["tex/white.png", "tex/grass.jpg", "tex/stone.jpg", "tex/water.jpg", "tex/wood.jpg", "tex/lava.jpg"];
table.onclick = function(e) {
var target = (e || window.event).target;
if (target.tagName in { TD: 1, TH: 1 }) {
target.className = "img";
console.log((e || window.event).target);
target.setAttribute('style', 'background-image:' + "url(" + def[i] + ")");
if (i < def.length) {
i++
}
if (i == def.length) {
i = 0;
}
}
};
Here is a working fiddle of what I have done so far:
https://jsfiddle.net/6L0armd4/
The desired result is that I start the array at single cells and it only counts for those cells. At the moment, it always gives the next texture, even when I select a different cell.
A possible solution : using ids to identify each cells, and an object to keep track of which background is currently used for each cells (using their id as key)
<html>
<head>
</head>
<body>
<table>
<tr>
<td id='1'></td>
<td id='2'></td>
<td id='3'></td>
</tr>
<tr>
<td id='4'></td>
<td id='5'></td>
<td id='6'></td>
</tr>
<tr>
<td id='7'></td>
<td id='8'></td>
<td id='9'></td>
</tr>
</table>
</body>
</html>
<script>
var table = document.getElementsByTagName('table')[0];
var def = ["https://cdn1.imggmi.com/uploads/2019/6/19/5e4aedcf566fa5e4501ab584d357be01-full.jpg", "https://cdn1.imggmi.com/uploads/2019/6/19/3d39445ffda6687a6b0e80a69a35fdea-full.jpg"];
var currents = {}
getNextIndex = function(index) {
return index === undefined || index >= def.length - 1 ? 0 : index + 1
}
table.onclick = function(e) {
var target = (e || window.event).target;
if (target.tagName in { TD: 1, TH: 1 }) {
var new_bg_index = getNextIndex(currents[target.id])
currents[target.id] = new_bg_index
target.setAttribute('style', 'background-image:' + "url(" + def[new_bg_index] + ")");
}
};
</script>
you need to make listener event
you may change the color codes to your image path on the below code and avoid any local path image links issue try to use online images direct ones .
var table = document.querySelector('#table')
var selectedCells = table.getElementsByClassName('selected')
table.addEventListener('click', function(e) {
var td = e.target
if (td.tagName !== 'TD') {
return
}
if (selectedCells.length) {
selectedCells[0].className = ''
}
td.className = 'selected'
})
table {
cursor: text;
}
tr {
background-color:white;
}
td {
font-size: 14;
cursor: default;
}
td.selected {
background-color: red;
// replace this with background image tag like this
background-image: url("paper.gif
<table border="1" cellpadding="8" cellspacing="2" id="table">
<tr>
<td>Cell one</td>
<td>Cell Tw</td>
<td>Cell three</td>
<td>Cell Four</td>
<td>Cell five</td>
<td>Cell sex</td>
<td>Cell five</td>
<td>cell seven</td>
<td>cell eight</td>
<td>cell nine</td>
<td>cell tens</td>
<td>cell eleven</td>
<td>cell twelve</td>
</tr>
<tr>
<td>AKo</td>
<td>KK</td>
<td>KQs</td>
<td>KJs</td>
<td>KTs</td>
<td>K9s</td>
<td>K8S</td>
<td>K7s</td>
<td>K6s</td>
<td>K5s</td>
<td>K4s</td>
<td>K3s</td>
<td>K2s</td>
Related
I have an HTML table that has some static data and some from MySQL. It is currently filtering properly, what I need help is adding the "yes" and "no" selections to the selection list. These are just test values, they are being read from MySQL. I am unable to figure out what values to insert here to add values from MySQL to the selection list. Any assistance will be appreciated! Thank you
.append($table.find('tbody tr')
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="/stylesheets/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
<meta charset="utf-8">
<title>Filter</title>
</head>
<script>
$.ajax({
url: 'http://localhost:7003/getTable',
type: "get",
dataType: "json",
success: function(data) {
drawTable(data);
}
});
function drawTable(data) {
for (var i = 0; i < data.length; i++) {
drawRow(data[i]);
}
}
</script>
</body>
</html>
<table id="myTable" class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th class="dropdown-header">Age</th>
<th>Email</th>
<th class="dropdown-header">Gender</th>
<th class="dropdown-header">Term</th>
<th class="dropdown-header">Enrolled</th>
</tr>
</thead>
<tbody>
<script>
function drawRow(rowData) {
var row = $("<tr />")
$("#myTable").append(row);
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td>').attr('data-field-name', 'age').text(rowData.County));
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td data-field-name="gender">' + rowData.County + '</td>'));
row.append($('<td data-field-name="term">' + rowData.County + '</td>'));
row.append($('<td data-field-name="enrolled">' + rowData.County + '</td>'));
}
</script>
<tr>
<td>John</td>
<td>Smith</td>
<td data-field-name="age">15</td>
<td>123</td>
<td data-field-name="gender">Male</td>
<td data-field-name="term">Summer2017</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
<td data-field-name="age">16</td>
<td>456</td>
<td data-field-name="gender">Female</td>
<td data-field-name="term">Fall2018</td>
<td data-field-name="enrolled">Fall2019</td>
</tr>
<tr>
<td>Bobby</td>
<td>Adams</td>
<td data-field-name="age">15</td>
<td>789</td>
<td data-field-name="gender">Male</td>
<td data-field-name="term">Spring2019</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
<tr>
<td>Sarah</td>
<td>Lee</td>
<td data-field-name="age">15</td>
<td>456</td>
<td data-field-name="gender">Female</td>
<td data-field-name="term">Fall2018</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
</tbody>
</table>
<script>
(function($) {
$.fn.tableFilterHeaders = function(filterFn) {
this.each((index, header) => {
let $header = $(header),
$table = $header.closest('table'),
text = $header.text(),
colIndex = $header.closest('th').index(),
fieldName = $header.attr('data-field-name') || text.toLowerCase(),
$select = $('<select>')
.data('fieldName', fieldName)
.append($('<option>').text(text).val('').prop('disabled', true))
.append($('<option>').text('All').val('all'))
.append($table.find('tbody tr')
.toArray()
.map(tr => {
return $(tr).find(`td:eq(${colIndex})`).text();
})
.filter(text => text.trim().length > 0)
.sort()
.filter((v, i, a) => a.indexOf(v) === i)
.map(text => {
return $('<option>').text(text).val(text);
}));
$header.empty().append($select.val('').on('change', filterFn));
});
};
$.fn.initRowClasses = function(oddCls, evenCls) {
this.find('tbody tr').each(function(i) {
$(this).toggleClass(oddCls, i % 2 == 0).toggleClass(evenCls, i % 2 == 1);
});
};
$.fn.updateRowClasses = function(oddCls, evenCls) {
this.find('tbody tr:visible:even').addClass(oddCls).removeClass(evenCls);
this.find('tbody tr:visible:odd').addClass(evenCls).removeClass(oddCls);
};
})(jQuery);
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
function filterText(e) {
let $filter = $(e.target),
$table = $filter.closest('table'),
$filters = $table.find('.dropdown-header select'),
filterObj = $filters.toArray().reduce((obj, filter) => {
let $filter = $(filter);
return Object.assign(obj, { [$filter.data('fieldName')] : $filter.val() });
}, {});
if ($filter.val() === 'all') {
$filter.val('')
}
$table.find('tbody tr').each(function() {
$(this).toggle($(this).find('td').toArray().every(td => {
let $td = $(td), fieldName = $td.attr('data-field-name');
if (fieldName != null) {
return filterObj[fieldName] === null ||
filterObj[fieldName] === '' ||
filterObj[fieldName] === 'all' ||
filterObj[fieldName] === $td.text();
}
return true;
}));
});
$table.updateRowClasses('odd', 'even');
}
</script>
Not showing yes and no options.
Your filtering logic and odd/even row coloring logic is called BEFORE the data returns from your ajax even though it appears AFTER on the page/code. This is how async methods work.
You need to call the header and coloring logic inside the drawTable() function after, of course, you are done drawing the table... like this:
function drawTable(data) {
for (var i = 0; i < data.length; i++) {
drawRow(data[i]);
}
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
}
Make sure to remove the foloowing 2 lines of code:
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
from your code, wherever elsewhere they appear. Leaving them will not break anything, it will just run multiple times unnecessary.
Here is what I have so far but I'm stuck because I cannot get the input elements to change the amount when the number of the quantity is changed.
function calculateTotal(quantity, price) {
var total = quantity * price;
return total;
}
function makeRow() {
var i = 0;
for (i = 0; i < 3; i++) {
var total = calculateTotal(quantities[i], prices[i]);
outputCartRow(filenames[i], titles[i], quantities[i], prices[i], total);
}
}
function outputCartRow(file, title, quantity, price, total) {
var content = "<tr><td><img src='" + file + "' class='photo' /></td>";
content += "<td>" + title + "</td>";
content += "<td><input class='quant' type='number' value='1'
onchange = 'newAmount' / > < /td>";
content += "<td>" + price + "</td>";
content += "<td class='amount'>" + total + "</td></tr>";
var section = document.querySelector(".rows").innerHTML;
document.querySelector(".rows").innerHTML = section + content;
}
function newAmount() {
var quantity = document.getElementsByClassName("quant");
var quantity1 = quantity[0];
var quantity2 = quantity[1];
var quantity3 = quantity[2];
var amount1 = calculateTotal(quantity1, 80);
var amount2 = calculateTotal(quantity2, 125);
var amount3 = calculateTotal(quantity3, 75);
var items = document.getElementsByClassName("amount");
for (var i = 0; i < items.length; i++) {
items[i] = amount1;
}
}
$(document).ready(function() {
$("input").change(function() {
alert("The text has been changed.");
});
});
js data;
var filenames = ["images/106020.jpg", "images/116010.jpg", "images/120010.jpg"];
var titles = ["Girl with a Pearl Earring", "Artist Holding a Thistle", "Portrait of Eleanor of Toledo"];
var quantities = [1, 1, 1];
var prices = [80, 125, 75];
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1.0,maximum-
scale=1.0,width=device-width">
<title>Chapter 08 - Project 01</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="css/styles.css" rel="stylesheet" />
<script src="js/data.js" type="text/JavaScript"></script>
<script src="js/functions.js" type="text/JavaScript"></script>
</head>
<body onload="makeRow();">
<div class="title">
<h1>Shopping Cart</h1>
</div>
<table class="table-fill">
<thead>
<tr>
<th colspan="2">Product</th>
<th>#</th>
<th>Price</th>
<th>Amount</th>
</tr>
</thead>
<tbody class="rows">
<tbody>
<tr class="totals">
<td colspan="4">Subtotal</td>
<td>$515.00</td>
</tr>
<tr class="totals">
<td colspan="4">Tax</td>
<td>$51.50</td>
</tr>
<tr class="totals">
<td colspan="4">Shipping</td>
<td>$40.00</td>
</tr>
<tr class="totals focus">
<td colspan="4">Grand Total</td>
<td>$606.50</td>
</tr>
</tbody>
</table>
</body>
</html>
<form> tag
IMO if using more than one form control✱ on a page, a <form> tag should be wrapped around everything. There are several advantages when you use a <form> tag:
HTMLFormControlsCollection and HTMLFormElement interface allows us to access form controls with a simple and terse syntax. Compare:
Common Procedure
// Reference <form> by #id
var main = document.getElementById('main');
// Collect radio buttons into a NodeList and convert it into an array
var radios = Array.from(document.querySelectorAll('[name=rad]'));
// Reference <button> by tagName
var button = document.querySelector('button');
HTMLForm | ControlsCollection | Element Interfaces
// Reference <form> by #id or [name]
var main = document.forms.main;
// Collect radio buttons into a HTMLCollection and convert it into an array
var radios = Array.from(main.elements.rad);
// Reference <button> by index
var button = main.elements[4];
Demo
Details commented in demo
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0,maximum-
scale=1.0,width=device-width">
<title>Chapter 08 - Project 01</title>
<style>
html,
body {
font: 400 16px/1.4 Consolas;
}
caption {
font-weight: 700;
font-size: 1.2rem;
}
table {
table-layout: fixed;
border-spacing: 7px;
}
th {
border-bottom: 3px ridge grey;
}
tfoot tr:nth-child(3) td:nth-child(2),
tfoot tr:nth-child(3) td:nth-child(1) {
border-bottom: 4px ridge grey;
}
.totals tr td,
tbody tr td:nth-of-type(3),
tbody tr td:nth-of-type(4),
tbody tr td:last-of-type,
tfoot tr td {
text-align: right;
}
td.cap {
text-align: left;
}
output::before {
content: '$';
}
input {
display: block;
width: 6ch;
text-align: center;
font: inherit;
}
</style>
</head>
<body>
<form id='cart'>
<table>
<caption>Shopping Cart</caption>
<thead>
<tr>
<th colspan="2">Product</th>
<th>Qty</th>
<th width='10%'>Price</th>
<th width='20%'>Amount</th>
</tr>
</thead>
<tbody class="rows"></tbody>
<tfoot class="totals">
<tr>
<td colspan="4">Subtotal</td>
<td><output id='sub'></output></td>
</tr>
<tr>
<td colspan="4">Tax (8.25%)</td>
<td><output id='tax' data-tax='.0825'></output></td>
</tr>
<tr>
<td colspan="4">Shipping ($3.00)</td>
<td><output id='SH'></output></td>
</tr>
<tr>
<td colspan="4">Grand Total</td>
<td><output id='grand'></output></td>
</tr>
</tfoot>
</table>
</form>
<script>
// Reference the <form>
var form = document.forms.cart;
// Data arrays
var imgArr = ["https://i.ibb.co/ZHvWsKb/o1z7p.jpg", "https://i.ibb.co/ZHvWsKb/o1z7p.jpg", "https://i.ibb.co/ZHvWsKb/o1z7p.jpg"];
var capArr = ["Girl with a Pearl Earring", "Artist Holding a Thistle", "Portrait of Eleanor of Toledo"];
var qtyArr = [0, 0, 0];
var prcArr = [80.69, 124.99, 75.00];
/*
setRow() -- passes an index counter and 4 variables
- Creates a template literal of a <tr>
- Interpolates variables into TL
- Parses the TL as HTML
*/
function setRow(i, img, cap, qty, prc) {
var R = `<tr id='R${i}'>
<td><img class='img' src='${img}' width='50px'></td>
<td class='cap'>${cap}</td>
<td><input id='qty${i}' class='qty' type='number' min='0' max='99'></td>
<td><output id='prc${i}' class='prc'></output></td>
<td><output id='amt${i}' class='amt'></output></td>
</tr>`;
var rows = document.querySelector('.rows');
rows.insertAdjacentHTML('beforeend', R);
var rID = document.getElementById('R' + i);
rID.children[2].children[0].value = qty;
rID.children[3].children[0].value = prc.toFixed(2);
rID.children[4].children[0].value = (parseFloat(qty) * parseFloat(prc)).toFixed(2);
}
/*
overRide() -- passes a 3D array
- Iterates through the 3D array
- On each iteration it passes array elements to the
setRow() function
*/
function overRide(x3DArray) {
var img, cap, qty, prc;
for (let x = 0; x < x3DArray[0].length; x++) {
img = x3DArray[0][x];
cap = x3DArray[1][x];
qty = x3DArray[2][x];
prc = x3DArray[3][x];
var cart = setRow(x, img, cap, qty, prc);
}
}
/*
calcAmt() callback function -- passes the Event Object
- Reference the tag receiving the user data (input.qty)
- Reference the tag registered to event (form#cart)
- Collect all form controls into a HTMLCollection
*/
/*
- if the clicked tag is NOT the registered tag...
- if the clicked tag has the .qty class...
- Reference the <tr> the clicked tag is nested in...
...get the index of <tr>...
...get the values of qty and prc...
...set the amt by qty x prc
*/
/*
- Collects all .amt into a NodeList then converts into an array.
- map() the array and extract each .amt value
- reduce() the array values into a single sum
- Set the .totals column values to calculate totals when the user enters data.
*/
function calcAmt(event) {
var tgt = event.target;
var cur = event.currentTarget;
var UI = this.elements;
if (tgt !== cur) {
if (tgt.className === 'qty') {
var rID = tgt.closest('tr').id;
var idx = rID.split('').slice(1).join('');
var qty = tgt.value;
var prc = UI['prc' + idx].value;
UI['amt' + idx].value = (parseFloat(qty) * parseFloat(prc)).toFixed(2);
var amtArray = Array.from(document.querySelectorAll('.amt'));
var subVal = amtArray.map(function(sub) {
return parseFloat(sub.value);
});
var amtVal = subVal.reduce(function(acc, cur) {
return acc + cur;
}, 0);
UI.sub.value = amtVal.toFixed(2);
UI.tax.value = (parseFloat(UI.sub.value) * parseFloat(UI.tax.dataset.tax)).toFixed(2);
UI.SH.value = (3).toFixed(2);
UI.grand.value = (parseFloat(UI.sub.value) + parseFloat(UI.tax.value) + parseFloat(UI.SH.value)).toFixed(2);
}
}
}
/*
Register the input event to the <form>
When user enters data to input.qty the callback
function calcAmt() is called
*/
form.addEventListener('input', calcAmt);
/*
This is a 3D array of the data arrays which will be
passed to the function overRide()
*/
var table = [
[...imgArr],
[...capArr],
[...qtyArr],
[...prcArr]
];
// Call the overRide() function -- pass the table array
overRide(table);
</script>
</body>
</html>
I have a table in html, I have set for each td an id that I will need to sort the table with a Jquery code.
Sorting works with the FireFox browser, but with Chrome it does not work ... do you know how to help me?
$(function() {
$(".table-user-th").click(function() {
var o = $(this).hasClass('asc') ? 'desc' : 'asc';
$('.table-user-th').removeClass('asc').removeClass('desc');
$(this).addClass(o);
var colIndex = $(this).prevAll().length;
var tbod = $(this).closest("table").find("tbody");
var rows = tbod.find("tr");
rows.sort(function(a, b) {
var A = $(a).find("td").eq(colIndex).attr('id');;
var B = $(b).find("td").eq(colIndex).attr('id');;
if (!isNaN(A)) A = Number(A);
if (!isNaN(B)) B = Number(B);
return o == 'asc' ? A > B : B > A;
});
$.each(rows, function(index, ele) {
tbod.append(ele);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1">
<thead>
<tr>
<th class="table-user-th">Firstname</th>
<th class="table-user-th">Lastname</th>
</tr>
</thead>
<tbody>
<tr>
<td id="Mark">Mark</td>
<td id="Red">Red</td>
</tr>
<tr>
<td id="Nick">Nick</td>
<td id="Sid">Sid</td>
</tr>
<tr>
<td id="Alex">Alex</td>
<td id="Nirv">Nirv</td>
</tr>
</tbody>
</table>
It seems like there is no purpose of using ids here.
Actually the problem was in you sort function. It should return not just true/false but the numeric difference between two values. As usual it is return -1/0/1
So here I wrote comparator func that does just that. And depending on sort type I just multiply it on -1 or 1.
I've also refactored a little bit your code not to use classes or ids. Using jquery you can use data method that stores data on element by key/value.
$(function() {
function cmp(a,b) {return a < b ? 1 : a > b ? -1 : 0}
$(".sortable-table").on('click', 'th', function() {
var th = $(this);
var colIndex = th.data('column');
if(typeof colIndex === 'undefined') {
return;
}
var sortType = th.data('sort') === 'asc' ? 'desc' : 'asc';
th.data('sort', sortType);
var table = $(this).closest("table");
table.find('thead th').removeClass('asc desc');
th.addClass(sortType);
var tbody = table.find("tbody");
var rows = tbody.find("tr");
rows.sort(function(a, b) {
var A = $(a).find("td").eq(colIndex).text();
var B = $(b).find("td").eq(colIndex).text();
return cmp(A,B) * (sortType === 'asc' ? -1 : 1);
});
$.each(rows, function(index, ele) {
tbody.append(ele);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" class="sortable-table">
<thead>
<tr>
<th data-column="0">Firstname</th>
<th data-column="1">Lastname</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mark</td>
<td>Red</td>
</tr>
<tr>
<td>Nick</td>
<td>Sid</td>
</tr>
<tr>
<td>Alex</td>
<td>Nirv</td>
</tr>
</tbody>
</table>
Update
Added
var table = $(this).closest("table");
table.find('thead th').removeClass('asc desc');
th.addClass(sortType);
I have installed sticky header module in my angular application and I want to obtain a sticky-responsive thead.
Initial
<!--"table" = responsive boostrap class-->
<table class="table">
<thead>
<tr>
<th>...</th>
<th>...</th>
</tr>
</thead>
<tbody>
<tr>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
After sticky header executes the table width is fixed:
<thead>
<tr>
<th style="width:173px">...</th>
<th style="width:173px">...</th>
</tr>
</thead>
I tried to remove the style attribute from the script, but this is not helpful. I have also seen that angular-scrollable-table directive is responsive.
var headersAreFixed = $q.defer();
function fixHeaderWidths() {
if (!$element.find("thead th .th-inner").length) {
$element.find("thead th").wrapInner('<div class="th-inner"></div>');
}
if($element.find("thead th .th-inner:not(:has(.box))").length) {
$element.find("thead th .th-inner:not(:has(.box))").wrapInner('<div class="box"></div>');
}
$element.find("table th .th-inner:visible").each(function (index, el) {
el = angular.element(el);
var width = el.parent().width(),
lastCol = $element.find("table th:visible:last"),
headerWidth = width;
if (lastCol.css("text-align") !== "center") {
var hasScrollbar = $element.find(".scrollArea").height() < $element.find("table").height();
if (lastCol[0] == el.parent()[0] && hasScrollbar) {
headerWidth += $element.find(".scrollArea").width() - $element.find("tbody tr").width();
headerWidth = Math.max(headerWidth, width);
}
}
var minWidth = _getScale(el.parent().css('min-width')),
title = el.parent().attr("title");
headerWidth = Math.max(minWidth, headerWidth);
el.css("width", headerWidth);
if (!title) {
// ordinary column(not sortableHeader) has box child div element that contained title string.
title = el.find(".title .ng-scope").html() || el.find(".box").html();
}
//el.attr("title", title.trim());
});
headersAreFixed.resolve();
}
I overrode the th width property with a css class in my main stylesheet:
<table class="table-fix">
<thead>
<tr>
<th class="table-header-fix2">...</th>
<th class="table-header-fix2">...</th>
</tr>
</thead>
.table-header-fix2{
width:12.50% !important; // 12.50 = fullScreenWidth / nr_Columns
}
I will update this answer if I manage to translate the code above into the js module
Update
If you have different table head structures in your app (for example 2 tables with 2 th and other 5 tables with 10 th) you might want to set the proper th width percentage for each table by doing a change in the fsm-sticky-header.js function setColumnHeaderSizes():
var thNumber = 0;
function setColumnHeaderSizes() {
if (clonedHeader.is('tr') || clonedHeader.is('thead')) {
var clonedColumns = clonedHeader.find('th');
thNumber = 100 / ($(".table-fix").find("tr:first th").length;
header.find('th').each(function (index, column) {
var clonedColumn = $(clonedColumns[index]);
clonedColumn.css( 'width', thNumber + '%');
});
}
};
please refer to previous question here: Sum total for column in jQuery
i used Aymen's solution, but i edited it to suite my need. It stopped working, my code as below as seen at jsfiddle: http://jsfiddle.net/unKDk/15/
<table id="sum_table" width="300" border="1">
<tr class="titlerow">
<td>Apple</td>
<td>Orange</td>
<td>Watermelon</td>
<td>Strawberry</td>
<td>Total By Row</td>
</tr>
<tr>
<td class="rowAA">1</td>
<td class="rowAA">2</td>
<td class="rowBB">3</td>
<td class="rowBB">4</td>
<td class="totalRow"></td>
</tr>
<tr>
<td class="rowAA">1</td>
<td class="rowAA">2</td>
<td class="rowBB">3</td>
<td class="rowBB">4</td>
<td class="totalRow"></td>
</tr>
<tr>
<td class="rowAA">1</td>
<td class="rowAA">5</td>
<td class="rowBB">3</td>
<td class="rowBB">4</td>
<td class="totalRow"></td>
</tr>
<tr class="totalColumn">
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
<td class="totalCol">Total:</td>
</tr>
</table>
Jquery part is
var totals=[0,0,0,0,0];
$(document).ready(function(){
var $dataRows=$("#sum_table tr:not('.totalColumn, .titlerow')");
$dataRows.each(function() {
$(this).find('.rowAA').each(function(i){
totals[i]+=parseInt( $(this).html());
});
$(this).find('.rowBB').each(function(i){
totals[i]+=parseInt( $(this).html());
});
});
$("#sum_table td.totalCol").each(function(i){
$(this).html("total:"+totals[i]);
});
});
how to solve the problem that caused the jquery calculate wrongly.
how to calculate total by row
i need the class name exactly same.
I am not quite sure what you want, but if you just want to sum all rows by column then see below..
var totalsByRow = [0, 0, 0, 0, 0];
var totalsByCol = [0, 0, 0, 0, 0];
$(document).ready(function() {
var $dataRows = $("#sum_table tr:not('.totalColumn, .titlerow')");
$dataRows.each(function(i) {
$(this).find('td:not(.totalRow)').each(function(j) {
totalsByCol[j] += parseInt($(this).html());
totalsByRow[i] += parseInt($(this).html());
});
});
for (var i = 0; i < totalsByCol.length - 1; i++) {
totalsByCol[totalsByCol.length - 1] += totalsByCol[i];
}
$("#sum_table td.totalCol").each(function(i) {
$(this).html("total:" + totalsByCol[i]);
});
$("#sum_table td.totalRow").each(function(i) {
$(this).html("total:" + totalsByRow[i]);
});
});
DEMO
Essentially you want to target all of the td elements that are in the middle rows. Each time you cycle over a new td, you want to add its value to both the last td in its row (unless it is the last td in the row), and also to the td in the last row that shares its index.
$("#sum_table tr:not(:first,:last)").each(function(c,row) {
$("td",row).text(function(i,t) {
var n = parseInt( t, 10 ) || 0;
$(this).nextAll(":last-child").text(function(a,o) {
return n + ( parseInt( o, 10 ) || 0 );
});
$(row).nextAll("tr:last").find("td:nth-child("+(++i)+")").text(function(a,o){
return "Total: " + ( n + ( parseInt( o.replace(/[^\d]/g,""), 10 ) || 0 ) );
});
});
});
This should work for any table of any size, not restricting you to x columns, or y rows.
Fiddle: http://jsfiddle.net/unKDk/34/
With Commentary
I would encourage you to read the comments in the example below as they will help you understand what is going on with each line.
// For each table row that is not first or last
$("#sum_table tr:not(:first,:last)").each(function(c,row) {
// For each td within this row
$("td",row).text(function(i,t) {
// Determine numerical value of this td's content
var n = parseInt( t, 10 ) || 0;
// Find last td in this row, change its text
$(this).nextAll(":last-child").text(function(a,o) {
// Increment its value with the value of current TD
return n + ( parseInt( o, 10 ) || 0 );
});
// Find last row, and td within of same index as current td, change its text
$(row).nextAll("tr:last").find("td:nth-child("+(++i)+")").text(function(a,o){
// Increment its value (removing non-numbers) with the value of current td
return "Total: " + ( n + ( parseInt( o.replace(/[^\d]/g,""), 10 ) || 0 ) );
});
// End our td loop
});
// End our tr loop
});