Kick some booty with invisible Flash!
JavaScript Games #2 - Solitaire
Writing a midi hifi system in JavaScript
You are here: irt.org | Articles | JavaScript | Miscellaneous | Keeping Count of Downloads [ previous next ]
Published on: Saturday 18th April 1998 By: Martin Webb
Have you got files on your web space that people can download? Do you want to count how many times they are downloaded? This article discusses how to keep count of how many times a file is downloaded. Using a combination of image or floating frame replacement, this utility loads a CGI image to increment a counter. You obviously need to have a CGI image counter for this to work - most people do - either from your ISP or from a third party.
The first question that needs answering is: How do can someone download a file from a web site? Using a normal link it is possible to download for example a zip file. By default the browser does not know how to handle a zip file, so it asks the user what it should do with it, so it prompts the user whether it should open it or save it to disk. Saving it to disk is the desired response.
Rather than have a link that connects directly to the zip file, e.g.:
<A HREF="download.zip">download zip file</A>
we can use the JavaScript protocol to capture the link selection and perform some other action, e.g.:
<SCRIPT LANGUAGE="JavaScript"><!-- function download() { // perform something processing in here } //--></SCRIPT> <A HREF="javascript:download()">download zip file</A>
The only problem with this approach is that browsers allow a shift-click or a right mouse button click on the link, which allows the visitor to save the file linked to. In our case this would case a problem because there is not a file pointed at by the link. A solution is to replace the link with a form button:
<SCRIPT LANGUAGE="JavaScript"><!-- function download() { // perform something processing in here } //--></SCRIPT> <FORM> <INPUT TYPE="BUTTON" VALUE="Download zip file" onClick="download()"> </FORM>
Most ISP's provide a basic CGI script that allows a counter to count how many times a page is visited. At the same time they generally provide an image of the counter so that you or your visitor can view the count. There are one or two of these such image counters on my pages, but you will not see them as they are hidden.
Generally a CGI Image Counter looks similar to:
<IMG SRC="http://www.somewhere.com/cgi-bin/counter.cgi" WIDTH=30 HEIGHT=16>
What this does, is instead of loading an image, it runs the CGI script at the server which then returns a variable image which is displayed on the screen. Obviously the implementation of your CGI Image Counter will be different to that shown above. To hide the returned image is very simple indeed:
<IMG SRC="http://www.somewhere.com/cgi-bin/counter.cgi" WIDTH=1 HEIGHT=1>
This still invokes the CGI script which returns an image, but its size is set very small indeed, 1 pixel wide by 1 pixel high. About the size of a full stop.
Okay then, we've got our basic image, now whats to stop us from using some good old image swapping code to change from one image to another? Nothing, except the fact that some older browsers do not allow image swapping - more on that in the next section.
If we start with a normal blank image:
<IMG SRC="blank.gif" WIDTH=1 HEIGHT=1>
And then name it:
<IMG SRC="blank.gif" NAME="counterimage" WIDTH=1 HEIGHT=1>
We can now use JavaScript to swap the image from the normal blank image to an image returned by a CGI Script:
<SCRIPT LANGUAGE="JavaScript"><!-- function download() { document.images['counterImage'].src = 'http://www.somewhere.com/cgi-bin/counter.cgi'; } //--></SCRIPT>
I mentioned in the previous section that not all browsers support image swapping. This is because they did not implement the JavaScript Image object. We can easily detect whether the browser supports the Image object with the following simple check:
<SCRIPT LANGUAGE="JavaScript"><!-- if (document.images) { // supports the Image object } else { // does not support the Image object } //--></SCRIPT>
So what can we do with browsers that do not support the Image object? Wel for Microsoft Internet Explorer 3, we can utilise floating frames. We can load an initial floating frame into the document containing just a blank image, and then, using JavaScript, we can change the contents of the floating frame so that it has the image returned by a CGI Script.
First the HTML code to display a hidden floating frame:
<IFRAME FRAMEBORDER="0" WIDTH="1" HEIGHT="1" MARGINHEIGHT="0" MARGINWIDTH="0" SRC="count0.html"> </IFRAME>
The initial source contained within the floating frame (count0.html) looks like:
<IMG SRC="blank.gif" WIDTH=1 HEIGHT=1>
The JavaScript code required to change the location of the floating frame looks like:
<SCRIPT LANGUAGE="JavaScript"><!-- document.frames[0].location.href = 'count1.html'; //--></SCRIPT>
Where the contents of count1.html looks like:
<IMG SRC="http://www.somewhere.com/cgi-bin/counter.cgi" WIDTH=1 HEIGHT=1>
So we now have the ability to swap images on MSIE3. Unfortunately, Netscape Navigator 2 does not support the Image object or floating frames, so we can't change an image to an Image Counter on demand, but, we can at least make sure it doesn't cause any problems.
We can bring together all the techniques described above to produce a utility that counts the number of times a form button is pressed and therefore the number of times a file download is requested.
First the JavaScript code to load either the hidden blank image, or the hidden floating frame, and display the form download button:
<FORM> <SCRIPT LANGUAGE="JavaScript"><!-- var useImage = false; var useFrame = false; if (document.images) useImage = true; else if (navigator.appVersion.indexOf('MSIE 3') > -1) useFrame = true; if (useImage) document.write('<IMG SRC="blank.gif" NAME="counterImage" WIDTH="1" HEIGHT="1">'); else if (useFrame) document.write('<IFRAME FRAMEBORDER="0" WIDTH="1" HEIGHT="11" MARGINHEIGHT="0" MARGINWIDTH="0" SRC="count0.html"><\/IFRAME>'); function download() { if (useImage) document.images['counterImage'].src = 'http://www.somewhere.com/cgi-bin/counter.cgi'; else if (useFrame) document.frames[0].location.href = 'count1.html'; window.location.href = 'download.zip'; } //--></SCRIPT> <INPUT TYPE="BUTTON" VALUE="Download zip file" onClick="download()"> </FORM>
Second, the initial contents (count0.html) of the floating frame:
<IMG SRC="blank.gif" WIDTH=1 HEIGHT=1>
Third, the reloaded floating frames contents (count1.html):
<IMG SRC="http://www.somewhere.com/cgi-bin/counter.cgi" WIDTH=1 HEIGHT=1>
Kick some booty with invisible Flash!
JavaScript Games #2 - Solitaire
Writing a midi hifi system in JavaScript
JavaScript Beginners Start Here