/* =============================================================================
* iFadeImg v1.2 -- DOM Fade Script
*
* When provided a function iFadeCalls() that makes calls to the function
* iFadeImgSetup(), this script builds image rotations with intermediate fade
* effects that works across most modern browsers. iFadeImgSetup() takes two
* arguments, the ID of the image to rotate and a JS array of objects specifying
* the image rotation order and complexity.
*
* Developed by Puna Tannehill
* Revised by Jake Kronika <jkronika@imagescape.com>
* For Imaginary Landscape, LLC <www.imagescape.com>
* Copyright (c) 2005-2006
*
* Last updated 2007.01.09
*
* Reuse or modification without permission is prohibited.
*
* ==============================================================================
* ############################################################################ *
* ##                        DO NOT MODIFY THIS FILE                         ## *
* ############################################################################ *
* --------------------------------------------------------------------------- */

// -- maintained for backwards compatibility -----------------------------------
var loop, initPause, subseqPause;
var iFadeImgSetup = function(image, array) {
  new iFade(image, array, {
    'loop' : loop,
    'initial_pause' : initPause,
    'subseq_pause' : subseqPause
  });
};

/* =============================================================================
*
* iFade class
*
* Creates a single image crossfade based on the given parameters
*
* parameters:
*   image : string ID or object variable identifying the image to fade
*   array : array of fade dictionaries (compatible with older array of arrays)
*   args  : optional dictionary of additional configuration variables
*           - loop         : loop forever? (boolean)
*           - initPause    : pause before first fade, in seconds (number)
*           - subseqPause  : pause before following fades, in seconds (number)
*
* USAGE:
*
* Create ONE instance of the iFade per page, using the following syntax:
*
*   new iFade(IMAGE_VAR, ARRAY_VAR[, ARGS_VAR]);
*
* The iFade object can be stored for future manipulation as well, as follows:
*
*   var ifade = new iFade(IMAGE_VAR, ARRAY_VAR[, ARGS_VAR]);
*
* ------------------------------------------------------------------------- */
var iFade = function(image, array, args) {
  // -- VARIABLES --------------------------------------------------------------
  this.image = image;
  this.array = array;

  // flags
  this.loop = false;
  this.controls = false;

  // pause durations
  this.initial_pause = 7;
  this.subseq_pause = 5;

  // redirect to this URL on stop
  this.stop_redirect = null;

  // use these images for controls
  this.control_images = {
    'rewind' : null,
    'stop' : null,
    'pause' : null,
    'play' : null,
    'forward' : null
  };

  if (args && typeof (args) == 'object') {
    // an argument dictionary exists, so update configurable values from it

    if (typeof (args.loop) == 'boolean') {
      // correct type for loop argument

      // update loop property with the argument's Boolean interpretation
      this.loop = Boolean(args.loop);
    }

    if (typeof (args.controls) != 'undefined') {
      // correct type for use_controls argument

      // update use_controsl property with the argument's Boolean interpretation
      this.controls = Boolean(args.controls);
    }

    if (typeof (args.initial_pause) == 'number'
        && isFinite (args.initial_pause)) {
      // correct type and value range for initial_pause argument

      // update initial_pause property with the argument's value
      this.initial_pause = args.initial_pause;
    }

    if (typeof (args.subseq_pause) == 'number'
        && isFinite (args.subseq_pause)) {
      // correct type and value range for subseq_pause argument

      // update subseq_pause property with the argument's value
      this.subseq_pause = args.subseq_pause;
    }

    if (typeof (args.stop_redirect) == 'string'
        && args.stop_redirect != '') {
      this.stop_redirect = args.stop_redirect;
    }

    if (typeof (args.control_images) == 'object') {
      for (var x in args.control_images) {
        if (typeof (args.control_images[x]) == 'string'
            && args.control_images[x] != '') {
          this.control_images[x] = args.control_images[x];
        }
      }
    }
  }

  if (!this.image || !this.array) {
    // required image and/or array not provided

    // return a null value and exit the constructor
    return null;
  }

  // unconfigurable values
  this.timeout = this.initial_pause * 1000;
  this.previous = null;
  this.current = 0;
  this.next = 1;
  this.step = 3;
  this.opacity = 100;
  this.delay_timer = null;
  this.rotate_timer = null;
  this.div = null;
  this.anchor = null;
  this.caption = null;

  // -- METHODS ----------------------------------------------------------------
  this.init = function() {
    if (typeof (this.image) == 'string'
        && document.getElementById) {
      this.image = document.getElementById(this.image);
    }

    if (typeof (this.array) == 'string') {
      this.array = eval (this.array);
    }

    if (!this.image || !this.array) {
      return false;
    }

    this.parse();
    this.preload();

    if (this.array.length < 2
        || !this.get_elements()) {
      return false;
    }

    this.image.style.background = '#fff none';
    this.image.style.border = 'none';
    this.image.style.filter = 'alpha(opacity='+this.opacity+')';
    this.div.style.height = this.image.offsetHeight + 'px';
    this.div.style.width = this.image.offsetWidth + 'px';

    this.setup_controls();

    if (document.all
        && !navigator.userAgent.match(/opera/i)) {
      var self = this;

      this.delay_timer = setTimeout (function() {
        self.iexplore_fade();
      }, this.timeout);

      this.timeout = this.subseq_pause * 1000;

      return true;
    }

    if (typeof (this.image.style.MozOpacity != 'undefined')) {
      this.image.style.MozOpacity = this.opacity / 100;
    }

    this.div.style.background =
      '#fff url('+this.array[this.next].image.src+') scroll left top no-repeat';

    this.delay();

    this.timeout = this.subseq_pause * 1000;

    return true;
  };

  this.parse = function() {
    // storage for the parsed array of created dictionaries
    var parsed = [];

    for (var i = 0; i < this.array.length; i++) {
      // traverse the elements in the original array

      // store the current sub-array
      var array = this.array[i];

      if (typeof array.image == 'string'
          && array.image != ''
          && typeof array.alt == 'string') {
        // this sub-array is a dictionary already

        // add the dictionary to the parsed array
        parsed.push(array);
      } else {
        // this sub-array is an incremental array and needs to be validated

        // storage for the created dictionary
        var obj = {};

        // flag to indicate invalid number of sub-array elements
        var skip = false;

        switch (array.length) {
          // evaluate and validate the length of the sub-array

          case 7: obj.onclick = array[6];
          case 6: obj.htmlDiv = array[5];
          case 5: obj.html = array[4];
          case 4: obj.target = array[3];
          case 3: obj.href = array[2];
          case 2:  // minimum number of elements found
            obj.alt = array[1];
            obj.image = array[0];
            break;
          default: // invalid number of elements in this sub-array
            skip = true;
            break;
        }

        if (skip) {
          // invalid number of elements in this sub-array

          // skip to the next sub-array
          continue;
        }

        // add the created dictionary to the parsed array
        parsed.push(obj);
      }
    }

    // overwrite the original array with a parsed version
    this.array = parsed;
  };

  this.get_elements = function() {
    if (typeof (this.image) == 'string'
        && document.getElementById) {
      this.image = document.getElementById(this.image);
    }

    if (typeof (this.image) != 'object') {
      return false;
    } else {
      this.anchor = this.image.parentNode;

      if (typeof (this.anchor) != 'object') {
        return false;
      } else {
        this.div = this.anchor.parentNode;

        if (typeof (this.div) != 'object') {
          return false;
        }
      }
    }

    return true;
  };

  this.preload = function() {
    for (var i = 0; i < this.array.length; i++) {
      var image = new Image();

      if (!image) {
        return false;
      }

      image.src = this.array[i].image;
      this.array[i].image = image;
    }
  };

  this.setup_controls = function() {
    if (this.controls
        && typeof (this.controls) != 'object'
        && document.createElement
        && document.createTextNode) {
      this.controls = { 'container' : document.createElement('div') };
      this.controls.container.className = 'iFadeControls';

      var buttons = [
        ['rewind', '<<', 'View Previous Image'],
        ['stop', '[ ]', 'Stop Rotation'],
        ['pause', '||', 'Pause Rotation'],
        ['play', '>', 'Resume Rotation'],
        ['forward', '>>', 'View Next Image']];

      for (var i = 0; i < buttons.length; i++) {
        var index = buttons[i][0],
            textual = buttons[i][1],
            alternate = buttons[i][2];

        this.controls[index] = document.createElement('button');
        this.controls[index].className = 'iFadeControl';
        this.controls[index].ifade = this;
        this.controls[index].title = alternate;

        if (typeof (this.control_images[index]) == 'string'
            && this.control_images[index] != '') {
          var image = document.createElement('img');
          image.src = this.control_images[index];
          image.border = 0;
          image.style.border = 'none';
          image.alt = textual;
          image.title = alternate;
          this.control_images[index] = image;
          this.controls[index].appendChild(this.control_images[index]);
        } else {
          this.controls[index].appendChild(document.createTextNode(textual));
        }

        this.controls[index].index = index;
        this.controls[index].onclick = function() {
          this.ifade[this.index]();
        };

        this.controls.container.appendChild(this.controls[index]);
      }

      this.controls.play.style.display = 'none';

      if (this.div.nextSibling) {
        this.div.parentNode.insertBefore(
          this.controls.container,
          this.div.nextSibling);
      } else {
        this.div.parentNode.appendChild(this.controls.container);
      }
    }
  };

  this.iexplore_fade = function() {
    clearTimeout (this.delay_timer);

    this.image.style.filter="blendTrans(duration=" + this.timeout + ")";
    this.image.style.filter="blendTrans(duration=crossFadeDuration)";
    this.image.filters.blendTrans.Apply();

    this.image.src = this.array[this.next].image.src;
    this.image.filters.blendTrans.Play();

    if (this.next == 0 && !this.loop) {
      return;
    }

    this.update();

    this.next++;

    if (this.next == (this.array.length)) {
      this.next = 0;
    }

    var self = this;
    this.delay_timer = setTimeout (function() {
      self.iexplore_fade()
    }, this.timeout);
  };

  this.delay = function() {
    var self = this;

    this.delay_timer = setTimeout (function() {
      self.rotate();
    }, this.timeout);

    return true;
  };

  this.rotate = function() {
    clearTimeout (this.delay_timer);

    var self = this;

    this.rotate_timer = setInterval (function() {
      self.fade();
    }, 33);

    return true;
  };

  this.fade = function() {
    if (typeof (this.image.filters) != 'object'
        && typeof (this.image.style.MozOpacity) == 'undefined') {
      clearInterval (this.rotate_timer);

      this.div.style.backgroundImage =
        'url('+this.array[this.next].image.src+')';
      this.image.src = this.array[this.next].image.src;

      this.update();
      this.flip();

      return true;
    }

    if (this.opacity > 0) {
      this.opacity = Math.max(this.opacity - this.step, 0);
      this.set_opacity(this.opacity);
    } else {
      clearInterval (this.rotate_timer);

      this.image.src = this.array[this.next].image.src;

      this.set_opacity(100);

      this.update();
      this.flip();
    }

    return true;
  };

  this.flip = function() {
    this.increment();

    var self = this;
    setTimeout (function() {
      self.div.style.backgroundImage =
        'url('+self.array[self.next].image.src+')';
    }, this.timeout / 4);

    if (this.current != 0 || this.loop) {
      this.delay();
    }

    return true;
  };

  this.update = function() {
    this.image.alt = this.image.title = this.array[this.next].alt;
    this.update_link();
    this.update_text();
  };

  this.update_link = function() {
    if (this.array[this.next].href
        && this.array[this.next].href != '') {
      this.anchor.title = this.array[this.next].alt;
      this.anchor.href = this.array[this.next].href;

      if (this.array[this.next].target
          && this.array[this.next].target != '') {
        this.anchor.target = this.array[this.next].target;
      } else {
        this.anchor.target = '_self';
      }

      if (this.array[this.next].onclick
          && ((typeof (this.array[this.next].onclick) == 'string'
               && this.array[this.next].target != '')
              || typeof (this.array[this.next].onclick) == 'function')) {
        this.anchor.onclick = this.array[this.next].onclick;
      }
    } else {
    	this.anchor.removeAttribute("href");
    	this.anchor.title = this.array[this.next].alt;
    }

    return true;
  };

  this.update_text = function() {
    if (this.array[this.next].htmlDiv) {
      if (typeof (this.array[this.next].htmlDiv) == 'string'
          && (this.array[this.next].htmlDiv == ''
              || !document.getElementById)) {
        this.array[this.next].htmlDiv = null;

        return false;
      } else if (typeof (this.array[this.next].htmlDiv) == 'string') {
        this.caption = this.array[this.next].htmlDiv =
          document.getElementById(this.array[this.next].htmlDiv);
      }

      if (typeof (this.caption) != 'object') {
        this.caption = null;
        this.array[this.next].htmlDiv = null;
      }
    }

    if (this.array[this.next].html
        && typeof (this.array[this.next].html) == 'string'
        && this.caption
        && typeof (this.caption.innerHTML) != 'undefined') {
      this.caption.innerHTML = this.array[this.next].html;
    } else {
      return false;
    }

    return true;
  };

  this.set_opacity = function(opacity) {
    this.opacity = opacity;

    if (typeof (this.image.filters) == 'object'
        && this.image.filters.alpha) {
      this.image.filters.alpha.opacity = this.opacity;
    } else if (typeof (this.image.style.MozOpacity) != 'undefined') {
      this.image.style.MozOpacity = this.opacity / 100;
    }

    return true;
  };

  this.rewind = function() {
    this.controls.pause.style.display = 'none';
    this.controls.play.style.display = '';

    this.decrement();

    return this.redisplay();
  };

  this.stop = function() {
    this.controls.pause.style.display = 'none';
    this.controls.play.style.display = '';

    this.previous = this.array.length - 1;
    this.current = 0;
    this.next = 1;

    if (typeof (this.stop_redirect) == 'string'
        && this.stop_redirect != '') {
      return window.location = this.stop_redirect;
    }

    return this.redisplay();
  };

  this.pause = function() {
    this.controls.pause.style.display = 'none';
    this.controls.play.style.display = '';

    clearTimeout (this.delay_timer);
    clearInterval (this.rotate_timer);

    return true;
  };

  this.play = function() {
    this.controls.play.style.display = 'none';
    this.controls.pause.style.display = '';

    if (document.all
        && !navigator.userAgent.match(/opera/i)) {
      this.iexplore_fade();
    } else {
      this.rotate();
    }
  };

  this.forward = function() {
    this.controls.pause.style.display = 'none';
    this.controls.play.style.display = '';

    this.increment();

    return this.redisplay();
  };

  this.redisplay = function() {
    clearTimeout (this.delay_timer);
    clearInterval (this.rotate_timer);

    this.set_opacity(100);

    this.div.style.backgroundImage = 'url('+this.array[this.next].image.src+')';
    this.image.src = this.array[this.current].image.src;

    this.update();

    return true;
  };

  this.increment = function() {
    this.current++;
    this.previous = this.current - 1;

    if (this.current >= this.array.length) {
      this.current = 0;
      this.previous = this.array.length - 1;
    }

    this.next = this.current + 1;

    if (this.next >= this.array.length) {
      this.next = 0;
    }
  };

  this.decrement = function() {
    this.current--;

    if (this.current <= 0) {
      this.current = this.array.length - 1;
      this.next = 0;
    }

    this.previous = this.current - 1;

    if (this.previous <= 0) {
      this.previous = this.array.length - 1;
    }
  };

  // -- INITIALIZATION ---------------------------------------------------------
  this.init();
};

/* =============================================================================
*
* Array extension -- push
*
* Implements the expected functionality of an array.push() method if no such
* method exists. Appends a single new item to the end of the array.
*
* parameters:
*   el : item to be appended to the array
*
* USAGE:
*
* Call this method as many times as needed, using the syntax:
*
*   ARRAY.push(ITEM_VAR);
*
* ------------------------------------------------------------------------- */
Array.prototype.push = (Array.prototype.push ? Array.prototype.push :
  function(el) {
    this[this.length] = el;
  }
);

var iFadeCalls = (typeof (iFadeCalls) == 'function' ? iFadeCalls : function() {
  return;
});

var preFadeLoad = window.onload;
window.onload = function() {
  if (typeof (preFadeLoad) == 'function') {
    preFadeLoad();
  }

  iFadeCalls();
};
