JQuery sum rows with unique id elements - javascript

I'm looking for a way to display the sum of all the input elements (quantity and amount) respectively in the last 2 cells of each line.
Every element in this table has a unique id. Each input element has an id that contains information about the row it appears in :
var trRows = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
trRows.forEach(function(trRow) {
var $sumQuantity = 0;
var $sumAmount = 0;
$(this).find('#tr' + trRow + 'input[id *= "qty"]').each(function() {
$sumQuantity += +$(this).text() || 0;
});
$(this).find('#tr' + trRow + 'input[id *= "amount"]').each(function() {
$sumAmount += +$(this).text() || 0;
});
$('#sumQtyTR' + trRows, this).html($sumQuantity);
$('#sumAmountTR' + trRows, this).html($sumAmount);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr id='tr2'>
<td id='td2_65'><span id='span_i2qty_65'><input id='input_i2qty_65' class='editbox'></span>
</td>
<td id='td2_65'><span id='span_i2amount_65'><input id='input_i2amount_65' class='editbox'></span>
</td>
<td id='td2_66'><span id='span_i2qty_66'><input id='input_i2qty_66' class='editbox'></span>
</td>
<td id='td2_66'><span id='span_i2amount_66'><input id='input_i2amount_66' class='editbox'></span>
</td>
<td id='sumQtyTR2'></td>
<td id='sumAmountTR2'></td>
</tr>
<tr id='tr3'>
<td id='td3_65'><span id='span_i3qty_65'><input id='input_i3qty_65' class='editbox'></span>
</td>
<td id='td3_65'><span id='span_i3amount_65'><input id='input_i3amount_65' class='editbox'></span>
</td>
<td id='td3_66'><span id='span_i3qty_66'><input id='input_i3qty_66' class='editbox'></span>
</td>
<td id='td3_66'><span id='span_i3amount_66'><input id='input_i3amount_66' class='editbox'></span>
</td>
<td id='sumQtyTR3'></td>
<td id='sumAmountTR3'></td>
</tr>
<!-- More rows -->
</table>
I can't figure out why sums are not displayed. Selectors ? Thanks

Recommendations
Within your code there are a few points of interest that may be worth consideration to reduce the clutter:
IDs are intended to be unique. There should never be a time where an ID is used in more than one place in an HTML document. In places where you think two or more elements might share an id, you should use a class instead
Unless you are using jQuery elsewhere, you should know that jQuery is not necessary. It does provide several advantages (including cross-browser compliance), but you should consider using native JavaScript and a packager that will add the necessary polyfills
Examples
The examples below are intended to be close in structure/design to the original source code in the OP for learning purposes; however, it should be noted that there are many ways to optimize to improve performance and readability.
One major point worth mentioning is in the logic flow. The structure in these examples are inefficient, since every time an input is updated it is looping over and recalculating sums for all of the rows. This could be improved by only calculating and updating the sum of the altered row. Additionally, holding an array of interested rows (e.g., row_ids) could be better improved with more semantic HTML and the use of classes (if needing to be selective).
There are some other major changes made to both the jQuery and ES6+ example below. Most notably is the onChange event handler. The code in the OP iterated over each ID immediately on page load, but never again. There needed to be a hook into some event that would be called when the input box was modified; thus the onChange or onBlur event is necessary in order to re-calculate the values.
jQuery Example
Given these two recommendations, I've made some substantial changes to your HTML and JavaScript, which include but are not limited to:
removed unnecessary IDs and added respective classes
use reduce for sum calculation
jQuery(document).ready(function($) {
let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
function changeEventHandler() {
$.each(row_ids, function(ndx, row_id) {
const $row = $('#' + row_id)
if (!$row.length)
return;
const quantity = $row.find('input.quantity').get().reduce(function(acc, input) {
acc += parseFloat(input.value) || 0;
return acc
}, 0)
const amount = $row.find('input.amount').get().reduce(function(acc, input) {
acc += parseFloat(input.value) || 0;
return acc
}, 0)
$row.find('.sum.quantity').text(quantity)
$row.find('.sum.amount').text(amount)
});
}
$(document).on('change', 'input', changeEventHandler)
})
.sum { background: #eee; }
th,td {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
table { width: 100%; }
input { width: 40%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Fill in each input with a number (watch sums auto-update):
<table>
<thead>
<tr>
<th>QTY 1</th>
<th>AMT 1</th>
<th>QTY 2</th>
<th>AMT 2</th>
<th>SUM QTY</th>
<th>SUM AMT</th>
</tr>
</thead>
<tbody>
<tr id='tr2'>
<!-- td: use class and not id -->
<!-- remove unnecessary classes -->
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<tr id='tr3'>
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<!-- More rows -->
</tbody>
</table>
ES6+ Example
Given the two recommendations, I've made some substantial changes to your HTML and JavaScript, which include but are not limited to:
removed unnecessary IDs and added respective classes
removed unnecessary jQuery code (used native event handling)
use reduce for sum calculation
use arrow functions for simplified syntax
Note: as mentioned prior, the code may not work in all browsers (all versions and variations), but should work in most of the newer browsers. The snippet will work in most (if not all) because it is configured to use babel
function changeEventHandler() {
let row_ids = ['tr2', 'tr3', 'tr4', 'tr5', 'tr6', 'tr7', 'tr8', 'tr9', 'tr10', 'tr11', 'tr12'];
// could iterate over the rows:
// document.querySelectorAll(selector)
// where selector is 'tr' or '[id^="tr"]'
row_ids.forEach(row_id => {
const row = document.querySelector(`#${row_id}`)
if (row == null)
return;
const qty_el = row.querySelectorAll('input.quantity')
const quantity = [...qty_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)
const amt_el = row.querySelectorAll('input.amount')
const amount = [...amt_el].reduce((acc, cv) => acc += parseFloat(cv.value) || 0, 0)
row.querySelector('.sum.quantity').textContent = quantity
row.querySelector('.sum.amount').textContent = amount
});
}
window.setTimeout(function() {
document.querySelectorAll('input').forEach(() => this.onchange = changeEventHandler)
},0);
.sum { background: #eee; }
th,td {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
table { width: 100%; }
input { width: 40%; }
Fill in each input with a number (watch sums auto-update):
<table>
<thead>
<tr>
<th>QTY 1</th>
<th>AMT 1</th>
<th>QTY 2</th>
<th>AMT 2</th>
<th>SUM QTY</th>
<th>SUM AMT</th>
</tr>
</thead>
<tbody>
<tr id='tr2'>
<!-- td: use class and not id -->
<!-- remove unnecessary classes -->
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<tr id='tr3'>
<td class="item_65"><span><input class='quantity'></span></td>
<td class="item_65"><span><input class='amount'></span></td>
<td class="item_66"><span><input class='quantity'></span></td>
<td class="item_66"><span><input class='amount'></span></td>
<td class="sum quantity"></td>
<td class="sum amount"></td>
</tr>
<!-- More rows -->
</tbody>
</table>

Related

How to loop through a table and get the td elements to follow a condition

I just want make so it the tr hides when the td does not follow the requirements, tried with jQuery and JavaScript, don't know what's wrong.
$(document).ready(function(){
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide;
}
else {
$(this).hide;
}
});
});
You can do this.
Hope this will help you.
$(document).ready(function() {
var value4 = 2;
var value5 = 4;
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide();
} else {
$(this).show();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td price_search="3">10</td>
<td price_search="2">20</td>
<td price_search="3">30</td>
</tr>
</table>
I am going to go out on a limb here and make broad assumptions on content not in the question.
Your .hide; is invalid syntax
You are missing value for two variables value4 and value4 which frankly are not well named variables at all. I will make an assumption that those are better named and that they come from somewhere during the page rendering.
I make an assumption that you have something you want to filter/hide by those upper/lower price points.
I make the assumption the attribute might contain values that need to be parsed (not a number as they are)
var lowerPricePoint = .45;
var upperPricePoint = 5.25;
$(function() {
$("td").filter('[price_search]').each(function() {
// parse out a price from perhaps formatted values
let price = Number.parseFloat($(this).attr("price_search").replace(/\$|,/g, ''));
// toggle visibility of the row
$(this).closest('tr').toggle(price > lowerPricePoint && price < upperPricePoint);
});
});
td {
border: solid black 1px;
padding: 0.4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<table>
<tr>
<td>Wear it</td>
<td price_search="123.13">Shoes</td>
</tr>
<tr>
<td>Drive it</td>
<td price_search="$23,123.13">Car</td>
</tr>
<tr>
<td>Drink it</td>
<td price_search="3.13">Beet Juice</td>
</tr>
<tr>
<td>Eat it</td>
<td price_search="12.13">Can of expensive corn</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="35">Radish</td>
</tr>
<tr>
<td>Use it</td>
<td price_search="1.45">Paper towel</td>
</tr>
<tr>
<td>Plain</td>
<td price_search="$1.87">Butter</td>
</tr>
<tr>
<td>Herb</td>
<td price_search="$2.45">Butter</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="15">Gum</td>
</tr>
</table>

jQuery selecting direct "parents", not similar

I got a fixed structure of a table like this one:
<table>
<tr><td class="lvl-0">1</td><tr>
<tr><td class="lvl-1">2</td><tr>
<tr><td class="lvl-2">3</td><tr>
<tr><td class="lvl-2">4</td><tr>
<tr><td class="lvl-2">5</td><tr>
<tr><td class="lvl-1">6</td><tr>
<tr><td class="lvl-2">7</td><tr>
<tr><td class="lvl-2 selected">8</td><tr>
<tr><td class="lvl-2">9</td><tr>
</table>
I want to select every lvl parent.
That means I want to select every lvl previously from the selected. Except similar. That means in this example it would be 6 and 1
I tried it with this:
var ss = [];
for(var l = lvl; l <= 5; l++){
ss.push('td.lvl-'+l);
}
var ul = jQuery('table').find(ss.join(',')).closest('tr');
var pa = jQuery('.selected').closest('tr').prevAll('tr').not(ul);
But it also select number 2
// EDIT
I have a jsfiddle
http://jsfiddle.net/g7yhwojg/3/ selected should be:
14
13
10
1
I got it on my own.
var lvls = [];
pa = pa.filter(function(){
var pc = jQuery(this).find('td').attr('class');
if(lvls.indexOf(pc) == -1){
console.log(pc);
lvls.push(pc);
return true;
}
return false;
});
http://jsfiddle.net/g7yhwojg/11/
I looped through all the upper elemnts and took everytime only the first.
While you've already posted your own answer, I thought I'd offer an alternative, in case you're interested:
// caching the selected element (selecting by its id):
var selected = $('#selected'),
// caching the regular expression, in case it might be
// be needed again later; this matches a serious of
// one or more (+) numbers (\d) at the end of the
// string ($):
levelRegex = /\d+$/,
// finding the numbers at the end of the selected
// element's class attribute, and using parseInt()
// to convert that to a number in base-10:
selectedLevel = parseInt(selected.attr('class').match(levelRegex), 10),
// caching the selected element's closest ancestor
// <tr> element:
selectedParent = selected.closest('tr'),
// caching the <tr> elements before the selectedParent:
rowsBefore = selectedParent.prevAll(),
// using map() to iterate over those elements and
// if their child <td> element has a class equal to
// 'lvl-' + (selectedLevel - 1)
// we first decrement selectedLevel, and then
// return the text of the current <tr> element;
// decrementing here means we can only ever
// retrieve the first instance of an element
// with a 'lower' level:
pseudoParents = rowsBefore.map(function (i) {
if ($(this).find('td').hasClass('lvl-' + (selectedLevel - 1))) {
--selectedLevel;
return this.textContent;
}
// converting the 'map' into a native Array:
}).get();
console.log(pseudoParents);
// ["14", "13", "10", "1"]
var selected = $('#selected'),
levelRegex = /\d+$/,
selectedLevel = parseInt(selected.attr('class').match(levelRegex), 10),
selectedParent = selected.closest('tr'),
rowsBefore = selectedParent.prevAll(),
pseudoParents = rowsBefore.map(function(i) {
if ($(this).find('td').hasClass('lvl-' + (selectedLevel - 1))) {
--selectedLevel;
return this.textContent.trim();
}
}).get();
// snippet logs to the bottom of the result panel:
snippet.log(pseudoParents);
// logs to the console (obviously):
console.log(pseudoParents);
// ["14", "13", "10", "1"]
.lvl-0 {
padding-left: 10px;
}
.lvl-1 {
padding-left: 30px;
}
.lvl-2 {
padding-left: 50px;
}
.lvl-3 {
padding-left: 70px;
}
.lvl-4 {
padding-left: 90px;
}
.lvl-5 {
padding-left: 110px;
}
body {
color: #ffffff;
background: #000000;
}
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td class="lvl-0">1</td>
</tr>
<tr>
<td class="lvl-1">2</td>
</tr>
<tr>
<td class="lvl-2">3</td>
</tr>
<tr>
<td class="lvl-2">4</td>
</tr>
<tr>
<td class="lvl-2">5</td>
</tr>
<tr>
<td class="lvl-1">6</td>
</tr>
<tr>
<td class="lvl-2">7</td>
</tr>
<tr>
<td class="lvl-2">8</td>
</tr>
<tr>
<td class="lvl-2">9</td>
</tr>
<tr>
<td class="lvl-1">10</td>
</tr>
<tr>
<td class="lvl-2">11</td>
</tr>
<tr>
<td class="lvl-2">12</td>
</tr>
<tr>
<td class="lvl-2">13</td>
</tr>
<tr>
<td class="lvl-3">14</td>
</tr>
<tr>
<td class="lvl-4">15</td>
</tr>
<tr>
<td class="lvl-4" id="selected">16</td>
</tr>
<tr>
<td class="lvl-3">17</td>
</tr>
<tr>
<td class="lvl-1">18</td>
</tr>
<tr>
<td class="lvl-2">19</td>
</tr>
<tr>
<td class="lvl-2">20</td>
</tr>
<tr>
<td class="lvl-2">21</td>
</tr>
</table>
External JS Fiddle demo, for experimentation and development.
Note that in both the Stack Snippet, and the JS Fiddle, I've corrected the HTML to close the <tr> elements, otherwise the erroneous <tr> tags at the end of each line of the <table> was creating a new, empty, <tr> for no reason.
References:
JavaScript:
JavaScript Regular Expressions Guide (MDN).
Node.textContent.
parseInt().
String.prototype.match().
String.prototype.trim().
jQuery:
attr().
closest().
get().
map().
prevAll().

Infinite scroll on table with merged cells (defined colspan/rowspan)

How can I implement the infinite scroll on a table with the merged cells?
I want to implement pivot grid with lots of data to be processed. The difficulty is drawing only visible parts of headers (+ scrolling buffer).
Possible solutions:
Without smooth scrolling, discretely, redraw all table header. (I would like smoothness)
Implement the div-table and organize creating and deleting items on scroll event. (Could not find an example of a dynamic div-table with the merged cells)
Implement the table header from the sequence of tables, that created and removed as necessary. (delete borders, share labels between the nearby tables)
Example:
var xHeaderWrapperEl = document.querySelector(".header-wrapper");
var xHeaderTableEl = document.querySelector(".header-table");
xHeaderWrapperEl.addEventListener("scroll", function () {
if (xHeaderWrapperEl.scrollLeft >= xHeaderTableEl.offsetWidth - xHeaderWrapperEl.offsetWidth){
console.log("scroll next page");
} else if (xHeaderWrapperEl.scrollLeft <= 0) {
console.log("scroll prev page");
} else {
console.log("scroll");
}
});
.header-wrapper {
overflow-x: scroll;
width: 250px;
height: auto;
display: flex;
//flex-flow: row nowrap;
}
<body>
<div class="header-wrapper">
<!-- 1st block -->
<table class="header-table" border="1">
<tr>
<td colspan="10"><div>0x1</div></td>
</tr>
<tr>
<td colspan="2"><div>1x1</div></td>
<td colspan="8" rowspan="2"><div>1x2</div></td>
</tr>
<tr>
<td colspan="2"><div>2x1</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
<!-- 2nd block -->
<table class="header-table" border="1">
<tr>
<td colspan="4"><div>0x1</div></td>
<td colspan="6"><div>0x2</div></td>
</tr>
<tr>
<td colspan="4" rowspan="2"><div>1x1</div></td>
<td colspan="6"><div>1x2</div></td>
</tr>
<tr>
<td colspan="6"><div>2x1</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
<!-- 3rd block -->
<table class="header-table" border="1">
<tr>
<td colspan="2"><div>0x1</div></td>
<td colspan="6"><div>0x2</div></td>
<td colspan="2"><div>0x3</div></td>
</tr>
<tr>
<td colspan="2"><div>1x1</div></td>
<td colspan="2"><div>1x2</div></td>
<td colspan="2"><div>1x3</div></td>
<td colspan="2"><div>1x4</div></td>
<td colspan="2"><div>1x5</div></td>
</tr>
<tr>
<td colspan="2"><div>2x1</div></td>
<td colspan="2"><div>2x2</div></td>
<td colspan="2"><div>2x3</div></td>
<td colspan="2"><div>2x4</div></td>
<td colspan="2"><div>2x5</div></td>
</tr>
<tr>
<td><div>3x1</div></td>
<td><div>3x2</div></td>
<td><div>3x3</div></td>
<td><div>3x4</div></td>
<td><div>3x5</div></td>
<td><div>3x6</div></td>
<td><div>3x7</div></td>
<td><div>3x8</div></td>
<td><div>3x9</div></td>
<td><div>3x10</div></td>
</tr>
</table>
</div>
</body>
Take note flexbox...
I am assuming that you will have 1mln columns table according to your answer.
It is not realistic to have such a table continuously scrollable.
It will take forever to scroll/find/consume information from there.
Therefore you have to have some pagination / filtering mechanism there.
And with the pagination your problem is less severe. Split it in partial table blocks wrapped in scrollable page container. So you will have scrollable pages similar to gmail's message list - paginated yet scrollable.

how to merge 2 rows together WITH 2 rows in html table?

I am not so good in English, to express myself, so I show it with examples to you!
Here is my HTML table with code:
<table border="1">
<tr id="tr1_1">
<td rowspan="2">1</td>
<td>tr1.1 td2</td>
<td>tr1.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr1_2">
<td>tr1.2 td2</td>
<td>td1.2 td3</td>
</tr>
<tr id="tr2_1">
<td rowspan="2">2</td>
<td>tr2.1 td2</td>
<td>tr2.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr2_2">
<td>tr2.2 td2</td>
<td>td2.2 td3</td>
</tr>
</table>
(You can see the result here)
For example, if I click on the second two rows' "up" link, the result should be this:
<table border="1">
<tr id="tr2_1">
<td rowspan="2">2</td>
<td>tr2.1 td2</td>
<td>tr2.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr2_2">
<td>tr2.2 td2</td>
<td>td2.2 td3</td>
</tr>
<tr id="tr1_1">
<td rowspan="2">1</td>
<td>tr1.1 td2</td>
<td>tr1.1 td3</td>
<td rowspan="2">
up/
down
</td>
</tr>
<tr id="tr1_2">
<td>tr1.2 td2</td>
<td>td1.2 td3</td>
</tr>
</table>
(You can see the final result here)
So how could I do this? I know the prev() and before() methods in javascript, but it merge only 1 row with 1 row, but I want to merge 2 rows WITH 2 rows!
I hope, someone can help me! Thank you!
Try this jQuery code :
$('.up').click(function() {
tr = $('tr[id^="'+$(this).closest('tr').attr('id').slice(0, 3)+'"]')
tr.insertBefore(tr.eq(0).prev().prev())
return false;
})
$('.down').click(function() {
tr = $('tr[id^="'+$(this).closest('tr').attr('id').slice(0, 3)+'"]')
tr.insertAfter(tr.eq(1).next().next())
return false;
})
And have a look to your fiddle edited : http://jsfiddle.net/lulu3030/UQz8u/6/
Just some explanations :
closest('tr') method find the nearest parent which has a tr tag
slice(0, 3) get the first 3 characters of a string
=> variable tr selects all elements which has the same 3 first id characters
insertBefore and insertAfter methods allows to move selected elements
Could be done like that too:
DEMO
$(function () {
$('.up, .down').on('click', function () {
var $tr = $(this).closest('tr'),
$flag = $('<tr/>').insertBefore($tr),
$rows = $tr.add($tr.next('tr')).detach()
methods = $(this).is('.up') ? ['insertBefore', 'prevAll'] : ['insertAfter', 'nextAll'];
if ($flag[methods[1]]('tr').eq(1).length) {
$rows[methods[0]]($flag[methods[1]]('tr').eq(1));
$flag.remove();
} else $flag.replaceWith($rows);
});
});

Manipulating <td>'s within different <tr>'s

I'm wondering if the following can be done.
I have a list of 'expenses' that I'm displaying in a table. 4 columns - amount, date, where, and what.
I was thinking I'd like to make each clickable via jQuery which would expand that particular expense, inline, to show a more detailed description.
What I'm trying to do is, on click, replace the contents of the 'tr' with a single 'td' that would contain the extended info. Problem is that 'td' only expands to about a quarter of the table. Is there any way of making it extend to the whole row, while maintaining the widths of the other 'td's in the other rows?
Here's what I would do. Working Demo.
<table id="expenses">
<thead>
<tr>
<td>Amount</td>
<td>Date</td>
<td>Where</td>
<td>What</td>
</tr>
</thead>
<tbody>
<tr class='expense' id='expense-1'>
<td>$5.99</td>
<td>4/2/2009</td>
<td>Taco Bell</td>
<td>Chalupa</td>
</tr>
<tr class='details' id='details-1'>
<td colspan='4'>
It was yummy and delicious
</td>
</tr>
<tr class='expense' id='expense-2'>
<td>$4.99</td>
<td>4/3/2009</td>
<td>Burger King</td>
<td>Whopper</td>
</tr>
<tr class='details' id='details-2'>
<td colspan='4'>
The king of burgers, indeed!
</td>
</tr>
<tr class='expense' id='expense-3'>
<td>$25.99</td>
<td>4/6/2009</td>
<td>Olive Garden</td>
<td>Chicken Alfredo</td>
</tr>
<tr class='details' id='details-3'>
<td colspan='4'>
I love me some italian food!
</td>
</tr>
</tbody>
</table>
With styles like these:
#expenses tr.expense {
cursor: pointer;
}
#expenses tr.details {
display: none;
}
And then have Javascript that looks like this:
$(function() {
$('tr.expense', '#expenses').click(function() {
var id = $(this).attr('id').split('-').pop();
var details = $('#details-'+id);
if(details.is(':visible')) {
details.hide();
} else {
details.show();
}
});
});
That should do it.
<td colspan="4"> ?

Categories

Resources