Export multiple html tables to PDF using jQuery tableHTMLExport plugin - javascript

I have multiple tables in my page and I want to export them into one pdf file.
I have tried this jQuery tableHTMLExport plugin https://www.jqueryscript.net/table/export-table-json-csv-txt-pdf.html. I have modified it but did not work well. It prints all the tables data except the heading for each table.
html file
<div id='print'>
<table>
<thead>
<tr>
<th>Career History</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td> <p> Job Title</p></td>
<td> <p> Company Name</p></td>
<td> <p> Start Date</p></td>
<td> <p> End Date</p></td>
</tr>
<?php foreach ($history as $h) { ?>
<tr>
<td>
<?php echo $h ['job_title']; ?>
</td>
<td>
<?php echo $h ['comapny_name']; ?>
</td>
<td>
<?php echo $h ['start_day']; ?>
</td>
<td>
<?php echo $h['end_day']; ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<table class="table" id="3">
<thead>
<tr>
<th>Documents</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>one</td>
<td>two</td>
<td>three</td>
<td>four</td>
</tr>
</tbody>
</table>
</div>
<input type='button' value='export pdf' id='save'/>
<script>
$("#save").click(function () {
$("#print").tableHTMLExport({
type: 'pdf',
filename: 'test.pdf' });
});
in the tableHTMLExport.js file I have add nested loop
function toJson(el) {
var i, j;
var jsonHeaderArray = [];
for (i = 0; i < 4; i++) {
$(el).find('thead').find('tr').not(options.ignoreRows).each(function () {
var tdData = "";
var jsonArrayTd = [];
$(this).find('th').not(options.ignoreColumns).each(function (index, data) {
if ($(this).css('display') !== 'none') {
jsonArrayTd.push(parseString($(this)));
}
});
jsonHeaderArray.push(jsonArrayTd);
});
for (j = 0; j < 4; j++) {
var jsonArray = [];
$(el).find('tbody').find('tr').not(options.ignoreRows).each(function () {
var tdData = "";
var jsonArrayTd = [];
$(this).find('td').not(options.ignoreColumns).each(function (index, data) {
if ($(this).css('display') !== 'none') {
jsonArrayTd.push(parseString($(this)));
}
});
jsonArray.push(jsonArrayTd);
});
}
return {header: jsonHeaderArray[i], data: jsonArray};
}
}

I have used available javaScript for exporting multiple tables and edited as my needs, you can attach this method to an input button
function generate() {
var doc = new jsPDF('p', 'pt');
var res1,res0;
var title = document.getElementById('title').value;
// first table
res0 = doc.autoTableHtmlToJson(document.getElementById('0'));
//get the columns & rows for first table
doc.autoTable(res0.columns, res0.data, {margin: {top: 80}});
// second table
res1 = doc.autoTableHtmlToJson(document.getElementById('1'));
// header for pdf file
var header = function (data) {
doc.setFontSize(18);
doc.setTextColor(40);
doc.setFontStyle('normal');
doc.text(title + " Profile", data.settings.margin.left, 50);
};
// setting up new option for the second table
var options = {
beforePageContent: header,
margin: {
top: 80
},
startY: doc.autoTableEndPosY() + 20
};
// add columns & rows for the second table
doc.autoTable(res1.columns, res1.data, options);
// save pdf file with the following name
doc.save("table.pdf");
}
if you have other solutions please share it.

Related

Merge rows with same value of first column only in html table

I have a dynamic html table, in which I want the rows in the first column only to be merged together if the values are same.Image of table. In the first column, the first two row values are same, so they should be merged but the row values of third column should not be merged.
<table id="example1" class="table table-bordered">
<thead>
<th class="hidden"></th>
<th>Area</th>
<th>Name</th>
<th>Party</th>
<th>Symbol</th>
<th>Total Number of Votes</th>
</thead>
<tbody>
<?php
$query="SELECT * FROM `candidates` ";
$result=mysqli_query($con,$query);
while($row = mysqli_fetch_array($result)){
$sql1 = "SELECT `Name`,`Symbol` FROM `party` WHERE `Party_ID` = '".$row["Party_ID"]."' " ;
$query1 = $con->query($sql1);
$row1 = $query1->fetch_assoc();
$sql2 = "SELECT `Name` FROM `part` WHERE `Part_No` = '".$row["Part_No"]."' " ;
$query2 = $con->query($sql2);
$row2 = $query2->fetch_assoc();
$time1 = filemtime("../party/".$row['Symbol']);
echo "
<tr>
<td class='hidden'></td>
<td>".$row2['Name']."</td>
<td>".$row['Name']."</td>
<td>".$row1['Name']."</td>
<td><img src='../party/".$row1['Symbol']."?".$time1."' alt='".$row1['Symbol']."' role='button' width='30px' height='30px' onclick='window.open(this.src)'></td>
<td>".$row['Total_Votes']."</td>
</tr>
";
}
?>
</tbody>
</table>
Ok, have a look at this as an example:
function mergeCells() {
let db = document.getElementById("databody");
let dbRows = db.rows;
let lastValue = "";
let lastCounter = 1;
let lastRow = 0;
for (let i = 0; i < dbRows.length; i++) {
let thisValue = dbRows[i].cells[0].innerHTML;
if (thisValue == lastValue) {
lastCounter++;
dbRows[lastRow].cells[0].rowSpan = lastCounter;
dbRows[i].cells[0].style.display = "none";
} else {
dbRows[i].cells[0].style.display = "table-cell";
lastValue = thisValue;
lastCounter = 1;
lastRow = i;
}
}
}
window.onload = mergeCells;
table {border-collapse: collapse;}
td {border:1px solid black; vertical-align: top;}
<table id="datatable">
<tbody id="databody">
<tr><td>1</td><td>Text item 1</td></tr>
<tr><td>1</td><td>Text item 10</td></tr>
<tr><td>2</td><td>Text item 3</td></tr>
<tr><td>2</td><td>Text item 9</td></tr>
<tr><td>3</td><td>Text item 7</td></tr>
<tr><td>4</td><td>Text item 6</td></tr>
<tr><td>5</td><td>Text item 2</td></tr>
<tr><td>5</td><td>Text item 4</td></tr>
<tr><td>5</td><td>Text item 5</td></tr>
<tr><td>5</td><td>Text item 8</td></tr>
</tbody>
</table>
I've just added enough to show how the functionality could work.

calculation of two input field into third input field having multiple table rows in jquery

I am doing calculation in the third input field based on the value filled in the two input field. And here I have multiple row. Each row calculation should be done separately so i am using each function. But the calculation is not working.
I am new in Jquery so where code is getting wrong??
<table>
<tr>
<th><?= __('Quantity Offered')?></th>
<th><?= __('Offer Price')?></th>
<th><?= __('Total Offer Price')?></th>
</tr>
<tr class="productNRow">
<td><?php echo $this->Form->input("supplier_offer_products.0.qty_offered",['id'=>'qtyOffered']);?></td>
<td><?php echo $this->Form->input("supplier_offer_products.0.offer_price",['id'=>'priceOffered']);?></td>
</tr>
<tr class="productNRow">
<td><?php echo $this->Form->input("supplier_offer_products.1.qty_offered",['id'=>'qtyOffered']);?></td>
<td><?php echo $this->Form->input("supplier_offer_products.1.offer_price",['id'=>'priceOffered']);?></td>
</tr>
</table>
<script>
$(document).ready(function(){
$(".productNRow").each(function(){
var sentRec = $(this);
var total;
$(this).find("#qtyOffered").on('change', function () {
var qty = $(sentRec).find("#qtyOffered").val();
var offer = $(sentRec).find("#priceOffered").val();
var total = qty * offer;
$('#totalOrder').val(total);
});
});
});
You cannot have multiple IDs. Use classes and add the missing #totalOrder elements.
The jQuery and PHP than could look like this:
jQuery(function( $ ) {
$(".productNRow").each(function() {
var $row = $(this);
var $qty = $row.find(".qtyOffered"); // use classes! (see PHP too)
var $prc = $row.find(".priceOffered");
var $tot = $row.find(".totalOrder");
$qty.on('input', function() {
var qty = $(this).val();
var offer = $prc.val();
var total = qty * offer;
$tot.val(total);
});
});
});
<table>
<tr>
<th>Quantity Offered</th>
<th>Offer Price</th>
<th>Total Offer Price</th>
</tr>
<tr class="productNRow">
<td>
<?php echo $this->Form->input("supplier_offer_products.0.qty_offered",['class'=>'qtyOffered']);?>
</td>
<td>
<?php echo $this->Form->input("supplier_offer_products.0.offer_price",['class'=>'priceOffered']);?>
</td>
<td>
<input class="totalOrder">
</td>
</tr>
<tr class="productNRow">
<td>
<?php echo $this->Form->input("supplier_offer_products.1.qty_offered",['class'=>'qtyOffered']);?>
</td>
<td>
<?php echo $this->Form->input("supplier_offer_products.1.offer_price",['class'=>'priceOffered']);?>
</td>
<td>
<input class="totalOrder">
</td>
</tr>
</table>
or going the other way around (input→parent→inputs) without using the .each() method
jQuery(function( $ ) {
$(".qtyOffered").on('input', function() {
var $row = $(this).closest(".productNRow");
var $prc = $row.find(".priceOffered");
var $tot = $row.find(".totalOrder");
var qty = $(this).val();
var offer = $prc.val();
var total = qty * offer;
$tot.val(total);
});
});

JQuery tablesorting code not working (no plugin)

I'm displaying a table with AJAX in my website. I wrote a JQuery code for sorting my table when it's send via AJAX and a <th>-tag is clicked. (I don't want to use a plugin. No, really, I don't want to use a plugin!)
This is my code:
PHP (index.php):
<form action="query.php" method="get">
<input type="search" name="query" autofocus="true" autocomplete="off" list="products">
<datalist id="products">
<?php
$sql = "SELECT * FROM products;";
$result = mysqli_query($con, $sql);
while ($product = mysqli_fetch_array($result)) {
echo "<option value=\"" . $product["productname"] . "\">" . $product["price"] . " $</option>";
}
?>
</datalist>
<button type="submit">Search</button>
</form>
<div class="result" align="center"></div>
PHP (query.php):
<?php
include_once "connection.php";
$query = trim($_GET["query"]);
$query = mysqli_real_escape_string($con, $query);
$sql = "SELECT * FROM products WHERE productname LIKE '%$query%' ORDER BY productname;";
$result = mysqli_query($con, $sql);
$result_no = mysqli_num_rows($result);
if ($result_no > 0) {
echo "<table>";
echo "<thead>";
echo "<tr>";
echo "<th>Product</th>";
echo "<th>Price</th>";
echo "<th>Quantity</th>";
echo "</tr>";
echo "</thead>";
echo "<tbody>";
while ($product = mysqli_fetch_array($result)) {
echo "<tr class=\"table\"><td align=\"left\">" . $product["productname"] . "</td><td align=\"right\">" . $product["price"] . " $</td><td align=\"right\">" . $product["quantity"] . "</td></tr>";
}
echo "</tbody>";
echo "<tfoot>";
if ($result_no == 1) {
echo "<tr><td colspan=\"3\" align=\"center\">" . $result_no . " product found." . "</td></tr>";
} else {
echo "<tr><td colspan=\"3\" align=\"center\">" . $result_no . " product found." . "</td></tr>";
}
echo "</tfoot>";
echo "</table>";
} elseif ($result_no <= 0) {
echo "<p>No products found.</p>";
}
mysqli_close($con);
?>
JQuery:
$(document).ready(function() {
$("form").on("submit", function(event) {
event.preventDefault();
var form = $(this);
$.ajax({
type: this.method,
url: this.action,
data: form.serialize(),
cache: false,
success: function(data) {
$("div.result").html(data);
$("th").on("click", function() {
var column = $(this).index();
var tbody = $("tbody");
var rows = tbody.find("tr");
var dir = $(this).data("dir") || -1;
dir *= -1;
rows.sort(function(a, b) {
var aVal = $($(a).find("td")[column]).text().toLowerCase();
var bVal = $($(b).find("td")[column]).text().toLowerCase();
return aVal > bVal ? 1 * dir : aVal < bVal ? -1 * dir : 0;
});
$(this).data("dir", dir);
tbody.empty();
$(rows).appendTo(tbody);
});
}
});
});
});
The connection.php is for connecting to my database. I use MySQL and PHPMyAdmin. My tables are 'users' for login data and 'products' for the shop products.
My Problem: The first line of the table is alway sorted at the wrong place.
Use the built in javascript sort function.
I extracted the relevant sort code from your example
I grabbed a sample table from w3cschools
I modified the js to store the sorted direction in the header cell.
I implemented a compare function (see linked sort documentation).
I replaced the tbody when the sort was complete.
EDIT: changed out HTML, added functionality to function to enable numeric sorting and not just alphabetically. Note the number class and the new if in the sort function
$("th").on("click", function() {
var column = $(this).index();
var numeric = $(this).hasClass("number"); //this class has been sprinkled to identify numeric sort.
var bdy = $(this).closest("table").find("tbody");
var rows = bdy.find("tr");
var dir = $(this).data("dir") || -1; //default direction is desc
dir *= -1; //reverse the stored direction
rows.sort(function(a, b) {
var aVal = $($(a).find("td")[column]).text().toLowerCase(); //get the text from one row
var bVal = $($(b).find("td")[column]).text().toLowerCase(); //get the text from row 2
if (numeric) { //added to handle numeric columns
aVal = parseFloat(aVal);
bVal = parseFloat(bVal);
}
return aVal > bVal ? 1 * dir : aVal < bVal ? -1 * dir : 0; // note the dir value to change direction
}); //sort the rows by the column content
bdy.empty(); //empty the body
$(rows).appendTo(bdy); //put the rows back
$(this).data("dir", dir); //log the direction
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
<thead>
<tr class="table">
<th class="table">Product</th>
<th class="table number">Price</th>
<th class="table number">Quantity</th>
</tr>
</thead>
<tbody>
<tr class="table">
<td align="left" class="table">Chainsaw</td>
<td align="right" class="table">60.00 $</td>
<td align="right" class="table">1</td>
</tr>
<tr class="table">
<td align="left" class="table">Hammer</td>
<td align="right" class="table">24.99 $</td>
<td align="right" class="table">2</td>
</tr>
<tr class="table">
<td align="left" class="table">Nails (25 per Box)</td>
<td align="right" class="table">9.99 $</td>
<td align="right" class="table">21</td>
</tr>
<tr class="table">
<td align="left" class="table">Screwdriver</td>
<td align="right" class="table">29.99 $</td>
<td align="right" class="table">2</td>
</tr>
<tr class="table">
<td align="left" class="table">Screws (25 per Box)</td>
<td align="right" class="table">15.00 $</td>
<td align="right" class="table">26</td>
</tr>
</tbody>
<tfoot>
<tr class="table">
<td colspan="3" align="center" class="table">5 products found.</td>
</tr>
</tfoot>
</table>
#FelixRewer, please include a sample rendered table, your question was updated with your PHP. I believe that the PHP is not your problem but the HTML that comes out the other end.
Yes, maybe you're right. So here's a code snippet with the output of query.php and the JQuery tablesorter (I also added my styles, I don't think it's relevant, but if yes, here it is.):
$("th").on("click", function() {
var column = $(this).index();
var table = $("table");
var tbody = table.find("tbody");
var rows = tbody.find("tr");
var dir = $(this).data("dir") || -1;
dir *= -1;
rows.sort(function(a, b) {
var aVal = $($(a).find("td")[column]).text().toLowerCase().trim();
var bVal = $($(b).find("td")[column]).text().toLowerCase().trim();
return aVal > bVal ? 1 * dir : aVal < bVal ? -1 * dir : 0;
});
$(this).data("dir", dir);
tbody.empty();
$(rows).appendTo(table);
});
.table {
margin: 3vmax;
border: 1px solid #000000;
border-collapse: collapse;
color: #000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table">
<thead>
<tr class="table">
<th class="table">Product</th>
<th class="table">Price</th>
<th class="table">Quantity</th>
</tr>
</thead>
<tbody>
<tr class="table">
<td align="left" class="table">Chainsaw</td>
<td align="right" class="table">60.00 $</td>
<td align="right" class="table">1</td>
</tr>
<tr class="table">
<td align="left" class="table">Hammer</td>
<td align="right" class="table">24.99 $</td>
<td align="right" class="table">2</td>
</tr>
<tr class="table">
<td align="left" class="table">Nails (25 per Box)</td>
<td align="right" class="table">9.99 $</td>
<td align="right" class="table">21</td>
</tr>
<tr class="table">
<td align="left" class="table">Screwdriver</td>
<td align="right" class="table">29.99 $</td>
<td align="right" class="table">2</td>
</tr>
<tr class="table">
<td align="left" class="table">Screws (25 per Box)</td>
<td align="right" class="table">15.00 $</td>
<td align="right" class="table">26</td>
</tr>
</tbody>
<tfoot>
<tr class="table">
<td colspan="3" align="center" class="table">5 products found.</td>
</tr>
</tfoot>
</table>
And yes I have the same problem here. I've tested a lot with my code and I think maybe the first line gets sorted at the wrong place, because of the <tfoot>, but that's just an assumption.
This topic is closed. Here's the code I was looking for:
JavaScript: https://jsfiddle.net/tf4e97w6/#&togetherjs=TGIj8qdzUO
jQuery: https://jsfiddle.net/15ke8Lqv/#&togetherjs=DACQV5mE9F
Code snippet:
$(document).ready(function() {
$("th").on("click", function() {
var column = $(this).index();
var table = $("table");
var tbody = table.find("tbody");
var rows = tbody.find("tr");
var dir = $(this).data("dir") || -1;
dir *= -1;
$(this).siblings().data("dir", -1);
rows.sort(function(a, b) {
var aVal = $($(a).find("td")[column]).html().toLowerCase().trim();
var bVal = $($(b).find("td")[column]).html().toLowerCase().trim();
if ($.isNumeric(aVal.charAt()) && $.isNumeric(bVal.charAt())) {
aVal = parseFloat(aVal);
bVal = parseFloat(bVal);
}
return aVal > bVal ? 1 * dir : aVal < bVal ? -1 * dir : 0;
});
$(this).data("dir", dir);
tbody.empty();
$(rows).appendTo(table);
});
});
h1 {
color: #cc1100;
}
table {
width: 100%;
}
table,
tr,
td {
border: 1px solid #000000;
border-collapse: collapse;
}
tfoot,
thead {
text-align: center;
background-color: #cccccc;
}
th:hover {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<caption>
<h1>Tablesorter</h1>
</caption>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$150</td>
</tr>
<tr>
<td>February</td>
<td>$160</td>
</tr>
<tr>
<td>March</td>
<td>$240</td>
</tr>
<tr>
<td>April</td>
<td>$160</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Sum: $710</td>
</tr>
</tfoot>
</table>
With kind regards,
Felix Rewer.

HTML Table to JSON file via AJAX

Is there any possibility to convert an HTML table to JSON with PHP?
I have this JavaScript:
<script>
(function() {
var jsonArr = [];
var obj = {};
var rowIx = 0;
var jsonObj = {};
var thNum = document.getElementsByTagName('th').length;
var arrLength = document.getElementsByTagName('td').length;
for(i = 0; i < arrLength; i++){
if(i%thNum === 0){
obj = {};
}
var head = document.getElementsByTagName('th')[i%thNum].innerHTML;
var content = document.getElementsByTagName('td')[i].innerHTML;
obj[head] = content;
if(i%thNum === 0){
jsonObj[++rowIx] = obj
}
}
var result = "<br>"+JSON.stringify({"Values": jsonObj});
document.write(result);
})();
</script>
which uses the below HTML code:
<TABLE border="3" rules="all" bgcolor="#E7E7E7" cellpadding="1" cellspacing="1">
<TR>
<TH align=center><font size="3" face="Arial">Date</font></TH>
<TH align=center><font size="3" face="Arial"><B>Teacher</B></font></TH>
<TH align=center><font size="3" face="Arial">?</font></TH>
<TH align=center><font size="3" face="Arial">Hour</font></TH>
<TH align=center><font size="3" face="Arial">Subject</font></TH>
<TH align=center><font size="3" face="Arial">Class</font></TH>
<TH align=center><font size="3" face="Arial">Room</font></TH>
<TH align=center><font size="3" face="Arial">(Teacher)</font></TH>
<TH align=center><font size="3" face="Arial">(Room)</font></TH>
<TH align=center><font size="3" face="Arial">XYY</font></TH>
<TH align=center><font size="3" face="Arial"><B>Information</B></font></TH>
<TH align=center><font size="3" face="Arial">(Le.) nach</font></TH>
</TR>
<TR><TD align=center><font size="3" face="Arial">24.9.</font></TD>
<TD align=center><font size="3" face="Arial"><B><strike>Dohe</strike></B></font></TD>
<TD align=center><font size="3" face="Arial">Free</font></TD>
<TD align=center><font size="3" face="Arial">1</font></TD>
<TD align=center><font size="3" face="Arial"><strike>Math</strike></font> </TD>
<TD align=center><font size="3" face="Arial">(9)</font> </TD>
<TD align=center><font size="3" face="Arial">---</font> </TD>
<TD align=center><font size="3" face="Arial"><strike>Dohe</strike></font></TD>
<TD align=center><font size="3" face="Arial">A001</font></TD>
<TD align=center> </TD>
<TD align=center> </TD>
<TD align=center><font size="3" face="Arial">Free.</font></TD>
</TR>
</TABLE>
to generate this JSON code:
{"Values":{"1":{"Date":"24.9.","Teacher":"Dohe","?":"Free","Hour":"1","Subject":"Math ","Class":"(9) ","Room":"--- ","(Teacher)":"Dohe","(Room)":"A001","XYY":" ","Information":" ","(Le.) nach":"Free."},"2":{"Date":"26.9.","Teacher":"John","?":"Free","Hour":"8","Subject":"Bio ","Class":"(9) ","Room":"--- ","(Teacher)":"John","(Room)":"A021","XYY":" ","Information":" ","(Le.) nach":"Free."}}}
The script is perfect but I need a script, which saves the JSON data to a file on the server automatically, without any user interaction.
If you say your JS logic is perfect, here is a PHP (ver 5.3+) conversion that uses DOM like your code.
This function loads a html file (you may use curl if it is an url) then convert it and save to a file.
function save_table_to_json ( $in_file, $out_file ) {
$html = file_get_contents( $in_file );
file_put_contents( $out_file, convert_table_to_json( $html ) );
}
function convert_table_to_json ( $html ) {
$document = new DOMDocument();
$document->loadHTML( $html );
$obj = [];
$jsonObj = [];
$th = $document->getElementsByTagName('th');
$td = $document->getElementsByTagName('td');
$thNum = $th->length;
$arrLength = $td->length;
$rowIx = 0;
for ( $i = 0 ; $i < $arrLength ; $i++){
$head = $th->item( $i%$thNum )->textContent;
$content = $td->item( $i )->textContent;
$obj[ $head ] = $content;
if( ($i+1) % $thNum === 0){ // New row. Slightly modified to keep it correct.
$jsonObj[++$rowIx] = $obj;
$obj = [];
}
}
return json_encode([ "Values" => $jsonObj ]);
}
// Example
save_table_to_json( 'table.html', 'data.json' );
Personally, I like using JQuery, yet if you don't know or can't insert it as a SRC, then we should assume to use JavaScript. So we will post the JSON data to our PHP via AJAX when the page is done loading. The PHP will then write this JSON into a new file on the server called subs.json and will be overwritten each time the script runs.
We will start with the JavaScript:
<script>
function collectData() {
var jsonArr = [];
var obj = {};
var rowIx = 0;
var jsonObj = {};
var thNum = document.getElementsByTagName('th').length;
var arrLength = document.getElementsByTagName('td').length;
for(i = 0; i < arrLength; i++){
if(i%thNum === 0){
obj = {};
}
var head = document.getElementsByTagName('th')[i%thNum].innerHTML;
var content = document.getElementsByTagName('td')[i].innerHTML;
obj[head] = content;
if(i%thNum === 0){
jsonObj[++rowIx] = obj;
}
}
return jsonObj;
}
function postJSONData(json){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/subPost.php");
xmlhttp.setRequestHeader("Content-Type", "application/application/x-www-form-urlencoded");
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var return_data = xmlhttp.responseText;
alert(return_data);
}
}
xmlhttp.send("values="+JSON.stringify(json));
}
postJSONData(collectData());
</script>
At this point, the page should post your JSON to a PHP page called subPost.php located at the same level as the page that is executing this JS. This PHP Will look like:
<?php
if(isset($_POST['values'])){
$values = $_POST['values'];
$fp = fopen('subs.json', 'w');
fwrite($fp, $values);
fclose($fp);
echo "Values written to subs.json.\r\n";
} else {
echo "No Post data received.";
}
?>
I made a working example you can see here: http://www.yrmailfrom.me/projects/testPost/ and the content of http://www.yrmailfrom.me/projects/testPost/subs.json is:
{"1":{"<font face=\"Arial\" size=\"3\">Date</font>":"<font face=\"Arial\" size=\"3\">24.9.</font>","<font face=\"Arial\" size=\"3\"><b>Teacher</b></font>":"<font face=\"Arial\" size=\"3\"><b><strike>Dohe</strike></b></font>","<font face=\"Arial\" size=\"3\">?</font>":"<font face=\"Arial\" size=\"3\">Free</font>","<font face=\"Arial\" size=\"3\">Hour</font>":"<font face=\"Arial\" size=\"3\">1</font>","<font face=\"Arial\" size=\"3\">Subject</font>":"<font face=\"Arial\" size=\"3\"><strike>Math</strike></font> ","<font face=\"Arial\" size=\"3\">Class</font>":"<font face=\"Arial\" size=\"3\">(9)</font> ","<font face=\"Arial\" size=\"3\">Room</font>":"<font face=\"Arial\" size=\"3\">---</font> ","<font face=\"Arial\" size=\"3\">(Teacher)</font>":"<font face=\"Arial\" size=\"3\"><strike>Dohe</strike></font>","<font face=\"Arial\" size=\"3\">(Room)</font>":"<font face=\"Arial\" size=\"3\">A001</font>","<font face=\"Arial\" size=\"3\">XYY</font>":"
This is not valid JSON. It seems that some data is being misunderstood. I suspect that this is due to characters in the values, like . I see this in the posted data:
"<font face=\"Arial\" size=\"3\">XYY</font>":"
[nbsp;","<font_face] => \"Arial\" size=\"3\">(Le.) nach</font>":"<font face=\"Arial\" size=\"3\"
>Free.</font>"}}
I was able to overcome this with another small JS function:
function nbsp2space(str) {
return String(str).replace(/ /g, ' ');
}
Then use this function in collectData() like so:
obj[head] = nbsp2space(content);
Now when the page executes, we post the data to the PHP and it's written to the file subs.json.
You can try some thing like this:
HTML
<table>
<tr>
<th>No</th>
<th>Name</th>
<th>Email</th>
</tr>
<tr>
<td>1</td>
<td>Test</td>
<td>test#example.com</td>
</tr>
<tr>
<td>2</td>
<td>Test 2</td>
<td>test2#example.com</td>
</tr>
<tr>
<td>3</td>
<td>Test 3</td>
<td>test3#example.com</td>
</tr>
</table>
Javascript
<script type="text/javascript">
jQuery(document).ready(function(){
data = new Array();
columns = [];
var row = new Array();
$('table tr').each(function(index,tr){
var index = index;
if(index == 0){ // First we get column names from th.
$(tr).find('th').each(function(thIndex,thValue){
columns.push($(thValue).text());
});
} else {
$(tr).find('td').each(function(tdIndex,tdValue){
row[tdIndex] = $(tdValue).text(); // Put each td value in row
});
data.push(row); // now push each row in data.
row = new Array(); // reset row after push
}
});
// Send it to PHP for further work:
$.post('json.php', { data: data, columns: columns }, function(response){
// TODO with response
});
})
</script>
json.php
$data = $_POST['data']; // Each rows values
$columns = $_POST['columns']; // Columns names
for($i = 0; $i < count($data); $i++) {
$json[] = array(($i+1) => array_combine($columns, $data[$i]));
}
$json = json_encode($json);
// TODO with $json eg: file_put_contents();
the output you will get after json_encode() is:
{"values":[{"1":{"No":"1","Name":"Test","Email":"test#example.com"}},{"2":{"No":"2","Name":"Test 2","Email":"test2#example.com"}},{"3":{"No":"3","Name":"Test 3","Email":"test3#example.com"}}]}
Note jQuery must be included before running this.

Pure Javascript: onClick executes toggle rows -- need image swap

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>

Categories