Intro:
This was an experiment to see whether client side script can be used for something making a slideshow viewer (with optional annotations in the form of text notes for each slide). The idea was to have the same page work for local viewing of images and also work on the server where the images are posted. This document describes the script a bit, and then ends with some conclusions.
You can try out the script here. To download it, just view source on the page or save it to a file.
The script:
Basically you can't safely access directories directly from javascript, since that could be a security issue. So the first question is how to get the file info we want to display. The standard trick is to load a listing of the directory you are perusing into a hidden frame and then reading the links out of it. This works provided that:
index.html file or the equivalent to
display in lieu of the directory listing.
Given those caveats, you write some script triggered in the
onLoad attribute of the listingframe (google "onload frame
directory listing" or somesuch for examples). But the real challenge is
getting something that will refresh the contents as you tab/enter your way
through the image links. This is harder, because you don't have any
control over what order the frames are loaded, and you need to call your
directory processing after the directory is there to work with. Ultimately
I ended up dynamically generating a frame within a frame to get the load
call happening at the right time. I also found it helpful to have a
scratchspace frame to use as a target that wouldn't inadvertently mess
things up. Here's an excerpt of the resulting frame setup:
html += '<frameset onload="writeListing(\'.\');" rows="5%, 95%, *" frameborder="1">';
html += '<frame name="description" src="about:blank" scrolling="auto">';
html += '<frameset cols="15%, 85%, *">';
html += '<frame name="nav" src="about:blank" scrolling="auto" noresize>';
html += '<frame name="display" src="about:blank" scrolling="auto" noresize>';
html += '<frame name="scratchspace" src="about:blank" scrolling="no" noresize>';
html += '<\/frameset>';
html += '<frame name="listing" src="about:blank" scrolling="no" noresize>';
html += '<\/frameset>';
The code to generate the source frame within the listing frame is:
function writeListing(dir) {
var d = listing.document;
d.open();
d.write('<frameset onLoad="parent.writeLinks(\'' + dir + '\');" rows="100%, *">');
d.write(' <frame name="source" src="' + dir + '" noresize scrolling="no">');
d.write('<\/frameset>');
d.close();
}
Once we have the frames, we basically just need to populate the contents. This amounts to a series of rules in priority order as to what constitutes something we want and what doesn't. For each link:
if((links[i].href.indexOf(".jpg")>=0)||
(links[i].href.indexOf(".JPG")>=0)||
(links[i].href.indexOf(".gif")>=0)||
(links[i].href.indexOf(".GIF")>=0)) {
var index=links[i].href.lastIndexOf(".");
var descr=links[i].href.substring(0,index) + '.txt';
var descrLink="about:blank"
for(var j=0;j<links.length;j++) {
if(links[j] == descr) {
descrLink=descr; } }
d.write('<a href="' + links[i].href + '" target="display" ' +
'onclick="parent.writeDescription(\'' + descrLink + '\')">' +
(links[i].text ? links[i].text : links[i].href) +
'<\/a><br>'); }
else if(links[i].href.indexOf("C=")>=0) {
//apache generated sorting link in directory listing
//d.write(links[i].text + '<br>');
}
else if(links[i].href.lastIndexOf("/") == links[i].href.length - 1) {
//ends with a terminating slash so must a be a directory link
d.write('<a href="' + links[i].href + '" target="scratchspace" ' +
'onclick="parent.writeListing(\'' + links[i].href + '\')">' +
(links[i].text ? links[i].text : links[i].href) +
'<\/a><br>'); }
else if(links[i].href.indexOf(".")>=0) {
//assume anything with an extension is a non-image file
//d.write(links[i].text + '<br>');
}
else { //assume directory by default
d.write('<a href="' + links[i].href + '" target="scratchspace" ' +
'onclick="parent.writeListing(\'' + links[i].href + '\')">' +
(links[i].text ? links[i].text : links[i].href) +
'<\/a><br>'); } }
The full script is here. View source to see the code. All the functionality is contained within the single file.
Conclusions:
You can do some impressive things with client side browser script, but lack of reliable file access (read or write) along with differences between browsers and browser versions pretty much limit this to display formatting. With server side display, you only need to test your resulting display pages across multiple browsers. With client side scripting, you also need to test the display generation code across multiple browsers, as opposed to a single known server environment. Significant UI functionality requires server support to handle what can't be done (or is difficult to do) in script.
So what if I want a simple picture browser running locally on my computer, where I could do things like enter text descriptions to annotate each image? Realistically, I would need to run a server process that would handle the input processing and write the description file. If I could run this server locally, then I would use the identical browser interface for both a standalone client or web installation. Only the URL would be different.
The concept of a browser-interface/local server (BILoc) application is discussed next.
© 2005 SAND Services Inc.
All Rights Reserved.