Button function does not work when in subpage - javascript

I have a function where i can download my table data into csv. But the button function only works when i place it in my index.html page, while my table's on the subpage.html page. But somehow, my button in the index page is able to download my table data in that subpage.html when i navigate to there.
Index.html : The button here works
<body>
<header ng-include="'views/header.html'"></header>
<main ng-view></main>
<button type="button" id="btnDownload"> Download as CSV</button>
</body>
Subpage.html : If i place the button here it doesn't work
<div>
<table id="tabletodownload" ng-show="auditoriums === 'none'" style="border:1px solid #000;">
<tr> <th> Customer Name </th> <th> Order Value </th> <th> Ordered On </th> </tr>
<tr ng-repeat="audit in auditoriums| limitTo: 1 - auditoriums.length">
<td>{{audit.NAME}}</td>
<td>{{audit.ADDRESSBLOCKHOUSENUMBER}}</td>
<td>{{audit.ADDRESSPOSTALCODE}}</td>
<td>{{audit.ADDRESSSTREETNAME}}</td>
</tr>
</table>
<br />
</div>
<button type="button" id="btnDownload"> Download as CSV</button>
Javascript code to DL to csv :
$(function() {
$('#btnDownload').click(function() {
$("#tabletodownload").tableToCSV({
filename: 'CustomerList'
});
});
});
jQuery.fn.tableToCSV = function (options) {
var settings = $.extend({
filename: ""
}, options);
var clean_text = function (text) {
text = $.trim(text.replace(/"/g, '""'));
return '"' + text + '"';
};
$(this).each(function () {
var table = $(this);
var caption = settings.filename;
var title = [];
var rows = [];
$(this).find('tr').each(function () {
var data = [];
$(this).find('th').each(function () {
var text = clean_text($(this).text());
title.push(text);
});
$(this).find('td').each(function () {
var text = clean_text($(this).text());
data.push(text);
});
data = data.join(",");
rows.push(data);
});
title = title.join(",");
rows = rows.join("\n");
var csv = title + rows;
var uri = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv);
var download_link = document.createElement('a');
download_link.href = uri;
var ts = new Date().getTime();
if (caption == "") {
download_link.download = ts + ".csv";
} else {
download_link.download = caption + "-" + ts + ".csv";
}
document.body.appendChild(download_link);
download_link.click();
document.body.removeChild(download_link);
});
};

If the index.html and subpage.html are 2 different pages (and not an angularjs template or something like that) then it's probably because the code that is handling the button click and the rest of your function doesn't exist in the subpage.html.
quick and dirty
I assume you're not using any build tools. The simplest way is to move the button function to a script tag inside subpage.html
the angularjs way
I see you're using angularjs in the project. Manually attaching evenlisterens like a button click isn't the angularjs way of doing thing. You could easily move the functionality to your angular controller that control's that page and add a ng-click attribute to the button that calls that function. This way you're letting the framework decide when and hpw to attach the click event listener instead of managing that yourself.
Btw...
Using a framework like angular/react/vue most of the times makes jQuery unnecessary. In this case you could also use a library that made for amgularjs to make a csv from a table. jQuery is very DOM way of thinking while angular is more of a DATA way of thinking. In my opinion is that why it's better to not mix these things.
This might help you:
https://github.com/kollavarsham/ng-table-to-csv

Related

How to get the value of an id and that it serves to delete an element from firebase realtime database?

It is the first time I use firebase and javascript, I am making a table where it shows me the data from a database in real time. For this, I'm pulling the data like this:
function getSonido() {
var firebase = "https://iotplatform-11dca-default-rtdb.firebaseio.com/users/awsBewgkSMcqiINzOoFUiUe9D6r1/data_widget/sensor/sonido.json";
var sensores = new EventSource(firebase);
sensores.addEventListener('put', function(e) {
var json = JSON.parse(e.data);
console.log(json);
if (json.path == "/") {
tbody = document.getElementById("tbody_sonido");
for (var key in json.data) {
var tr = document.createElement("tr");
var td_sensor = document.createElement("td");
var td_sonido = document.createElement("td");
var input_sonido = document.createElement("input");
var td_ruta = document.createElement("td");
var td_button = document.createElement("td");
input_sonido.type = "number";
input_sonido.id = key;
input_sonido.readOnly = true;
input_sonido.disabled = true;
td_sensor.innerHTML = json.data[key].name;
td_ruta.innerHTML = "/" + key + "/sonido";
td_button.innerHTML = '<button class="btn btn-danger delete" id="' + key + '" type="button">Borrar</button>';
td_sonido.appendChild(input_sonido);
tr.appendChild(td_sensor);
tr.appendChild(td_sonido);
tr.appendChild(td_ruta);
tr.appendChild(td_button);
tbody.appendChild(tr);
document.getElementById(key).value = json.data[key].sonido;
}
} else {
s = json.path.split("/");
console.log(s[1]);
console.log(json.data);
document.getElementById(s[1]).value = json.data;
}
});
};
<!DOCTYPE html>
<html lang="en">
<head>
<title>Widgets</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<script type="text/javascript" src="/static/js/get_sensores.js"></script>
</head>
<body>
<h1>Sound sensors</h1>
<table id="table_sonido" class="table table-striped">
<thead id="thead_sonido">
<tr>
<th>Name</th>
<th>Value</th>
<th>Route</th>
</tr>
</thead>
<tbody id="tbody_sonido">
<!-- One row will be added for each item in the json file -->
</tbody>
</table>
<script>
document.onload = getSonido();
</script>
</body>
</html>
Place a button on each item in the table that is added, all buttons have the same class but the ID value of each button will depend on the item saved in firebase, in console the button is displayed like this
I am trying to remove the element that I click to delete, for that I must get the value of the ID of the button, investigating found that I could use console.log(document.getElementsByClassName("delete")[0].id); but there I am specifying which button I want to get the value from, which is not correct.
Looking for I saw that some used the jQuery library but don't explain much the process.
While I found a solution to that first problem, I was working with the way to eliminate the element, in the documentation comes something like this curl -X DELETE \ 'https://[PROJECT_ID].firebaseio.com/locations.json' so try using something like this:
const request = new Request('https://iotplatform-11dca-default-rtdb.firebaseio.com/users/awsBewgkSMcqiINzOoFUiUe9D6r1/data_widget/sensor/sonido/0x459ece7.json', { method: 'DELETE'})
const response = await fetch(request)
return await response.json()
This would run with an onclick within a function but it also does nothing, try the same using the SDK, perform the configuration and use remove(), to remove but I also did not work and it marked me error or simply did not run.
I hope I have explained and I know that it is very extensive but I have already been several days and I have looked a lot for how to do this firebase even in videos but I just do not get the result I need and I have been trying everything for several days but I simply can not make it work.
I hope you can help me

Callback function on a url?

In my web app, I want to be able to click on a href link within a datatable that loads a second table on a new page, which in turn filters out rows so that the table only displays rows with the same id as the id of the row I clicked on in the previous table/page.
The code below does not work. I believe this is because before it has had time to save the row data from the first table, a new web page is already being opened and it is too late to save the data as it is no longer there. Is there a way to create a callback so that my javascript function is executed before the href link is opened?
Or maybe I am doing this completely wrong?
Any help would be appreciated.
Datatable.Column() code: (the user clicks on an image/url link within the table):
"data": "ErrorCount",
"render": function (data, type, row) {
if (type === 'display') {
return (data === 0)
? data = '<span data-search="0"></span>'
: data = '<a id="errors" href="http://localhost/WTM/LogError/Index" type="hidden" class="fas fa-exclamation-triangle" style="color:red"></a>';
}
return data;
},
Javascript filter function:
var clickError = document.getElementById("errors")
var xTable = $('#TABLE_ONE').DataTable();
var yTable = $('#TABLE_TWO').DataTable();
$('clickError').click(function () {
var rowData = xTable.row(this).data();
yTable.columns(0).search(rowData.TaskSchedulerLogUid).draw();
});
Multiple issues here:
ID's can't be repeated in a page, use class instead
$('clickError') is invalid selector
The elements in question are dynamically rendered and thus won't all exist when the code is run. Use event delegation
The row is not the <a>
Fixes:
HTML
'<a ̶i̶d̶=̶"̶e̶r̶r̶o̶r̶s̶"̶ class="errors"...
JS
$('#tableID').on('click', 'a.errors', function(e){
e.preventDefault();
var row = $(this).closest('tr')[0];
var rowData = xTable.row(row).data();
yTable.columns(0).search(rowData.TaskSchedulerLogUid).draw();
})
For anyone interested. I found a different way of doing this.
First I added the search query/row ID to the url of the new page I wanted to open like this:
'
then I extracted the search query/ID from the url, and searched the table on the new page using the newly extracted search query/ID, like this:
var queryString = window.location.search;
queryString = queryString.substring(4);
if (queryString == null) {
throw "Error: id is null"
} else {
WtmDetails.vars.secondaryTable.columns(0).search(queryString).draw();
}

How to get complete data from (html) bootstrap table when pagination is turned on

I am using bootstrap table in my web page and want to get complete textual data from all table cells, when pagination is on. I have tried the following method and it returns all the data:
var data = $('#' + tableID).bootstrapTable('getData')
Now when i traverse data object to get value for every cell it works fine but, for those cells which have some nested html , for example:
<td class="danger">cell 4</td>
<td>
google
</td>
Now, in this case, i want to get value for second cell as google but it returns me whole html as
google
Any idea, how i can get only textual value.
I can't do any server side operation, I have to achieve this using javascript/jquery. I have also tried using jquery:
function getColData(tableID,colIndex) {
var colArray = $('#' + tableID + ' td:nth-child'+'('+colIndex+')').map(function(){
return $(this).text();
}).get();
return colArray
}
it returns data correctly but only which is visible on active page and i want all the data.
Based on your file on JSFiddle I have modified the JS part as follows, this will get you the text on every td(i.e. text or text content) and not the values of their attributes. Basically this traverses through the DOM searching for tags embedded in ones - except for those on the table header - then obtains the text value.
var table = $('#table'), button = $('#button');
button.click(function() {
var data = [];
table.find('tr:not(:first)').each(function(i, row) {
var cols = [];
$(this).find('td').each(function(i, col) {
cols.push($(this).text());
});
data.push(cols);
});
alert(data);
});
You can see it in action here
UPDATE:
This will get you all data regardless of pagination, also it will strip tags and nested tags.
var table = $('#table'), button = $('#button');
button.click(function() {
var messedData = table.bootstrapTable('getData');
var data = [];
$.each(messedData, function(i, row) {
var rowData = {
'name': row['0'],
'star': row['1'],
'forks': row['2'],
'desc': row['3'],
}
for (prop in rowData) {
var tmp = document.createElement("div");
tmp.innerHTML = rowData[prop];
rowData[prop] = tmp.textContent || tmp.innerText || "";
}
data.push(rowData);
});
console.log(data);
});
You can see it here
Since the actual data is coming in as a string, I don't think bootstrap-table can't differentiate it from the other data. The simple solution I can think of is to use substring() to extract the data from the cells that contain custom html.
http://jsfiddle.net/vwg5Lefz/
The alternative is to go through the generated table <td> and use text() to get the text data from the cells.
http://jsfiddle.net/n0djy60v/

download file without using ajax

I am trying to follow this example to show progress bar without using ajax to download file.
I use knockout,html and webapi. I am having below code which calls href on click event of button
this.getMeData= function () {
uRlPath("/api/GetSomeData?id=" + 12)
+ "&name=" + getName.toString()
+ "&downloadtoken=" + new Date().getTime());
$('#myLink').click();
location.href = $('#myLink').attr('href');
};
This is my html
<tr>
<td class="labelText">
<button data-bind="click: getMeData">
Download Data
</button>
</td>
</tr>
<tr>
<td>
<a id="myLink" data-bind="attr: { href: uRlPath }" style="visibility: hidden">Open </a>
</td>
</tr>
I now want to call some function on click event of my href
This is my webapi method which returns me cookie and binary file
public HttpResponseMessage GetSomeData(int id, string name, string downloadtoken)
{
var returnData= new HttpResponseMessage(HttpStatusCode.OK);
returnData.Content = new ByteArrayContent(mybyteArray);
var cookie = new CookieHeaderValue("downloadtoken", downloadtoken);
returnData.Headers.AddCookies(new CookieHeaderValue[] { cookie });
returnData.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
returnData.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
returnData.Content.Headers.ContentDisposition.FileName = "myfile.pdf";
return returnData;
}
To be very precise i want to have same behaviour as provided in example. In example they use form to submit but i dont have any form as i just use html,knockout. I have included all libraries mentioned in example.
Do let me know if you need more inputs.
I found solution myself. I used below code to check constantly for cookie
var attempts = 30;
var checkTime
startProgressBar(true)
checkTime= window.setInterval(function () {
var cookieValue = $.cookie('downloadtoken');
if ((cookieValue == token) || (attempts == 0)){
stopDownload();
}
attempts --;
}, 1000);
In finishDownload function i clear cookie and stop progress bar
function stopDownload() {
window.clearInterval(checkTime);
$.cookie('downloadtoken', null); //clears this cookie value
stopProgressBar(false);
}
This is html code for progress bar
<div data-bind="visible: stopProgressBar" style="top:248px;left: 320px;">
<img src="../images/ProgressBar.jpg" />
</div>
If you just want to call the blockUIForDownload function when the link is clicked, you can do it with a "click" binding, just like you did for the button:
<a id="myLink" data-bind="attr: {href: uRlPath}, click: blockUIForDownload" style="visibility: hidden">Open</a>
(This assumes the function is already defined within the viewModel.)
See official documentation for the "click" binding here: http://knockoutjs.com/documentation/click-binding.html
However, it looks to me like you're overcomplicating it a bit - in the example you posted, a hidden input field is required because they're using a form input as a means to transfer the token to the server.
In your case the token is passed as a part of an href attribute, so you can greatly simplify the code:
1) Remove the invisible link completely
2) Replace the getMeData function with the following:
this.getMeData= function () {
window.open("/api/GetSomeData?id=" + 12
+ "&name=" + getName.toString()
+ "&downloadtoken=" + new Date().getTime());
blockUIForDownload();
};

Export html table to excel using javascript

I tried to export my html table to excel using the code given in this Gist. But after exporting, when i opened the file, It displays the html code of the demo page in excel. Can anyone please give the correct sample of javascript used to export the html table to excel (Should be opened in office Calc too).
EDIT: Attached the image screenshot.
Here is a function I made.
Add "remove" class on elements you do not want to show in the excel.
function exportExcel(id,name){ //<table> id and filename
var today = new Date();
var date = ('0'+today.getDate()).slice(-2)+"-"+('0'+(today.getMonth()+1)).slice(-2)+"-"+today.getFullYear();
var file_name = name+"_"+date+".xls"; //filename with current date, change if needed
var meta = '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
var html = $("#"+id).clone();
html.find('.remove').remove(); //add the 'remove' class on elements you do not want to show in the excel
html.find('a').each(function() { //remove links, leave text only
var txt = $(this).text();
$(this).after(txt).remove();
});
html.find('input, textarea').each(function() { //replace inputs for their respectives texts
var txt = $(this).val().replace(/\r\n|\r|\n/g,"<br>");
$(this).after(txt).remove();
});
html.find('select').each(function() { //replace selects for their selected option text
var txt = $(this).find('option:selected').text();
$(this).after(txt).remove();
});
html.find('br').attr('style', "mso-data-placement:same-cell"); //make line breaks show in single cell
html = "<table>"+html.html()+"</table>";
var uri = 'data:application/vnd.ms-excel,'+encodeURIComponent(meta+html);
var a = $("<a>", {href: uri, download: file_name});
$(a)[0].click();
}
Call it on an event, example:
$("#export_button").click(function(e){
exportExcel("table_id", "filename");
});

Categories