The HTML and Javascript on this page have been released into the public domain with the following caveats: The sample images on this page have rights that may be claimed by their individual owners (don't use them!). The findPos function is a third party function from quirksmode (http://www.quirksmode.org/js/findpos.html ) and while his copyright and code philosophy mostly mirrors mine, you might want to check out the quirksmode Copyright Page if you plan to use the function commercially or plan to redestribute it in other works.
<HTML>
<HEAD>
<TITLE>Javascript Filmstrip: Example #6</title>
<style type='text/css'>
.thumbnail {
margin-right: 5px;
width: 75px;
height: 75px;
}
.filmstrip {
position: absolute;
overflow: hidden;
height: 75px;
cursor: w-resize;
}
.detail {
position: absolute;
border: 1px solid black;
background-color: #DDDDDD;
display: none;
cursor:move;
}
.detailLink {
text-decoration: none;
color: black;
}
.detailLink:hover {
background-color: black;
color: white;
}
.detailComments {
font-family: verdana;
font-size: 9pt;
color: black;
display: none;
}
.detailImg {
cursor: move;
padding: 5px;
}
</style>
</HEAD>
<BODY onresize='bindStrip()'>
<P>The HTML and Javascript on this page have been released into the public domain with the following caveats:
The sample images on this page have rights that may be claimed by their individual owners (don't use them!).
The findPos function is a third party function from quirksmode (<A HREF="http://www.quirksmode.org/js/findpos.html">http://www.quirksmode.org/js/findpos.html</A> )
and while his copyright and code philosophy mostly mirrors mine, you might want to check out
the quirksmode <A HREF="http://www.quirksmode.org/about/copyright.html">Copyright Page</A> if you plan
to use the function commercially or plan to redestribute it in other works.
<P><div id='filmstrip' class='filmstrip'></div>
<BR><BR><BR>
<CENTER>
<table style='border: 1px solid black; overflow: hidden;' width=75% height=75 cellspacing=0 cellpadding=0 id='landingZone'>
<tr><td> </Td></tr>
</table>
</CENTER>
<BR><BR>
<div id='detailFrame' class='detail'>
<A HREF="javascript:flickrGo()" class='detailLink'>LINK</A>
<A HREF="javascript:flickrZoom()" class='detailLink'>ZOOM</A>
<A HREF="javascript:showPic()" class='detailLink'>CLOSE</A>
<div id='detailPic' onMouseOver='document.getElementById("comments").style.display="block"' onMouseOut='document.getElementById("comments").style.display="none"'></div>
<div id='comments' class='detailComments'></div>
</div>
<script type='text/javascript'>
////////////////////////////////////////////////////////////////////////////////
// Declare global variables
////////////////////////////////////////////////////////////////////////////////
var _allImages = new Array(); // Holds all of the image data from server
var _filmstrip = document.getElementById('filmstrip'); // Our filmstrip layer
var _landingZone= document.getElementById('landingZone'); // Table which creates the filmstrip bondary
var _detail = document.getElementById('detailFrame'); // Detail layer.
var _filmWidth = 0; // Width in pixels of our filmstrip
var _totalChange = 0; // Total pixels moved/changed
var _savedTarget = null; // Target object of drag event
var _orgCursor = null; // Original cursor Style
var _dragXoffset = 0; // X offset of the move event
var _dragYoffset = 0; // Y offset of the move event
var _scrollOK = false; // True if we can scroll filmstrip
var _totalOffset=0; // offset position of the filmstrip
var _originalOffset=0; // Offset of strip before we started moving it.
var _leftOffset=0; // The left location of the landingZone table
var _currentPic = 0; // Index of current Picture
var _dragOK=false; // True when we can move the detail window
var _topOffset=0; // The top position of the landingZone table.
////////////////////////////////////////////////////////////////////////////////
// These are the AJAX routines to get data from the server.
////////////////////////////////////////////////////////////////////////////////
function importData(fileName) {
var AJAX = null; // Initialize the AJAX variable.
if (window.XMLHttpRequest) { // Are we working with mozilla?
AJAX=new XMLHttpRequest(); // Yes -- this is mozilla.
} else { // Not Mozilla, must be IE
AJAX=new ActiveXObject("Microsoft.XMLHTTP"); // Wheee, ActiveX, how do we format c: again?
} // End setup Ajax.
if (AJAX==null) { // If we couldn't initialize Ajax...
alert("Your browser doesn't support AJAX."); // Sorry msg.
return false // Return false (WARNING - SAME AS ALREADY PROCESSING!)
} else {
AJAX.onreadystatechange = function() { // When the browser has the request info..
if (AJAX.readyState==4 || AJAX.readyState=="complete") { // see if the complete flag is set.
processData(AJAX.responseText);
} // End Ajax readystate check.
} // End create post-process fucntion block.
AJAX.open("GET", fileName, true); // Open the url
AJAX.send(null); // Send the request.
return true; // Everything went a-ok.
} // End Ajax setup aok if/else block
}
function processData (dat) {
_allImages = dat.split('``'); // Explode the server image data into array elements
var ktr=0; // Initialize our counter
_filmstrip.innerHTML=''; // Initialize our filmstrip
_filmWidth=0; // Initiaize the film width.
var tmp = ''; // Temp variable to hold our HTML as we build it.
while ((ktr<_allImages.length)&&(_allImages[ktr].indexOf('EOF*EOF')<0)){ // For each record in allImages.
record = _allImages[ktr].split('~|~'); // Explode record into individual fields.
// The next line builds our HTML in a variable, this is faster than doing X innerHTML insertions.
tmp+='<img src="'+record[1]+'_s.jpg" class="thumbnail" onMouseUp="showPic(\''+ktr+'\')">';
_filmWidth+=80; // Increment our filmstrip Width counter.
ktr++; // Increment our counter
} // End WHILE loop
_filmstrip.innerHTML=tmp; // Insert tmp into our filmstrip layer.
_totalOffset=0; // Reset filmstrip to start at beginning.
bindStrip(); // rebind the strip to the landingzone.
}
////////////////////////////////////////////////////////////////////////////////
// End AJAX routines.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// These functions help anchor the filmstrip to the landingZone table
////////////////////////////////////////////////////////////////////////////////
function findPos(obj) {
// Credit for this function: http://www.quirksmode.org/js/findpos.html
// Visit the URL for a complete tutorial on this function
var curleft = curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
curtop = obj.offsetTop
curwidth = obj.offsetWidth;
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
}
return [curleft,curtop,curwidth];
}
function bindStrip() { // moves filmstrip into the landingZone table.
ofs=findPos(_landingZone); // Find the left/top & width of table
_filmstrip.style.top=ofs[1]+'px'; // Set filmstrip's top location
_filmstrip.style.left=ofs[0]+'px'; // Set filmstrip's left location
_topOffset = ofs[1]; // Remember top offset globally
_leftOffset= ofs[0]; // Remember the left offset globally
// The next line crops the filmstrip and shows only a small section of it
_filmstrip.style.clip='rect(0px,'+(_landingZone.offsetWidth+_totalOffset)+'px,80px,'+_totalOffset+'px)';
_filmstrip.style.left=(_leftOffset-_totalOffset)+'px'; // set the left offset of the filmstrip
}
////////////////////////////////////////////////////////////////////////////////
// End filmstrip anchor functions.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Begin Drag/Scroll Handlers
////////////////////////////////////////////////////////////////////////////////
function scrollHandler(e) {
// This function handles the draging of the filmstrip from left to right
if (e == null) { e = window.event; } // Get event data
_totalChange=(_dragXoffset-e.clientX); // Calculate total movement
if (e.button<=1&&_scrollOK){ // Is mouse down and scroll enabled?
_totalOffset=_originalOffset+(_dragXoffset-e.clientX); // Find the distance mouse has moved
if ((_totalOffset) < 0) { // Are we scrolling too far left?
_totalOffset=0; // Yes, set the offset to 0
_originalOffset=0; // and the original
_dragXoffset=e.clientX; // and reset the mouse.
_totalChange=20; // Simulate a move so we don't open a pic.
}
if ((_totalOffset+_landingZone.offsetWidth)>=(_filmWidth-5)) { // Are we too far right?
_totalOffset=(_filmWidth-_landingZone.offsetWidth-5); // Yes, set offset to max
_originalOffset=(_filmWidth-_landingZone.offsetWidth-5);// and the original
_dragXoffset=e.clientX; // reset the mouse
_totalChange=20; // Simulate a move so we don't open a pic.
}
// Set the visible clip here.
_filmstrip.style.clip='rect(0px,'+(_landingZone.offsetWidth+_totalOffset)+'px,80px,'+_totalOffset+'px)';
// And set the left offset
_filmstrip.style.left=(_leftOffset-_totalOffset)+'px';
// return false so the browser won't try to do it's events!
return false;
}
}
function cleanup(e) {
// called when user releases a mouse button after a drag event
_scrollOK = false; // Setting this to false disables scrollHandler
_dragOK = false; // This disables the move handler (detail window)
_savedTarget.style.cursor=_orgCursor; // Change back to the original cursor shape
document.onmousemove=null; // Disable the mousemove handler
document.onmouseup=null; // Disable the mouseup handler
}
function moveHandler(e){ // Called on mousemove when detail layer is dragable
if (e == null) { e = window.event; } // Get the event data
if (e.button<=1&&_dragOK){ // Make sure mouse button is down and ok to drag
_savedTarget.style.left=e.clientX-_dragXoffset+'px'; // Move to the new left offset
_savedTarget.style.top=e.clientY-_dragYoffset+'px'; // Move to the new top offset.
return false; // Return false so browser doesn't do its own thing
} // End button/dragOK check
}
function dragHandler(e) {
_totalChange=0; // Total pixels moved
var cursorType='-moz-grabbing'; // Set hand to "grab"
if (e == null) { e = window.event; cursorType='w-resize';} // Package event for IE
var target = e.target != null ? e.target : e.srcElement; // Get the target object
//Handle filmstrip
if (target.className=="filmstrip"||target.className=="thumbnail") { // Check if event over filmstrip
_savedTarget=target; // This is our target object
_orgCursor=target.style.cursor; // This was our orginal cursor
_originalOffset=_totalOffset; // Mark the current offset
target.style.cursor=cursorType; // Set mouse to grab if possible
_scrollOK=true; // flag filmstrip as scrollable
_dragXoffset=e.clientX; // remember original X position
document.onmousemove=scrollHandler; // set up a mouse-move handler
document.onmouseup=cleanup; // set up a button-up handler
return false; // return FALSE -- IMPORTANT!!!!
} else {
//Handle detail window
if (target.className.indexOf('detail')>=0) { // Check to see if we're over a datail layer
_savedTarget=document.getElementById('detailFrame'); // This is our target object
_orgCursor=target.style.cursor; // This was our orginal cursor
target.style.cursor=cursorType; // Set mouse to grab if possible
_dragOK=true; // flag filmstrip as scrollable
_dragXoffset=e.clientX-parseInt(_savedTarget.style.left); // Remember original X position
_dragYoffset=e.clientY-parseInt(_savedTarget.style.top); // Remember original Y position
document.onmousemove=moveHandler; // set up a mouse-move handler
document.onmouseup=cleanup; // set up a button-up handler
return false; // return FALSE -- IMPORTANT!!!!!!!
}
}
}
////////////////////////////////////////////////////////////////////////////////
// End drag/scroll Handlers
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// These functions support the detail Window
////////////////////////////////////////////////////////////////////////////////
function showPic(idx) {
if ((_totalChange<-5)||(_totalChange>5)) { return false } // User scrolled, not a click event so return.
detail=document.getElementById('detailFrame'); // get the detail window
detailComments=document.getElementById('comments'); // get the comments window
detailImg=document.getElementById('detailPic'); // get the picture window
if (idx==null) {idx=_currentPic} // set idx if nothing was passed.
if ((detail.style.display=='block')&&(idx==_currentPic)) { // If the detail window is visible
detail.style.display='none'; // Make it invisible
detailImg.innerHTML=''; // Clear out last picture
detailComments.innerHTML=''; // Clear out last comments
} else { // Detail Window is not visible
var record = _allImages[idx].split('~|~'); // Get the image record
detailImg.innerHTML='<img src="'+record[1]+'.jpg" class="detailImg">'; // Insert the pic
detailComments.innerHTML=record[3]; // Insert the comments
detail.style.display='block'; // Make the detail window visible
_currentPic=idx; // Remember the current picture.
}
}
function flickrGo() {
var record = _allImages[_currentPic].split('~|~'); // Get the image record
document.location.href=record[2]; // Navigate to the photo's web page on flickr.
}
function flickrZoom() {
var record = _allImages[_currentPic].split('~|~'); // Get the image record
document.location.href=record[1]+'_o.jpg'; // Navigate to the original resolution picture on flickr
}
////////////////////////////////////////////////////////////////////////////////
// End detail window functions
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// This area executed as document loads.
////////////////////////////////////////////////////////////////////////////////
importData("filmstrip.txt"); // get the images to load from the server....
bindStrip(); // Place the filmstrip inside the landingZone table
document.onmousedown = dragHandler; // Call dragHandler on mouse down
_detail.style.top=_topOffset+90+'px'; // Initialize the location of the detail window
_detail.style.left='200px'; // Initialize the horizontal position of the detail window
</script>
</body>
</HTML>