/*
  Full Size display (fs) - Show full size picture on clicking a thumbnail.
  Written for Ania Shreeve @ www.aniashreeve.com picture galleries
  by David Hucklesby @ www.hucklesby.com July 2007
  For help or queries, write mail@hucklesby.com
*/

// function addEvent(): under CC-GNU LGPL license
// from Dustin Diaz @ http://www.dustindiaz.com/rock-solid-addevent/

function addEvent( obj, type, fn ) {
  if (obj.addEventListener) {
    obj.addEventListener( type, fn, false );
    EventCache.add(obj, type, fn);
  }
  else if (obj.attachEvent) {
    obj["e"+type+fn] = fn;
    obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
    obj.attachEvent( "on"+type, obj[type+fn] );
    EventCache.add(obj, type, fn);
  }
  else {
    obj["on"+type] = obj["e"+type+fn];
  }
}

var EventCache = function(){
  var listEvents = [];
  return {
    listEvents : listEvents,
    add : function(node, sEventName, fHandler){
      if (!listEvents.push) return;
      listEvents.push(arguments);
    },
    flush : function(){
      var i, item;
      for(i = listEvents.length - 1; i >= 0; i = i - 1){
        item = listEvents[i];
        if(item[0].removeEventListener){
          item[0].removeEventListener(item[1], item[2], item[3]);
        };
        if(item[1].substring(0, 2) != "on"){
          item[1] = "on" + item[1];
        };
        if(item[0].detachEvent){
          item[0].detachEvent(item[1], item[2]);
        };
        item[0][item[1]] = null;
      };
    }
  };
}();

if (typeof Array.prototype.push !== 'function') {
  Array.prototype.push = ArrayPush;
  function ArrayPush(value) {
    this[this.length] = value;
  }
}

// First, some helper functions -

var tools = {
  addClass: function(element, myClass) {
    var classValue = myClass.replace(/\-/g, "\\-");
    var re = new RegExp("\\b ?"+classValue+"\\b");
    if (re.test(element.className)) return false;
    element.className += ' '+classValue;
    return true;
  },

  hasClass: function(element, myClass) {
    if (!element.className) return false;
    var classValue = myClass.replace(/\-/g, "\\-");
    var re = new RegExp("\\b ?"+classValue+"\\b");
    return re.test(element.className);
  },

  removeClass: function(element, myClass) {
    var classValue = myClass.replace(/\-/g, "\\-");
    var re = new RegExp("\\b ?"+classValue+"\\b");
    if (!re.test(element.className)) return false;
    element.className = element.className.replace(re, '');
    return true;
  },

  getAppliedStyle: function(element, CSSproperty) {
    var CSSvalue = '';
  // CSSproperty is of the form "margin-left"; IE requires "marginLeft"
    var IEproperty = CSSproperty;
    while (IEproperty.indexOf('-') != -1) {
      IEproperty = IEproperty.replace(/(\w+)-(\w)(.*)/,
        function(match, sub1, sub2, sub3, offset, str) {
          return sub1 + sub2.toUpperCase() + sub3;
        }
      );
    }
    if (window.getComputedStyle) {
      var computedStyle = window.getComputedStyle(element, '');
      if (computedStyle) CSSvalue = computedStyle.getPropertyValue(CSSproperty);
    } else if (element.currentStyle && !window.opera) {
      CSSvalue = element.currentStyle[IEproperty];
    }
    return CSSvalue;
  }
};

// The enchilada -
//  setup:
//  fadeMsie:
//  show:
//  hide:
//  setOpacity:
//  fade:
//  fadeMsie:
//  setFadeInState:
//  setFadeOutState:
//  addElements:
//  addPicture:
//  doPositioning:
//  deactivateLinks:
//  reactivateLinks:

var fs = {
  setup: function() {
  // requires: DOM methods support, plus a <div id="main">
  // containing a <div class="gallerycontainer"> that holds the thumbnails
    if (!document.getElementById
     || !document.getElementsByTagName
     || !document.createElement
     || !document.getElementById('main')
    ) return;

  // conditional comments to detect IE Win -
    /*@cc_on
      @if (@_win32)
        fs.isMSIE = true;
      @end @*/

    fs.main = document.getElementById('main');
    var mainDivs = fs.main.getElementsByTagName('div');
    var found = false;
    for (var i=0, j=mainDivs.length; i<j; i++) {
      fs.gallerycontainer = mainDivs[i];
      found = tools.hasClass(fs.gallerycontainer, 'gallerycontainer');
      if (found) break;
    }
    if (!found) return;

  // this detects activation of any link in the gallery :
    addEvent(fs.gallerycontainer, 'click', fs.show);

    var links = document.getElementsByTagName('a');
    for (var i=0, j=links.length; i<j; i++) {
    // deactivate link to current page
      if (!!document.body.id && tools.hasClass(links[i].parentNode, document.body.id)) {
        if (links[i].removeAttribute) links[i].removeAttribute('href');
        else links[i].href = '';
      }
      if (tools.hasClass(links[i], 'thumbnail')) {
    // only way to cancel default link action in Safari 2 :
        links[i].onclick = function() {return false;};
        links[i].savedHref = links[i].href;
        fs.thumbLinks[fs.thumbLinks.length] = links[i];
      }
    }
    fs.addElements();
  },

//  Main controls - "show" and "hide" the full-size picture

  show: function(e) {
    var clicked = (window.event) ? window.event.srcElement : e.target;
    while (clicked && clicked.tagName.toLowerCase() !== 'a' && clicked.tagName.toLowerCase() !== 'div') {
      clicked = clicked.parentNode;
    }
    if (!clicked || clicked.tagName.toLowerCase() !== 'a') return;

    if (fs.bigImage && fs.bigImage.parentNode) {
      fs.displayArea.removeChild(fs.bigImage);
      fs.bigImage = null;
    }
    fs.boxes[0].style.visibility = 'hidden';
    fs.bigImage = new Image();
    fs.bigImage.onload = fs.addPicture;
    fs.bigImage.alt = clicked.firstChild.alt;
    fs.bigImage.title = '';
    fs.bigImage.src = clicked.href;

    if (window.scrollTo) window.scrollTo(0, fs.gallerycontainer.offsetTop - 5);
    fs.displayArea.style.height = (fs.gallerycontainer.offsetHeight + fs.main.bottomPadding) + 'px';

    fs.displayArea.state = 'fading_in';
    fs.displayArea.time = 0;
    if (fs.isMSIE) {
    // IE has a glitch fading something with a filter; remove it -
      fs.closeButton.style.filter = '';
      fs.fadeMsie();
    } else {
      fs.fade();
    }
    fs.displayArea.style.display = 'block';
  },

  hide: function(e) {
    if (window.event) window.event.cancelBubble = true;
    if (e && e.stopPropagation) e.stopPropagation();
//    clearTimeout(fs.TIMEOUT_ID); // addPicture may still be waiting for image
    fs.displayArea.state = 'fading_out';
    if (fs.isMSIE) fs.fadeMsie();
    else fs.fade();
  },

//  Fade-in and fade-out routines - use browser-dependent CSS opacity

  setOpacity: function(percentOpacity, element) {
    if (typeof element.style.opacity == 'string') {
      var isMoz = (typeof element.style.MozOpacity == 'string');
      if (isMoz && percentOpacity === 100) element.style.opacity = 0.9999; // avoid Moz "flash"
      else element.style.opacity = percentOpacity / 100;
    }
    else if (typeof element.style.filter == 'string') element.style.filter = 'alpha(opacity=' + percentOpacity + ');';
    else if (typeof element.style.MozOpacity == 'string') element.style.MozOpacity = percentOpacity / 100;
  },

  fade: function() {
    var duration = 1000, interval = 50;
    switch (fs.displayArea.state) {
      case 'fading_in':
        window.setTimeout('fs.fade()', interval);
        fs.setOpacity(fs.displayArea.time * 100 / duration, fs.displayArea);
        fs.displayArea.time += interval;
        if (fs.displayArea.time > duration) {
          fs.displayArea.state = 'full';
          fs.deactivateLinks();
        }
        break;
      case 'fading_out':
        window.setTimeout('fs.fade()', interval);
        fs.displayArea.time -= interval;
        fs.setOpacity(fs.displayArea.time * 100 / duration, fs.displayArea);
        if (fs.displayArea.time <= 0) {
          fs.displayArea.state = 'hidden';
          fs.displayArea.style.display = 'none';
          fs.reactivateLinks();
        }
    }
    return;
  },

  fadeMsie: function() {
    fs.closeButton.style.visibility = 'hidden'; /* Avoid IE opacity bug */
    fs.displayArea.style.filter = 'progID:DXImageTransform.Microsoft.Fade(Duration=1)';
    switch (fs.displayArea.state) {
      case 'fading_in':
        fs.displayArea.style.visibility = 'hidden';
        fs.displayArea.filters[0].Apply();
        fs.displayArea.style.visibility = 'visible';
        fs.displayArea.filters[0].Play();
        fs.setFadeInState();
        break;
      case 'fading_out':
        fs.boxes[0].style.visibility = 'hidden';
        fs.displayArea.style.visibility = 'visible';
        fs.displayArea.filters[0].Apply();
        fs.displayArea.style.visibility = 'hidden';
        fs.displayArea.filters[0].Play();
        fs.setFadeOutState();
        break;
    }
  },

  setFadeInState: function() {
    if (fs.displayArea.filters.item('DXImageTransform.Microsoft.Fade').status !== 2) {
      fs.displayArea.state = 'full';
      fs.closeButton.style.visibility = 'visible'; /* Fix IE opacity bug */
      fs.setOpacity(fs.closeButton.opacityValue, fs.closeButton);
      fs.deactivateLinks();
      return;
    }
    window.setTimeout('fs.setFadeInState()', 20);
  },

  setFadeOutState: function() {
    if (fs.displayArea.filters.item('DXImageTransform.Microsoft.Fade').status !== 2) {
      fs.displayArea.style.display = 'none';
      fs.displayArea.state = 'hidden';
      fs.reactivateLinks();
      return;
    }
    window.setTimeout('fs.setFadeOutState()', 20);
  },

// Routines to create and populate the display area "layer"

  addElements: function() {
  // first, some measurements:
    fs.main.leftBorder = parseInt(tools.getAppliedStyle(fs.main, 'border-left-width'));
    fs.main.rightBorder = parseInt(tools.getAppliedStyle(fs.main, 'border-right-width'));
    fs.main.leftPadding = parseInt(tools.getAppliedStyle(fs.main, 'padding-left'));
    fs.main.rightPadding = parseInt(tools.getAppliedStyle(fs.main, 'padding-right'));
    fs.main.bottomPadding = parseInt(tools.getAppliedStyle(fs.main, 'padding-bottom'));
    fs.main.availableWidth = fs.main.offsetWidth - fs.main.leftBorder - fs.main.rightBorder;
  // create the container
    if (document.getElementById('fs-display')) {
      fs.displayArea = document.getElementById('fs-display');
    } else {
      fs.displayArea = document.createElement('div');
      fs.displayArea.id = 'fs-display';
      fs.gallerycontainer.appendChild(fs.displayArea);
    }
  // compute its dimensions and offset
    fs.displayArea.style.width = fs.main.availableWidth + 'px';
    fs.displayArea.style.height = (fs.gallerycontainer.offsetHeight + fs.main.bottomPadding) + 'px';
    fs.displayArea.style.left = (- fs.main.leftPadding) + 'px';
    fs.displayArea.style.top = 0;
    fs.displayArea.style.position = 'absolute';

    var picture = document.createElement('div'); picture.id = 'picture';
    var box1 = document.createElement('div'); box1.id = 'box1';
    var box2 = document.createElement('div'); box2.id = 'box2';
    var box3 = document.createElement('div'); box3.id = 'box3';

    fs.boxes[0] = picture; fs.boxes[1] = box1; fs.boxes[2] = box2; fs.boxes[3] = box3;
    var p =  document.createElement('p');
    box2.appendChild(box3);
    box1.appendChild(box2);
    picture.appendChild(box1);
    picture.appendChild(p);
    fs.displayArea.appendChild(picture);

    var button = document.createElement('a');
    var buttonText = document.createTextNode('Close ');
    var span = document.createElement('span');
    var spanText = document.createTextNode('×');

    span.appendChild(spanText);
    button.appendChild(buttonText);
    button.appendChild(span);
    button.href = '#void';
    button.style.width = fs.main.availableWidth + 'px';
    button.style.position = 'absolute';
    button.style.top = '0';
    button.style.left = '0';
    fs.setOpacity(40, button);
    button.opacityValue = 40;
    fs.closeButton = button;
    fs.displayArea.appendChild(button);

    addEvent(button, 'mouseover', function() {fs.setOpacity(100, this);});
    addEvent(button, 'focus', function() {fs.setOpacity(100, this);});
    addEvent(button, 'mouseout', function() {fs.setOpacity(this.opacityValue, this);});
    addEvent(button, 'blur', function() {fs.setOpacity(this.opacityValue, this);});
    addEvent(button, 'click', fs.hide);
  },

  addPicture: function() {
    var caption = fs.boxes[0].lastChild;
    var captionText = document.createTextNode(fs.bigImage.alt);
    var oldText = caption.firstChild;
    if (oldText) {
      caption.removeChild(oldText);
      oldText = null;
    }
    caption.appendChild(captionText);
    fs.doPositioning();
    fs.displayArea.appendChild(fs.bigImage);
    fs.boxes[0].style.visibility = 'visible';
    return;
  },

  doPositioning: function() {
  // compute sizes of the boxes holding the image
    var iWidth = fs.bigImage.width + 2, iHeight = fs.bigImage.height + 2; // 1px border
    var leftPos = Math.round((fs.main.availableWidth - iWidth) / 2), topPos = Math.floor((654 - iHeight)/2);
    fs.boxes[0].style.position = 'absolute';
    fs.boxes[0].style.width = iWidth + 'px';
    fs.boxes[0].style.left = (leftPos + 3) + 'px';
    fs.boxes[0].style.top = (topPos + 8) + 'px';

    fs.boxes[1].style.position = 'relative';
    fs.boxes[1].style.width = iWidth + 'px';
    fs.boxes[1].style.height = iHeight + 'px';
    fs.boxes[1].style.top = '0';
    fs.boxes[1].style.left = '0';

    fs.boxes[2].style.position = 'absolute';
    fs.boxes[2].style.top = '2px';
    fs.boxes[2].style.left = '2px';
    fs.boxes[2].style.width = (iWidth - 8) + 'px';
    fs.boxes[2].style.height = (iHeight - 8) + 'px';

    fs.boxes[3].style.position = 'absolute';
    fs.boxes[3].style.top = '2px';
    fs.boxes[3].style.left = '2px';
    fs.boxes[3].style.width = (iWidth - 16) + 'px';
    fs.boxes[3].style.height = (iHeight - 16) + 'px';

    fs.bigImage.style.position = 'absolute';
    fs.bigImage.style.display = 'block';
    fs.bigImage.style.left = (leftPos - 5) + 'px';
    fs.bigImage.style.top = topPos + 'px';
  },

  deactivateLinks: function() {
  // remove href to disable the links on the thumbnails
  // this stops keyboard users having to tab thru invisible links
    if (fs.thumbLinks.length === 0 || !fs.thumbLinks[0].removeAttribute) return;
    for (var i=0, j=fs.thumbLinks.length; i<j; i++) {
      fs.thumbLinks[i].removeAttribute('href');
    }
  },

  reactivateLinks: function() {
  // re-activate the links on the thumbs
    if (fs.thumbLinks.length === 0) return;
    for (var i=0, j=fs.thumbLinks.length; i<j; i++) {
      fs.thumbLinks[i].href = fs.thumbLinks[i].savedHref;
    }
  },

  isMSIE: false,
  boxes: [],
  closeButton: null,
  main: null,
  displayArea: null,
  bigImage: null,
  gallerycontainer: null,
  thumbLinks: []
};

addEvent(window,'unload',EventCache.flush);
addEvent(window, 'load', fs.setup);
