download file without using ajax - javascript

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();
};

Related

Javascript export local storage

I have this piece of code on a site that exports the contents of local storage to a file in JSON format.
For some reason it stopped working. I tested it in multiple browsers but it's all the same...
No errors get displayed, yet it doesn't export either.
The different variables seem fine, yet it just isn't exporting.
To be honest I have no clue how to do this differently so any help would be appreciated.
Thx
function exportHistory() {
console.log("started");
var _myArray = JSON.stringify(localStorage , null, 4); //indentation in json format, human readable
var vLink = document.getElementById('exportHistory'),
var vBlob = new Blob([_myArray], {type: "octet/stream"}),
vName = 'working_history_' + todayDate() + '.json',
vUrl = window.URL.createObjectURL(vBlob);
console.log(vLink);
vLink.setAttribute('href', vUrl);
vLink.setAttribute('download', vName );
console.log("finished");
}
<button class="btn btn-outline-secondary btn-sm" id="exportHistory" onclick="exportHistory()">Export History</button >
Here you need to add the download attribute to an anchor tag <a> rather than the clicking button itself. You need to create an anchor tag with display:none and programmatically click it to download the file. Here is an example. Notice the button only used to execute the function and href and download attributes are added to the <a> tag.
function exportHistory() {
console.log("started");
var _myArray = JSON.stringify(localStorage , null, 4); //indentation in json format, human readable
//Note: We use the anchor tag here instead button.
var vLink = document.getElementById('exportHistoryLink');
var vBlob = new Blob([_myArray], {type: "octet/stream"});
vName = 'working_history_' + todayDate() + '.json';
vUrl = window.URL.createObjectURL(vBlob);
console.log(vLink);
vLink.setAttribute('href', vUrl);
vLink.setAttribute('download', vName );
//Note: Programmatically click the link to download the file
vLink.click();
console.log("finished");
}
Now add an empty anchor tag to the DOM.
<button class="btn btn-outline-secondary btn-sm" id="exportHistory" onclick="exportHistory()">Export History</button >
<a id="exportHistoryLink" style="display: none;">Export</a>

Button function does not work when in subpage

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

Obtain variable between tag and append to URL

I have a webpage that was developed by someone else. I want to take the variable that they are displaying on when the page loads from the following tag <h3 id="TAGS"></h3> and append that to a this example URL http://someurl.com/<variable>.
I'm not a JavaScript person so any help would be appreciated.
I tried the following which did not work
var myURL = $('#TAGS').innerHTML
<input type="button" value="Download" onclick="window.location.href=\'http://someurl.com/' + myURL + '\'"/>
JAVASCRIPT + jQuery:
Create a global variable like var downloadURL = "" and make a function in jQuery:
$( document ).ready(function() {
var myURL = $("#TAGS").html();
downloadURL = "http://someurl.com/" + myURL;
});
and then you make your button like this:
<input type="button" value="Download" onclick="download()"/>
having the method download do whatever you want:
function download() {
if(downloadURL!="") {
window.location.href=downloadURL;
}
else {
//you don't have a value set
}
downloadURL="";
}
JAVASCRIPT: Create a global variable like var downloadURL = "" and make a function to load on page load:
window.onload = function() {
var myURL = document.getElementById("TAGS").innerHTML;
downloadURL = "http://someurl.com/" + myURL;
});
and then you make your button like this:
<input type="button" value="Download" onclick="download()"/>
having the method download do whatever you want:
function download() {
if(downloadURL!="") {
window.location=downloadURL;
}
else {
//you don't have a value set
}
downloadURL="";
}
You're trying to use Jquery library with '$' sign. if you didn't install that library simply don't use it. instead, you can use pure browser JavaScript function.
var myURL = document.getElementById("TAGS").innerHTML;
myURL will be whatever inside the HTML element.
for example: <h3 id="TAGS">test</h3>
myURL = test
Try this code:
var myURL = $('#TAGS').val()
But don't forget include jQuery to you code.

Refresh Button when clicking on it

I got a button which i want to reload on click. But only the button should be reloaded, not the rest of the page.
The button looks like this:
<a href="{$module_data.GM_PRODUCTS_BUTTON_BUY_NOW_URL}" id="click{php}echo ''.$counter.'';{/php}" class="addcart button_green button_set action_add_to_cart"{if $module_data.PRODUCTS_NAME != ''} title="{$module_data.PRODUCTS_NAME|replace:'"':'"'} {$txt.text_buy}"{/if}
onclick="return checkAddToCart(event, '{$module_data.QTY_DATA.ID}', {$product_stock}, {$product_max_order}, {$module_data.PRODUCTS_ID}, {php}echo $row['customers_basket_quantity']{/php}, {php}echo "'click".$counter."'";{/php});">
<span class="button-outer">
<span class="button-inner">{$button.add_to_cart}</span>
</span>
</a>
Now i told javascript that echo "'click".$counter."'"; is the clickid.
I tried the following thing to reload my page on click:
function checkAddToCart(event, tid, stock, maxallowed, pid, pquantity, clickid)
{
var clickid_string = clickid.toString();
var bought = Number($("#"+tid).val());
stock = Number(stock);
maxallowed = Number(maxallowed);
var ans = (bought>stock) || (bought > maxallowed);
if(ans)
{
event.stopPropagation();
event.preventDefault();
alert("Maximale Bestellmenge: " + Math.min(maxallowed, stock));
}
else {
$("#"+clickid_string).load("#"+clickid_string);
}
return !ans;
}
It is not working, and i have absolutly no idea why. By the ay, my system works with SMARTY tpl.
If you want to run a php script on click of a button you need to learn ajax. Ajax its just a simple way to use javascript, to run pages in background without reload the current page.
<span class="button-outer" onClick="addDataToDB(this);">...</span>
<script>
function addDataToDB(el) {
var elem = $(el);
/* GET ALL YOUR DATA*/
var name = ...
/* Create an AJAX request to your phpfunction */
}
</script>
Check some tutorials in youtube.

delay javascript function until after file has been uploaded on asp page

Can someone please tell me how to delay the resetting of a div background-image until a file upload has completed? All the parts individually work, however
I have to delay the setting of the background by having an alert pop up and then leave a while before clicking ok - I can't have since a user will not know how long to leave before pressing...
Any help appreciated though I should say that I briefly looked at jquery/ajax but found that it would only work in IE once before requiing a page refresh
Html...
<iframe id="MyFrame" name="MyFrame" style="display:none;"></iframe>
<form id="browseform" method="post" action="disp_photosave.asp" enctype="multipart/form-data" target="MyFrame">
<p>Please select your photo...</p>
<img src="Images/button_browse.gif">
<input type="hidden" name="tab" value="0">
<input type="file" id="upload" name="filesent" onchange="this.form.submit(); load_bk_photo()">
<input type="hidden" name="tempid" value="<%=(TId)%>">
<input type="hidden" name="side" value="<%=(strSide)%>">
<input type="hidden" name="varid" value="<%=(Request.querystring("varid"))%>">
<input type="hidden" name="prodid" value="<%=(Request.querystring("prodid"))%>">
</form>
javascript...
function load_bk_photo(){
var activeId = '<%=(activeTempStoreId)%>'
var redStr_id = "side1"
d = new Date();
time_temp = d.getTime();
photoUrl = "photos/merged_"+activeId+"_"+redStr_id+".png?"+d.getTime()
alert ("timebbb = "+time_temp )
$('#resizable-img').css('background-image','url("' + photoUrl + '")');
$('#resizable-img').css('display','block');
}
vbscript on disp_photosave.asp...
<%
Set Upload = Server.CreateObject("csASPUpload.Process")
Set Image = Server.CreateObject("csImageFile.Manage")
prodid = prodSet.Fields.Item("id").Value
redStr = "side1"
fieldPrefix = "front_"
If Upload.FileQty > 0 Then
Image.ReadVariant Upload.FileData(0)
Image.WriteFile Server.MapPath("this works ok"
Image.ResizeFit scale_width, scale_height
Image.WriteFile Server.MapPath("this works ok"
storeHeight = Image.Height
storeWidth = Image.Width
Set MyConn=Server.CreateObject("ADODB.Connection")
MyConn.Open "dsn=xxx;uid=xxx;password=xxx;"
SQLString = "this works ok"
MyConn.Execute(SQLString)
MyConn.Close
Set MyConn = Nothing
End if
%>
I also need to return the value storeHeight and storeWidth to the main page to use later so if anyone can advise me on that too.
Thanks in advance for any help.
Your load_bk_photo function has some issues (missing semi-colons, creating global variables), try changing to this:
function load_bk_photo(){
//we can use the `var` keyword once and separate each variable declaration by a comma, then finish all the declarations with a semi-colon
var activeId = '<%=(activeTempStoreId)%>',
redStr_id = "side1",
d = new Date(),
time_temp = d.getTime(),
photoUrl = "photos/merged_" + activeId + "_" + redStr_id+".png?" + time_temp;
alert ("timebbb = " + time_temp );
//you can use one `.css()` function call to do both operations
$('#resizable-img').css({
'background-image' : 'url("' + photoUrl + '")',
display : 'block'
});
}
You were creating global variables which is only necessary if you are changing the value of variables outside the scope of this function.
Onto your main question, you can set a load event handler for the <iframe> element as a callback function on your upload:
$('#MyFrame').on('load', function () {
//The iframe has loaded and you can do what you want, including get the contents of the iframe (server-response)
var response = $(this).contents().find('body').text();
});
Make sure to set this binding before the source of the <iframe> is changed.
Note that .on() is new in jQuery 1.7 and in this case is the same as .bind().
.on(): http://api.jquery.com/on
UPDATE
I don't know asp classic but if you output something like storeWidth|storeHeight in your asp code then you can get that response in you JavaScript and do what you want with it:
$('#MyFrame').on('load', function () {
//The iframe has loaded and you can do what you want, including get the contents of the iframe (server-response)
var response = $(this).contents().find('body').text().split('|');
alert(response[0] + 'x' + response[1] + 'px');
});
I would use a global callback method:
JavaScript:
window.uploadComplete = function (returnData) {
$('#resizable-img').css('background-image','url("' + returnData.photoUrl + '")');
$('#resizable-img').css('display','block');
alert(returnData.storeHeight + "|" + returnData.storeWidth);
}
And in ASP, return this to the iFrame:
<script>
parent.uploadComplete({photoUrl: "urltophoto",storeHeight: "<value from asp var>", storeWidth: "<value from asp var>"});
</script>

Categories