﻿/***********************************************************************
                 Angelwatt Image Viewer version 1.2.0
************************************************************************
Author: Kendall Conrad of Angelwatt.com
Home page: http://www.angelwatt.com/coding/image_viewer.php
Created: 2008-02-16
Updated: 2008-08-10
Description: Takes links to images and makes the links show the image on
the page rather than opening a new page.
License:
* This work is licensed under a Creative Commons Attribution-Share Alike
  3.0 United States License 
  http://creativecommons.org/licenses/by-sa/3.0/us/
***********************************************************************/
AngelwattImageViewer = function()
{
  /****  User Settings  ****/
  var vars = {
    id:          '',      // id attribute of HTML section to apply this script
    loadImg:     '/images/loading.gif', // loading image path
    textColor:   '#fff',  // Text color for loading message
    bgColor:     '#000',  // Background color for the slide
    bgOpacity:   0.8,     // Background opacity: 0-1
    borderSize:  1,       // Border for image, measured in pixels
    borderColor: '#fff',  // Border color
    fadeIn:      true,    // If image should fade in to appearance
    zoomIn:      true     // If image should zoom into appearance
  };
  /**** End User Settings ****/
  
  var slide, slideLoad, sBg;
  var img; // the image
  var y, yScroll, yPage, x, centerY, centerX;
  var regImg = /\.(jpg|jpeg|gif|png|bmp)$/i; // match image types
  var startOp = 0;
  var currOp = startOp;
  var fxTime = .3;  // time duration of effects in seconds
  var dur = 60;
  var deltaOp = dur / fxTime / 1000;
  var imgX = 0;
  var imgY = 0;
  var currX = 0;
  var currY = 0;
  
  CenterImg = function () {
    img.style.top = centerY - (img.height / 2) +"px";
    img.style.left = centerX - (img.width / 2) +"px";
    if (parseInt(img.style.top) < yScroll) {
      img.style.top = yScroll +'px';
    }
  };
  ShowImg = function () {
    imgX = img.width;
    imgY = img.height;
    currX = Math.ceil(imgX / 4);
    currY = Math.ceil(imgY / 4);
    CenterImg();
    img.style.zIndex = 5;     // bring image to front
    slideLoad.innerHTML = ''; // remove loading message
    if (vars['fadeIn'] == true) OpacityUp();
    if (vars['zoomIn'] == true) ZoomUp();
  };
  OpacityUp = function() {
    if (currOp >= 1) return;
    currOp += deltaOp;
    img.style.opacity = currOp;
    setTimeout('OpacityUp()', dur);
  };
  ZoomUp = function() {
    if (currX >= imgX && currY >= imgY) return;
    
    if (currX < imgX) {
      currX += Math.ceil(imgX * deltaOp);
      img.width = currX;
    } if (currX > imgX) img.width = currX = imgX;
    
    if (currY < imgY) {
      currY += Math.ceil(imgY * deltaOp);
      img.height = currY;
    } if (currY > imgY) img.height = currY = imgY;
    //CenterImg();
    setTimeout(function(){ ZoomUp(); }, dur);
  };
  HideSlide = function () {
    slide.style.display = 'none';
    if (document.getElementById('slideImg')) {
      if (vars['fadeIn'] == true) {
        document.getElementById('slideImg').style.opacity = 0;
      }
      document.getElementById('slideImg').parentNode.removeChild(
        document.getElementById('slideImg'));
    }
  };
  FindLinkedImages = function(id) {
    var links;
    if (id != '' && document.getElementById(id)) {
      links = document.getElementById(id).getElementsByTagName('a');
    }
    else { links = document.getElementsByTagName('a'); }
    for (var a=0, l=links.length; a < l; a++) {
      if (regImg.test(links[a].href)) {
        links[a].onclick = function() { ChangeSlide(this); return false; }
      }
    }
  };
  ChangeSlide = function (target) {
    currOp = startOp;
    img = new Image();
    if (vars['loadImg'] != '') {
      slideLoad.innerHTML = '<img src="'+ vars['loadImg'] +'"\
        alt="Loading" width="20" height="20"\
        style="position:relative; display:inline; z-index:2;\
        margin:0 auto; padding:0; border:none; cursor:default;" />\
        <br />Loading...';
    }
    else { slideLoad.innerHTML = 'Loading...'; }
    slide.style.display = 'block'; // put up slide with loading msg

    // Get screen height, viewport height
    y = window.innerHeight
       || document.documentElement.clientHeight
       || document.document.clientHeight;
    // Find horizontal page position
    yScroll = window.pageYOffset
       || document.documentElement.scrollTop
       || document.body.scrollTop;
    // Get full height of the page
    yPage = self.innerHeight + window.scrollMaxY
       || document.body.scrollHeight
       || document.body.offsetHeight;
    // Set slide background to full height of page
    document.getElementById('slideBG').style.height =
      (yPage < y) ? '100%' : yPage + "px";
    // Get page width
    x = window.innerWidth
       || document.documentElement.clientWidth
       || document.body.clientWidth;
    centerY = Math.floor(y/2) + yScroll;
    centerX = Math.floor(x/2);
    // center loading image
    slideLoad.style.marginTop = centerY-64 +"px";

    img.onload = function()
    {
      /*** Create image tag and style it ***/
      img.id    = 'slideImg';
      img.alt   = '';
      img.title = 'Click to close';
      img.style.position = 'absolute';
      img.style.display  = 'block';
      img.style.margin   = '0 auto';
      img.style.border   = vars['borderSize'] +'px solid '+ vars['borderColor'];
      img.style.cursor   = 'pointer';
      img.style.zIndex   = 0; // hide the image away until loaded
      img.style.opacity  = (vars['fadeIn'] == true) ? startOp : 1;
      img.onclick = HideSlide;

      CenterImg(img); // attempt to center it
      // add slide to page
      slide.insertBefore(img, slide.firstChild);
      ShowImg();
    };
    img.src = target.getAttribute('href');
  };
  // Get any query string on javascript url for any user setting overrides
  ParseJSArgs = function(vars) {
    var scripts = document.getElementsByTagName('script');
    for (var x=0; x < scripts.length; x++) {
      // Looking for script with source to this file
      if (!scripts[x].src || !/image\-viewer/.test(scripts[x].src)) continue;
      // Check if any arguments were entered
      if (!/\?.+/.test(scripts[x].src)) continue;
      var args = scripts[x].src.split('?')[1].split('&');
      for (var y=0; y < args.length; y++) {
        var pair = args[y].split('=');
        if (pair.length != 2) continue;            // skip if not a pair
        if (vars[pair[0]] === undefined) continue; // skip if not a known var
        vars[pair[0]] = pair[1];
      }
    }
  };
  Init = function() {
    ParseJSArgs(vars);
    // Create slide HTML and assign styling
    slide = document.createElement('div');
    slide.id             = 'slide';
    slide.style.display  = 'none';
    slide.style.position = 'absolute';
    slide.style.top      = '0px';
    slide.style.left     = '0px';
    slide.style.width    = '100%';
    slide.style.height   = '100%';
  
    // Create and style background
    sBg = document.createElement('div');
    sBg.id                    = 'slideBG';
    sBg.style.position        = 'absolute';
    sBg.style.top             = '0px';
    sBg.style.left            = '0px';
    sBg.style.margin          = '0 auto';
    sBg.style.width           = '100%';
    sBg.style.textAlign       = 'center';
    sBg.style.backgroundColor = vars['bgColor'];
    sBg.style.opacity         = vars['bgOpacity'];
    sBg.style.zIndex          = '2';
    sBg.onclick               = HideSlide;
  
    // Create and style loading message
    slideLoad = document.createElement('p');
    slideLoad.style.margin   = '0 auto';
    slideLoad.style.fontSize = '2em';
    slideLoad.style.color    = vars['textColor'];
  
    // Build slide
    sBg.appendChild(slideLoad);
    slide.appendChild(sBg);
    body = document.getElementsByTagName('body')[0];
    body.appendChild(slide);
    body.style.height = "100%";
    FindLinkedImages(vars['id']); // Find links and attach events
  };
  /*** Ensure onload isn't overwritten ***/
  function appendOnLoad(fx)
  { 
    var old = window.onload;
    if (typeof old != 'function') { window.onload = fx; }
    else { window.onload = function() { old(); fx(); } }
  }
  appendOnLoad(Init);
}();
