After trying to get my website working with other lightboxes, it seemed a good idea to make a new one, Most responsive lightboxes require very large libraries and are not easily customizable. So I wrote my own for this site. Here is a demo.

'Render unto Caesar that which is Caesar's': a demonstration of the yView lightbox
'Render unto Caesar that which is Caesar's': a demonstration of the yView lightbox

Overview

It started with the original Dynamic Drive lightbox version in Multithumb, which was one of the smallest I could find. But it had a number of problems: it didn't resize images to smaller screens;the captions are hidden behind the images; the opacity animation only works after the second load of the same picture, and it has no built-in slideshow support.

On the other hand, it was very well written, and one of the smallest around, and didn't require jQuery or Mootools. So I decided to fix it, and add it to Joomla, and extend it to support Youtube videos. So I am sharing it in case anyone is interested in working with me on it, and this version isn't finished yet, but here is the code. as it stands currently.

Page Layout

When the page loads, Yview adds an invisible DIV element to the end of the BODY element which contains some nested DIVs:

Yview DIV Elements
Yview DIV Elements

The Yback element is a fixed DIV that that is invisible when Yview is not in use. When visible, it fills the entire screen, adding some opacity to dim the rest of the page while the image is being displayed. It also contains an animated GIF which may display while the image is being fetched (if the image is large enough or the connection slow enough to cause any delay during load).

The Ybox div contains the full-size image, and the Yfooter div contains the caption and close text. All these DIVs are styled with CSS, which is added to the page header if a lightbox is needed on the page.

Integration with Joomla

I started with Multithumb, which I've used for years. But now the site uses Mavik's thumbnails, for three reasons. First, Mavik provides a developer license. Second, the thumbnails are stored in the image directory, rather the cache, so Prizm optimization can be run on the thumbnails. Third, Mavik supports template overrides, which simplifies integration. This got my going. However then I found I could use Imagick to obtain equal image quality as from Prizm, and automate the image optimization; and Mavick's thumbnail library only supports GD2, and not Imagick, So I wrote my own plugin from scratch, which is described here:

Yview Thumbnails for Joomla

The JavaScript Portion

For the Joomla plugin, the script adds the HTML elements necessary to the BODY element. The additions are meant cross-browser compatible and shrink the image as best as possible to fit on a screen, if the image is too large to fit. Otherwise it centers the image. The background uses about five lines of CSS to center a busy icon on the screen,for which I have seen many hundreds of lines of code, but so far the five lines of CSS seem to work fine. The image calculations require to know the actual pixel (x,y) values for the center of the screen and its size, so that code is more complicated, but it looks pretty much the same as it did the last time I made something like this a decade ago. I'm sure it could be done better in JQuery, but this is only 4KB:)

Hide LIne Numbers
  1. /******************************************************************************/
  2. /* yView: the Smallest Responsive LightBox in Pure JavaScript  
  3. /* v 0.7, 3/25/2015
  4. /* GNU GPL, Ernest Meyer, http://www.yofiel.com  
  5. /******************************************************************************/
  6. var yView={yw:0,yh:0,yt:0
  7. ,yInit:function(){var i, c, y, v, s, n;
  8.     var divTag=document.createElement("div")
  9.     divTag.id="Yview"
  10.     divTag.style="float:left;width:100%;clear:both"
  11.     divTag.innerHTML='<div id="yBack"><div id="ySpin"></div><div id="yBox"><div id="yImage" onClick="javascript:yView.yClose()"></div><div id="yFoot"></div></div></div>'
  12.     document.body.appendChild(divTag)
  13.     this.ySpin=document.getElementById("ySpin")
  14.     this.yBack=document.getElementById("yBack")
  15.     this.yFoot=document.getElementById("yFoot")
  16.     this.yBox=document.getElementById("yBox")
  17.     this.yImage=document.getElementById("yImage")
  18.     this.yL=document.getElementsByTagName("a")
  19.     for (var i=0;i&#60;this.yL.length;i++){
  20.         if((this.yL[i].getAttribute("data-img"))||(this.yL[i].getAttribute("rel")=="thumb")){                    
  21.                 this.yL[i].setAttribute("onclick",    
  22.                     "yView.yStop();yView.yLoad("+i+");return false")
  23.  
  24.         }
  25.     }
  26. },yChange:function(i,d){
  27.     yView.yStop()
  28.     var yc=0
  29.     for(var j=0;j&#60;yL.length;j++){
  30.         yc=i+j+d
  31.         if(yc>=yL.length)yc-=yL.length
  32.         else if(yc&lt;0)yc+=yL.length
  33.         if((this.yL[i].getAttribute("data-img"))||(this.yL[i].getAttribute("rel")=="thumb")){                        
  34.             yView.yLoad(yc)
  35.             return
  36.         }
  37.     }
  38. },yLoad:function(i){
  39.     this.yBack.style.visibility="visible"
  40.     ySpin.style.visibility="visible"
  41.     yBox.style.visibility="hidden"
  42.     yL=document.getElementsByTagName("a")
  43.     this.yImage.innerHTML='"img src="'+yLi.getAttribute('href')+'" alt=" " >'
  44.     var $t="";
  45.     var p=yL[i].childNodes[0]
  46.     this.yImg=this.yImage.getElementsByTagName("img")[0]
  47.     if(p.getAttribute("title"))$t=p.getAttribute("title")
  48.     else if(p.getAttribute("alt"))$t=p.getAttribute("alt")
  49.     this.yFoot.innerHTML='<div>'+$t+'</div><div class="btn fltrt" onclick="yView.yClose();">CLOSE X</div>'
  50.     yt=0;
  51.     this.yImg.onload=function(){
  52.         yw=yImage.offsetWidth
  53.         yh=yImage.offsetHeight+40
  54.         yView.yDraw(true)
  55.     }
  56.     if(this.yImg.onerror){
  57.         yView.ySpin.style.visibility="hidden"
  58.         yView.yStop()
  59.     }
  60. },yDraw:function(doAnim){
  61.     var yW, yH, x, y
  62.     if(typeof(window.innerWidth)=='number'){
  63.         yW=window.innerWidth-32
  64.         yH=window.innerHeight-32
  65.     }else{
  66.         yW=document.documentElement.clientWidth-32
  67.         yH=document.documentElement.clientHeight-32
  68.     }
  69.     if( (yw &#60; yW) && ( yh &#60; yH) ) {
  70.         yBox.style.width=yw*yt+'px'
  71.         yBox.style.height=yh*yt+'px'
  72.         yBox.style.top=yH*.5-yh*.5*yt+'px'
  73.         yBox.style.left=yW*.5-yw*.5*yt+'px'
  74.     }else{
  75.         x=yW/yw 
  76.         y=yH/yh     
  77.         if(x&#60;y){ 
  78.             yBox.style.width=yW*yt+'px'
  79.             yBox.style.height=yh*x*yt+'px'
  80.             yBox.style.top=yH*.5-yBox.style.height*.5*yt+'px'
  81.             yBox.style.left='0px'
  82.         }else{ 
  83.             yBox.style.width=yw*y*yt+1+'px'
  84.             yBox.style.height=yH*yt+'px'
  85.             yBox.style.top='0px' 
  86.             yBox.style.left=yW*.5-yBox.style.width*.5*yt+'px'
  87.         }
  88.     }
  89.     yBox.style.maxWidth=yBox.style.width
  90.     yBox.style.maxHeight=yBox.style.height
  91.     yBox.style.visibility="visible"
  92.     ySpin.style.visibility="hidden"
  93.     if(doAnim)this.yTimer=setInterval("yView.yAnim()",20)
  94. },yAnim:function(){
  95.     yt+=.1
  96.     if(yt&#60;=1) yView.yDraw(false)
  97.     else yView.yStop()
  98. },yStop:function(){
  99.     clearInterval(this.yTimer)
  100. },yMove:function(){
  101.     if(yBox.style.visibility=="visible") 
  102.         setTimeout(yView.yDraw(false),100)
  103. },yClose:function(){
  104.     this.yStop()
  105.     this.yBack.style.visibility="hidden"
  106.     this.ySpin.style.visibility="hidden"
  107.     this.yBox.style.visibility="hidden"
  108.     this.yImg.innerHTML=""
  109. },yClean:function(){
  110.     this.yStop()
  111.     this.yBack=null
  112.     this.ySpin=null
  113.     this.yBox=null
  114.     this.yFoot=null
  115.     this.yImage=null
  116.     if(this.yImg)this.yImg.onload=null
  117.     this.featureImage=null
  118.     for(var i=0;i&#60;this.yL.length;i++)
  119.         this.yL[i].onclick=null
  120. },yDo:function(e1,ref,task){
  121.     var task=(window.addEventListener)?task:"on"+task
  122.     if (e1.addEventListener)e1.addEventListener(task,ref,false)
  123.     else e1.attachEvent(task,ref)
  124. }}
  125. yView.yDo(window,function(){yView.yInit()},"load")
  126. yView.yDo(window,function(){yView.yMove()},"resize")
  127. yView.yDo(window,function(){yView.yClean()},"unload")

Known Issues

After resizing a page, browsers do not report correct framesize (needs timeout before resize of duration tbd)

Acknowldegments

Thanks to Lokesh Dhakar for sharing his original lightbox(http://lokeshdhakar.com/projects/lightbox2/).

changelog

This is one of those things I shall probably be diddling with over the next year or so, so if you are interested please drop a note in the forums here.

  • v0.1 - 2/22/2015: Iniital responsive version
  • v0.2 - 2/23//2015: Added zoom animation
  • v0.3 - 2/23//2015: Added semitransparent backdrop
  • v0.4 - 2/23//2015: Changes for IE edge mode support
  • v0.5 - 2/24//2015: Changes for IE8 support (but the version on this site also contains a Youtube player, which requiles HTML5)
  • v0.6 - 3/8/2015: Added slideshow viewer.