I have the following html:
<table id='myTable'>
<tbody>
<tr>
<td id=col1">12</td>
<td id=col2">55</td>
<td id=col3">142</td>
<td id=col4">7</td>
</tr>
</tbody>
</table>
I would like to use JQuery to append everything after column 3 (col3) to a new row. Ideally I would end up with something like this:
<table id='myTable'>
<tbody>
<tr>
<td id=col1">12</td>
<td id=col2">55</td>
<td id=col3">142</td>
</tr>
<tr>
<td id=col4">7</td>
</tr>
</tbody>
</table>
Any ideas how this could be achieved? I have tried a few things but haven't been able to get it working.
You could define a generic redistribution function, that takes as argument the desired number of columns, and which just fills up the rows with content from top to bottom, using that number of columns.
It could even be a jQuery plugin:
$.fn.redistribute = function(maxNumCols) {
if (maxNumCols < 1) return;
$(this).each(function () {
let cells = Array.from($("td", this));
let $tr = $("tr", this);
let rowCount = Math.ceil(cells.length / maxNumCols);
for (let i = 0; i < rowCount; i++) {
let $row = i >= $tr.length ? $("<tr>").appendTo(this) : $tr.eq(i);
$row.append(cells.splice(0, maxNumCols));
}
});
}
// I/O management
function alignTable() {
let cols = +$("input").val(); // Get desired number of columns
$("#myTable").redistribute(cols); // Apply to table
}
// Refresh whenever input changes
$("input").on("input", alignTable);
// Refresh on page load
alignTable();
table { border-collapse: collapse; border: 2px solid }
td { border: 1px solid; padding: 4px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Desired number of columns: <input type="number" size="3" value="4" min="1">
<table id='myTable'>
<tbody>
<tr>
<td>12</td>
<td>55</td>
<td>142</td>
<td>7</td>
<td>20</td>
<td>410</td>
<td>99</td>
</tr>
</tbody>
</table>
Here is a version with one extra statement that sets the colspan on the very last td element so it occupies the remaining columns in the last row:
$.fn.redistribute = function(maxNumCols) {
if (maxNumCols < 1) return;
$(this).each(function () {
let cells = Array.from($("td", this));
let $tr = $("tr", this);
let rowCount = Math.ceil(cells.length / maxNumCols);
for (let i = 0; i < rowCount; i++) {
let $row = i >= $tr.length ? $("<tr>").appendTo(this) : $tr.eq(i);
$row.append(cells.splice(0, maxNumCols));
}
$("td", this).last().attr("colspan", rowCount * maxNumCols - cells.length + 1);
});
}
// I/O management
function alignTable() {
let cols = +$("input").val(); // Get desired number of columns
$("#myTable").redistribute(cols); // Apply to table
}
// Refresh whenever input changes
$("input").on("input", alignTable);
// Refresh on page load
alignTable();
table { border-collapse: collapse; }
td { border: 1px solid; padding: 4px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Desired number of columns: <input type="number" size="3" value="4" min="1">
<table id='myTable'>
<tbody>
<tr>
<td>12</td>
<td>55</td>
<td>142</td>
<td>7</td>
<td>20</td>
<td>410</td>
<td>99</td>
</tr>
</tbody>
</table>
It sounds like you're still new to jQuery. To give you an idea how to solve your described problem, I have written a solution here. I hope it helps you.
// parameters for splitting
var splitIndex = 3,
splitClass = '.split-columns';
// start the splitting
splitColumnsIntoRows();
function splitColumnsIntoRows() {
var $tables = $(splitClass),
numberTables = $tables.length;
if (numberTables == 0) {
return;
}
for (var i = 0; i < numberTables; i++) {
iterateSplittingRows($($tables[i]).find('tr'));
}
}
function iterateSplittingRows($currentRows) {
var $currentRow,
numberRows = $currentRows.length;
if (numberRows == 0) {
return;
}
for (var i = 0; i < numberRows; i++) {
$currentRow = $($currentRows[i]);
iterateSplittingFields($currentRow, $currentRow.find('th, td'));
}
}
function iterateSplittingFields($currentRow, $currentFields) {
var $newRow,
newRows = [],
childrenLength,
numberFields = $currentFields.length;
if (numberFields == 0) {
return;
}
for (var i = 0; i < numberFields; i++) {
if (i < splitIndex) {
continue;
}
if (i % splitIndex == 0) {
$newRow = $('<tr></tr>');
}
$newRow.append($currentFields[i]);
if (i == numberFields - 1) {
childrenLength = $newRow.children().length;
// fill the row with empty fields if the length does not fit the splitIndex
for (var j = splitIndex; j > childrenLength; j--) {
$newRow.append($('<td></td>'));
}
}
if (
(i >= splitIndex && i % splitIndex == splitIndex - 1)
||
i == numberFields - 1
){
newRows.push($newRow);
}
}
$currentRow.after(newRows);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable" class="split-columns">
<tbody>
<tr>
<td class="col_01">01</td>
<td class="col_02">02</td>
<td class="col_03">03</td>
<td class="col_04">04</td>
<td class="col_05">05</td>
<td class="col_06">06</td>
<td class="col_07">07</td>
<td class="col_08">08</td>
<td class="col_09">09</td>
</tr>
<tr>
<td class="col_10">10</td>
<td class="col_11">11</td>
<td class="col_12">12</td>
<td class="col_13">13</td>
<td class="col_14">14</td>
<td class="col_15">15</td>
<td class="col_16">16</td>
<td class="col_17">17</td>
</tr>
<tr>
<td class="col_19">19</td>
<td class="col_20">20</td>
<td class="col_21">21</td>
<td class="col_22">22</td>
<td class="col_23">23</td>
<td class="col_24">24</td>
<td class="col_25">25</td>
</tr>
</tbody>
</table>
Related
I have mockup like this
The HTML table to work with
The table above will calculate subtotal and total_harga using the entered value in jumlah. Calculations work fine, but my code is still using static JavaScript.
If there are a lot of rows in the table, it will be troublesome, if you have to write the getElementById code for all the inputs. How to use looping so that all the inputs can be handled without describing the table rows one by one. This is my HTML and JavaScript.
<div class="container">
<table class="tg" id="sales">
<thead>
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0lax">1</td>
<td class="tg-0lax">MIE INSTAN</td>
<td class="tg-keyup"> <input type="text" id="input1" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan1">5000</td>
<td class="tg-0lax" id="diskon_satuan1">500</td>
<td class="tg-0lax" id="sub_total1"></td>
</tr>
<tr>
<td class="tg-0lax">2</td>
<td class="tg-0lax">SUSU UHT</td>
<td class="tg-keyup"><input type="text" id="input2" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan2">6000</td>
<td class="tg-0lax" id="diskon_satuan2">1000</td>
<td class="tg-0lax" id="sub_total2"></td>
</tr>
<tr>
<td class="tg-0lax">3</td>
<td class="tg-0lax">KERIPIK</td>
<td class="tg-keyup"> <input type="text" id="input3" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan3">8000</td>
<td class="tg-0lax" id="diskon_satuan3">500</td>
<td class="tg-0lax" id="sub_total3"></td>
</tr>
<tr>
<td class="tg-0lax"></td>
<td class="tg-1lax" colspan="4">TOTAL HARGA</td>
<td class="tg-0lax" id="total_price"></td>
</tr>
</tbody>
</table>
this is my code javascript :
function CalculationPrice() {
let input1 = document.getElementById("input1").value;
let input2 = document.getElementById("input2").value;
let input3 = document.getElementById("input3").value;
let hargaSatuan1 = document.getElementById("harga_satuan1").innerText;
let hargaSatuan2 = document.getElementById("harga_satuan2").innerText;
let hargaSatuan3 = document.getElementById("harga_satuan3").innerText;
let diskonSatuan1 = document.getElementById("diskon_satuan1").innerText;
let diskonSatuan2 = document.getElementById("diskon_satuan2").innerText;
let diskonSatuan3 = document.getElementById("diskon_satuan3").innerText;
if(input1.length == 0){
let total1 = document.getElementById("sub_total1").innerHTML = 0;
}else if(input1.length > 0){
let subinput = (parseInt(hargaSatuan1) - parseInt(diskonSatuan1)) * parseInt(input1)
let total1 = document.getElementById("sub_total1").innerHTML = subinput;
}
if(input2.length == 0){
let total2 = document.getElementById("sub_total2").innerHTML = 0;
}
else if(input2.length > 0){
let subinput2 = (parseInt(hargaSatuan2) - parseInt(diskonSatuan2)) * parseInt(input2)
let total2 = document.getElementById("sub_total2").innerHTML = subinput2;
}
if(input3.length == 0){
let total3 = document.getElementById("sub_total3").innerHTML = 0;
}
else if(input3 !== null){
let subinput3 = (parseInt(hargaSatuan3) - parseInt(diskonSatuan3)) * parseInt(input3)
let total3 = document.getElementById("sub_total3").innerHTML = subinput3;
}
let total1 = document.getElementById("sub_total1").innerText
let total2 = document.getElementById("sub_total2").innerText
let total3 = document.getElementById("sub_total3").innerText
let total_price = parseInt(total1) + parseInt(total2) + parseInt(total3)
let totalPriceHtml = document.getElementById("total_price").innerHTML = formatRupiah(total_price, "Rp.");
}
function formatRupiah(angka, prefix) {
let number_string = angka.toString().replace(/[^,\d]/g, ""),
split = number_string.split(","),
sisa = split[0].length % 3,
rupiah = split[0].substr(0, sisa),
ribuan = split[0].substr(sisa).match(/\d{3}/gi);
if (ribuan) {
separator = sisa ? "." : "";
rupiah += separator + ribuan.join(".");
}
rupiah = split[1] != undefined ? rupiah + "," + split[1] : rupiah;
return prefix == undefined ? rupiah : rupiah ? "Rp. " + rupiah : "";
}
Using ids on a table makes a lot of unnecessary work, it's much easier to rely on the structure of a static table. And, instead of inline event handlers, we can benefit from event delegation. Here's an example of how to listen input event on tbody and a simple reduce loop to calculate the total sum of subtotals.
const tbody = document.querySelector('#sales'),
rows = Array.from(tbody.rows), // All the rows of the tbody
total = rows.pop().cells[2]; // The TOTAL HARGA cell
function calcTot(e) {
const value = +e.target.value || 0,
rowIndex = e.target.closest('tr').rowIndex - 1, // Constant 1 = the amount of the rows in thead
cells = Array.from(rows[rowIndex].cells),
harga = +cells[3].textContent,
diskon = +cells[4].textContent,
sub = cells[5];
sub.textContent = harga - diskon * value;
total.textContent = rows.reduce((acc, row) => {
return acc += +row.cells[5].textContent;
}, 0);
}
// Calculate the first sums
rows.forEach(row => {
// Call calcTot with a fake event object
calcTot({target: row.cells[2]});
});
tbody.addEventListener('input', calcTot);
<div class="container">
<table class="tg">
<thead>
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</thead>
<tbody id="sales">
<tr>
<td class="tg-0lax">1</td>
<td class="tg-0lax">MIE INSTAN</td>
<td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">5000</td>
<td class="tg-0lax">500</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax">2</td>
<td class="tg-0lax">SUSU UHT</td>
<td class="tg-keyup"><input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">6000</td>
<td class="tg-0lax">1000</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax">3</td>
<td class="tg-0lax">KERIPIK</td>
<td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">8000</td>
<td class="tg-0lax">500</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax"></td>
<td class="tg-1lax" colspan="4">TOTAL HARGA</td>
<td class="tg-0lax"></td>
</tr>
</tbody>
</table>
</div>
Notice also, that I've moved the sales id from the table tag to the tbody tag, and how the event handler function is used to calculate the subtotal and total sums without an actual event by passing an object which contains the needed information of the event object.
First, you should have the data source (in an array of objects). Such as:
var dataSource = [
{ id: 1, item: "MIE INSTAN", HargaSatuan: 5000, DiskonSatuan: 500 },
{ id: 2, item: "SUSU UHT", HargaSatuan: 6000, DiskonSatuan: 1000 },
{ id: 3, item: "KERIPIK", HargaSatuan: 8000, DiskonSatuan: 500 },
]
Then, you can loop through this array to construct your table, using either JQuery or JavaScript's "insertRow()".
Reference link for JavaScript's insertRow()
<html>
<head>
<style>
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid black
}
</style>
</head>
<body>
<table id="myTable">
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</table>
<br>
<script>
function myFunction() {
var dataSource = [{
id: 1,
item: "MIE INSTAN",
hargaSatuan: 5000,
diskonSatuan: 500
},
{
id: 2,
item: "SUSU UHT",
hargaSatuan: 6000,
diskonSatuan: 1000
},
{
id: 3,
item: "KERIPIK",
hargaSatuan: 8000,
diskonSatuan: 500
},
]
var table = document.getElementById("myTable");
dataSource.forEach(function(data, index) {
var row = table.insertRow(index + 1);
var noCell = row.insertCell(0);
var itemCell = row.insertCell(1);
var jumlahCell = row.insertCell(2);
var hargaSatuanCell = row.insertCell(3);
var diskonSatuanCell = row.insertCell(4);
var subTotalCell = row.insertCell(5);
noCell.innerHTML = data.id;
itemCell.innerHTML = data.item;
hargaSatuanCell.innerHTML = data.hargaSatuan;
diskonSatuanCell.innerHTML = data.diskonSatuan
})
}
myFunction()
</script>
</body>
</html>
You only need to modify the datasource and refresh the table if there are any new data.
This might not be the best method of doing this, but this will give you a basic understanding on the algorithm and steps required for your needs.
Can you help me with this problem? I can't use return x value for my other function. I want when I click on some element, then script load ID of clicked element and then change color of element with this ID.
Is there some better solution for my problem? (in pure JS, not in Jquery)
Thanks.
<p id="1">foo</p>
<p id="2">bar</p>
<p id="3">baz</p>
<script>
document.addEventListener('click', function(e) {
x=e.target.id;
return x
});
document.getElementById(x).onclick =
function(x) {
if (document.getElementById(x).style.backgroundColor !== 'yellow') {
document.getElementById(x).style.backgroundColor = 'yellow';
}
else {
document.getElementById(x).style.backgroundColor = 'red';
}
};
</script>
Change your code to below.
<p id="1">foo</p>
<p id="2">bar</p>
<p id="3">baz</p>
document.addEventListener('click', function(e) {
x=e.target.id;
function() {
var bgColor = document.getElementById(x).style.backgroundColor;
if (bgColor !== 'yellow') {
bgColor = 'yellow';
}
else {
bgColor = 'red';
}
}
});
</script>
Ok i find solution on my problem.
The solution was put all my script in one function and than evrything work.
I learning JS about 1 mount and now I have made one simple LIGHTS OFF game.
Now I nedd some function that check all cells color and alert end of game, but i cant answer a new question because by question is not voted well, and i dont know why.
Here is the example of my code:
document.addEventListener('click', function(e) {
var x = e.target.id
var up = ((Math.floor(x.charAt(0))-1).toString()).concat(x.charAt(1));
var down = ((Math.floor(x.charAt(0))+1).toString()).concat(x.charAt(1));
var left = (x.charAt(0)).concat((Math.floor(x.charAt(1))-1).toString());
var right = (x.charAt(0)).concat((Math.floor(x.charAt(1))+1).toString());
if( document.getElementById(x).style.backgroundColor == ''){document.getElementById(x).style.backgroundColor = 'black';}
else{document.getElementById(x).style.backgroundColor ='';}
if(document.getElementById(up)!=null){
if( document.getElementById(up).style.backgroundColor == ''){document.getElementById(up).style.backgroundColor = 'black';}
else{document.getElementById(up).style.backgroundColor ='';}}
if(document.getElementById(down)!=null){
if( document.getElementById(down).style.backgroundColor == ''){document.getElementById(down).style.backgroundColor = 'black';}
else{document.getElementById(down).style.backgroundColor ='';}}
if(document.getElementById(left)!=null){
if( document.getElementById(left).style.backgroundColor == ''){document.getElementById(left).style.backgroundColor = 'black';}
else{document.getElementById(left).style.backgroundColor ='';}}
if(document.getElementById(right)!=null){
if( document.getElementById(right).style.backgroundColor == ''){document.getElementById(right).style.backgroundColor = 'black';}
else{document.getElementById(right).style.backgroundColor ='';}}
// var all = document.getElementsByTagName("TD");
// var i;
// for (i = 0; i < all.length; i++) {
// all[i].style.backgroundColor!=='yellow';
// alert('a')
// break}
})
td {
padding: 50px;
background-color: yellow;
<table>
<tr>
<td id='11'></td>
<td id='12'></td>
<td id='13'></td>
<td id='14'></td>
<td id='15'></td>
</tr>
<tr>
<td id='21'></td>
<td id='22'></td>
<td id='23'></td>
<td id='24'></td>
<td id='25'></td>
</tr>
<tr>
<td id='31'></td>
<td id='32'></td>
<td id='33'></td>
<td id='34'></td>
<td id='35'></td>
</tr>
<tr>
<td id='41'></td>
<td id='42'></td>
<td id='43'></td>
<td id='44'></td>
<td id='45'></td>
</tr>
<tr>
<td id='51'></td>
<td id='52'></td>
<td id='53'></td>
<td id='54'></td>
<td id='55'></td>
</tr>
</table>
Looking to replace all the "?" in the table below with the expected values.
Should I just add classes to the <th> that has a value in them and add them?
<table id="repair-invoice">
<tr>
<th>Item</th>
<th>Parts</th>
<th>Labor</th>
<th>Total</th>
</tr>
<tr>
<td>Automatic Transmission Replacement</td>
<td>$1,809.99</td>
<td>$830.00</td>
<td>?</td>
</tr>
<tr>
<td>Exhaust system replace</td>
<td>$279.99</td>
<td>$225.00</td>
<td>?</td>
</tr>
<tr>
<td>Replace air filter</td>
<td>$9.99</td>
<td>$0.00</td>
<td>?</td>
</tr>
<tr>
<td colspan="3">Total</td>
<td>?</td>
</tr>
</table>
You can iterate over the row/column combination and sum of the values like
var sum = 0;
$('#repair-invoice tr').slice(1, -1).each(function() {
var $tr = $(this),
total = 0;
$tr.find('td').slice(1, -1).each(function() {
total += +$(this).text().replace(/\$|,/g, '') || 0;
});
$tr.find('td:last-child').text(total);
sum += total;
});
$('#repair-invoice tr:last-child td:last-child').text(sum.toFixed(2)); //will have to format and display the value
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="repair-invoice">
<tr>
<th>Item</th>
<th>Parts</th>
<th>Labor</th>
<th>Total</th>
</tr>
<tr>
<td>Automatic Transmission Replacement</td>
<td>$1,809.99</td>
<td>$830.00</td>
<td>?</td>
</tr>
<tr>
<td>Exhaust system replace</td>
<td>$279.99</td>
<td>$225.00</td>
<td>?</td>
</tr>
<tr>
<td>Replace air filter</td>
<td>$9.99</td>
<td>$0.00</td>
<td>?</td>
</tr>
<tr>
<td colspan="3">Total</td>
<td>?</td>
</tr>
</table>
In case you want to follow D.R.Y :
function removeDollar(num) {
return num.substring(1, num.length);
}
function parseCurrency(num) {
return parseFloat(removeDollar(num).replace(/,/g, ''));
}
function addNumbers(num1, num2) {
return parseFloat(num1) + parseFloat(num2);
}
$(document).ready(function () {
var parts = [];
var labor = [];
for (var i = 0; i < 3; i++) {
parts[i] = $("#repair-invoice > tbody > tr:nth-child("+(2+i)+") > td:nth-child(2)").text();
labor[i] = $("#repair-invoice > tbody > tr:nth-child("+(2+i)+") > td:nth-child(3)").text();
$("#repair-invoice > tbody > tr:nth-child(" + (2 + i) + ") > td:nth-child(4)").html('$'+addNumbers(parseCurrency(parts[i]) , parseCurrency(labor[i])));
}
var Total = 0;
for (var i = 0; i <3; i++) {
var rowTotal = parseCurrency($("#repair-invoice > tbody > tr:nth-child(" + (2 + i) + ") > td:nth-child(4)").text());
Total = addNumbers(Total, rowTotal);
}
$("#repair-invoice > tbody > tr:nth-child(5) > td:nth-child(2)").html('$' + Total.toFixed(2));
});
It's part of the larger task. Why is the problem Nan and how to solve it? The table is added together elements from several pools <input> which elemenatymi table. All code is summed up in the table of size k / d.
Why is the problem Nan and how to solve it?
function licz(tableID){
var table = document.getElementById(tableID);
var k, d, s=0, temp;
var i = table.rows.length;
for(k=1; k<=i; k++){
for(d=0; d<2; d++){
temp = parseFloat(document.getElementById(tableID).rows[k].cells[d].innerHTML);
alert(temp);
s=s+temp;
}
document.getElementById(tableID).rows[k].cells[d].innerHTML = s;
}
}
<form name="roz" action="">
<table id="tyg" class="product_values" style="width: 20%" border=1>
<tr>
<td> Pon </td>
<td> Wt </td>
<td> Sum </td>
</tr><tr>
<td> <input type="number" name="inp_a" ></td>
<td> 4 </td>
<td></td>
</table>
</form>
<button onclick="licz('tyg')">go</button>
This is not right way for getting value from child elements you should do something like this :
JavaScript:
function licz(tableID){
var table = document.getElementById(tableID);
var k, d, temp;
var i = table.rows.length;
for (k = 1; k <= i; k++) {
for (d = 0; d < 2; d++) {
if (d == 0) {
temp = parseFloat(document.getElementById(tableID).rows[k].cells[d].childNodes[1].value);
}
if (d == 1) {
temp = temp + parseFloat(document.getElementById(tableID).rows[k].cells[d].innerHTML);
}
}
document.getElementById(tableID).rows[k].cells[d].innerHTML = temp;
document.getElementById('num').v
}
}
HTML:
<table id="tyg" class="product_values" style="width: 20%" border=1>
<tr>
<td> Pon </td>
<td> Wt </td>
<td> Sum </td>
</tr>
<tr>
<td> <input id = 'num' type="number" name="inp_a" ></td>
<td> 4 </td>
<td></td>
</tr>
</table>
well... it's a good question. You should read DOM for knowing more about this.
First post, long time looker. Stack Overflow ROCKS!
Need some help. I am primarily a Business Intelligence/Data Warehouse professional. I need to use a bit of Javascript to create a collapsing row report in a report writing tool where I cannot anticipate the ability to call JQuery (Internal LAN deployment). Therefore I need pure Javascript.
The premise is I need the report to open with rows only at the Manager/District level but have the ability to open the District clusters to see the assigned Sales Reps and their contribution.
I found code that does this (quite well actually by hiding the repeating District Manager's name) but it uses text objects ("+" and "--") to render the links behind the OnClick event. I really, really, really, really need to have it show alternating images.
I tried simply modifying these two sections but the code to render the image in the first block does not match the code for the second block, this causes the ternary operation to fail and the images to do not alternate as expected.
lnk.innerHTML =(lnk.innerHTML == "+")?"--":"+";
var link ='+';
The code below contains the working code with text for onClick action and below a simple onClick that switches the images. Essentially I need the Folder Icons to be in the first cell of the Manager/District grids. I forced the working collapse code into the main Javascript block just to save space.
Any help, insight, guidance, electric cattle prod shocks (ouch) would be appreciated.
Thanks in advance.
UPDATE: created a CodePen for this to make it easier to see what works right now:
http://codepen.io/anon/pen/yjLvh
Thanks!
<html>
<head>
<style type="text/css">
table { empty-cells: show; }
cell {font-family:'Calibri';font-size:11.0pt;color: #000000;}
TD{font-family: Calibri; font-size: 10.5pt;}
TH{font-family: Calibri; font-size: 10.5pt; }
</style>
</head>
<body>
<SCRIPT type=text/javascript>
var tbl;
var toggleimage=new Array("http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png","http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png")
function trim(str){
return str.replace(/^\s*|\s*$/g,"");
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function toggleSection(lnk){
var td = lnk.parentNode;
var table = getParent(td,'TABLE');
var len = table.rows.length;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;
var rowHead=table.rows[rowIndex].cells[1].innerHTML;
lnk.innerHTML =(lnk.innerHTML == "+")?"--":"+";
vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';
for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
table.rows[i].cells[1].style.visibility="hidden";
}
}
}
function toggleRows(){
tables =document.getElementsByTagName("table");
for(i =0; i<tables.length;i++){
if(tables[i].className.indexOf("expandable") != -1)
tbl =tables[i];
}
if(typeof tbl=='undefined'){
alert("Could not find a table of expandable class");
return;
}
//assume the first row is headings and the first column is empty
var len = tbl.rows.length;
var link ='+';
var rowHead = tbl.rows[1].cells[1].innerHTML;
for (j=1; j<len;j++){
//check the value in each row of column 2
var m = tbl.rows[j].cells[1].innerHTML;
if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
// tbl.rows[j].cells[0].style.textAlign="center";
tbl.rows[j].style.background = "#FFFFFF";
}
else
tbl.rows[j].style.display = "none";
}
}
var oldEvt = window.onload;
var preload_image_1=new Image()
var preload_image_2=new Image()
preload_image_1.src=toggleimage[0]
preload_image_2.src=toggleimage[1]
var i_image=0
function testloading() {
isloaded=true
}
function toggle() {
if (isloaded) {
document.togglepicture.src=toggleimage[i_image]
}
i_image++
if (i_image>1) {i_image=0}
}
window.onload = function() { if (oldEvt) oldEvt(); toggleRows(); testloading();}
</SCRIPT>
<TABLE class=expandable width="400px" border="1" cellspacing="0" frame="box" rules="all" >
<THEAD>
<TR>
<TH bgColor="#E6E4D4"> </TH>
<TH bgColor="#E6E4D4" align="left">Manager</TH>
<TH bgColor="#E6E4D4" align="left">Sales Rep</TH>
<TH bgColor="#E6E4D4" align="left">Amount </TH></TR>
</THEAD>
<TBODY>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD><i>Georgia District Reps</i></TD>
<TD>500000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Rex Smtih</TD>
<TD>350000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Alex Anderson</TD>
<TD>150000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD><i>Texas District Reps</i></TD>
<TD>630000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Bill Smith</TD>
<TD>410000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Simon Wilkes</TD>
<TD>220000</TD></TR>
</TBODY></font></TABLE>
<br>
<br>
<img name="togglepicture" src="http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png" border="0">
</body>
</html>
working demo
<html>
<head>
<style type="text/css">
table { empty-cells: show; }
cell {font-family:'Calibri';font-size:11.0pt;color: #000000;}
TD{font-family: Calibri; font-size: 10.5pt;}
TH{font-family: Calibri; font-size: 10.5pt; }
</style>
</head>
<body>
<SCRIPT type=text/javascript>
var tbl;
var toggleimage=new Array("http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png","http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png")
var closedImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_closed_folder.png\" border=\"0\" height=\"20\">";
var openImgHTML = "<img name=\"togglepicture\" src=\"http://www.iconlooker.com/user-content/uploads/wall/thumb/misc._icons_open_folder.png\" border=\"0\" height=\"20\">";
function trim(str){
return str.replace(/^\s*|\s*$/g,"");
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function toggleSection(lnk){
var td = lnk.parentNode;
var table = getParent(td,'TABLE');
var len = table.rows.length;
var tr = getParent(td, 'tr');
var rowIndex = tr.rowIndex;
var rowHead=table.rows[rowIndex].cells[1].innerHTML;
lnk.innerHTML =(lnk.innerHTML == openImgHTML)?closedImgHTML:openImgHTML;
vStyle =(tbl.rows[rowIndex+1].style.display=='none')?'':'none';
for(var i = rowIndex+1; i < len;i++){
if (table.rows[i].cells[1].innerHTML==rowHead){
table.rows[i].style.display= vStyle;
table.rows[i].cells[1].style.visibility="hidden";
}
}
}
function toggleRows(){
tables =document.getElementsByTagName("table");
for(i =0; i<tables.length;i++){
if(tables[i].className.indexOf("expandable") != -1)
tbl =tables[i];
}
if(typeof tbl=='undefined'){
alert("Could not find a table of expandable class");
return;
}
//assume the first row is headings and the first column is empty
var len = tbl.rows.length;
var link =''+closedImgHTML+'';
var rowHead = tbl.rows[1].cells[1].innerHTML;
for (j=1; j<len;j++){
//check the value in each row of column 2
var m = tbl.rows[j].cells[1].innerHTML;
if(m!=rowHead || j==1){
rowHead=m;
tbl.rows[j].cells[0].innerHTML = link;
// tbl.rows[j].cells[0].style.textAlign="center";
tbl.rows[j].style.background = "#FFFFFF";
}
else
tbl.rows[j].style.display = "none";
}
}
var oldEvt = window.onload;
var preload_image_1=new Image()
var preload_image_2=new Image()
preload_image_1.src=toggleimage[0]
preload_image_2.src=toggleimage[1]
var i_image=0
function testloading() {
isloaded=true
}
function toggle() {
if (isloaded) {
document.togglepicture.src=toggleimage[i_image]
}
i_image++
if (i_image>1) {i_image=0}
}
window.onload = function() { if (oldEvt) oldEvt(); toggleRows(); testloading();}
</SCRIPT>
<TABLE class=expandable width="400px" border="1" cellspacing="0" frame="box" rules="all" >
<THEAD>
<TR>
<TH bgColor="#E6E4D4"> </TH>
<TH bgColor="#E6E4D4" align="left">Manager</TH>
<TH bgColor="#E6E4D4" align="left">Sales Rep</TH>
<TH bgColor="#E6E4D4" align="left">Amount </TH></TR>
</THEAD>
<TBODY>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD><i>Georgia District Reps</i></TD>
<TD>500000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Rex Smtih</TD>
<TD>350000</TD></TR>
<TR>
<TD> </TD>
<TD>Sarah Jones</TD>
<TD>Alex Anderson</TD>
<TD>150000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD><i>Texas District Reps</i></TD>
<TD>630000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Bill Smith</TD>
<TD>410000</TD></TR>
<TR>
<TD> </TD>
<TD>William Hobby</TD>
<TD>Simon Wilkes</TD>
<TD>220000</TD></TR>
</TBODY></font></TABLE>
<br>
<br>
</body>
</html>