//
// Call this project 'Janimate' ?
//

var XHTMLNS = "http://www.w3.org/1999/xhtml";

var animations = new Array();
var objcache = new Array();
var docheight = 0, docwidth = 0;

addEvent(window, "load", _startup);

// startup {{{
function _startup()
{
   getWindowSize();
   
   if(startup)
      startup();
}
// }}}
function animation(objid, delay, steps) // {{{
{
   // Required values.
   this.id = (new Date()).getTime();
   this.delay = delay;
   this.steps = steps;
   
   // Setup stuff and defaults.
   this.obj = getObject(objid);
   this.stepsrun = 0;
   this.started = false;
   this.paused = false;
   this.timer = null;
   this.destroyobj = false;

   // Optional values. Determine the behaviour of the object.
   this.x = null;
   this.y = null;
   this.offsetX = 0;
   this.offsetY = 0;
   // Fade "in", "out", or "none"
   this.fade = "none";
   // Callback function for when the animation completes.
   this.callback = undefined;
   // Array of strings, one for each step in the animation.
   this.frames = null;
   
   if(this.obj)
   {
      this.parentobj = this.obj.parentNode;
      this.id = objid;
   }
   else
   {
      var parentname = objid.split(":")[1];
      this.parentobj = getObject(parentname);
      
      if(!this.parentobj)
      {
         alert("Couldn't find parent object: " + parentname + "/" + objid);
         return null;
      }
      
      this.obj = document.createElementNS(XHTMLNS, "span");
      this.obj.style.position = "absolute";
      this.obj.className = "tempanimation";
      
     
      this.parentobj.appendChild(this.obj);
      this.destroyobj = true;
   }
   
   animations[this.id] = this;

   this.start = function () // {{{
   {
   with(this)
   {
      //console.debug("Starting animation for " + id + " " + this);

      if(this.x && this.y)
         moveObject(this.obj, this.x, this.y);

      started = true;
      timer = setTimeout("animations['" + id + "'].step()", delay);
   }
   } // }}}

   this.stop = function () // {{{
   {
   with(this)
   {
      //console.debug("Stopping animation for " + id);
      started = false;
      clearTimeout(timer);
   }
   } // }}}
   
   this.pause = function () // {{{
   {
   with(this)
   {
      //console.debug("Pausing animation for " + id);
      paused = true;
      clearTimeout(timer);
   }
   } // }}}

   this.resume = function () // {{{
   {
   with(this)
   {
      //console.debug("Pausing animation for " + id);
      paused = false;
      timer = setTimeout("animations['" + id + "'].step()", delay);
   }
   } // }}}

   this.step = function () // {{{
   {
   with(this)
   {
      //console.debug("Stepping animation for " + id + ", at step " + stepsrun + " / " + steps + ", x delta is " + (offsetX / steps));
      stepsrun++;
      var pos = getPosition(obj);

      // Deal with any movement.
      if(offsetX != 0 || offsetY != 0) 
         moveObject(obj, pos[0] + (offsetX == 0 ? 0 : offsetX / steps), pos[1] + (offsetY == 0 ? 0 : offsetY / steps));

      // Deal with any fading.
      if(fade == "in")
         obj.style.opacity = stepsrun / steps;
      else if(fade == "out")
         obj.style.opacity = 1 - (stepsrun / steps);
      else if(fade == "in-out")
      {
         var opacity = ((stepsrun)  / steps) * 2;
         obj.style.opacity = (opacity < 1.0 ? opacity : 1 - (opacity - 1));
      }

      // Deal with any innerHTML changes.
      if(frames)
      {
         //console.debug("setting frame to " + ((stepsrun - 1) % frames.length) + " " + stepsrun);
         set(obj, frames[(stepsrun - 1) % frames.length]);
      }

      // Set up the call to the next step, if any.
      if(started)
         if(stepsrun < steps)
            timer = setTimeout("animations['" + id + "'].step()", delay);
         else
         {
            started = false;
            
            if(destroyobj)
               parentobj.removeChild(obj);

            if(callback != undefined)
               callback(this);
         }
   }
   } // }}}

} // }}}

function moveOffset(childID, parentID, offsetX, offsetY) // {{{
{
   var childObj  = getObject(childID);
   var parentObj = getObject(parentID);

   var parentPos = getPosition(parentObj);

   var childSize = getSize(childID);

   if(offsetX == "-width") {
      offsetX = 0 - childSize[0];
   } else if(offsetX == "+width") {
      offsetX = childSize[0];
   }

   if(offsetY == "-height") {
      offsetY = 0 - childSize[1];
   } else if(offsetY == "+height") {
      offsetY = childSize[1];
   }
   
   moveObject(childObj, parentPos[0] + offsetX, parentPos[1] + offsetY);
} // }}}
function moveObject(id, x, y) // {{{
{
   var obj = getObject(id);
   var pos = getPosition(obj);
   var size = getSize(obj);
   
   if(x == undefined)
      x = pos[0];

   if(y == undefined)
      y = pos[1];

   if(typeof(x) == "string")
      if(x.indexOf("width") != -1)
         if(x.indexOf("-") != -1)
            x = pos[0] - size[0];
         else
            x = pos[0] + size[0];
      else
         x = 0

   if(typeof(y) == "string")
      if(y.indexOf("height") != -1)
         if(y.indexOf("-") != -1)
            y = pos[1] - size[1];
         else
            y = pos[1] + size[1];
      else
         y = 0

   obj.style.left = x + "px";
   obj.style.top = y + "px";
} // }}}
function getObject(id) // {{{
{
   // If we were passed an object reference, return it.
   if(typeof(id) == "object")
      return id;
   else
   {
      // Return the cached object reference, if we have it.
      if(typeof(objcache[id]) == "object")
         return objcache[id];

      if(document.getElementById)
         x = document.getElementById(id);
      else if(document.all)
         x = document.all[id];
      else if(document.layers)
         x = document.layers[id];

      // Add the object reference to the cache.
      objcache[id] = x;

      return x;
   }
}
// }}}
function getPosition(id) // {{{
{
   var obj = getObject(id);
   var curtop = 0;
   var curleft = 0;

   if (obj.offsetParent)
   {
      while(obj.offsetParent)
      {
         curtop += obj.offsetTop
         curleft += obj.offsetLeft
         obj = obj.offsetParent;
      }
   }
   else if(obj.y && obj.x)
   {
      curtop += obj.y;
      curleft += obj.x;
   }
   return new Array(curleft, curtop);
} // }}}
function getSize(id) // {{{
{
   var obj = getObject(id);
   return new Array(obj.offsetWidth, obj.offsetHeight);
} // }}}

// getWindowSize {{{
function getWindowSize()
{
	if( typeof( window.innerWidth ) == 'number' )
	{
		//Non-IE
		docwidth = window.innerWidth;
		docheight = window.innerHeight;
	}
	else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) )
	{
		//IE 6+ in 'standards compliant mode'
		myWidth = document.documentElement.clientWidth;
		myHeight = document.documentElement.clientHeight;
	}
	else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) )
	{
		//IE 4 compatible
		myWidth = document.body.clientWidth;
		myHeight = document.body.clientHeight;
	}
}
// }}}
// addEvent {{{
// Add an eventListener to browsers that support it.
// Originally by Scott Andrew.
function addEvent(id, evType, fn)
{
   var obj = getObject(id);

   if(obj.addEventListener)
   {
      obj.addEventListener(evType, fn, true);
      return true;
   }
   else if(obj.attachEvent)
   {
      var r = obj.attachEvent("on"+evType, fn);
      return r;
   } 
   else 
      return false;
}
// }}}
// hide, show, set {{{
function hide(id)
{
   getObject(id).style.display = "none";
}

function show(id)
{
   getObject(id).style.display = "block";
}

function set(id, content)
{
   getObject(id).innerHTML = content;
}
// }}}


