Generating table row by row after user input - javascript

When the user enters the page, an HTML table with two rows is generated. First row is the table header, while the second row in its first cell has an input box, while the other cells are empty.
barcode
product
amount
price
input box
After the user enters the barcode in the input box I need to:
update the other cells with the details of the product (stored into a MySQL database) based on the barcode inserted;
generate another row like the previous one.
So, after the first input the table should be like this:
barcode
product
amount
price
54573498759384
trousers
10
99 $
input box
and so on...
I read here and there and I came to conclusion that I probably need AJAX, but I never used it before so your help, just to start, in as simple as possible words, would be really appreciated.
I am using only PHP and Javascript. I never used JQuery.
Thanks in advance.
At the moment I haven't found a way.

Just add your ajax call to get data from your backend in the onBarcodeChange function
function onBarcodeChange(id) {
// ... cal your backend/SQL to get data
const mockData = {
product: `Product ${id}`,
amount: getRandomInt(100),
price: getRandomInt(10)
}
const {
product,
amount,
price
} = mockData
document.getElementById(`product${id}`).innerText = product
document.getElementById(`amount${id}`).innerText = amount
document.getElementById(`price${id}`).innerText = price
addTableRow(id + 1)
}
function addTableRow(id) {
const barcodeInput = document.createElement('input')
barcodeInput.placeholder = "Enter barcode"
barcodeInput.onchange = () => onBarcodeChange(id)
// create 4 cells
const cellNames = ['barcode', 'product', 'amount', 'price']
const cells = cellNames.map(name => {
const cell = document.createElement('td')
cell.id = `${name}${id}`
return cell
})
// add input to the 1st cell
cells[0].appendChild(barcodeInput)
const row = document.createElement('tr')
cells.forEach(cell => row.appendChild(cell))
const table = document.getElementById('products')
table.appendChild(row)
barcodeInput.focus()
}
function getRandomInt(max) {
const min = 1
return Math.floor(Math.random() * (max - min) + min);
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
<table id='products'>
<tr>
<th>barcode</th>
<th>product</th>
<th>amount</th>
<th>price</th>
</tr>
<tr>
<td id='barcode1'>
<input placeholder="Enter barcode" onchange="onBarcodeChange(1)">
</td>
<td id="product1"></td>
<td id="amount1"></td>
<td id="price1"></td>
</tr>
</table>

Related

I need to display that how many '1' values have 3rd and 4th columns

Since I am new in Web Development sorry for that. My HTML table has 4 rows and i need to find how many 1 values in my 3rd and 4th columns. 3rd and 4th columns of table consists of 1's and 0's.
Html code that i need to find '1' values in checkOne classes.
<th><input type="text" id="filter0" placeholder="name"></th>
<th><input type="text" id="filter1" placeholder="Date"></th>
<th><input type="text" class="checkOne" id="filter2" placeholder="Line1"></th>
<th><input type="text" class="checkOne" id="filter3" placeholder="Line2"></th>
JavaScript code that i use display for number of rows
function rowCount(){
var a = document.getElementById("filter");
var rows = a.rows.length - 1;
alert("Total Rows: " + rows);
//alert(line1 has ... 1 values)
//alert(line2 has ... 1 values)
}
You can go through each of the rows adding together the numbers in the 3rd and 4th cell in each row.
Note that rows as you have defined it is a live collection of elements. It is not an array as such so you have to first turn it into an array to use forEach on it.
Here's a very simple snippet demonstrating this:
function rowCount() {
const rows = document.getElementById("filter").rows;
let valuesCount = 0;
[...rows].forEach(row => { // uses the spread function to create an array
const n3 = Number(row.querySelector(':nth-child(3)').innerHTML);
const n4 = Number(row.querySelector(':nth-child(4)').innerHTML);
if (n3 === 1) valuesCount++;
if (n4 === 1) valuesCount++;
})
return valuesCount;
}
alert(rowCount());
<table id="filter">
<tr>
<td>a</td>
<td>b</td>
<td>1</td>
<td>0</td>
</tr>
</table>
Something like this should help
function rowCount(){
const rows = document.getElementById("filter").rows;
let valuesCount = 0;
Array.from(rows).forEach(row => {
if (row.cells[2].innerHtml === 1 || row.cells[3].innerHtml === 1) valuesCount++
})
return valuesCount
}

How do I merge extra js to possibly have highlighted table filtered text tesults?

HTML
<input id="myInput" type="text" onkeyup="ContactsearchFX()"
placeholder="Search Titles">
*</p>
<table id="myTable" style="width: 100%" class="style1">
JAVASCRIPT
window.onload = function() {
var rows = document.querySelectorAll('tr');
for (var i = 0; i < rows.length; i++) {
rows[i].style.display = 'none';
}
}
function ContactsearchFX() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
var rows = document.querySelectorAll('tr');
if (input.value.length == 0) {
for (var i = 0; i < rows.length; i++) {
rows[i].style.display = 'none';
}
}
}
Have been trying to implement https://markjs.io/ among other various highlight solutions with no fix or solution.
Hope there is enough info to go on. Please do ask if you need more details.
Setup
Judging by the code you've shared, you're probably not using es6 or a js bundler to setup your project. This means no imports and the library <scrpit>s go inside your index.html
Steps
Verify you are loading the script correctly
Clean up the code
separate it to chunks to better understand what's failing
Update the code with the highlight functionality described by the "getting started" of the package
Notes
With the mark.js library it would be best to clean up the mark (.unmark()) before applying it again. because it will add more elements on each change. That's why we keep a single instance of mark per context (context is the table element) instead of creating a new instance inside the highlightChanges function
The snippet below is not the optimal implementation of this functionality but it can serve for a starting point. It was based on the original code
Snippet with added highlight
var input, table, rows, markInstance;
window.onload = function init() {
input = document.getElementById("myInput");
table = document.getElementById('myTable');
rows = table.querySelectorAll('tr');
markInstance = new Mark(table);
clear();
}
function ContactsearchFX() {
clear();
if (input.value.length == 0) return;
filterRows(input.value);
highlightMatches(input.value);
}
function clear() {
markInstance.unmark();
for (var i = 0; i < rows.length; i++) {
rows[i].style.display = 'none';
}
}
function filterRows(text) {
var part = text.toUpperCase();
for (i = 0; i < rows.length; i++) {
var row = rows[i];
var td = row.getElementsByTagName("td")[0];
if (td) {
// part = GI
// innerHtml = <MARK DATA-MARKJS="TRUE">G</MARK>ITHUB (wont match)
// innerText = GITHUB (will match)
var content = td.innerText.toUpperCase();
if (content.includes(part)) {
row.style.display = "";
}
}
}
}
function highlightMatches(text) {
markInstance.mark(text);
}
.input-wrap {
margin-bottom: 12px;
}
.hints {
display: none;
margin-top: 12px;
}
#myInput:invalid~.hints {
display: block;
}
mark {
background: orange;
font-weight: bold;
color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.js"></script>
<div class="input-wrap">
<label>
Search Titles:
<input id="myInput" type="text" required
onkeyup="ContactsearchFX()"
placeholder="Search Titles" />
<span class="hints">
Hints: type "git", "bit", "forge" ...
</span>
</label>
</div>
<table id="myTable" style="width: 100%" class="style1">
<tr>
<th>Title</th>
<th>Description</th>
</tr>
<tr>
<td>Github</td>
<td>Is the HUB</td>
</tr>
<tr>
<td>Gitlab</td>
<td>Have nice CI</td>
</tr>
<tr>
<td>Bitbucket</td>
<td>Has Jira integration (Duh)</td>
</tr>
<tr>
<td>SourceForge</td>
<td>Open source projects live here. It is said</td>
</tr>
</table>
And a more appropriate version for production
Quick look through the examples and the API for the options parameter of the mark() function review that we can substitute most of the logic with the hooks from the options
The input event handler is debounceed (function from from lodash _.debounce) this way the filtering will start when the user stops typing (for more than 250ms)
Content is again .unmark()ed at the start - the different part is that we use the options parameter with a done callback to continue with highlightMatches when unmark finishes
The options parameter have an each prop which is a callback for each element that matches. Using this callback we can search for it's parent that we know must be a row, and we add a class show so the row can become visible.
There's also a noMatch prop which will be called (back) if the texts matches nothing so we can show some hint to maybe try a different text
The options parameter hold other useful props that can configure the matching like, wildcards, case sensitive matching and so on...
var input, table, rows, noMatches, markInstance;
window.onload = function init() {
input = document.getElementById('myInput');
noMatches = document.getElementById('noMatches');
table = document.getElementById('myTable');
rows = table.querySelectorAll('tr');
markInstance = new Mark(table);
input.addEventListener('keyup', _.debounce(ContactsearchFX, 250));
}
function ContactsearchFX() {
resetContent();
markInstance.unmark({
done: highlightMatches
});
}
function resetContent() {
noMatches.textContent = '';
rows.forEach(function(row) {
row.classList.remove('show');
});
}
function highlightMatches() {
markInstance.mark(input.value, {
each: showParantRow,
noMatch: onNoMatches,
})
}
function showParantRow(element) {
var row = element.closest('tr');
row.classList.add('show');
}
function onNoMatches(text) {
noMatches.textContent = 'No records match: "' + text + '"';
};
.input-wrap {
margin-bottom: 12px;
}
#myInput:invalid~.hints {
display: block;
}
#noMatches:empty, #noMatches:empty + .hints {
display: none;
}
.filterTable tr {
display: none;
}
.filterTable .show {
display: table-row;
}
mark {
background: orange;
font-weight: bold;
color: black;
}
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"></script>
<div class="input-wrap">
<label>
Search Titles:
<input id="myInput" type="text" required
placeholder="Search Titles" />
</label>
</div>
<div class="hintsWrap">
<p id="noMatches"></p>
<p class="hints">
Hints: type "git", "bit", "forge" ...
</p>
</div>
<table id="myTable" style="width: 100%" class="filterTable">
<tr>
<td>Github</td>
<td>Is the HUB</td>
</tr>
<tr>
<td>Gitlab</td>
<td>Have nice CI</td>
</tr>
<tr>
<td>Bitbucket</td>
<td>Has Jira integration (Duh)</td>
</tr>
<tr>
<td>SourceForge</td>
<td>Open source projects live here. It is said</td>
</tr>
</table>

Search through HTML table columns

I am developing a site that contains a live search. This live search is used to search for contacts in a contact list (An HTML table). The contact list is a table with 2 columns, with each column containing a contact. The search works but, it returns the whole row, not just the matching columns.
Meaning that if I search for A in a table like the one in the snippet below; the search returns the whole row ( A || B ), not just A. Is there any way I could refine my function to search through columns instead of rows?
Hope I explained myself clearly.
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</table>
Function
<script>
function myFunction() {
//variables
var input, filter, table, tr, td, i;
input = document.getElementById("search");
filter = input.value.toUpperCase();
table = document.getElementById("table");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td)
{
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
I've modified your code to iterate all the td elements in your table. instead of hiding the cells that don't contain the filter text I've opted to apply an opacity to them. It makes it clearer in the example what is happening.
When doing work on key down, don't forget to debounce the event. See this post for a good introduction: https://davidwalsh.name/javascript-debounce-function
function myFunction() {
//variables
var
input = document.getElementById("search"),
filter = input.value.toUpperCase(),
table = document.querySelector('table'),
cells = table.querySelectorAll('td');
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
if (cell.innerHTML.toUpperCase().indexOf(filter) > -1) {
cell.classList.remove('no-match');
} else {
cell.classList.add('no-match');
}
}
}
const
form = document.getElementById('form'),
input = document.getElementById("search");
form.addEventListener('submit', onFormSubmit);
input.addEventListener('keyup', onKeyUp);
function onFormSubmit(event) {
event.preventDefault();
myFunction();
}
function onKeyUp(event) {
// Debounce this event in your code or you will run into performance issues.
myFunction();
}
.no-match {
opacity: .2;
}
<form id="form">
<label>
Filter text
<input type="text" id="search"/>
</label>
<button>Filter</button>
</form>
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</table>

Restrict 1st table row for datatables

Hi I am currently working on datatables and I wrote a code when a table row has been click there is a specific function that will be called.
The problem is when I click the table row for the table header it also does the function (IT MUST NOT).
Here is a snippet of my code when I click the table row there will be a function called.
$('#response-contact-container').on('click', 'tr', function(){
var table = $('#response-contact-container').DataTable();
var data = table.row(this).data();
$('#edit-contact-settings').modal('hide');
$('.modal-backdrop').remove();
var community_contacts = ['c_id','firstname','lastname','prefix','office','sitename','number','rel'];
var employee_contacts = ['eid','firstname','lastname','nickname','birthday','email','numbers','grouptags'];
var counter = 1;
var container = document.getElementById("contact-settings-wrapper");
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for(var i=1; i< data.length; i++) {
var label = document.createElement("label");
var input = document.createElement("input");
if (data[0].charAt(0)=="c") {
var t = document.createTextNode(community_contacts[i].capitalize());
label.appendChild(t);
container.appendChild(label);
input.type = "text";
input.name = community_contacts[i];
input.className = "form-control";
input.value = data[i];
container.appendChild(input);
container.appendChild(document.createElement("br"));
} else {
var t = document.createTextNode(employee_contacts[i].capitalize());
label.appendChild(t);
container.appendChild(label);
input.type = "text";
input.name = community_contacts[i];
input.className = "form-control";
input.value = data[i];
container.appendChild(input);
container.appendChild(document.createElement("br"));
}
console.log(data[i]);
counter++;
}
$('#edit-contact').modal('show');
});
I want the header be able to not perform the function under the onclick in jQuery, but I don't want it to disable because I want to use the datatables built in feature that sort the cells.
Thanks
I interpret your question to be the following: when I click on a table row, can I call a click handler if and only if that row has <td> elements, not <th> elements, i.e. only when it is a non-header row?
To accomplish this, use the jQuery .has() selector. Specifically, in your code, instead of
...on('click', 'tr', ...
use
...on('click', 'tr:has(td)', ...
In the example below, the selected element's currentTarget result shows that it is indeed the row, and not the cell, that is the click's current target. Moreover, it calls the handler function (or not) as follows:
when you click on a normal data row, i.e. a row with all <td> cells
not when you click on a normal header row, i.e. a row with all <th> cells
when you click on a mal-formed row that (inappropriately) contains both <th> and <td> rows
You should never form a table row in the last way. However, that example show how the selector is working. Specifically, even if you click on the <th> cell in that row, the click handler will still fire because you are clicking on a cell in a row that contains at least one <td> cell. That should never be what you want, but it illustrates what's going on in terms of what is actually being selected.
var counter = 0;
$('#myTable').on('click', 'tr:has(td)', function(e) {
console.log(e.currentTarget);
});
$('#myTable').on('click', 'tr', function(e) {
counter += 1;
console.log(counter + ' clicks');
});
table {
border-collapse: collapse;
}
td, th {
border: black solid 1px;
padding: 0.5em;
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<th>normal header row - cell #1 - <th></th>
<th>normal header row - cell #2 - <th></th>
</tr>
<tr>
<th>malformed (mixed) row - cell #1 - <th></th>
<td>malformed (mixed) row - cell #2 - <td></td>
</tr>
<tr>
<td>normal data row - cell #1 - <td></td>
<td>normal data row - cell #2 - <td></td>
</tr>
</table>

How to order the table rows based on its value in javascript

Am working on the table, my aim is to display rows orderly based on its sum of columns. I mean, highest valued rows should be displayed first and then, second highest values, then, go on.. Have tried and could not make it. Just give me an idea, and that is good enough for me. Am not able to come to any idea on how to reshuffle the rows based on its sum values. Any idea on this?
<div id="na_1" style="border: 1px solid gray;width: 450px;padding:10px;">
<form>
<input type="radio" value="All" onclick="Turnthis();"/>All
<input type="radio" value="Top15" onclick="TurnOutthis();"/>Top5
</form>
<table id="bt_01" border="1" width="100%">
<thead>
<tr><td>head1</td><td>head2</td><td>head3</td><td>head4</td><td>head5</td><td>head6</td><td>head7</td></tr>
</thead>
<tbody>
<tr><td>Subject1</td><td>501</td><td>501</td><td>501</td><td>550</td><td>560</td><td>570</td></tr>
<tr><td>Subject2</td><td>620</td><td>640</td><td>605</td><td>650</td><td>600</td><td>604</td></tr>
<tr><td>Subject3</td><td>730</td><td>730</td><td>740</td><td>750</td><td>760</td><td>790</td></tr>
<tr><td>Subject4</td><td>700</td><td>701</td><td>700</td><td>702</td><td>700</td><td>703</td></tr>
<tr><td>Subject5</td><td>220</td><td>201</td><td>202</td><td>222</td><td>210</td><td>203</td></tr>
<tr><td>Subject6</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject7</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject8</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Total</td><td>202</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tbody>
</table>
</div>
After I pressed the 'Top5' button, then, the table should be displayed as follows[sample]
<div id="na_1" style="border: 1px solid gray;width: 450px;padding:10px;">
<form>
<input type="radio" value="All" onclick="Turnthis();"/>All
<input type="radio" value="Top15" onclick="TurnOutthis();"/>Top5
</form>
<table id="bt_01" border="1" width="100%">
<thead>
<tr><td>head1</td><td>head2</td><td>head3</td><td>head4</td><td>head5</td><td>head6</td><td>head7</td></tr>
</thead>
<tbody>
<tr><td>Subject3</td><td>730</td><td>730</td><td>740</td><td>750</td><td>760</td><td>790</td></tr>
<tr><td>Subject4</td><td>700</td><td>701</td><td>700</td><td>702</td><td>700</td><td>703</td></tr>
<tr><td>Subject2</td><td>620</td><td>640</td><td>605</td><td>650</td><td>600</td><td>604</td></tr>
<tr><td>Subject1</td><td>501</td><td>501</td><td>501</td><td>550</td><td>560</td><td>570</td></tr>
<tr><td>Subject5</td><td>220</td><td>201</td><td>202</td><td>222</td><td>210</td><td>203</td></tr>
</tbody>
</table></div>
Hope this makes sense. For your kind information, i except code only in javascript not in jquery.
The trick is to get the rows you want and put them into an array, then sort the array and put the rows into the table in the right order. The following will sort the rows based on the cell values, so if the first cell value is equal, it uses the second, and so on. The sort may not be stable since it just uses the built–in Array.prototype.sort. If you want to to be stable, that is pretty simple (but generally not required).
Firstly, get the relevant tBody element and rows:
var tBody = document.getElementById('bt_01').tBodies[0];
var rows = tBody.rows;
rows is a live collection so you want to build an array form it (also helps with sorting). The following works fine in modern browsers:
var rowArr = Array.prototype.slice.call(rows);
But will not work in IE 8 and lower, you'll need to use a for loop (just one extra line of code):
var rowArr = [];
for (var i=0, iLen=rows.length; i<iLen; i++) rowArr[i] = rows[i];
To keep the last row as the last, just keep a reference:
var lastRow = rowArr[rowArr.length - 1];
Now sort based on the cell values from the second cell onward:
rowArr.sort(function(a, b) {
var aVal, bVal;
for (var i = 1, iLen = a.cells.length; i<iLen; i++) {
aVal = a.cells[i].textContent || a.cells[i].innerText;
bVal = b.cells[i].textContent || b.cells[i].innerText;
if (aVal != bVal) return aVal - bVal;
}
return 0;
});
Now put the rows into order:
for (var j=0, jLen=rowArr.length; j<jLen; j++) {
tBody.appendChild(rowArr[j]);
}
and finally, put the bottom row back at the bottom:
tBody.appendChild(lastRow);
and you're done. And it's shorter than the offered jQuery alternative (and likely a lot faster). ;-)
It would be best to put footer row in separate tFoot section as you've done with the header.
Edit
If you want to sort based on the sum of the values in each row, the sort part becomes:
rowArr.sort(function(a, b) {
var aSum = 0, bSum = 0;
for (var i = 1, iLen = a.cells.length; i<iLen; i++) {
aSum += parseFloat(a.cells[i].textContent || a.cells[i].innerText);
bSum += parseFloat(b.cells[i].textContent || b.cells[i].innerText);
}
return aSum - bSum;
});
I assume you want the "total" row at the end of the table after sort.Otherwise code can be 10-12 lines shorter.
i come up with this solution.I've commented out every portion for convenience .With a little help form getElementsByTagName,removeChild,createElement,and appendChild methods you can achieve what you are trying to do.It is really simple.I advice you go through it.The main thing is create an array of objects which hold three properties.And the properties are the actual tr element,its sum and the first td element which holds subject1,2,3....and Total string.Then sort them down with Array.prototype.sort() then add them serially to your tbody element
var radio=document.getElementById('radio');
if(radio.checked == true){ //check for radio element is checked or not
radio.checked=false;
}
var table=document.getElementById('bt_01');
var serialTdArr=[]; //array which will hold the array of objects
var storageForTotal='';// store the tr element that has 'Total' as value of its first td element
function Turnthis(e){
var tbody=document.getElementsByTagName('tbody')[0]; //get the current tbody element
var tr=tbody.getElementsByTagName('tr'); //get all tr elements inside tbody
for(i=0;i<tr.length;i++){ // loop over the tr elements
var sum=0;
var td=tr[i].getElementsByTagName('td'); //get all td element inside every tr element
for(j=1;j<td.length;j++){
sum+=parseInt(td[j].innerHTML); // sum them up
}
var firstTd=td[0].innerHTML; //save every subject1,subject2,3,...and Total string to a seperate variable
serialTdArr.push({index:tr[i],sum:sum,pointer:firstTd}); // an object which holds the tr element,its sum and its first td element value is pushed inside serialTdArr
}
var sortedArr=serialTdArr.sort(function(a,b){ // sort them down from higher to lower
if(a.sum < b.sum){
return 1;
}
if(a.sum > b.sum){
return -1;
}
return 0;
});
table.removeChild(tbody); // remove the current tbody
var newTbody=document.createElement('tbody'); // create a new tbody
table.appendChild(newTbody); // append it to table
for(i=0;i<sortedArr.length;i++){
if((sortedArr[i].pointer) != 'Total'){ // if it has no "Total" string then add them to tbody
newTbody.appendChild(sortedArr[i].index); // add to tbody
}else{
storageForTotal=sortedArr[i].index; // 'Total' row will be seperated and stored in a variable to be added later at the end of the table
}
}
newTbody.appendChild(storageForTotal); // add the tr which 'Total' to the last of td element
}
<div id="na_1" style="border: 1px solid gray;width: 450px;padding:10px;">
<form>
<input type="radio" id='radio' value="Sort Them All" onchange="Turnthis();"/>Sort Them All
</form>
<table id="bt_01" border="1" width="100%">
<thead>
<tr><td>head1</td><td>head2</td><td>head3</td><td>head4</td><td>head5</td><td>head6</td><td>head7</td></tr>
</thead>
<tbody>
<tr><td>Subject1</td><td>501</td><td>501</td><td>501</td><td>550</td><td>560</td><td>570</td></tr>
<tr><td>Subject2</td><td>620</td><td>640</td><td>605</td><td>650</td><td>600</td><td>604</td></tr>
<tr><td>Subject3</td><td>730</td><td>730</td><td>740</td><td>750</td><td>760</td><td>790</td></tr>
<tr><td>Subject4</td><td>700</td><td>701</td><td>700</td><td>702</td><td>700</td><td>703</td></tr>
<tr><td>Subject5</td><td>220</td><td>201</td><td>202</td><td>222</td><td>210</td><td>203</td></tr>
<tr><td>Subject6</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject7</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject8</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Total</td><td>202</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tbody>
This code works and tested on Chrome 30
Non-jQuery version (updated question):
<html>
<body>
<div id="na_1" style="border: 1px solid gray;width: 450px;padding:10px;">
<table id="bt_01" border="1" width="100%">
<thead>
<tr><td>head1</td><td>head2</td><td>head3</td><td>head4</td><td>head5</td><td>head6</td><td>head7</td></tr>
</thead>
<tbody>
<tr><td>Subject1</td><td>501</td><td>501</td><td>501</td><td>550</td><td>560</td><td>570</td></tr>
<tr><td>Subject2</td><td>620</td><td>640</td><td>605</td><td>650</td><td>600</td><td>604</td></tr>
<tr><td>Subject3</td><td>730</td><td>730</td><td>740</td><td>750</td><td>760</td><td>790</td></tr>
<tr><td>Subject4</td><td>700</td><td>701</td><td>700</td><td>702</td><td>700</td><td>703</td></tr>
<tr><td>Subject5</td><td>220</td><td>201</td><td>202</td><td>222</td><td>210</td><td>203</td></tr>
<tr><td>Subject6</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject7</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject8</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>202</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tfoot>
</table>
</div>
<input type='button' onclick='sort()' value='sort by sum' />
<script>
function sort() {
var t = document.getElementById('bt_01').children[1]; // tbody
var arr = [];
// find all tr
var trs = t.children;
for(;trs.length;) {
var tr = trs[0];
// find all td and calculate the sum
var sum = 0;
var tds = tr.children;
for(var y in tds) {
var td = tds[y];
var v = +td.textContent;
if (!isNaN(v)) sum += v;
};
// move them to arr
tr = tr.parentNode.removeChild(tr)
arr.push({sum: sum,tr: tr});
};
// sort it
arr.sort(function(a, b) {
if (a.sum < b.sum) return 1;
if (a.sum > b.sum) return -1;
return 0;
});
// attach back the tr in order
for (var z in arr) t.appendChild(arr[z].tr)
}
</script>
</body>
</html>
jQuery version:
<html>
<body>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<div id="na_1" style="border: 1px solid gray;width: 450px;padding:10px;">
<table id="bt_01" border="1" width="100%">
<thead>
<tr><td>head1</td><td>head2</td><td>head3</td><td>head4</td><td>head5</td><td>head6</td><td>head7</td></tr>
</thead>
<tbody>
<tr><td>Subject1</td><td>501</td><td>501</td><td>501</td><td>550</td><td>560</td><td>570</td></tr>
<tr><td>Subject2</td><td>620</td><td>640</td><td>605</td><td>650</td><td>600</td><td>604</td></tr>
<tr><td>Subject3</td><td>730</td><td>730</td><td>740</td><td>750</td><td>760</td><td>790</td></tr>
<tr><td>Subject4</td><td>700</td><td>701</td><td>700</td><td>702</td><td>700</td><td>703</td></tr>
<tr><td>Subject5</td><td>220</td><td>201</td><td>202</td><td>222</td><td>210</td><td>203</td></tr>
<tr><td>Subject6</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject7</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
<tr><td>Subject8</td><td>200</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>202</td><td>201</td><td>200</td><td>202</td><td>200</td><td>203</td></tr>
</tfoot>
</table>
</div>
<input type='button' onclick='sort()' value='sort by sum' />
<script>
function sort() {
var t = $('#bt_01').find('tbody');
var arr = [];
// find all tr
t.find('tr').each(function(idx, tr) {
tr = $(tr);
// find all td and calculate the sum
var sum = 0;
tr.find('td').each(function(idx, td) {
td = $(td);
var v = +td.text();
if (!isNaN(v)) sum += v;
});
// move them to arr
arr.push({sum: sum,tr: tr.detach()});
});
// sort it
arr.sort(function(a, b) {
if (a.sum < b.sum) return 1;
if (a.sum > b.sum) return -1;
return 0;
});
// attach back the tr in order
for (var z in arr) t.append(arr[z].tr)
}
</script>
</body>
</html>

Categories