Changeset 4527

Show
Ignore:
Timestamp:
04/28/08 14:07:16 (7 months ago)
Author:
carndt
Message:

Lots of improvements and updates for Lightbox. See CHANGELOG.txt for more infor

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • projects/tgLightbox/trunk

    • Property svn:ignore set to
      build
      dist

  • projects/tgLightbox/trunk/Lightbox.egg-info

    • Property svn:ignore set to
      entry_points.txt
      dependency_links.txt
      not-zip-safe
      PKG-INFO
      requires.txt
      SOURCES.txt
      sqlobject.txt
      top_level.txt

  • projects/tgLightbox/trunk/lightbox/__init__.py

    r1056 r4527  
    1 from lightbox.widgets import Lightbox 
    2  
    3 __all__ = ["Lightbox"] 
     1from lightbox.widgets import * 
  • projects/tgLightbox/trunk/lightbox/release.py

    r1062 r4527  
    11# Release information about Lightbox 
     2"""This is a TurboGears_ widget wrapper for the Lightbox2_ JavaScript library 
     3by Lokesh Dhakar. 
    24 
    3 version = "2.0" 
     5You can view the widgets in the TurboGears Toolbox_. 
     6 
     7For further information, visit the `Lightbox widget homepage`_. 
     8 
     9.. _turbogears: http://www.turbogears.org/ 
     10.. _lightbox2: http://www.lokeshdhakar.com/projects/lightbox2/ 
     11.. _toolbox: http://docs.turbogears.org/1.0/Toolbox 
     12.. _lightbox widget homepage: http://docs.turbogears.org/tgLightbox 
     13 
     14""" 
     15 
     16version = "2.1" 
    417 
    518description = "Lightbox photo display widget" 
    6 author = "Lokesh Dhakar, Kevin Dangoor
     19author = "Lokesh Dhakar, Kevin Dangoor, Christopher Arndt
    720email = "dangoor+lightbox@gmail.com" 
    8 copyright = "Copyright 2006
     21copyright = "Copyright 2006 - 2008
    922 
    1023# if it's open source, you might want to specify these 
    11 url = "http://www.turbogears.org/widgets/
    12 download_url = "http://www.turbogears.org/widgets/
     24url = "http://docs.turbogears.org/tgLightbox
     25download_url = "http://pypi.python.org/pypi/Lightbox
    1326license = "MIT" 
  • projects/tgLightbox/trunk/lightbox/static/css/lightbox.css

    r1056 r4527  
    1 #lightbox{ 
    2         position: absolute; 
    3         top: 40px; 
    4         left: 0; 
    5         width: 100%; 
    6         z-index: 100; 
    7         } 
    8 #lightbox img{ border: none;    } 
     1#lightbox{      position: absolute;     left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;} 
     2#lightbox img{ width: auto; height: auto;} 
     3#lightbox a img{ border: none; } 
    94 
    10 #imageContainer{ 
    11         position: relative; 
    12         padding: 10px; 
    13         background-color: #fff; 
    14         width: 250px; 
    15         height: 250px; 
    16         margin: 0 auto; 
    17         } 
     5#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; } 
     6#imageContainer{ padding: 10px; } 
    187 
    19 #loading{ 
    20         position: absolute; 
    21         top: 40%; 
    22         left: 0%; 
    23         height: 25%; 
    24         width: 100%; 
    25         text-align: center; 
    26         line-height: 0; 
    27         } 
    28 #hoverNav{ 
    29         position: absolute; 
    30         top: 0; 
    31         left: 10px; 
    32         height: 100%; 
    33         width: 100%; 
    34         z-index: 10; 
    35         } 
     8#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; } 
     9#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; } 
    3610#imageContainer>#hoverNav{ left: 0;} 
    3711#hoverNav a{ outline: none;} 
    3812 
    39 #prevLink, #nextLink{ 
    40         width: 49%; 
    41         height: 100%; 
    42         background: transparent url(../images/blank.gif) no-repeat; /* Trick IE into showing hover */ 
    43         display: block; 
    44         } 
    45 #prevLink { left: 0; float: left; } 
    46 #nextLink { right: 0; float: right; } 
    47 #prevLink:hover, #prevLink:visited:hover { background: url(../images/prev.gif) left 53% no-repeat; } 
    48 #nextLink:hover, #nextLink:visited:hover { background: url(../images/next.gif) right 53% no-repeat; } 
     13#prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; } 
     14#prevLink { left: 0; float: left;} 
     15#nextLink { right: 0; float: right;} 
     16#prevLink:hover, #prevLink:visited:hover { background: url(../images/prevlabel.gif) left 15% no-repeat; } 
     17#nextLink:hover, #nextLink:visited:hover { background: url(../images/nextlabel.gif) right 15% no-repeat; } 
    4918 
     19#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; } 
    5020 
    51 #imageData{ 
    52         font: 10px Verdana, Helvetica, sans-serif; 
    53         background-color: #fff; 
    54         margin: 0 auto; 
    55         padding:0 10px 0 10px; 
    56         line-height: 1.4em; 
    57         height: 38px; 
    58         } 
     21#imageData{     padding:0 10px; color: #666; } 
    5922#imageData #imageDetails{ width: 70%; float: left; text-align: left; }   
    6023#imageData #caption{ font-weight: bold; } 
    61 #imageData #numberDisplay{ display: block; clear: left; }                        
    62 #imageData #bottomNavClose{ width: 36px; float: right;  }        
    63                  
    64 #overlay{ 
    65         position: absolute; 
    66         top: 0; 
    67         left: 0; 
    68         z-index: 90; 
    69         width: 100%; 
    70         height: 500px; 
    71         background-color: #000; 
    72         filter:alpha(opacity=60); 
    73         -moz-opacity: 0.6; 
    74         opacity: 0.6; 
    75         } 
     24#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em;  }                        
     25#imageData #bottomNavClose{ width: 66px; float: right;  padding-bottom: 0.7em; outline: none;}           
     26 
     27#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; } 
  • projects/tgLightbox/trunk/lightbox/static/javascript/lightbox.js

    r1056 r4527  
    11// ----------------------------------------------------------------------------------- 
    22// 
    3 //      Lightbox v2.0   
    4 //      by Lokesh Dhakar - http://www.huddletogether.com 
    5 //      3/27/06 
    6 // 
    7 //      For more information on this script, visit: 
    8 //      http://huddletogether.com/projects/lightbox2/ 
     3//      Lightbox v2.04 
     4//      by Lokesh Dhakar - http://www.lokeshdhakar.com 
     5//      Last Modification: 2/9/08 
     6// 
     7//      For more information, visit: 
     8//      http://lokeshdhakar.com/projects/lightbox2/ 
    99// 
    1010//      Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ 
     11//      - Free for use in both personal and commercial projects 
     12//              - Attribution requires leaving author name, author link, and the license info intact. 
    1113//       
    12 //      Credit also due to those who have helped, inspired, and made their code available to the public. 
    13 //      Including: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.org), Thomas Fuchs(mir.aculo.us), and others. 
    14 // 
     14//  Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets. 
     15//              Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous. 
    1516// 
    1617// ----------------------------------------------------------------------------------- 
    1718/* 
    1819 
    19         Table of Contents 
    20         ----------------- 
    21         Configuration 
    22         Global Variables 
    23  
    24         Extending Built-in Objects       
    25         - Object.extend(Element) 
    26         - Array.prototype.removeDuplicates() 
    27         - Array.prototype.empty() 
    28  
    29         lightbox Class Declaration 
    30         - initialize() 
    31         - start() 
    32         - changeImage() 
    33         - resizeImageContainer() 
    34         - showImage() 
    35         - updateDetails() 
    36         - updateNav() 
    37         - preloadNeighborImages() 
    38         - end() 
    39          
    40         Miscellaneous Functions 
    41         - getPageScroll() 
    42         - getPageSize() 
    43         - getKey() 
    44         - listenKey() 
    45         - showSelectBoxes() 
    46         - hideSelectBoxes() 
    47         - pause() 
    48         - addLoadEvent() 
    49         - initLightbox() 
    50          
    51         Function Calls 
    52         - addLoadEvent(initLightbox) 
    53          
     20    Table of Contents 
     21    ----------------- 
     22    Configuration 
     23 
     24    Lightbox Class Declaration 
     25    - initialize() 
     26    - updateImageList() 
     27    - start() 
     28    - changeImage() 
     29    - resizeImageContainer() 
     30    - showImage() 
     31    - updateDetails() 
     32    - updateNav() 
     33    - enableKeyboardNav() 
     34    - disableKeyboardNav() 
     35    - keyboardAction() 
     36    - preloadNeighborImages() 
     37    - end() 
     38     
     39    Function Calls 
     40    - document.observe() 
     41    
    5442*/ 
    5543// ----------------------------------------------------------------------------------- 
    5644 
    5745// 
    58 //      Configuration 
    59 // 
    60 var fileLoadingImage = "images/loading.gif";             
    61 var fileBottomNavCloseImage = "images/close.gif"; 
    62 var borderSize = 10; 
     46//  Configurationl 
     47// 
     48LightboxOptions = Object.extend({ 
     49    fileLoadingImage:        'images/loading.gif',      
     50    fileBottomNavCloseImage: 'images/closelabel.gif', 
     51 
     52    overlayOpacity: 0.8,   // controls transparency of shadow overlay 
     53 
     54    animate: true,         // toggles resizing animations 
     55    resizeSpeed: 7,        // controls the speed of the image resizing animations (1=slowest and 10=fastest) 
     56 
     57    borderSize: 10,         //if you adjust the padding in the CSS, you will need to update this variable 
     58 
     59        // When grouping images this is used to write: Image # of #. 
     60        // Change it for non-english localization 
     61        labelImage: "Image", 
     62        labelOf: "of" 
     63}, window.LightboxOptions || {}); 
    6364 
    6465// ----------------------------------------------------------------------------------- 
    6566 
    66 // 
    67 //      Global Variables 
    68 // 
    69 var imageArray = new Array; 
    70 var activeImage; 
    71  
    72 // ----------------------------------------------------------------------------------- 
    73  
    74 // 
    75 //      Additional methods for Element added by SU, Couloir 
    76 //      - further additions by Lokesh Dhakar (huddletogether.com) 
    77 // 
    78 Object.extend(Element, { 
    79         getWidth: function(element) { 
    80                 element = $(element); 
    81                 return element.offsetWidth;  
    82         }, 
    83         setWidth: function(element,w) { 
    84                 element = $(element); 
    85         element.style.width = w +"px"; 
    86         }, 
    87         setHeight: function(element,h) { 
    88                 element = $(element); 
    89         element.style.height = h +"px"; 
    90         }, 
    91         setTop: function(element,t) { 
    92                 element = $(element); 
    93         element.style.top = t +"px"; 
    94         }, 
    95         setSrc: function(element,src) { 
    96         element = $(element); 
    97         element.src = src;  
    98         }, 
    99         setHref: function(element,href) { 
    100         element = $(element); 
    101         element.href = href;  
    102         }, 
    103         setInnerHTML: function(element,content) { 
    104                 element = $(element); 
    105                 element.innerHTML = content; 
    106         } 
    107 }); 
    108  
    109 // ----------------------------------------------------------------------------------- 
    110  
    111 // 
    112 //      Extending built-in Array object 
    113 //      - array.removeDuplicates() 
    114 //      - array.empty() 
    115 // 
    116 Array.prototype.removeDuplicates = function () { 
    117         for(i = 1; i < this.length; i++){ 
    118                 if(this[i][0] == this[i-1][0]){ 
    119                         this.splice(i,1); 
     67var Lightbox = Class.create(); 
     68 
     69Lightbox.prototype = { 
     70    imageArray: [], 
     71    activeImage: undefined, 
     72     
     73    // initialize() 
     74    // Constructor runs on completion of the DOM loading. Calls updateImageList and then 
     75    // the function inserts html at the bottom of the page which is used to display the shadow  
     76    // overlay and the image container. 
     77    // 
     78    initialize: function() {     
     79         
     80        this.updateImageList(); 
     81         
     82        this.keyboardAction = this.keyboardAction.bindAsEventListener(this); 
     83 
     84        if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10; 
     85        if (LightboxOptions.resizeSpeed < 1)  LightboxOptions.resizeSpeed = 1; 
     86 
     87            this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0; 
     88            this.overlayDuration = LightboxOptions.animate ? 0.2 : 0;  // shadow fade in/out duration 
     89 
     90        // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension. 
     91        // If animations are turned off, it will be hidden as to prevent a flicker of a 
     92        // white 250 by 250 box. 
     93        var size = (LightboxOptions.animate ? 250 : 1) + 'px'; 
     94         
     95 
     96        // Code inserts html at the bottom of the page that looks similar to this: 
     97        // 
     98        //  <div id="overlay"></div> 
     99        //  <div id="lightbox"> 
     100        //      <div id="outerImageContainer"> 
     101        //          <div id="imageContainer"> 
     102        //              <img id="lightboxImage"> 
     103        //              <div style="" id="hoverNav"> 
     104        //                  <a href="#" id="prevLink"></a> 
     105        //                  <a href="#" id="nextLink"></a> 
     106        //              </div> 
     107        //              <div id="loading"> 
     108        //                  <a href="#" id="loadingLink"> 
     109        //                      <img src="images/loading.gif"> 
     110        //                  </a> 
     111        //              </div> 
     112        //          </div> 
     113        //      </div> 
     114        //      <div id="imageDataContainer"> 
     115        //          <div id="imageData"> 
     116        //              <div id="imageDetails"> 
     117        //                  <span id="caption"></span> 
     118        //                  <span id="numberDisplay"></span> 
     119        //              </div> 
     120        //              <div id="bottomNav"> 
     121        //                  <a href="#" id="bottomNavClose"> 
     122        //                      <img src="images/close.gif"> 
     123        //                  </a> 
     124        //              </div> 
     125        //          </div> 
     126        //      </div> 
     127        //  </div> 
     128 
     129 
     130        var objBody = $$('body')[0]; 
     131 
     132                objBody.appendChild(Builder.node('div',{id:'overlay'})); 
     133         
     134        objBody.appendChild(Builder.node('div',{id:'lightbox'}, [ 
     135            Builder.node('div',{id:'outerImageContainer'},  
     136                Builder.node('div',{id:'imageContainer'}, [ 
     137                    Builder.node('img',{id:'lightboxImage'}),  
     138                    Builder.node('div',{id:'hoverNav'}, [ 
     139                        Builder.node('a',{id:'prevLink', href: '#' }), 
     140                        Builder.node('a',{id:'nextLink', href: '#' }) 
     141                    ]), 
     142                    Builder.node('div',{id:'loading'},  
     143                        Builder.node('a',{id:'loadingLink', href: '#' },  
     144                            Builder.node('img', {src: LightboxOptions.fileLoadingImage}) 
     145                        ) 
     146                    ) 
     147                ]) 
     148            ), 
     149            Builder.node('div', {id:'imageDataContainer'}, 
     150                Builder.node('div',{id:'imageData'}, [ 
     151                    Builder.node('div',{id:'imageDetails'}, [ 
     152                        Builder.node('span',{id:'caption'}), 
     153                        Builder.node('span',{id:'numberDisplay'}) 
     154                    ]), 
     155                    Builder.node('div',{id:'bottomNav'}, 
     156                        Builder.node('a',{id:'bottomNavClose', href: '#' }, 
     157                            Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage }) 
     158                        ) 
     159                    ) 
     160                ]) 
     161            ) 
     162        ])); 
     163 
     164 
     165                $('overlay').hide().observe('click', (function() { this.end(); }).bind(this)); 
     166                $('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this)); 
     167                $('outerImageContainer').setStyle({ width: size, height: size }); 
     168                $('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this)); 
     169                $('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this)); 
     170                $('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this)); 
     171                $('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this)); 
     172 
     173        var th = this; 
     174        (function(){ 
     175            var ids =  
     176                'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +  
     177                'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';    
     178            $w(ids).each(function(id){ th[id] = $(id); }); 
     179        }).defer(); 
     180    }, 
     181 
     182    // 
     183    // updateImageList() 
     184    // Loops through anchor tags looking for 'lightbox' references and applies onclick 
     185    // events to appropriate links. You can rerun after dynamically adding images w/ajax. 
     186    // 
     187    updateImageList: function() {    
     188        this.updateImageList = Prototype.emptyFunction; 
     189 
     190        document.observe('click', (function(event){ 
     191            var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]'); 
     192            if (target) { 
     193                event.stop(); 
     194                this.start(target); 
     195            } 
     196        }).bind(this)); 
     197    }, 
     198     
     199    // 
     200    //  start() 
     201    //  Display overlay and lightbox. If image is part of a set, add siblings to imageArray. 
     202    // 
     203    start: function(imageLink) {     
     204 
     205        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' }); 
     206 
     207        // stretch overlay to fill page and fade in 
     208        var arrayPageSize = this.getPageSize(); 
     209        $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' }); 
     210 
     211        new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity }); 
     212 
     213        this.imageArray = []; 
     214        var imageNum = 0;        
     215 
     216        if ((imageLink.rel == 'lightbox')){ 
     217            // if image is NOT part of a set, add single image to imageArray 
     218            this.imageArray.push([imageLink.href, imageLink.title]);          
     219        } else { 
     220            // if image is part of a set.. 
     221            this.imageArray =  
     222                $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]'). 
     223                collect(function(anchor){ return [anchor.href, anchor.title]; }). 
     224                uniq(); 
     225             
     226            while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; } 
     227        } 
     228 
     229        // calculate top and left offset for the lightbox  
     230        var arrayPageScroll = document.viewport.getScrollOffsets(); 
     231        var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10); 
     232        var lightboxLeft = arrayPageScroll[0]; 
     233        this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show(); 
     234         
     235        this.changeImage(imageNum); 
     236    }, 
     237 
     238    // 
     239    //  changeImage() 
     240    //  Hide most elements and preload image in preparation for resizing image container. 
     241    // 
     242    changeImage: function(imageNum) {    
     243         
     244        this.activeImage = imageNum; // update global var 
     245 
     246        // hide elements during transition 
     247        if (LightboxOptions.animate) this.loading.show(); 
     248        this.lightboxImage.hide(); 
     249        this.hoverNav.hide(); 
     250        this.prevLink.hide(); 
     251        this.nextLink.hide(); 
     252                // HACK: Opera9 does not currently support scriptaculous opacity and appear fx 
     253        this.imageDataContainer.setStyle({opacity: .0001}); 
     254        this.numberDisplay.hide();       
     255         
     256        var imgPreloader = new Image(); 
     257         
     258        // once image is preloaded, resize image container 
     259 
     260 
     261        imgPreloader.onload = (function(){ 
     262            this.lightboxImage.src = this.imageArray[this.activeImage][0]; 
     263            this.resizeImageContainer(imgPreloader.width, imgPreloader.height); 
     264        }).bind(this); 
     265        imgPreloader.src = this.imageArray[this.activeImage][0]; 
     266    }, 
     267 
     268    // 
     269    //  resizeImageContainer() 
     270    // 
     271    resizeImageContainer: function(imgWidth, imgHeight) { 
     272 
     273        // get current width and height 
     274        var widthCurrent  = this.outerImageContainer.getWidth(); 
     275        var heightCurrent = this.outerImageContainer.getHeight(); 
     276 
     277        // get new width and height 
     278        var widthNew  = (imgWidth  + LightboxOptions.borderSize * 2); 
     279        var heightNew = (imgHeight + LightboxOptions.borderSize * 2); 
     280 
     281        // scalars based on change from old to new 
     282        var xScale = (widthNew  / widthCurrent)  * 100; 
     283        var yScale = (heightNew / heightCurrent) * 100; 
     284 
     285        // calculate size difference between new and old image, and resize if necessary 
     286        var wDiff = widthCurrent - widthNew; 
     287        var hDiff = heightCurrent - heightNew; 
     288 
     289        if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});  
     290        if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});  
     291 
     292        // if new and old image are same size and no scaling transition is necessary,  
     293        // do a quick pause to prevent image flicker. 
     294        var timeout = 0; 
     295        if ((hDiff == 0) && (wDiff == 0)){ 
     296            timeout = 100; 
     297            if (Prototype.Browser.IE) timeout = 250;    
     298        } 
     299 
     300        (function(){ 
     301            this.prevLink.setStyle({ height: imgHeight + 'px' }); 
     302            this.nextLink.setStyle({ height: imgHeight + 'px' }); 
     303            this.imageDataContainer.setStyle({ width: widthNew + 'px' }); 
     304 
     305            this.showImage(); 
     306        }).bind(this).delay(timeout / 1000); 
     307    }, 
     308     
     309    // 
     310    //  showImage() 
     311    //  Display image and begin preloading neighbors. 
     312    // 
     313    showImage: function(){ 
     314        this.loading.hide(); 
     315        new Effect.Appear(this.lightboxImage, {  
     316            duration: this.resizeDuration,  
     317            queue: 'end',  
     318            afterFinish: (function(){ this.updateDetails(); }).bind(this)  
     319        }); 
     320        this.preloadNeighborImages(); 
     321    }, 
     322 
     323    // 
     324    //  updateDetails() 
     325    //  Display caption, image number, and bottom nav. 
     326    // 
     327    updateDetails: function() { 
     328     
     329        // if caption is not null 
     330        if (this.imageArray[this.activeImage][1] != ""){ 
     331            this.caption.update(this.imageArray[this.activeImage][1]).show(); 
     332        } 
     333         
     334        // if image is part of set display 'Image x of x'  
     335        if (this.imageArray.length > 1){ 
     336            this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + '  ' + this.imageArray.length).show(); 
     337        } 
     338 
     339        new Effect.Parallel( 
     340            [  
     341                new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),  
     342                new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })  
     343            ],  
     344            {  
     345                duration: this.resizeDuration,  
     346                afterFinish: (function() { 
     347                        // update overlay size and update nav 
     348                        var arrayPageSize = this.getPageSize(); 
     349                        this.overlay.setStyle({ height: arrayPageSize[1] + 'px' }); 
     350                        this.updateNav(); 
     351                }).bind(this) 
     352            }  
     353        ); 
     354    }, 
     355 
     356    // 
     357    //  updateNav() 
     358    //  Display appropriate previous and next hover navigation. 
     359    // 
     360    updateNav: function() { 
     361 
     362        this.hoverNav.show();                
     363 
     364        // if not first image in set, display prev image button 
     365        if (this.activeImage > 0) this.prevLink.show(); 
     366 
     367        // if not last image in set, display next image button 
     368        if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show(); 
     369         
     370        this.enableKeyboardNav(); 
     371    }, 
     372 
     373    // 
     374    //  enableKeyboardNav() 
     375    // 
     376    enableKeyboardNav: function() { 
     377        document.observe('keydown', this.keyboardAction);  
     378    }, 
     379 
     380    // 
     381    //  disableKeyboardNav() 
     382    // 
     383    disableKeyboardNav: function() { 
     384        document.stopObserving('keydown', this.keyboardAction);  
     385    }, 
     386 
     387    // 
     388    //  keyboardAction() 
     389    // 
     390    keyboardAction: function(event) { 
     391        var keycode = event.keyCode; 
     392 
     393        var escapeKey; 
     394        if (event.DOM_VK_ESCAPE) {  // mozilla 
     395            escapeKey = event.DOM_VK_ESCAPE; 
     396        } else { // ie 
     397            escapeKey = 27; 
     398        } 
     399 
     400        var key = String.fromCharCode(keycode).toLowerCase(); 
     401         
     402        if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox 
     403            this.end(); 
     404        } else if ((key == 'p') || (keycode == 37)){ // display previous image 
     405            if (this.activeImage != 0){ 
     406                this.disableKeyboardNav(); 
     407                this.changeImage(this.activeImage - 1); 
     408            } 
     409        } else if ((key == 'n') || (keycode == 39)){ // display next image 
     410            if (this.activeImage != (this.imageArray.length - 1)){ 
     411                this.disableKeyboardNav(); 
     412                this.changeImage(this.activeImage + 1); 
     413            } 
     414        } 
     415    }, 
     416 
     417    // 
     418    //  preloadNeighborImages() 
     419    //  Preload previous and next images. 
     420    // 
     421    preloadNeighborImages: function(){ 
     422        var preloadNextImage, preloadPrevImage; 
     423        if (this.imageArray.length > this.activeImage + 1){ 
     424            preloadNextImage = new Image(); 
     425            preloadNextImage.src = this.imageArray[this.activeImage + 1][0]; 
     426        } 
     427        if (this.activeImage > 0){ 
     428            preloadPrevImage = new Image(); 
     429            preloadPrevImage.src = this.imageArray[this.activeImage - 1][0]; 
     430        } 
     431     
     432    }, 
     433 
     434    // 
     435    //  end() 
     436    // 
     437    end: function() { 
     438        this.disableKeyboardNav(); 
     439        this.lightbox.hide(); 
     440        new Effect.Fade(this.overlay, { duration: this.overlayDuration }); 
     441        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' }); 
     442    }, 
     443 
     444    // 
     445    //  getPageSize() 
     446    // 
     447    getPageSize: function() { 
     448                 
     449             var xScroll, yScroll; 
     450                 
     451                if (window.innerHeight && window.scrollMaxY) {   
     452                        xScroll = window.innerWidth + window.scrollMaxX; 
     453                        yScroll = window.innerHeight + window.scrollMaxY; 
     454                } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac 
     455                        xScroll = document.body.scrollWidth; 
     456                        yScroll = document.body.scrollHeight; 
     457                } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari 
     458                        xScroll = document.body.offsetWidth; 
     459                        yScroll = document.body.offsetHeight; 
    120460                } 
     461                 
     462                var windowWidth, windowHeight; 
     463                 
     464                if (self.innerHeight) { // all except Explorer 
     465                        if(document.documentElement.clientWidth){ 
     466                                windowWidth = document.documentElement.clientWidth;  
     467                        } else { 
     468                                windowWidth = self.innerWidth; 
     469                        } 
     470                        windowHeight = self.innerHeight; 
     471                } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode 
     472                        windowWidth = document.documentElement.clientWidth; 
     473                        windowHeight = document.documentElement.clientHeight; 
     474                } else if (document.body) { // other Explorers 
     475                        windowWidth = document.body.clientWidth; 
     476                        windowHeight = document.body.clientHeight; 
     477                }        
     478                 
     479                // for small pages with total height less then height of the viewport 
     480                if(yScroll < windowHeight){ 
     481                        pageHeight = windowHeight; 
     482                } else {  
     483                        pageHeight = yScroll; 
     484                } 
     485         
     486                // for small pages with total width less then width of the viewport 
     487                if(xScroll < windowWidth){       
     488                        pageWidth = xScroll;             
     489                } else { 
     490                        pageWidth = windowWidth; 
     491                } 
     492 
     493                return [pageWidth,pageHeight]; 
    121494        } 
    122495} 
    123496 
    124 // ----------------------------------------------------------------------------------- 
    125  
    126 Array.prototype.empty = function () { 
    127         for(i = 0; i <= this.length; i++){ 
    128                 this.shift(); 
    129         } 
    130 
    131  
    132 // ----------------------------------------------------------------------------------- 
    133  
    134 // 
    135 //      lightbox Class Declaration 
    136 //      - initialize() 
    137 //      - start() 
    138 //      - changeImage() 
    139 //      - resizeImageContainer() 
    140 //      - showImage() 
    141 //      - updateDetails() 
    142 //      - updateNav() 
    143 //      - preloadNeighborImages() 
    144 //      - end() 
    145 // 
    146 //      Structuring of code inspired by Scott Upton (http://www.uptonic.com/) 
    147 // 
    148 var lightbox = Class.create(); 
    149  
    150 lightbox.prototype = { 
    151          
    152         // initialize() 
    153         // Constructor runs on completion of the DOM loading. Loops through anchor tags looking for  
    154         // 'lightbox' references and applies onclick events to appropriate links. The 2nd section of 
    155         // the function inserts html at the bottom of the page which is used to display the shadow  
    156         // overlay and the image container. 
    157         // 
    158         initialize: function() {         
    159                 if (!document.getElementsByTagName){ return; } 
    160                 var anchors = document.getElementsByTagName('a'); 
    161  
    162                 // loop through all anchor tags 
    163                 for (var i=0; i<anchors.length; i++){ 
    164                         var anchor = anchors[i]; 
    165                          
    166                         var relAttribute = String(anchor.getAttribute('rel')); 
    167                          
    168                         // use the string.match() method to catch 'lightbox' references in the rel attribute 
    169                         if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){ 
    170                                 anchor.onclick = function () {myLightbox.start(this); return false;} 
    171                         } 
    172                 } 
    173  
    174                 // The rest of this code inserts html at the bottom of the page that looks similar to this: 
    175                 // 
    176                 //      <div id="overlay"></div> 
    177                 //      <div id="lightbox"> 
    178                 //              <div id="imageContainer"> 
    179                 //                      <img id="lightboxImage"> 
    180                 //                      <div style="" id="hoverNav"> 
    181                 //                              <a href="#" id="prevLink"></a> 
    182                 //                              <a href="#" id="nextLink"></a> 
    183                 //                      </div> 
    184                 //                      <div id="loading"> 
    185                 //                              <a href="#" id="loadingLink"> 
    186                 //                                      <img src="images/loading.gif"> 
    187                 //                              </a> 
    188                 //                      </div> 
    189                 //              </div> 
    190                 //              <div id="imageData"> 
    191                 //                      <div id="imageDetails"> 
    192                 //                              <span id="caption"></span> 
    193                 //                              <span id="numberDisplay"></span> 
    194                 //                      </div> 
    195                 //                      <div id="bottomNav"> 
    196                 //                              <a href="#" id="bottomNavClose"> 
    197                 //                                      <img src="images/close.gif"> 
    198                 //                              </a> 
    199                 //                      </div> 
    200                 //              </div> 
    201                 //      </div>   
    202  
    203  
    204                 var objBody = document.getElementsByTagName("body").item(0); 
    205                  
    206                 var objOverlay = document.createElement("div"); 
    207                 objOverlay.setAttribute('id','overlay'); 
    208                 objOverlay.style.display = 'none'; 
    209                 objOverlay.onclick = function() { myLightbox.end(); return false; } 
    210                 objBody.appendChild(objOverlay); 
    211                  
    212                 var objLightbox = document.createElement("div"); 
    213                 objLightbox.setAttribute('id','lightbox'); 
    214                 objLightbox.style.display = 'none'; 
    215                 objBody.appendChild(objLightbox); 
    216          
    217                 var objImageContainer = document.createElement("div"); 
    218                 objImageContainer.setAttribute('id','imageContainer'); 
    219                 objImageContainer.onclick = null; 
    220                 objLightbox.appendChild(objImageContainer); 
    221          
    222                 var objLightboxImage = document.createElement("img"); 
    223                 objLightboxImage.setAttribute('id','lightboxImage'); 
    224                 objImageContainer.appendChild(objLightboxImage); 
    225          
    226                 var objHoverNav = document.createElement("div"); 
    227                 objHoverNav.setAttribute('id','hoverNav'); 
    228                 objImageContainer.appendChild(objHoverNav); 
    229          
    230                 var objPrevLink = document.createElement("a"); 
    231                 objPrevLink.setAttribute('id','prevLink'); 
    232                 objPrevLink.setAttribute('href','#'); 
    233                 objHoverNav.appendChild(objPrevLink); 
    234                  
    235                 var objNextLink = document.createElement("a"); 
    236                 objNextLink.setAttribute('id','nextLink'); 
    237                 objNextLink.setAttribute('href','#'); 
    238                 objHoverNav.appendChild(objNextLink); 
    239          
    240                 var objLoading = document.createElement("div"); 
    241                 objLoading.setAttribute('id','loading'); 
    242                 objImageContainer.appendChild(objLoading); 
    243          
    244                 var objLoadingLink = document.createElement("a"); 
    245                 objLoadingLink.setAttribute('id','loadingLink'); 
    246                 objLoadingLink.setAttribute('href','#'); 
    247                 objLoadingLink.onclick = function() { myLightbox.end(); return false; } 
    248                 objLoading.appendChild(objLoadingLink); 
    249          
    250                 var objLoadingImage = document.createElement("img"); 
    251                 objLoadingImage.setAttribute('src', fileLoadingImage); 
    252                 objLoadingLink.appendChild(objLoadingImage); 
    253          
    254                 var objImageData = document.createElement("div"); 
    255                 objImageData.setAttribute('id','imageData'); 
    256                 objLightbox.appendChild(objImageData); 
    257          
    258                 var objImageDetails = document.createElement("div"); 
    259                 objImageDetails.setAttribute('id','imageDetails'); 
    260                 objImageData.appendChild(objImageDetails); 
    261          
    262                 var objCaption = document.createElement("span"); 
    263                 objCaption.setAttribute('id','caption'); 
    264                 objImageDetails.appendChild(objCaption); 
    265          
    266                 var objNumberDisplay = document.createElement("span"); 
    267                 objNumberDisplay.setAttribute('id','numberDisplay'); 
    268                 objImageDetails.appendChild(objNumberDisplay); 
    269                  
    270                 var objBottomNav = document.createElement("div"); 
    271                 objBottomNav.setAttribute('id','bottomNav'); 
    272                 objImageData.appendChild(objBottomNav); 
    273          
    274                 var objBottomNavCloseLink = document.createElement("a"); 
    275                 objBottomNavCloseLink.setAttribute('id','bottomNavClose'); 
    276                 objBottomNavCloseLink.setAttribute('href','#'); 
    277                 objBottomNavCloseLink.onclick = function() { myLightbox.end(); return false; } 
    278                 objBottomNav.appendChild(objBottomNavCloseLink); 
    279          
    280                 var objBottomNavCloseImage = document.createElement("img"); 
    281                 objBottomNavCloseImage.setAttribute('src', fileBottomNavCloseImage); 
    282                 objBottomNavCloseLink.appendChild(objBottomNavCloseImage); 
    283         }, 
    284          
    285         // 
    286         //      start() 
    287         //      Display overlay and lightbox. If image is part of a set, add siblings to imageArray. </