Instead of linking directly to files for download on a web site we link to a page that says "thank you for downloading". The page has tracking codes on it so we know how many people have downloaded the file. The page launches the download file using the jQuery code shown which adds a short delay after the page loads before the download begins. The download location has a content disposition header so it always downloads properly in the browser leaving the "thank you for downloading" page visible. This all works well.
The problem comes if the user carries on browsing past this page and then hits back. The download fires again.
Using window.location.replace(href); didn't seem to fix it.
The issue is further complicated by the fact that the CMS delivering the page has set it to expire immediately so it's not being cached.
Suggestions for (i) ways to avoid this problem; (ii) any better ways to handle file download / thank you pages?
jQuery Code
$(document).ready(function () {
$('a.autoDownload').each(function () {
setTimeout('navigateToDownload("' + $(this).attr('href') + '")', 4000);
});
});
function navigateToDownload(href) {
document.location.href = href;
}
One possible approach would be to set a cookie via Javascript when the page first loads. Then, if that page is ever loaded again, you can check for the presence of the cookie, and if present, do not execute the auto download?
Using the Cookie plugin for jQuery as an example:
$(document).ready(function () {
$('a.autoDownload').each(function () {
var hasDownloadedThisLink = $.cookie("site." + $(this).attr('id'));
if (!hasDownloadedThisLink) {
$.cookie("site." + $(this).attr('id'), "true");
setTimeout('navigateToDownload("' + $(this).attr('href') + '")', 4000);
}
});
});
This is just an example. If you went this way, you'd have to consider how many possible download links there might be, as there is a limit on how many cookies you can set. Also notice that I used an id attribute of the links to identify them in the cookie - I figured this would be more suitable that using some form the href attribute. I also prefixed the cookie name with site..
Well there are a couple of solutions to this. Here's an example:
function navigateToDownload(href){
var e = document.createElement("iframe");
e.src=href;
e.style.display='none';
document.body.appendChild(e);
}
Other implemenatations might exist, but I doubt they're less "hacky".
Related
I have a Chrome extension that allows you to download data from certain sites.
For the past few days, I have attempted to add a feature that will download data from the sites when they are linked from other sites without having to visit the page and click the addon created download button IF the link to the site ends with #ndslink.
I figured out a solution, but it is INCREDIBLY sloppy and I am looking for a better way to implement this.
Here's the behavior:
Site A links Site B with an href ending in #nddownload. The link is clicked.
The extension disables the default action (open a new window), and instead creates an iframe on Site A and loads the linked URL into the frame.
The extension now runs Site B's content script, which specifically looks for #nddownload in the url, and, when found, proceeds to download some data that would normally be downloaded through a manual "Download" button added onto the page via the extension.
Here is my code.
Site B's content script:
var decklist = [];
$('.col-name').each(function(i, el) {
// IRRELEVANT CODE TRIMMMED
}
});
var data = decklist.join("\r\n");
var saveData = (function () {
// IRRELEVANT CODE TRIMMMED
}());
$(document).ready(function(){
var html = $('.t-deck-title').html();
fileName = $('.t-deck-title').text() + '.txt';
//html = html.replace(/hearthstonedeckdl/, '</br><a class="download" href="#download">DOWNLOAD</a>');
$('.t-deck-title').html(html);
if (window.location.href.indexOf("#ndslink") > -1) {
saveData(data, fileName);
}
$(document).on('click', 'a[href="#download"]', function(){
saveData(data, fileName);
});
});
Script loaded on all URLs (incl Site A):
var $jg = jQuery.noConflict();
$jg(document).ready(function(){
$jg('a[href$="#ndslink').click(function(e) {
e.preventDefault();
});
$jg(document).on('click', 'a[href$="#ndslink"]', function(){
//saveData(data, fileName);
var frameurl = $jg(this).text();
$jg('body').prepend('<iframe id="nddownload" />');
$jg("#nddownload").attr("src", frameurl);
//e.preventDefault();
// Send link to background and download.
});
});
I feel as if I am committing a horrible sin by going this route, but being new to Chrome extensions and generally being inexperienced I could not find a proper way to handle this. I've probably also broken my extension 10 different ways while attempting to do this so a real solution would be much appreciated.
I'm also actually unsure how to go about properly destroying the iframe once the saveData function completes.
I have a link which when clicked redirects the user to the same page except with additional parameters:
<a id="lnkExportToPDF" href="javascript:void(0)">Export</a>
$('#lnkExportToPDF').click(function (e) {
e.preventDefault();
window.location.href = path + 'users/export/' + parm1 + '/' + parm2;
});
On the server side I handle it by checking for "export" in the request path, and if it's found I write a PDF file to the response:
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.Clear();
response.AddHeader("Content-Type", "application/pdf");
response.AddHeader("Content-Disposition", String.Format("attachment; filename=" + filename + ".pdf; size={0}", buffer.Length.ToString()));
response.BinaryWrite(buffer);
response.End();
Everything works and the user can download the file, but any additional actions by the user that uses the loader.gif which is on the page shows an unanimated loader.
What could be causing this to happen? Is there any way to refresh/reload the page/javascript after the response is complete?
edit: I've found a useful JS tool here: http://fgnass.github.io/spin.js/ but I'd prefer not to use it unless absolutely necessary
edit2: I also tried using a generic handler (.ashx) to handle the request (ie. changing the href to point to the handler), but as soon as the page redirects and the file is written, same thing happens
edit3: The problem is only happening in Firefox so far. I've tried Chrome and IE and the gif stays animated in those browsers. (latest versions of each)
edit4: If I use an iframe with the src as the image it solves the issue, but it's very hacky and the style of it looks different across all browsers with regards to centering/padding/margins.
edit5: Yeah. If I inspect the frozen gif with firebug it magically unfreezes itself.
I managed to recreate the problem in firefox and I really can't find a way to "unfreeze" the gif. When I added a completely different file after a download and that too was frozen I gave up with that approach.
What I did instead was to test different ways to trigger the download. I found no window.location solutions that worked, what did work though was this:
window.open(path + 'users/export/' + parm1 + '/' + parm2);
window.open opens a new tab and downloads the file through that instead of the current tab as window.location does. It will return to the current tab as soon as the download starts.
Edit
You could also use a hidden iframe:
var iframe = document.getElementById('iframe');
iframe.src = path + 'users/export/' + parm1 + '/' + parm2;
I confirm that I have the same behavior with firefox, and the first that come to my mind is to use SetTimeOut but still the same behavior, so on firefox for some reason, this window.location.href is also call the "Stop" on browser, that this cause the gif animation to stop.
So what I found and you can solve your issue, that this is not happends on simple links.
And if you change your code you can archive the same effect with a link.
So change this
$('#lnkExportToPDF').click(function (e) {
e.preventDefault();
window.location.href = "page.aspx";
});
to something like this
$('#lnkExportToPDF').attr("href", "page.aspx");
and you have the same results, and gif will still moving.
Here is the fiddle test.
On the test I add to move to paypal, because is slow moving and you can see the animation stop or not, also pp not let show on iframe, so on example you stay on example and not load the page.
When you click on this example, the issue is appears only on firefox !
http://jsfiddle.net/hn7S9/4/
One other issue that I think is that if you need to make your parametres to the next page on click, you probably need to redesign that and fix them before your click.
This is possible because for sure is not depends on the last click on the dynamic create link. So make the link with their parametres before the click.
You could try an asynchronous approach on the click to allow the browser to parse the event queue after the click has initiated:
$('#lnkExportToPDF').click(function (e) {
e.preventDefault();
setTimout(function() {
window.location.href = path + 'users/export/' + parm1 + '/' + parm2;
}, 20);
});
How about allowing the link to actually fire, but opening it in a new tab?
That shouldn't interrupt anything about the gif, and is semantically fine, other than I guess it would leave a tab open. You could get rid of the content-disposition, and allow the browser /user to decide what to do with it though.
<a id="lnkExportToPDF" target="_blank">Export</a>
$('#lnkExportToPDF').click(function (e) {
$(this).attr("href", path + 'users/export/' + parm1 + '/' + parm2);
});
Instead of setting the window.location.href, you can use a form with method="get" and submit it. This form could either be coded into your HTML or created dynamically. See this Answer:
https://stackoverflow.com/a/21742326/1614903
Here's my solution. It's faster and easier than any fix or workaround I've found. Just open the problem page in Chrome. Chrome has it's own problems, but this isn't one of them. Whenever I encounter a page full of gifs that causes Firefox to freeze, I just copy the URL, close the tab, open Chrome, and paste in the URL. I works every time! :o)
For example, there is a "Link" called go to view at the bottom of the my page, which is redirecting to http://localhost/test.php.
If we use $_SERVER['HTTP_REFERER'] in test.php page it will display the url of the page from which link was clicked.
The problem is this: my URL can be seen at the target page. This needs to be avoided. How can i do this using javascript?
When JavaScript gets to it, it is too late. Plus JavaScript can not do it.
There is no cross-browser solution. For example this code works in Chrome, but not in FF:
classic html link<br/>
js trickery
<script>
function goto(url) {
var frame = document.createElement("iframe");
frame.style.display = "none";
document.body.appendChild(frame);
frame.contentWindow.location.href="javascript:top.location.href = '" + url + "';";
}
</script>
There are third party solutions. You can find any number of them by searching "referer hide" or "refer mask" with you favorite search engine. - Some of them look sady, so try to find a trustworty one.
On the other hand. This is part of Internet culture. Referers can be used for valuable statistics for example. And if your website is in a crawler's index, they can find the link anyway.
Check http://www.referhush.com/
As sentence on this site says :"Webmasters can use this tool to prevent their site from appearing in the server logs of referred pages as referrer."
1- OPEN FIREBUG, on the console tab
2- OPEN YOUR GMAIL ACCOUNT,
3- when gmail is loaded, click on one of your label (at the left under the draft box)
4- WITH FIREBUG YOU SEE THAT THE PAGE DOES NOT COMLETLY RELAOD SINCE ALL PREVIOUS ACTION STILL THERE FOR THE CURRENT DOCUMENT, BUT THE BROWSER COMPLETLY ACT LIKE THE PAGE HAVE BEEN RELOADED, stop button browser own loading effect, etc...)
5- !!!!! this is it..!!!!
Does some on have a clue on how site like Gmail can make the browser load on ajax call ( I mean show the loading icon and all, history, etc)
I already know what to check for the history navigation but how in the world they can make the browser to act like this was a simple link that load a complete new page.
from what I see with things like firebug Gmail basically retrieve mail information in JSON and than use some Javascript to render it to the user. But how they make the browser load in the while.
In gmail once it is loaded, obviously they ain't load all the data, from all your folder in background, so when you click on some of your folder and the data is not already loaded they make the browser 'load' like if it were loading a complete new page, while they retrieve the information from their server with some ajax call ( in Firefox you see the browser act like when you click on a normal link, loading icon, stop (x) button activated, and all).
Is it clear?
I came up with some 'ugly' code to achieve my goal that work quite nice in FireFox and IE (sadly it seems to not work in Chrome/WebKit and Opera).
I tell the browser to go to a url that it will not be able to reach before the ajax call end, with window.location=. The browser start to load and than when the ajax call sucess I call window.stop() (window.document.execCommand('Stop') for IE) than innerHTML the ajax data in the document
To me its look ugly and since it not work properly in Chrome/Webkit, this is apparently not the way to go.
There are many ways to utilize AJAX.
Gmail needs to load a lot of files/data before something meaningful can be displayed for the users.
E.g. showing the folder tree first doesn't make sense if it's not clickable or not ready for any interactive use.
Hence, what they do is show something lightweight like a loading graphic/progress bar while asynchronously (behind the scene), pull more data from the server until they can populate the page with a full interface for usage.
I don't know how to explain further. Maybe wiki can help: http://en.wikipedia.org/wiki/Ajax_%28programming%29
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/
Use one of the methods shown as triggering a browser busy state in the table on the page above.
document.getElementById('iframe').src = "http://www.exemple.com/browser_load.html";
They are using iFrame. By changing the source of the iFrame.
Sitepoint has a book "Build Your Own AJAX Applications" and they show some content (all?) in this tutorial:
http://articles.sitepoint.com/article/build-your-own-ajax-web-apps
They will guide you with your AJAX coding.
Think this is your answer:
http://www.obviously.com/tech_tips/slow_load_technique
Looks like gmail and facebook method (browser is showing page as "loading" with loading icons etc. - it is just simulating, because there is a background ajax request) :)
$(function($){
$('a').attr('onclick','return false;').click(function(){
var title = $(this).attr('title');
var href = $(this).attr('href');
$('title').html(title);
$('#content').load(href+' #content', function(){
history.pushState(null, null, href);
}, function(responseText) {
var title = responseText.match(/<title>([^<]*)/)[1];
document.title = title;
});
});
});
window.onpopstate = function( e ) {
var returnLocation = history.location || document.location;
var returnTitle = history.propertyName || document.title;
$('title').html(returnLocation.title)
$('#content').load(returnLocation.href+ ' #content', function(){
history.pushState(null, null, href);
}, function(responseText) {
var title = responseText.match(/<title>([^<]*)/)[1];
document.title = title;
});
}
Background: I have an HTML page which lets you expand certain content. As only small portions of the page need to be loaded for such an expansion, it's done via JavaScript, and not by directing to a new URL/ HTML page. However, as a bonus the user is able to permalink to such expanded sections, i.e. send someone else a URL like
http://example.com/#foobar
and have the "foobar" category be opened immediately for that other user. This works using parent.location.hash = 'foobar', so that part is fine.
Now the question: When the user closes such a category on the page, I want to empty the URL fragment again, i.e. turn http://example.com/#foobar into http://example.com/ to update the permalink display. However, doing so using parent.location.hash = '' causes a reload of the whole page (in Firefox 3, for instance), which I'd like to avoid. Using window.location.href = '/#' won't trigger a page reload, but leaves the somewhat unpretty-looking "#" sign in the URL. So is there a way in popular browsers to JavaScript-remove a URL anchor including the "#" sign without triggering a page refresh?
As others have mentioned, replaceState in HTML5 can be used to remove the URL fragment.
Here is an example:
// remove fragment as much as it can go without adding an entry in browser history:
window.location.replace("#");
// slice off the remaining '#' in HTML5:
if (typeof window.history.replaceState == 'function') {
history.replaceState({}, '', window.location.href.slice(0, -1));
}
Since you are controlling the action on the hash value, why not just use a token that means "nothing", like "#_" or "#default".
You could use the shiny new HTML5 window.history.pushState and replaceState methods, as described in ASCIIcasts 246: AJAX History State and on the GitHub blog. This lets you change the entire path (within the same origin host) not just the fragment. To try out this feature, browse around a GitHub repository with a recent browser.
Put this code on head section.
<script type="text/javascript">
var uri = window.location.toString();
if (uri.indexOf("?") > 0) {
var clean_uri = uri.substring(0, uri.indexOf("?"));
window.history.replaceState({}, document.title, clean_uri);
}
</script>
There is also another option instead of using hash,
you could use javascript: void(0);
Example: Open Div
I guess it also depends on when you need that kind of link, so you better check the following links:
How to use it: http://www.brightcherry.co.uk/scribbles/2010/04/25/javascript-how-to-remove-the-trailing-hash-in-a-url/
or check debate on what is better here: Which "href" value should I use for JavaScript links, "#" or "javascript:void(0)"?
$(document).ready(function() {
$(".lnk").click(function(e) {
e.preventDefault();
$(this).attr("href", "stripped_url_via_desired_regex");
});
});
So use
parent.location.hash = '' first
then do
window.location.href=window.location.href.slice(0, -1);
As others have said, you can't do it. Plus... seriously, as the jQuery Ajaxy author - I've deployed complete ajax websites for years now - and I can guarantee no end user has ever complained or perhaps ever even noticed that there is this hash thing going on, user's don't care as long as it works and their getting what they came for.
A proper solution though is HTML5 PushState/ReplaceState/PopState ;-) Which doesn't need the fragement-identifier anymore:
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
For a HTML5 and HTML4 compatible project that supports this HTML5 State Functionality check out https://github.com/browserstate/History.js :-)