Executing code before and after downloading a file with Datatables (JS) - javascript

I am using Datatables to create some tables with data. I am using the option they have to include a download CSV button. However, since I am working with large amounts of data, I wanted to put a "Loading, please wait..." gif on the screen so users know it is downloading. However, the gif loading I have requires that I activate it before the downloading starts, and deactivate it after the downloading finishes (really it's just adding a class to the body which makes it a bit transparent and adds a wheel gif). I haven't found a way to run code before and after download. I think I can do before with action, but not after.
Can anyone help me out with this? Is there a way to do code before download and after download? Or, in absence of that, is there maybe a better way I can implement a waiting gif while it prepares the csv for download?

You can extend the csv-button and call the original action inside it. This enables you to show a custom loading-indicator while the export is being processed.
$(document).ready(function() {
let table = $('#example').DataTable({
processing: true,
dom: 'Bfrtip',
buttons: [{
extend: 'csv',
text: 'CSV Export',
action: function(e, dt, button, config) {
console.log('csv button clicked');
this.processing(true); // show indicator on button
console.log('before csv export');
config.filename = 'my-export'; // set filename
$.fn.dataTable.ext.buttons.csvHtml5.action.call(this, e, dt, button, config); // call export-action
console.log('after csv export');
this.processing(false); // hide indicator on button
}
}],
});
});
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/b-1.5.6/b-html5-1.5.6/datatables.min.css" />
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/b-1.5.6/b-html5-1.5.6/datatables.min.js"></script>
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test-1</td>
<td>Test 1234</td>
</tr>
<tr>
<td>Test-3</td>
<td>I dont know!</td>
</tr>
<tr>
<td>Test-2</td>
<td>Another...</td>
</tr>
<tr>
<td>Alpha-1</td>
<td>Apple Test</td>
</tr>
<tr>
<td>Alpha-2</td>
<td>Banana Test</td>
</tr>
<tr>
<td>Alpha-3</td>
<td>Coconut</td>
</tr>
<tr>
<td>Beta-1</td>
<td>Beta</td>
</tr>
<tr>
<td>Beta-2</td>
<td>Not Alpha</td>
</tr>
<tr>
<td>Alpha-1</td>
<td>Apple Test</td>
</tr>
<tr>
<td>Alpha-2</td>
<td>Banana Test</td>
</tr>
<tr>
<td>Alpha-3</td>
<td>Coconut</td>
</tr>
<tr>
<td>Beta-1</td>
<td>Beta</td>
</tr>
<tr>
<td>Beta-2</td>
<td>Not Alpha</td>
</tr>
</tbody>
</table>

Related

How to create excel with data from html pages?

I have an excel spreadsheet template. I need to create excel file from data in html/php page. That is, the data on the html page is scattered throughout the page, and I need to somehow collect all this data (through classes or ids) and place it in certain cells of the table.
I tried a lot of ready-made solutions, for example https://github.com/jmaister/excellentexport/tree/master/test
<html>
<head>
<script type="text/javascript" src="https://unpkg.com/xlsx#0.15.1/dist/xlsx.full.min.js"></script>
</head>
<body>
<table id="tbl_exporttable_to_xls" border="1">
<thead>
<th>Sr</th>
<th>Name</th>
<th>Location</th>
<th>Job Profile</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>
<p>Amit Sarna</p>
</td>
<td>Florida</td>
<td>Data Scientist</td>
</tr>
<tr>
<td>2</td>
<td>
<p>Sagar Gada</p>
</td>
<td>California</td>
<td>Sr FullStack Dev</td>
</tr>
<tr>
<td>3</td>
<td>
<p>Ricky Marck</p>
</td>
<td>Nevada</td>
<td>Sr .Net Dev</td>
</tr>
<tr>
<td>4</td>
<td>
<p>Andrea Ely</p>
</td>
<td>New York</td>
<td>Sr Delivery Mgr</td>
</tr>
<tr>
<td>5</td>
<td>
<p>Sunita Devgan</p>
</td>
<td>Colorado</td>
<td>UiUx Expert</td>
</tr>
</tbody>
</table>
<button onclick="ExportToExcel('xlsx')">Export table to excel</button>
<script>
function ExportToExcel(type, fn, dl) {
var elt = document.getElementById('tbl_exporttable_to_xls');
var wb = XLSX.utils.table_to_book(elt, { sheet: "sheet1" });
return dl ?
XLSX.write(wb, { bookType: type, bookSST: true, type: 'base64' }) :
XLSX.writeFile(wb, fn || ('MySheetName.' + (type || 'xlsx')));
}
</script>
</body>
</html>
Only import from html table is used everywhere.
Sorry for my English, so I'm attaching images for more details.
enter image description here
Tried options
https://codepedia.info/javascript-export-html-table-data-to-excel
https://github.com/jmaister/excellentexport/tree/master/test
https://www.webslesson.info/2021/07/how-to-display-excel-data-in-html-table.html
https://codepedia.info/javascript-export-html-table-data-to-excel
but everywhere there is an import only by html table

JQuery remove button from td cell?

I have table where user can click to unlock the record. I want to remove Unlock button and replace with the text. For example once they click unlock button will be removed and text will show up like 'Record is unlocked'. I'm not sure why my current code doesn't remove button. If anyone can help please let me know. Thank you.
$('.unlockBtn').on('click',unlockRecord);
function unlockRecord(){
var trID = $(this).parents("tr").prop('id');
if(confirm("Are you sure you want to unlock this record?")){
$.ajax({
type: 'POST',
url: 'Application.cfc?method=unlockRec',
data: {'recID':trID},
dataType: 'json'
}).done(function(obj){
var numRecs = obj.RECORDCOUNT;
if(obj.STATUS == 200){
$('#' + trID).closest('.unlockBtn').remove();
}else{
alert('Error')
}
}).fail(function(jqXHR, textStatus, errorThrown){
alert("Error: "+errorThrown);
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>User Name</th>
<th>Status</th>
<th>Date</th>
<th></th>
</tr>
</thead>
<tbody>
<tr id="11">
<td>Jack, Smith</td>
<td>Active</td>
<td>12/01/2017</td>
<td>01:16 PM</td>
<td class="unlockBtn" style="text-align: center;">
<input name="unlock" id="unlock" value="Unlock" type="button">
</td>
</tr>
</tbody>
</table>
Also do you want to remove the actual cell or just replace the contents? I would think what you want to do is first place your click event on the button and not the cell (e.g. $('.unlockBtn .unlock').on('click',unlockRecord); then when you want to replace the button with text, you'd remove the event listener and replace the cell contents
$('#' + trID)
.find('input[type="button"]')
.off()
.parent('.unlockBtn')
.html('Record is unlocked');
Finally (maybe this is just due to you posting an example, but just in case, if this is a table where the html row shown is duplicated a lot you'll want to change the button id to something that's unique per/row like you do with the table row to avoid conflict
Just add back your ajax call and you will be done.
$('.unlockBtn').on('click',unlockRecord);
function unlockRecord(){
var trID = $(this).parents("tr").prop('id');
if(confirm("Are you sure you want to unlock this record?")){
var cell = $(event.srcElement);
$( cell ).replaceWith( "<div>Record Unlocked</div>" );
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>User Name</th>
<th>Status</th>
<th>Date</th>
<th></th>
</tr>
</thead>
<tbody>
<tr id="11">
<td>Jack, Smith</td>
<td>Active</td>
<td>12/01/2017</td>
<td>01:16 PM</td>
<td class="unlockBtn" style="text-align: center;">
<input name="unlock" id="unlock" value="Unlock" type="button">
</td>
</tr>
</tbody>
</table>

find child table selector from parent table - jQuery

I have a table structure like this. Fairly simple one.
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
At runtime I am binding a new row to this table for a particular rowclick. This new row contains a new table.
Now on clicking the row again, I want to be able to remove the newly added row(the new table).
I am using bootstrap table.
Here is what I have tried so far.
$('#myTable').on('click-row.bs.table', function (e, row, $element) {
//if ($element.has('#newlyAddedTable').length) { ....// did not work
if ($('#myTable').has('#newlyAddedTable').length) { // this removes the table on any row click. Not what I intend to do
{
$("#newlyAddedTable").remove();
} else {
// some operation...
}
}
I want to be able to remove the newly added table on the row it was created.
Just more explanation based on the Answers below:
<tr> ----------> if i click this
<td>
<table id="newlyAddedTable"> ---------> this is added
</table>
</td>
</tr>
<tr> ----------> if i again click this or maybe any other row in the table
<td>
<table id="newlyAddedTable"> ---------> this is removed
</table>
</td>
</tr>
Update: from OP's comment below it sounds like the best way to implement the new table is to use a class selector and not an id selector. The code below has been updated accordingly. ***Where previously there was an id for newTable there is a class ---> #newTable ===> .newTable:
Just change:
$('#myTable').has('#newlyAddedTable').length
To:
$('.newlyAddedTable', $element).length //element === clicked row -- see demo
vvvvv DEMO vvvvv
$('#myTable').bootstrapTable().on('click-row.bs.table', function(e, row, $element) {
if( $('.newTable', $element).length ) {
$('.newTable', $element).remove();
} else {
$('td:first', $element)
.append( '<table class="newTable"><tr><td>NEW TABLE</td></tr></table>' );
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.7.0/bootstrap-table.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.7.0/bootstrap-table.min.css" rel="stylesheet"/>
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
Try replacing your remove code with this:
$(document).on("click", "#newlyAddedTable", function(){
$(this).remove();
});
The code above registers a click listener on the document. The second parameter filters those events for those with the target #newlyAddedTable. This way you don't have to register a new click handler every time you insert a row (as in #VimalanJayaGanesh's solution).
P.S. If you are adding HTML that looks like this:
<tr>
<td>
<table id="newlyAddedTable">
</table>
</td>
</tr>
Then you are probably actually wanting to remove the parent tr (not the table with the id). There are two ways to fix this.
You can change the selector that filters click events and so have the tr handle the click rather than the table element in my example code:
$(document).on("click", "tr:has(#newlyAddedTable)", function(){
You can leave the selector as is but grab the parent tr from the table and remove that changing the remove line above to:
$(this).parents("tr").first().remove()
or
$(this).parent().parent().remove()
As I don't have your complete code / fiddler, here is a possible solution.
Are you looking for something like this?
$('#add').on('click', function()
{
var newRow = '<tr CLASS="newrow"><td colspan="3"><table><tr><td>Test</td><td>User</td><td>test#example.com</td></table></td></tr>'
$('#myTableBody').append(newRow);
Remove()
});
function Remove()
{
$('.newrow').off('click').on('click', function()
{
$(this).remove();
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
<button type='button' id='add'>Add</button>
Note:
The following line indicates that,
$('.newrow').off('click').on('click', function()
the click event will be binded to the new row only once.
The reason for adding 'off('click') is, when you are dynamically adding rows (with common class 'newrow') to the table, the events will be binded several times. To avoid that, remove the previously binded click event and add a new one.

jQuery or JS transformation of dynamic HTML table

I need to find a TABLE within a DIV tag and perform modifications on the header. The available reporting tool does not allow to identify the generated table but allows script and DIV insertion.
Consider the table below where the header is the first line:
<div id="ScrollHeader">
<table>
<tr>
<td>Browser</td>
<td>Visits</td>
<td>Pages/Visit</td>
<td>Avg. Time on Site</td>
<td>% New Visits</td>
<td>Bounce Rate</td>
<td>Avg. Time on Site</td>
<td>% New Visits</td>
<td>Bounce Rate</td>
</tr>
<tr>
<td>Firefox first</td>
<td>1,990</td>
<td>3.11</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
</tr>
<tr>
<td>Firefox</td>
<td>1,990</td>
<td>3.11</td>
<td>00:04:22 test test test</td>
<td>70.00%</td>
<td>32.61%</td>
<td>00:04:22</td>
<td>70.00%</td>
<td>32.61%</td>
</tr>
</table>
</div>
I need a JavaScript or jQuery code to transform the table to the following:
<div id="ScrollHeader">
<table>
<thead>
<tr>
<th>Browser</th>
<th>Visits</th>
<th>Pages/Visit</th>
<th>Avg. Time on Site</th>
<th>% New Visits</th>
<th>Bounce Rate</th>
<th>Avg. Time on Site</th>
<th>% New Visits</th>
<th>Bounce Rate</th>
</tr>
</thead>
<tr>
<td>Firefox first</td>
<td class="numeric">1,990</td>
<td class="numeric">3.11</td>
<td class="numeric">00:04:22</td>
<td class="numeric">70.00%</td>
<td class="numeric">32.61%</td>
<td class="numeric">00:04:22</td>
<td class="numeric">70.00%</td>
<td class="numeric">32.61%</td>
</tr>
</table>
</div>
The code needs to identify the table within <div id="ScrollHeader">, insert THEAD before the first TR, change the TD to TH in the first line and close it with </thead>.
I have tried using $("div p[id^='ScrollHeader']").length to find the DIV and $("tr:first") to perform <table>.prepend(document.createElement('thead')); without success.
Try this:
$('#ScrollHeader table tr:eq(0)').wrap('<thead />');
$('#ScrollHeader table tr:eq(0) td').each(function () {
$('#ScrollHeader table tr:eq(0)').append($('<th />').html($(this).html()));
$(this).remove();
});
$('#ScrollHeader tr:first')
.wrap('<thead />')
.children().each(function(){
text = $(this).text();
$(this).replaceWith('<th>'+text+'</th>');
});
$('#ScrollHeader thead').insertBefore('#ScrollHeader tbody');
you can see it working here

jQuery slideUp bug?

I'm messing around with some jQuery stuff for a mockup and noticed some odd behavior. I'm hoping someone here can shed some light on it.
This is all mockup / test code, so please excuse the sloppyness.
So I have a table that I'm using in conjunction with the jQuery datatable plugin:
http://www.datatables.net/
My table markup is as follows:
<table id="dexterIndex">
<thead>
<tr>
<th>Name</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test 1</td>
<td>Yes</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 2</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 3</td>
<td>Yes</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 4</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 5</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 6</td>
<td>No</td>
<td>2009-2010</td>
<td>Fall 2010</td>
<td>Fall 2010</td>
</tr>
<tr>
<td>Test 7</td>
<td>Yes</td>
<td>2008-2009</td>
<td>Fall 2009</td>
<td>Fall 2009</td>
</tr>
</tbody>
</table>
Now, the functionality I'm going for is:
On hover change the row background color
If hovering for more than 'x' seconds slide down a sub-row for the row being hovered over.
Here is a screenshot of the effect working correctly (generally):
Upon leaving the row with one's mouse the sub-row slides back up.
This all works, but it seems that each time it slides back up it falls short by about a pixel. Here is an image after hovering/un-hovering 10 times. This is the table in the state after the sub-row slides up (meaning it's not just the sub-row showing with no text).
If I change slideUp/slideDown to fadeIn/fadeOut everything works fine and I don't get extra pixels. (I'll probably end up just using the fades, but i'm curious about this behavior).
This is what safari is reporting about the DOM in the bugged state (also, why can't I copy/paste in the Safari Web Inspector?):
And finally, here is some sloppy jQuery that handles the actual moving parts:
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('#dexterIndex').dataTable()
$('#dexterIndex tbody tr')
.hover(function() {
var table_row = this
table_row.hovering = true
window.setTimeout(function() {
if (table_row.hovering) {
$('.school-info').slideUp('fast', function() {
$(this).remove()
})
table_row.hovering = false
var tr = $('<tr />').attr({'class': 'school-info',})
$(table_row).after(tr)
$('<td />')
.attr({
'colspan': 5
})
.css({
'display': 'none'
})
.text("Sub Row")
.appendTo(tr)
.slideDown('fast')
}
}, 2000)
$(this).children().each(function() {
(this.oldColor === undefined)? this.oldColor = $(this).css('background-color'): null;
$(this).css({'background-color': '#f3ffc0'})
})
},
function() {
this.hovering = false
$('.school-info').slideUp('fast', function() {
$(this).remove()
})
$(this).children().each(function() {
$(this).css({'background-color': this.oldColor})
})
})
})
TL;DR: slideUp slides up one pixel less each time, fadeOut doesn't have any issues.
If anyone can shed some light on this issue it'd be greatly appreciated.
Couple of questions/ideas:
It seems this technique is being used for UI/richness, meaning that the sub-rows aren't calculated when the user hovers nor does it get created from an ajax call, etc. But you aren't hiding and unhiding the data, but instead creating it on hover and then removing it afterward. This is potentially very inaccessible and adds extra overhead to the browser-script.
So I'd suggest having the table load with the actual sub-rows and having your jquery hide them during load. You could simply add a class like "sub_row" to those tables.
Second, is this only happening in Safari? Is it happening in Firefox? Either way, I would guess you are losing a pixel from the browser adding a default border. I don't know why this would keep adding that border on each slideup, but I'm sure someone else here can spot that.
Lastly, I'm unfamiliar with your selector syntax. you are selecting your tds and trs as :
$('<tr />)
and
$(')
instead of:
$('tr')
and
$('td')
Any reason why?

Categories

Resources