Suppose that your website allows people to download information. Now pretend that you are providing this information as a way to attract people to your business – a common situation on the web today. It follows that you would want to collect some contact information from your users before allowing them to begin the download.
Most websites require a registration for this. Some are blatant about it while others create the account behind the scenes, so that the user does not know they have been granted access to a member module and protected downloads.
What happens if you don’t want to sign up new users? This may be a fringe case but it is desired more commonly than it is implemented. This was the situation for one of my customers. He wanted a pop-up window that would collect the user’s name and email address before allowing the download.
If you open a new window (or tab) where the address belongs to a downloadable file, web browsers will then close the window once it starts. I thought this might be the best way:
- Open popup
- Collect information
- Spawn new popup for download
- Close the original popup
- Allow the browser to close the second popup, once the download starts
For some reason, the browser refused to close the second popup after the first was closed. I could script around this by using Javascript’s setTimeout to close the first popup, but there is no definitive cross-browser method to know that a download has started. Suppose that the user is on dial-up or satellite? We may need to wait 20 seconds, 30 seconds, or more to be sure no “random” anomalies occur.
Scratch that option. The next possibility is to set document.location.href to the URL of the download except that, in my experience, the browser stops executing scripts the same way it does if you navigated to another page. The first popup window remains open.
Our third choice is more promising. We could create a function called “some_custom_function()” on the parent document (that created the popup) and then call it as window.opener.some_custom_function() before window.close() in the popup window. This will notify the original page that the form has been completed. some_custom_function() can set document.location.href for the parent document, and voila! The popup closes and the user is given a download.
If Internet Exploder did not continue to control 25% of internet browser share, we could stop here. Unfortunately Microsoft is always introducing poor browser design. Their information bar, by default, will prevent these downloads from your website (which can sometimes be good to slow the spread of viruses). The user has to click on the yellow bar, tell it to allow the download, and then the browser reloads your page! This kills any ability you had to give the user a download via Javascript.
Microsoft does provide a way to turn off the Information Bar in Internet Exploder:
But let’s be realistic: You can’t ask your customers to do this before entering their contact details. They will go somewhere else instead.
It may be easier at this point to create a hack using a lightbox and an iframe, but many of the same problems would exist so I continued to expand this hack:
- Open popup
- Collect Information
- Notify parent that we were successful
- Parent rewrites its own url (ie. document.location.href = document.location.href.replace(/[#?].*$/, ‘?download’))
- Close popup
- Parent window reloads and checks for the presence of a custom $_GET parameter via Javascript (ie. document.location.href.indexOf(’?download’) != -1). If found, it sets window.onload** with an anonymous function that sets document.location.href to the path of the download.
Our entire purpose in modifying the URL is to pass information to ourselves when Internet Exploder performs a page refresh. This method works on Firefox 4, IE 8, and Chrome 5.
The reason for our usage of window.onload is that when document.location.href is changed, the browser will stop loading the page. We want the user to remain on the site if they wish to continue browsing.
Are you confused yet? Did this make sense? I hope that it did, and would love to hear of any improvements you make.
** I am aware that several Javascript frameworks, such as jQuery, allow for cross-browser compatibility with multiple onload functions. Implementing that on the site would have been a large ordeal (as lightboxes would have been) and window.onload was not being used for anything important. I do not foresee that changing on this particular site.