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.




 


LINK ZOOM CLOSE
<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>&nbsp</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>