// Cross-browser event handling
// by Scott Andrew LePera
// http://www.scottandrew.com/weblog/articles/cbs-events

// Modified 2004-08-10 by Andrew Grgeory to work around Konqueror bug
// Modified 2004-06-04 by Andrew Gregory to support legacy (NS3,4) browsers
// http://www.scss.com.au/family/andrew/

function addEvent(obj, evType, fn, useCapture){
  /* adds an eventListener for browsers which support it
     Written by Scott Andrew: nice one, Scott */
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent){
	var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
	return false;
  }
};

// eg. addEvent(imgObj, 'mousedown', processEvent, false);
function addEvent2(obj, evType, fn, useCapture) {
  // work around Konqueror bug #57913 which prevents
  // window.addEventListener('load',...) from working
  var ua = navigator.userAgent;
  var konq = ua.indexOf('KHTML') != -1 && ua.indexOf('Safari') == -1 && obj == window && evType == 'load';
  // don't use addEventListener for Konq, have Konq fall back to the old
  // obj.onload method
  if (obj.addEventListener && !konq) {
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent) {
    return obj.attachEvent('on' + evType, fn);
  } else {
    if (!obj.cb_events) {
      obj.cb_events = new Object();
      obj.cb_ftemp = null;
    }
    var events = obj.cb_events[evType];
    if (!events) {
      events = new Array();
      obj.cb_events[evType] = events;
    }
    var i = 0;
    while ((i < events.length) && (events[i] != fn)) {
      i++;
    }
    if (i == events.length) {
      events[i] = fn;
      obj['on' + evType] = new Function("var ret=false,e=this.cb_events['"+evType+"'];if(e){for(var i=0;i<e.length;i++){this.cb_ftemp=e[i];ret=this.cb_ftemp()||ret;}return ret;}");
    }
    return true;
  }
};

// eg. removeEvent(imgObj, 'mousedown', processEvent, false);
function removeEvent(obj, evType, fn, useCapture) {
  // work around Konqueror bug #57913 which prevents
  // window.addEventListener('load',...) from working
  var ua = navigator.userAgent;
  var konq = ua.indexOf('KHTML') != -1 && ua.indexOf('Safari') == -1 && obj == window && evType == 'load';
  // don't use addEventListener for Konq, have Konq fall back to the old
  // obj.onload method
  if (obj.removeEventListener && !konq) {
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.detachEvent) {
    return obj.detachEvent('on' + evType, fn);
  } else {
    var ret = false;
    if (obj.cb_events) {
      var events = obj.cb_events[evType];
      if (events) {
        // remove any matching functions from the events array, shuffling items
        // down to fill in the space before truncating the array
        var dest = 0;
        for (var src = 0; src < events.length; src++) {
          if (dest != src) {
            events[dest] = events[src];
          }
          if (events[dest] == fn) {
            ret = true;
          } else {
            dest++;
          }
        }
        events.length = dest;
      }
    }
    return ret;
  }
};


// ---------------------------------------------------------------------------------
// Fade engine
// ---------------------------------------------------------------------------------

//Colors to use when fading the result area
/* white */
var Color= new Array();
Color[1] = "FFFFFF";
Color[2] = "F6FAF7";
Color[3] = "ECF5F0";
Color[4] = "E3F0E9";
Color[5] = "D9EBE1";
Color[6] = "D0E5D9";
Color[7] = "CAE2D5";


function faderesult()
{
	if (document.getElementById('resultscontainer')) {
    	for(iCounter=1;iCounter < 7; iCounter++) {
			setTimeout("setbg('#" + Color[iCounter] + "')", iCounter * 150);
		}
		setTimeout("setbg('#c4dfd0')", 8 * 150);
	}
};

function setbg(col)
{
	oResult = document.getElementById('resultscontainer');
	oResult.style.backgroundColor = col;
};



// ---------------------------------------------------------------------------------
// End Fade engine
// ---------------------------------------------------------------------------------




// ---------------------------------------------------------------------------------
// Animation engine
// ---------------------------------------------------------------------------------

// Animation housekeeping
var animating = 0; // Incremented at start of each animation, decremented afterwards. If zero, the interval timer is disabled
var animaterID; // ID of the timer used for animating
// 'zoomer' module of the animation engine smoothly moves an element from the position/size of the start element to the target element
var zoomerElement = null; // Element being shifted; null if none
var zoomerStart; // Where we're shifting from
var zoomerTarget; // Where we're shifting to
var zoomerStartScroll; // Where we're scrolling from
var zoomerTargetScroll; // Where we're scrolling to
var zoomerProgress; // 0..1 of how far we are
var zoomerStep; // 0..1 of how much to shift each step
// 'closer' module of the animation engine closes an element by smoothly reducing it's height to zero
var closerElement = null; // Element being closed; null if none
var closerStartHeight; // Starting height
var closerProgress; // 0..1 of how far we are
var closerStep; // 0..1 of how much to shift each step

// Start animation engine
function startAnimating()
{
    if(animating++ == 0)
        animaterID = window.setInterval("doAnimate();",25);
};

// Stop animation engine
function stopAnimating()
{
    if(--animating == 0)
        window.clearInterval(animaterID)
};

// Perform an animation engine tick, calling each of the known animation modules
function doAnimate()
{
    if(zoomerElement)
        doZoomer();
    if(closerElement)
        doCloser();
};

// Start moving the element 'e' from the position of the element 'start' to the position of the element 'target'
function startZoomer(e,start,target,slowly)
{
    stopZoomer();
    zoomerElement = e;
    zoomerStart = start;
    zoomerStartScroll = findScrollY();
    zoomerTargetScroll = ensureVisible(target);
    zoomerTarget = target;
    zoomerProgress = 0;
    zoomerStep = slowly ? 0.01 : 0.12;
    startAnimating();
};

// Stop any ongoing zoomer animation
function stopZoomer()
{
    if(zoomerElement)
        {
        stopAnimating();
        zoomerElement.style.visibility = "hidden";
        zoomerTarget.style.opacity = 1;
        window.scrollTo(0,zoomerTargetScroll);
        zoomerElement = null;
        }
};

// Perform a tick of the zoomer animation
function doZoomer()
{
    zoomerProgress += zoomerStep;
    if(zoomerProgress >= 1.0)
        stopZoomer();
    else
        {
        var f = slowInSlowOut(zoomerProgress);
        var zoomerStartLeft = findPosX(zoomerStart);
        var zoomerStartTop = findPosY(zoomerStart);
        var zoomerStartWidth = zoomerStart.offsetWidth;
        var zoomerStartHeight = zoomerStart.offsetHeight;
        var zoomerTargetLeft = findPosX(zoomerTarget);
        var zoomerTargetTop = findPosY(zoomerTarget);
        var zoomerTargetWidth = zoomerTarget.offsetWidth;
        var zoomerTargetHeight = zoomerTarget.offsetHeight;
        zoomerElement.style.left = zoomerStartLeft + (zoomerTargetLeft-zoomerStartLeft) * f;
        zoomerElement.style.top = zoomerStartTop + (zoomerTargetTop-zoomerStartTop) * f;
        zoomerElement.style.width = zoomerStartWidth + (zoomerTargetWidth-zoomerStartWidth) * f;
        zoomerElement.style.height = zoomerStartHeight + (zoomerTargetHeight-zoomerStartHeight) * f;
        zoomerElement.style.visibility = "visible";
        zoomerTarget.style.opacity = zoomerProgress;
        window.scrollTo(0,zoomerStartScroll + (zoomerTargetScroll-zoomerStartScroll) * f);
        }
};

// Start closing an element
function startCloser(e,slowly)
{
    // Stop any existing close operation
    stopCloser();
    // Create the wrapper div that doesn't have any padding or margins or anything to confuse offsetWidth vs. style.width
    var wrapper = createTiddlyElement(e.parentNode,"div",null,null);
    e.parentNode.insertBefore(wrapper,e);
    wrapper.appendChild(e);
    closerElement = wrapper;
    // Save the information for the close operation
    closerStartHeight = closerElement.offsetHeight;
    closerProgress = 0;
    closerStep = slowly ? 0.01 : 0.12;
    closerElement.style.overflow = "hidden";
    startAnimating();
};

// Stop closing the current element
function stopCloser()
{
    if(closerElement)
        {
        stopAnimating();
        closerElement.parentNode.removeChild(closerElement);
        closerElement = null;
        }
};

// Perform a tick of the closer animation
function doCloser()
{
    closerProgress += closerStep;
    if(closerProgress > 1.0)
        stopCloser();
    else
        {
        var f = slowInSlowOut(closerProgress);
        var h = closerStartHeight * (1-f)
        closerElement.style.height = (h <= 2) ? 2 : h;
        closerElement.style.opacity = (1-f);
        }
};


// Map a 0..1 value to 0..1, but slow down at the start and end
function slowInSlowOut(progress)
{
    return(1-((Math.cos(progress * Math.PI)+1)/2));
};

// Get the scroll position for window.scrollTo necessary to scroll a given element into view
function ensureVisible(e)
{
    var posTop = findPosY(e);
    var posBot = posTop + e.offsetHeight;
    var winTop = findScrollY();
    var winHeight = findWindowHeight();
    var winBot = winTop + winHeight;
    if(posTop < winTop)
        return(posTop);
    else if(posBot > winBot)
        {
        if(e.offsetHeight < winHeight)
            return(posTop - (winHeight - e.offsetHeight));
        else
            return(posTop);
        }
    else
        return(winTop);
};

function findWindowHeight()
{
	return(window.innerHeight ? window.innerHeight : document.body.clientHeight);
};

function findScrollY()
{
	return(window.scrollY ? window.scrollY : document.body.scrollTop);
};

// From QuirksMode.com
function findPosX(obj)
{
        var curleft = 0;
        if (obj.offsetParent)
        {
                while (obj.offsetParent)
                {
                        curleft += obj.offsetLeft;
                        obj = obj.offsetParent;
                }
        }
        else if (obj.x)
                curleft += obj.x;
        return curleft;
};

// From QuirksMode.com
function findPosY(obj)
{
        var curtop = 0;
        if (obj.offsetParent)
        {
                while (obj.offsetParent)
                {
                        curtop += obj.offsetTop;
                        obj = obj.offsetParent;
                }
        }
        else if (obj.y)
                curtop += obj.y;
        return curtop;
};

// Create a non-breaking space
function insertSpacer(place)
{
    place.appendChild(document.createTextNode(String.fromCharCode(160)));
};