/*******************************
** Paradise Framework
** (c) 2006 by Pierfilippo D'Alessandro
*/

/*******************************
** Context
*/

var Paradise;

Paradise = new Object();

Paradise.setOpacity = function(node, opacity)
{
  node.style.filter = 'alpha(opacity:' + opacity + ')'; // IE

  opacity /= 100;
  node.style.KHTMLOpacity = opacity;  // Safari < 1.2, Konqueror
  node.style.MozOpacity = opacity;    // old Mozilla and Firefox
  node.style.opacity = opacity;       // Safari 1.2+, new Mozilla and Firefox, CSS3
}

Paradise.getEventNode = function(evn)
{
  var ev, node;

  ev = evn ? evn:window.event;

  node = null;

  if(ev.target) node = ev.target;
  else if(ev.srcElement) node = ev.srcElement;

  // correct Safari bug
  if(node != null && node.nodeType == 3)
    node = node.parentNode ? node.parentNode:node.parentElement;

  return node;
}

Paradise.getParentWith = function(node, property)
{
  var DOMRoot;

  if(node == null)
    return null;

  DOMRoot = document.all ? 'BODY':'HTML';

  while(node.tagName != DOMRoot && typeof(node[property]) == 'undefined')
    node = node.parentNode ? node.parentNode:node.parentElement;

  return node.tagName == DOMRoot ? null:node;
}

Paradise.isClass = function(node, clsName)
{
  var i, classArray, c1, c2;

  c1 = node.getAttribute('className');
  c2 = node.getAttribute('class');

  c1 = (typeof(c1) == 'string' ? c1.split(' '):[]);
  c2 = (typeof(c2) == 'string' ? c2.split(' '):[]);

  classArray = c1.concat(c2);

  for(i = 0;i < classArray.length;i++)
    if(classArray[i] == clsName)
      return true;

  return false;
}

/*******************************
** Timer
*/

function Timer(handler, delay)
{
  this.id = null;
  this.delay = delay;
  this.handler = handler;
}

Timer.prototype.start = function()
{
  this.stop();
  this.run();
}

Timer.prototype.run = function()
{
  this.id = setTimeout(this.handler, this.delay)
}

Timer.prototype.stop = function()
{
  if(this.id != null)
  {
    clearTimeout(this.id);
    this.id = null;
  }
}

/*******************************
** Fader
*/

function Fader(nodeId, opacity, speed)
{
  this.node = document.getElementById(nodeId);
  this.timer = new Timer('Fader.handler(\'' + nodeId + '\')', 50);
  this.privateSetOpacity(opacity);
  this.maxSpeed = speed;
  this.speed = 0;

  Fader.registry[nodeId] = this;
}

Fader.registry = new Array();

Fader.handler = function(nodeId)
{
  var fader, opacity;

  fader = Fader.registry[nodeId];

  opacity = fader.opacity + fader.speed;

  if(opacity < 0)
    opacity = 0;

  if(opacity > 100)
    opacity = 100;

  fader.privateSetOpacity(opacity);

  if(opacity == 0 || opacity == 100)
  {
    fader.speed = 0;
    fader.timer.stop();
  } else {
    fader.timer.run();
  }
}

Fader.prototype.privateSetOpacity = function(opacity)
{
  this.opacity = opacity;

  if(opacity == 0)
  {
    if(this.node.style.visibility != 'hidden')
      this.node.style.visibility = 'hidden';
  } else {
    if(this.node.style.visibility != 'visible')
      this.node.style.visibility = 'visible';
  }

  Paradise.setOpacity(this.node, opacity);
}

Fader.prototype.fadeTo = function(opacity)
{
  var direction;

 direction = opacity - this.opacity;

  if(direction < 0)
  {
    this.speed = -this.maxSpeed;
    this.timer.start();
  }

  if(direction == 0)
  {
    this.speed = 0;
    this.timer.stop();
  }

  if(direction > 0)
  {
    this.speed = +this.maxSpeed;
    this.timer.start();
  }
}

Fader.prototype.jumpTo = function(opacity)
{
  this.speed = 0;
  this.timer.stop();
  this.privateSetOpacity(opacity);
}

/*******************************
** Drop Down Menu Binder
*/

function DropDownMenuBinder(sensorId, menuId)
{
  var sensor, menu, list, i;

  sensor = document.getElementById(sensorId);
  menu = document.getElementById(menuId);

  sensor.boundMenu = menu;
  sensor.onmouseover = this.show;
  sensor.onfocus = this.show; // TAB
  sensor.onmouseout = this.hide;
  sensor.onblur = this.hide; // TAB

  menu.boundMenu = menu;

  list = menu.getElementsByTagName('a');

  for(i = 0;i < list.length;i++)
  {
    list[i].onmouseover = this.show;
    list[i].onfocus = this.show; // TAB
    list[i].onmouseout = this.hide;
    list[i].onblur = this.hide; // TAB
  }

  menu.fader = new Fader(menuId, 0, 10);
}

DropDownMenuBinder.fade = function(evn, opacity)
{
  var sensor;

  sensor = Paradise.getParentWith(
    Paradise.getEventNode(evn),
    'boundMenu'
  );

  if(sensor && sensor.boundMenu)
    sensor.boundMenu.fader.fadeTo(opacity);
}

DropDownMenuBinder.prototype.show = function(evn)
{
  DropDownMenuBinder.fade(evn, 100);
}

DropDownMenuBinder.prototype.hide = function(evn)
{
  DropDownMenuBinder.fade(evn, 0);
}

/*******************************
** Plenoptic Binder
*/

function PlenopticBinder(sensorIdArray, nodeIdArray)
{
  var i, sensor, node, nodes, opacities;

  nodes = new Array();
  opacities = new Array();
  for(i = 0;i < sensorIdArray.length;i++)
  {
    sensor = document.getElementById(sensorIdArray[i]);
    node = document.getElementById(nodeIdArray[i]);

    nodes[i] = node;
    opacities[i] = 0;

    sensor.boundPlenoptic = this;
    sensor.boundIndex = i;
    sensor.onmouseover = this.show;
    sensor.onmouseout = this.hide;

    node.fader = new Fader(nodeIdArray[i], 0, 5);
  }

  this.nodes = nodes;
  this.opacities = opacities;
}

PlenopticBinder.blend = function(evn, level)
{
  var i, sensor, nodes, opacities;

  sensor = Paradise.getParentWith(
    Paradise.getEventNode(evn),
    'boundPlenoptic'
  );

  if(sensor && sensor.boundPlenoptic)
  {
    nodes = sensor.boundPlenoptic.nodes;
    opacities = sensor.boundPlenoptic.opacities;

    for(i = 0;i < nodes.length;i++)
    {
      if(nodes[i].style.zIndex != '0')
        nodes[i].style.zIndex = '0';
      opacities[i] = 0;
    }

    nodes[sensor.boundIndex].style.zIndex = level;
    opacities[sensor.boundIndex] = level;

    for(i = 0;i < nodes.length;i++)
    {
      nodes[i].fader.fadeTo(opacities[i]);
    }
  }
}

PlenopticBinder.prototype.show = function(evn)
{
  PlenopticBinder.blend(evn, 100);
}

PlenopticBinder.prototype.hide = function(evn)
{
  PlenopticBinder.blend(evn, 0);
}
