﻿function AnimationFrame(left, top, width, height, time)
{
  this.Left = left;
  this.Top = top;
  this.Width = width;
  this.Height = height;
  this.Time = time;
  
  this.Copy = function(frame)
  {
    this.Left = frame.Left;
    this.Top = frame.Top;
    this.Width = frame.Width;
    this.Height = frame.Height;
    this.Time = frame.Time;
  }
  
  this.Apply = function(element)
  {
    element.style.height = this.Height + 'px';
  }
}

function AnimationObject(element)
{
  if(typeof(element) == "string")
    element = document.getElementById(element);
  
  var frames = null;  
  var timeoutID = -1;
  var running = 0;
  var currentFI = 0;
  var currentData = null;
  var lastTick = -1;
  var callback = null;
  
  var prevDir = 0;
  
  this.linktext = function()
  { 
    if(prevDir == 1)
      return "more..."; 
    else
      return "close";
  }
  
  this.AddFrame = function(frame)
  {
    frames.push(frame); 
  }
  
  this.SetCallback = function(cb)
  {
    callback = cb;
  }
  
  this.ClearFrames = function()
  {
    if(running != 0)
      this.Stop();
    frames = new Array();
    frames.push(new AnimationFrame(0,0,0,0,0));
    frames[0].Time = 0;
    frames[0].Left = parseInt(element.style.left);
    frames[0].Top = parseInt(element.style.top);
    frames[0].Width = parseInt(element.style.width);
    frames[0].Height = parseInt(element.style.height);
    currentFI = 0;
    prevDir = 0;
    currentData = new AnimationFrame(0,0,0,0,0);    
  }
  
  this.ResetToStart = function()
  {
    if(running != 0)
      this.Stop();
    currentFI = 0;
    prevDir = 0;
    currentData = new AnimationFrame(0,0,0,0,0);
    frames[0].Apply(element);
  }
  
  this.ResetToEnd = function()
  {
    if(running != 0)
      this.Stop();
    currentFI = 0;
    prevDir = 0;
    currentData = new AnimationFrame(0,0,0,0,0);
    frames[frames.length - 1].Apply(element); 
  }
  
  this.RunForward = function()
  {
    if(running == 1)
      return;
    if(running == -1)
      this.Stop();
    if(frames.length == 1 || element == null)
      return;  
      
    lastTick = new Date().getTime();

    //Start from the begining
    if(prevDir == 0)
    {
      currentFI = 1;
      currentData.Time = 0;
      currentData.Left = parseInt(element.style.left);
      currentData.Top = parseInt(element.style.top);
      currentData.Width = parseInt(element.style.width);
      currentData.Height = parseInt(element.style.height);
      frames[0].Copy(currentData);
    }
    else if(prevDir != 1)
    {
      currentFI++;
      currentData.Time = frames[currentFI].Time - currentData.Time;
    }
      
    running = 1;
    animate();
  }
  
  this.RunBackward = function()
  {
    if(running == -1)
      return;
    if(running == 1)
      this.Stop();
    if(frames.length == 1 || element == null)
      return;
       
    lastTick = new Date().getTime();
    
    //Start from the end
    if(prevDir == 0)
    {
      currentFI = frames.length-2;
      currentData.Left = parseInt(element.style.left);
      currentData.Top = parseInt(element.style.top);
      currentData.Width = parseInt(element.style.width);
      currentData.Height = parseInt(element.style.height);
      currentData.Time = frames[frames.length-1].Time;
      frames[frames.length-1].Copy(currentData);
      currentData.Time = 0;
    }
    else if(prevDir != -1)
    {
      currentData.Time = frames[currentFI].Time - currentData.Time;
      currentFI--;
    }
      
    running = -1;
    animate();
  }
 
  this.RunSlider = function()
  {
    if(running == 1 || running == -1)
      this.Stop();
    if(frames.length == 1 || element == null)
      return;  
      
    lastTick = new Date().getTime();
    //link = document.getElementById("accbutton" + element.id.substring(9)); 
  
    //Start from the begining
    if(prevDir == 0 || prevDir ==-1)
    {
      currentFI = 1;
      currentData.Time = 0;
      currentData.Left = parseInt(element.style.left);
      currentData.Top = parseInt(element.style.top);
      currentData.Width = parseInt(element.style.width);
      currentData.Height = parseInt(element.style.height);
      frames[0].Copy(currentData);
      running = 1;
      //link.innerHTML = "close";
    }
    //Start from the end
    else if(prevDir = 1)
    {
      currentFI = frames.length-2;
      currentData.Left = parseInt(element.style.left);
      currentData.Top = parseInt(element.style.top);
      currentData.Width = parseInt(element.style.width);
      currentData.Height = parseInt(element.style.height);
      currentData.Time = frames[frames.length-1].Time;
      frames[frames.length-1].Copy(currentData);
      currentData.Time = 0;
      running = -1;
    }
    onceonly();
  }

 
  this.Stop = function()
  {
    if(running == 0)
      return;
    if(timeoutID != -1)
      clearTimeout(timeoutID);
    prevDir = running;
    running = 0;
  }
  
  function animate()
  {
    if(running == 0)
      return;
    var curTick = new Date().getTime();
    var tickCount = curTick - lastTick;
    lastTick = curTick;
    
    var timeLeft = frames[((running == -1) ? currentFI + 1 : currentFI)].Time - currentData.Time;
    
    while(timeLeft <= tickCount)
    {
      currentData.Copy(frames[currentFI]);
      currentData.Time = 0;
      currentFI += running;
      if(currentFI >= frames.length || currentFI < 0)
      {
        currentData.Apply(element);
        lastTick = -1;
        prevDir = 0;
        running = 0;
        if(callback != null)
          callback();
        return;
      }
      tickCount = tickCount - timeLeft;
      timeLeft = frames[((running == -1) ? currentFI + 1 : currentFI)].Time - currentData.Time;
    }
    
    if(tickCount != 0)
    {
      currentData.Time += tickCount;
      var ratio = currentData.Time/frames[((running == -1) ? currentFI + 1 : currentFI)].Time;
      currentData.Left = frames[currentFI-running].Left + (frames[currentFI].Left - frames[currentFI-running].Left) * ratio;
      currentData.Top = frames[currentFI-running].Top + (frames[currentFI].Top - frames[currentFI-running].Top) * ratio;
      currentData.Width = frames[currentFI-running].Width + (frames[currentFI].Width - frames[currentFI-running].Width) * ratio;
      currentData.Height = frames[currentFI-running].Height + (frames[currentFI].Height - frames[currentFI-running].Height) * ratio; 
    }
    
    currentData.Apply(element);
  
    timeoutID = setTimeout(animate, 33);
  }
  
  function onceonly()
  {
    if(running == 0)
      return;
    var curTick = new Date().getTime();
    var tickCount = curTick - lastTick;
    lastTick = curTick;
    
    var timeLeft = frames[((running == -1) ? currentFI + 1 : currentFI)].Time - currentData.Time;
    
    while(timeLeft <= tickCount)
    {
      currentData.Copy(frames[currentFI]);
      currentData.Time = 0;
      currentFI += running;
      if(currentFI >= frames.length || currentFI < 0)
      {
        currentData.Apply(element);
        lastTick = -1;
        prevDir = running;
        running = 0;
        if(callback != null)
          callback();
        return;
      }
      tickCount = tickCount - timeLeft;
      timeLeft = frames[((running == -1) ? currentFI + 1 : currentFI)].Time - currentData.Time;
    }
    
    if(tickCount != 0)
    {
      currentData.Time += tickCount;
      var ratio = currentData.Time/frames[((running == -1) ? currentFI + 1 : currentFI)].Time;
      currentData.Left = frames[currentFI-running].Left + (frames[currentFI].Left - frames[currentFI-running].Left) * ratio;
      currentData.Top = frames[currentFI-running].Top + (frames[currentFI].Top - frames[currentFI-running].Top) * ratio;
      currentData.Width = frames[currentFI-running].Width + (frames[currentFI].Width - frames[currentFI-running].Width) * ratio;
      currentData.Height = frames[currentFI-running].Height + (frames[currentFI].Height - frames[currentFI-running].Height) * ratio; 
    }
    
    currentData.Apply(element);
  
    timeoutID = setTimeout(onceonly, 33);
  }

 
   this.ClearFrames();
  
}

var example2 = null;

function makeAnimation()
{
  example2 = new AnimationObject("ex2Box");
  example2.AddFrame(new AnimationFrame(598,10,35,25,2000));
  example2.AddFrame(new AnimationFrame(608,10,25,35,100));
  example2.AddFrame(new AnimationFrame(608,205,25,35,1000));
  example2.AddFrame(new AnimationFrame(598,215,35,25,100));
  example2.AddFrame(new AnimationFrame(10,215,35,25,2000));
  example2.AddFrame(new AnimationFrame(10,205,25,35,100));
  example2.AddFrame(new AnimationFrame(10,10,25,35,1000));
  example2.AddFrame(new AnimationFrame(10,10,35,25,100));
}

function AroundAndAround()
{ 
  if(example2 == null)
    makeAnimation();
  example2.SetCallback(example2.RunForward);
  example2.RunForward(); 
}

function StopEx2()
{
  if(example2 == null)
    makeAnimation();
  example2.Stop();
}

function BackEx2()
{
  if(example2 == null)
    makeAnimation();
  example2.SetCallback(example2.RunBackward);
  example2.RunBackward();
}

function ResetEx2()
{
  if(example2 == null)
    makeAnimation();
  example2.ResetToStart();
}

var allAnimations=new Array()

function slide(index, lines)
{
  if(allAnimations[index] == null) 
    {
    vHeight = lines * 17;
    element = document.getElementById("Accordion" + index);  
    allAnimations[index] = new AnimationObject(element);
    vLeft =  1; 
    vTop =  1; 
    vWidth =  250;
    vTime = 350;
    allAnimations[index].AddFrame(new AnimationFrame(vLeft,vTop,vWidth,vHeight,vTime));
    }
  allAnimations[index].RunSlider(); 
  link = document.getElementById("accbutton" + index); 
  link.innerHTML = allAnimations[index].linktext();
}


