// --- Common ---

function $l(el) {
  return (typeof(el) == 'string' ? document.getElementById(el) : el);
}

function $l_(id, container, tag) {
  if (typeof(id) != 'string') return id;
  if (!container) return document.getElementById(id); 
  var list = container.getElementsByTagName(tag ? tag.toUpperCase() : '*');
  for (var i = 0, l = list.length; i < l; i++) {
    var el = list[i];
    if (el.id == id) return el;
  }
  return null;
}

function getAbsPos(el) {
  var pos = {left:0, top:0};
  while (el && el.tagName != 'BODY') {
    pos.left += el.offsetLeft;
    pos.top += el.offsetTop;
    el = el.offsetParent;
  }
  return pos;
}

function getAbsTop(el) {
  var top = 0;
  while (el && el != document.body) {
    top += el.offsetTop;
    el = el.offsetParent;
  }
  return top;
}


function isChildOf(el, parent) {
  while (el != null) {
    if (el == parent) return true;
    el = el.parentNode;
  } 
  return false;
}


function findSubChild(element, tag, className) {
  var list = element.getElementsByTagName(tag.toUpperCase());
  if (className == null) return (list.length > 0 ? list[0] : null);
  for (var i = 0, l = list.length; i < l; i++) {
    var el = list[i];
    if (el.className == className) return el;
  }
  return null;
}

function findParentNode(el, tag, className) {
  if (el == null) return null;
  if (tag) tag = tag.toUpperCase();
  while (true) {
    el = el.parentNode;
    if (el == null) return null;
    if ((!tag || tag == '*' || el.tagName == tag)
     && (className == null || el.className == className)) return el;
  }
}

function trim(s) { return s.replace(/^\s+/, '').replace(/\s+$/, '') }

var
  userAgent = navigator.userAgent,
  isKHTML = (userAgent.indexOf('KHTML') >= 0),
  isOpera = (userAgent.indexOf('Opera') >= 0),
  isIE = (!isOpera && userAgent.indexOf('MSIE') >= 0),
  isIE50 = (isIE && /MSIE 5\.0/.test(userAgent) && navigator.platform == 'Win32'),
  isMozilla = (!isKHTML && !isOpera &&  userAgent.indexOf('Gecko') >= 0);

function setupEvent(el, eventType, handler, capture) {
  if (el.attachEvent) el.attachEvent('on'+eventType, handler)
  else if (el.addEventListener) el.addEventListener(eventType, handler, capture);
}

function removeEvent(el, eventType, handler, capture) {
  if (el.detachEvent) el.detachEvent('on'+eventType, handler)
  else if (el.removeEventListener) el.removeEventListener(eventType, handler, capture);
}

function cancelEvent(event) {
  event.returnValue = false;
  if (event.preventDefault) event.preventDefault();
  event.cancelBubble = true;
  if (event.stopPropagation) event.stopPropagation();
}

function isLeftButtonEvent(event) {
  if (isIE) {
    if (event.button == 1) return true;
  } else 
    if (event.button == 0) return true;
  return false;
}

var
  mouseMoveListeners = [],
  mouseAbsPosX = 0,
  mouseAbsPosY = 0;

function addMouseMoveListener(handler, object) {
  var i, o;
  for (i = 0; i < mouseMoveListeners.length; i++) {
    o = mouseMoveListeners[i];
    if (o.method == handler && o.instance == object) return false;
  }
  if (mouseMoveListeners.length == 0)
    setupEvent(document, 'mousemove', mouseMoveEventHandler);
  mouseMoveListeners.push({method: handler, instance: object});
  return true;
}

function removeMouseMoveListener(handler, object) {
  var i, o;
  for (i = 0; i < mouseMoveListeners.length; i++) {
    o = mouseMoveListeners[i];
    if (o.method == handler && o.instance == object) {
      mouseMoveListeners.splice(i, 1);
      if (mouseMoveListeners.length == 0)
        removeEvent(document, 'mousemove', mouseMoveEventHandler);
      return;
    }
  }
}

function mouseMoveEventHandler(event) {
  if (document.body == null) return;
  mouseAbsPosX = event.clientX + document.body.scrollLeft;
  mouseAbsPosY = event.clientY + document.body.scrollTop;
  var i, o;
  for (i = 0; i < mouseMoveListeners.length; i++) {
    o = mouseMoveListeners[i];
    if (o.method) o.method.call(o.instance || window, event);
  }
}


var
  activeMouseOverElement;

function mouseOverElement(event, el, func) {
  var el = $l(el);
  var target = (event.target || event.toElement);
  while (target && target != el) target = target.parentNode;
  if (target && target != activeMouseOverElement) {
    activeMouseOverElement = target;
    if (func) func(target);
  }
}

function mouseOutElement(event, el, func) {
  var el = $l(el);
  var target = (event.relatedTarget || event.toElement);
  while (target && target != el) target = target.parentNode;
  if (target != activeMouseOverElement && activeMouseOverElement != null) {
    if (func) func(activeMouseOverElement);
    activeMouseOverElement = null;
  }
}



function isNumber(prm) {
  return (typeof(prm.valueOf()) == 'number');
}

function isString(prm) {
  return (typeof(prm.valueOf()) == 'string');
}

function isFunction(prm) {
  return (typeof(prm.valueOf()) == 'function');
}

function isArray(prm) {
  return (typeof(prm.valueOf()) == 'array' || (typeof(prm) == 'object' && 'join' in prm));
}


if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(item, first) {
    for (var i = first || 0, l = this.length; i < l; i++) {
      if (this[i] === item) return i;
    }
    return -1;
  }
}

Array.prototype.addItem = function(item) {
  var i = this.indexOf(item);
  if (i < 0) {
    i = this.length;
    this.push(item);
  }
  return i;
}

Array.prototype.removeItem = function(item) {
  var i = this.indexOf(item);
  if (i >= 0) this.removeItemByIndex(i);
  return i;
}

Array.prototype.removeItemByIndex = function(i) {
  if (this.splice) {
    this.splice(i, 1);
  } else {
    var l = this.length;
    for (var j = i+1; j < l; j++) this[j-1] = this[j];
    this.length = l-1;
  }
}


/*
//-- Zoom --

var
  zoomingElements = [],
  zoomingFastToSlow = true;

// grow: D - down, R - right, F - fast to slow, S - slow to fast, '+' - open, '-' - close
function zoom(el, grow, delta, delay) {
  el = $l(el);
  if (el.zoomIntervalId) {
    clearInterval(el.zoomIntervalId);
    el.zoomIntervalId = null;
    el.zooming = false;
  }
  var direction = '', action = '', fast = null;
  if (grow) {
    grow = grow.toUpperCase();
    if (grow.indexOf('R') >= 0) direction = 'R'
    else if (grow.indexOf('D') >= 0) direction = 'D';
    if (grow.indexOf('+') >= 0) action = '+'
    else if (grow.indexOf('-') >= 0) action = '-';
    if (grow.indexOf('F') >= 0) fast = true
    else if (grow.indexOf('S') >= 0) fast = false;
  }
  if (direction == '') direction = (el.zoomDirection || 'D');  // down
  el.zoomDirection = direction;
  var offsetProp = (direction == 'D' ? 'offsetHeight' : 'offsetWidth');
  var styleProp = (direction == 'D' ? 'height' : 'width');
  if (action == '') {
    if (el.zoomAction) action = (el.zoomAction == '+' ? '-' : '+')
    else action = (el[offsetProp] > 0 ? '-' : '+');
  }
  el.zoomAction = action;
  if (fast == null) fast = el.zoomingFastToSlow || zoomingFastToSlow;
  el.zoomingFastToSlow = fast;
  if (delta == 'quick') {
    if (action == '+') {
      el.style.display = 'block';
      el.style.visibility = 'visible';
      el.style[styleProp] = (el.zoomMaxSize ? el.zoomMaxSize+'px' : '');
    } else {
      el.style.display = 'none';
    }
    el.zoomCurSize = el[offsetProp];
    if (el.afterZoom) {
      var i = zoomingElements.addItem(el);
      setTimeout('callAfterZoom('+i+')', 0);
    }
    el.zoomed = (action == '+');
    return;
  }
  el.zoomAlpha = 1.4;
  el.style.overflow = 'hidden';
  if (action == '+') {
    el.style.display = 'block';
    if (el.zoomMaxSize) el.zoomNewSize = el.zoomMaxSize
    else {
      el.style[styleProp] = '';
      el.zoomNewSize = el[offsetProp];
    }
    if (fast) {
      el.zoomCurEzis = el.zoomNewSize/el.zoomAlpha;
      el.zoomCurSize = el.zoomNewSize - el.zoomCurEzis;
    } else {
      if (!el.zoomCurSize) el.zoomCurSize = 1;
    }
  } else {
    if (fast) {
      if (!('zoomCurSize' in el)) el.zoomCurSize = el[offsetProp]/el.zoomAlpha;
      else el.zoomCurSize = el.zoomCurSize/el.zoomAlpha;
    } else {
      el.zoomCurEzis = 1;
      if (!('zoomCurSize' in el)) el.zoomCurSize = el[offsetProp];
      el.zoomCurSize -= el.zoomCurEzis;
    }
    el.zoomNewSize = 0;
  }
  el.zoomDelta = delta;
  el.style.visibility = 'visible';
  el.style[styleProp] = Math.round(el.zoomCurSize)+'px';
  var h = el[offsetProp];  // to prevent show full block in Fx
  el.zoomed = false;
  el.zooming = true;
  var i = zoomingElements.addItem(el);
  el.zoomIntervalId = setInterval('stepZooming('+i+')', delay || 50);
}

function stepZooming(i) {
  var el = zoomingElements[i];
  if (!el) return;
  var styleProp = (el.zoomDirection == 'D' ? 'height' : 'width');
  var finished = false;
  if (el.zoomDelta) {
    if (el.zoomAction == '+') {
      el.zoomCurSize += el.zoomDelta;
      if (el.zoomCurSize >= el.zoomNewSize) {
        el.zoomCurSize = el.zoomNewSize;
        finished = true;
      }
    } else {
      el.zoomCurSize -= el.zoomDelta;
      if (el.zoomCurSize < 1) {
        el.zoomCurSize = 0;
        finished = true;
      }
    }
  } else {
    if (el.zoomAction == '+') {
      if (el.zoomingFastToSlow) {
        var prevSize = el.zoomCurSize;
        el.zoomCurEzis = el.zoomCurEzis/el.zoomAlpha;
        el.zoomCurSize = el.zoomNewSize - el.zoomCurEzis;
        if (Math.round(el.zoomCurSize) == Math.round(prevSize)) {
          el.zoomCurSize = el.zoomNewSize;
          finished = true;
        }
      } else {
        el.zoomCurSize = el.zoomCurSize*el.zoomAlpha;
        if (el.zoomCurSize >= el.zoomNewSize) {
          el.zoomCurSize = el.zoomNewSize;
          finished = true;
        }
      }
    } else {
      if (el.zoomingFastToSlow) {
        el.zoomCurSize = el.zoomCurSize/el.zoomAlpha;
      } else {
        el.zoomCurEzis = el.zoomCurEzis*el.zoomAlpha;
        el.zoomCurSize -= el.zoomCurEzis;
      }
      if (el.zoomCurSize < 1) {
        el.zoomCurSize = 0;
        finished = true;
      }
    }
  }
  if (!finished) {
    el.style[styleProp] = Math.round(el.zoomCurSize)+'px';
    if (el.whileZoom) el.whileZoom(el);
  } else {
    clearInterval(el.zoomIntervalId);
    el.zoomIntervalId = null;
    el.zooming = false;
    el.zoomed = (el.zoomCurSize > 0);
    if (el.zoomCurSize == 0) el.style.display = 'none';
    el.style[styleProp] = (el.zoomMaxSize ? el.zoomMaxSize+'px' : '');
    el.style.overflow = '';
    if (el.afterZoom) setTimeout('callAfterZoom('+i+')', 0)
    else zoomingElements.removeItemByIndex(i);
  }
}

function callAfterZoom(i) {
  var el = zoomingElements[i];
  zoomingElements.removeItemByIndex(i);
  callEventHandler(el.afterZoom, el);
}*/



// warnings
function warn(s) {
  alert(s);
}


// element info
function elInfo(el) {
  if (el == null) return 'null';
  if (typeof(el) == 'string') return "'"+el+"'";
  if (typeof(el) == 'number' || typeof(el) == 'boolean') return el;
  return (el.nodeName || el) + (el.id ? '#'+el.id : '') + (el.className ? '.'+el.className : '');
}


// Iterator  1.0  15.05.2008

// Iterator constructor, �������� �� ����������
function Iterator(interval) {
  this.interval = interval;
  this.items = [];
}

// ������ ����������
Iterator.iterators = {};

// �������� �� ��������� - 25 ������ � �������
Iterator.defInterval = 40;


// Iterator.startIterate(obj[, interval[, method]]) - ����� ������
//----------------------------------------------------------------
// ������� (��� �������������) �������� ��� ������� ���������,
// ��������� �������� ������ obj.method()
//
// �����:
//  var iterator = Iterator.startIterate(obj[, interval[, method]])
//   obj - ������ (����� ����������� � ���������� ���������)
//   interval - �������� ����� ���������� � �������������
//   method - �����, ���������� ��� ���������,
//            ���� �� ������, ����� ���������� obj.onIterate()
// ���������� ������ �� ��������
//
Iterator.startIterate = function(obj, interval, method) {
  if (!interval) interval = Iterator.defInterval;
  var it = Iterator.iterators[interval];
  if (!it) {
    it = Iterator.iterators[interval] = new Iterator(interval);
  }
  it.addObj(obj, method);
  return it;
}

// Iterator class
Iterator.prototype = {

// private method - ��������� ���� (obj, method) � ��������
  addObj: function(obj, method) {
    if (!method) method = obj.onIterate;
    this.items.push({obj: obj, method: method});
    if (!this.intervalId) {
      var iterator = this;
      this.intervalId = setInterval(function(){iterator.iterate()}, this.interval);
    }
  },

// iterator.stopIterate(obj, reason[, method])
//----------------------------------------------------------------
// ������������� �������� ������ obj.method()
// ���� method �� �����, ������������� ������ ���������� �������� ��� ������� obj
// reason - ������� ���������, ���������� � ����� obj.onEndIterate()
  stopIterate: function(obj, reason, method) {
    var items = this.items;
    for (var i = 0, l = items.length; i < l; i++) {
      var item = items[i];
      if (item.obj == obj && (method == null || item.method == method)) {
        this.removeObjByIdx(i, reason);
        return;
      }
    }
  },

// iterator.removeObjByIdx(idx, reason)
//----------------------------------------------------------------
// ������������� �������� ������ � �������� idx.
// reason - ������� ���������.
// �������� c������ obj.onEndIterate(reason, method)
//
  removeObjByIdx: function(idx, reason) {
    var items = this.items;
    var item = items[idx];
    if (item) {
      items.removeItemByIndex(idx);
      var obj = item.obj;
      if (obj.onEndIterate) obj.onEndIterate(reason, item.method);
    }
  },

// private method - ���������� ����� ������ ���������,
// �������� ������ �������� ��������: obj.method(iterator, idx)
  iterate: function() {
    var items = this.items;
    for (var i = items.length-1; i >= 0; i--) {
      var item = items[i];
      item.method.call(item.obj, this, i);
    }
    if (items.length == 0 && this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
  }

}



// Animator  1.0  15.05.2008

// Equation class - ������� ���������/���������� ���� ��������
Equation = {
  
// �������� - ����������� ��� ��������
  linear: function(t) {
    return t
  },

// ������������ - ���������
  quadroIn: function(t) {
    return t*t;
  },
// ����������
  quadroOut: function(t) {
    return Math.sqrt(t);
  },
// ���������, ����������� �����������
  quadroInOut: function(t) {
    if (t < 1/2)
      return 2*t*t;
    else
      return (Math.sqrt(2*t - 1) + 1)/2;
  },

// ����������
  cubicIn: function(t) {
    return t*t*t;
  },

  cubicOut: function(t) {
    return Math.pow(t, 1/3);
  },

  cubicInOut: function(t) {
    if (t < 1/2)
      return 2*t*t;
    else
      return (Math.pow(2*t - 1, 1/3) + 1)/2;
  },

// 4-� c������
  quartIn: function(t) {
    return t*t*t*t;
  },

  quartOut: function(t) {
    return Math.sqrt(Math.sqrt(t));
  },

  quartInOut: function(t) {
    if (t < 1/2)
      return 8*t*t*t*t;
    else
      return (Math.sqrt(Math.sqrt(2*t - 1)) + 1)/2;
  },

// ����������������
  expIn: function(t) {
    return (t <= 0 ? 0 : Math.pow(2, 10*(t - 1)));
  },

  expOut: function(t) {
    return (t >= 1 ? 1 : (-Math.pow(2, -10*t) + 1));
  },

  expInOut: function(t) {
    if (t <= 0) return 0;
    if (t >= 1) return 1;
    if (t < 1/2)
      return Math.pow(2, 10*(2*t - 1))/2;
    else
      return (2 - Math.pow(2, -10*(2*t - 1)))/2;
  },

// �� ����������
  expIn2: function(t) {
    var n = 3;  // 1 - ��. ������, 5 - �����
    var v = (Math.exp(t*n)-1)/(Math.exp(n)-1);
    return v;
  },

  expOut2: function(t) {
    return (1 - Equation.expIn2(1 - t));
  },

  expInOut2: function(t) {
    if (t < 1/2)
      return Equation.expIn2(2*t)/2
    else
      return (Equation.expOut2(2*t - 1) + 1)/2;
  },

// c��������             
  sineIn: function(t) {
    return Math.sin((t-1)*Math.PI/2) + 1;
  },

  sineOut: function(t) {
    return Math.sin(t*Math.PI/2);
  },

  sineInOut: function(t) {
    return (Math.sin((t-1/2)*Math.PI)+1)/2;
  },

// ���� ����������
  circIn: function(t) {
    return 1 - Math.sqrt(1 - t*t);
  },

  circOut: function(t) {
    return Math.sqrt(t*(2 - t));
  },

  circInOut: function(t) {
    if (t < 1/2)
      return (1 - Math.sqrt(1 - 4*t*t))/2;
    else
      return (Math.sqrt((2*t - 1)*(3 - 2*t))+1)/2;
  }

}








// ��������� �� ��������� ��� ��������
AnimationDefaults = {
    interval: 40          // �������� ����� ���������� (��)
//  defTime: 500,         // ���� defTime - ������������ �������� (��)
//  defSteps: 12,         // ���� defSteps - ���������� �����
//  equ: Equation.linear  // ������� ���� ��������
}

// Animation constructor - �������� �������-��������
//----------------------------------------------------------------
// �����:
//  new Animation({��������: ��������, ...});
//
// ���������:
//  obj - ����������� �������.
//  id - �������������� ��� ���������, �������� id: 'height' - ��������� ������ ��������.
//      �������� �� ����� �������� � ���� �� ����������� obj � id ��������� ���������� ��������
//  interval - �������� ����� ���������� � �������������.
//  time - ������������ �������� � �������������, ���������� ����� ������ �������� �� �������.
//  steps - ���������� ����� ��������, ���������� ����� ������ �������� �� ���������� �����.
//      ���� �� ����� �� time �� steps, ����� ������������ �� AnimationDefaults.defTime ��� defSteps
//  styleProperty - ��� c������� ����� obj, ������� ���� ������.
//      �������� 'left' ��� ��������� obj.style.left
//  startValue - ��������� �������� ��������, �������� 0
//  finalValue - �������� �������� ��������, �������� 42 (��������� �� 0 �� 42)
//  round - ���� �� false, �� ����� ������������� �������� �����������.
//      ���� true, �� ���������� ������������ �������� Math.round
//      ����� ���� ������� �� ������� ����������, �������� round: Math.ceil
//  units - �������, ������������ � ��������, �������� 'px'
//  t - ��������� �������� ��������� ���� �������� �� ������� [0, 1],
//      0 - ������ (�� ���������), 1/2 - c�������, 1 - �����
//  fast - �������� �� �����������, ����� ���������� ������� ����������
//  onCustomIterate - c������, ������������ ��� ������ �������� ����� ������� t, equT � value,
//      �� ����� ����������� �������� ��������. ������ ������: obj.onCustomIterate(idx)
//      ��� idx - ������ ������� Animation-������� ��� ������ iterator.removeObjByIdx(idx, reason)
//  onEndAnimation - �������, ��������������� � ���������� ��������.
//      ������ ������: obj.onEndAnimation(reason)
//
// ���������� ������ �� ������-��������. ��������� ������ �������������,
// �.�. ��� ������������� ����������� � ������ Animations
//
function Animation(params) {
//����������� ��������� � this
  expandObj(this, params);
  expandObj(this, AnimationDefaults);
  this.state = 'init';

//����� ���������� �������� � �������� �
  var prevAni = Animations.findObj(this.obj, this.id);
  if (prevAni) {
    prevAni.finalize('aborted');
  }

//�������� �������� � ������ Animations
  Animations.push(this);

//�������� �� ��������� ����������
  if (this.fast || this.time == 0 || this.steps == 0 || (this.startValue == this.finalValue && this.startValue != null)) {
    this.callFinalize();
    return;
  }

//���������� ����� (time | steps)
  this.mode = ('time' in this) ? 'time' :
              ('steps' in this) ? 'steps' :
              (this.defTime != null) ? 'time' :
              (this.defSteps != null) ? 'steps' : 'time';

//���c������ ��������� ����� ��� ������� ���
//<--  �������� time ��� steps == null
  if (this.mode == 'steps') {
    if (!('steps' in this)) this.steps = this.defSteps || 0;
    this.curStep = (this.t ? Math.round(this.steps*this.t) : 0);
  } else {
    if (this.time == null) this.time = this.defTime || 0;
    this.startTime = new Date().getTime() - (this.t ? this.time*this.t : 0);
  }

//�����a������� ��������� ����������
  if (this.t == null) this.t = 0;
  this.equT = (this.equ ? this.equ(this.t) : this.t);
  if (this.units == null) this.units = '';
  if (this.round) {
    if (typeof(this.round) == 'boolean') this.round = Math.round
  }

//��������� ��������
  this.state = 'processing';
  this.iterator = Iterator.startIterate(this, this.interval);
}


// Animation class
Animation.prototype = {

// event - ���������� ����������, ��� � ���������� ��������
  onIterate: function(iterator, idx) {
    if (this.state != 'processing') return;

//  ��������� t
    if (this.mode == 'steps') {
//    ��������� t �� ������ ����
      this.t = (++this.curStep)/this.steps;
    } else {
//    ��������� t �� �������
//    if (this.startTime) {
      this.t = (new Date().getTime() - this.startTime)/this.time;
//    } else {
//      this.startTime = new Date().getTime() - this.time*this.t;
//    }
    }
    if (this.t > 1) this.t = 1;

//  ���������� t ����� equation-�������
    this.equT = (this.equ ? this.equ(this.t) : this.t);

//  ��������� value �� ������ startValue � finalValue
    if (this.startValue != null && this.finalValue != null) {
      this.value = this.startValue + (this.finalValue - this.startValue)*this.equT;
      if (this.round) this.value = this.round(this.value);
    }

//  ������� ������� ���������� �������
    if (this.onCustomIterate) this.onCustomIterate(idx);

//  �������� ��������
    if (this.obj && this.obj.style && this.styleProperty && this.value != null) {
      this.obj.style[this.styleProperty] = this.value + this.units;
    }

//  ���� ���������, ��������� ��������
    if (this.t >= 1) this.callFinalize();
  },

// animation.callFinalize(reason)
//----------------------------------------------------------------
// ��������� ��������, �������� finalize() ����� ���������.
// ������������, ����� ����, ���� ������� onEndAnimation ��������� ����� ����������� �����,
// � �� ������ ����� ������.
//   reason - ������� ���������� �������� ��� ����� � onEndAnimation
//      �������� '' ��� 'finished' - ������� ���������� ��������,
//      'aborted' - �������� �������� ������ ���������
//
  callFinalize: function(reason) {
    this.state = 'finishing';
    var animation = this;
    setTimeout(function(){animation.finalize(reason)}, 0);
  },

// ��������� ��������, �������� onEndAnimation
  finalize: function(reason) {
    if (this.state != 'finished') {
      this.state = 'finished';
      if (!reason) reason = 'finished';
      if (this.iterator) {
        this.iterator.stopIterate(this, reason);
        this.iterator = null;
      } else {
//      � fast-������ �������� �� ���������
        this.onEndIterate(reason);
      }
    }
  },

// event, ���������� ��� ���������� ��������.
// this == intance of Animation
  onEndIterate: function(reason) {
    Animations.removeItem(this);
    if (this.onEndAnimation) this.onEndAnimation(reason);
  }

}


// ������ �������� ��������
Animations = [];

Animations.indexOfObj = function(obj, id) {
  for (var i = 0, l = this.length; i < l; i++) {
    var a = this[i];
    if (a.obj == obj && a.id == id) return i;
  }
  return -1;
}

Animations.findObj = function(obj, id) {
  var idx = this.indexOfObj(obj, id);
  return (idx >= 0 ? this[idx] : null);
}

Animations.removeObj = function(obj, id) {
  var idx = this.indexOfObj(obj, id);
  if (idx >= 0) this.removeItemByIndex(idx);
}










//-- zoom ----------------------------------------------

// ��������� �� ��������� ��� zoom
zoomDefaults = {
//interval: 40,   // �������� ����� ���������� (��)
  defTime: 500,   // ������������ zoom-� (��)
//defSteps: 25,   // ���������� �����
                  // ���� defTime, ���� defSteps ����������
//action: 'auto', // ��������: ����������, ��������, ���� (���� ������� ����� - ��������, ���� ����� - ����������)
                  // '+' == 'show' | '-' == 'hide' | '' == 'auto'
  overflow: 'hidden,', // ������� zoom-� overflow: 'hidden', ������ overflow: ''
  dir: 'v'        // ����������� zoom-� (v - ������������, h - ��������������), ������������
//equ: Equation.expInOut // ������� ���� ��������
}

// zoom - ��������������/������������ ��������
//----------------------------------------------------------------
// �����:
//  zoom(el, <���������...>, <���������...>, ...);
//
//  el - ������� ��� ��� id
//  ��������� ��������� ���������� � �����: {��������: ��������, ��������: ��������, ...}
//  ����� ����� ����� ���� ��������� ��� �� ���� ������.
//
// ���������:
//  interval - �������� ����� ���������� � �������������.
//  time - ������������ zoom-� � �������������, ���������� ����� ������ zoom-� �� �������.
//  steps - ���������� ����� zoom-�, ���������� ����� ������ zoom-� �� ���������� �����.
//    ���� �� ����� �� time �� steps, ����� ������������ �� zoomDefaults.defTime ��� defSteps
//  dir - ����������� zoom-�: 'v' - ������������ (�� ���������), 'h' - ��������������.
//  action - �������� (����������, ��������, ����):
//    '+', 'show' - ����������;  '-', 'hide' - c�������;
//    '', 'auto' - ���� ������� ����� - ��������, ���� ����� - ����������.
//  overflow - ��������� ��� ������ �������� overflow ��������, 'keep' - �� ������.
//  fast - zoom �� ���� ���, ��� ��������.
//  onZoomIterate - c������, ������������ ��� ������ ��������, ��. Animation.onCustomIterate
//  afterZoom - �������, ��������������� � ���������� zoom-�.
//    ������ ������: obj.afterZoom(reason)
//    ��� reason - ������� ��������� zoom-�:
//      'finished' - zoom ���������� ���������,
//      'aborted' - zoom ��� ������� ������ zoom-��.
//
function zoom(el, param1, param2/*...*/) {
  el = $l(el);
  var params = {
    obj: el,
    units: 'px',
    round: true,
    onEndAnimation: zoom.onEndZoom
  }

//�������� ��������� �� param1, param2, ...
  for (var i = arguments.length-1; i > 0; i--) {
    var arg = arguments[i];
    if (typeof(arg) == 'string') {
      if (arg == '+' || arg == '-') arg = {action: arg}
      else {
        warn('Invalid zoom('+elInfo(el)+') argument: "'+arg+'"');
        continue;
      }
    } else if (typeof(arg) == 'number') {
      warn('Invalid zoom('+elInfo(el)+') argument: '+arg);
      continue;
    }
    expandObj(params, arg);
  }
  expandObj(params, zoomDefaults);

//���������� ����������� ���� (v | h)
  params.dir = (params.dir != '' && ('horizontal').indexOf(params.dir) == 0 ? 'h' : 'v');
  var property = params.id = params.styleProperty = (params.dir == 'h' ? 'width' : 'height');

//��������, ���� �� �������� ��������
  var prevAni = Animations.findObj(el, property);

//���������� �������� (show | hide)
  var show = 
    (!params.action || params.action == 'auto' ?
      (prevAni ?
        prevAni.action == 'hide' : (property == 'width' ? el.offsetWidth : el.offsetHeight) == 0)
    :
      (params.action != '-' && params.action != 'hide'));
  var action = params.action = (show ? 'show' : 'hide');

  if (params.onZoomIterate) params.onCustomIterate = params.onZoomIterate;

//������������� overflow
  if (params.overflow != null && params.overflow != 'keep') {
    setStylePropFor(el, 'overflow', params.overflow);
    params.overflowSet = true;
  }
  if (params.overflowX != null && params.overflowX != 'keep' && el.style.overflowX != null) {
    setStylePropFor(el, 'overflowX', params.overflowX);
    params.overflowXSet = true;
  }
  if (params.overflowY != null && params.overflowY != 'keep' && el.style.overflowY != null) {
    setStylePropFor(el, 'overflowY', params.overflowY);
    params.overflowYSet = true;
  }
  
  if (prevAni) {
    var sameAction = (prevAni.action == action);
    params.startValue = prevAni[(sameAction ? 'startValue' : 'finalValue')];
    params.finalValue = prevAni[(sameAction ? 'finalValue' : 'startValue')];
    params.t = (sameAction ? prevAni.t : 1 - prevAni.t);
  } else {
    params.startValue = (property == 'width' ? el.offsetWidth : el.offsetHeight) || 1;
    params.finalValue = (show ? zoom.getMaxValue(el, property) : 1);
  }

//��������� ��������
  new Animation(params);
}

// privat - ���������� ������ ��� ������ ����� � ����������� ���������
zoom.getMaxValue = function(el, property) {
  var offsetProp = (property == 'width' ? 'offsetWidth' : 'offsetHeight');
  var curValue = el[offsetProp];
  if (curValue == 0) {
    el.style.display = 'block';
    el.style.visibility = 'visible';
  }
  el.style[property] = '';
  var maxValue = el[offsetProp];
  el.style[property] = (curValue || 1)+'px';
  var h = el[offsetProp];  // to prevent show full block in ff
  return maxValue;
}

// event, ���������� ��� ���������� ��������.
// this == intance of Animation
zoom.onEndZoom = function(reason) {
  if (this.overflowSet) {
    this.overflowSet = false;
    unsetStylePropFor(this.obj, 'overflow');
  }
  if (this.overflowXSet) {
    this.overflowXSet = false;
    unsetStylePropFor(this.obj, 'overflowX');
  }
  if (this.overflowYSet) {
    this.overflowYSet = false;
    unsetStylePropFor(this.obj, 'overflowY');
  }
  if (!reason || reason == 'finished') {
    this.obj.style[this.styleProperty] = '';
    if (this.action == 'hide') this.obj.style.display = 'none';
  }
  if (this.afterZoom) this.afterZoom(reason);
}







//-- fade ----------------------------------------------

// ��������� �� ��������� ��� fade-�
fadeDefaults = {
//interval: 40,   // �������� ����� ���������� (��)
//defTime: 160,   // ������������ fade-� (��)
  defSteps: 4     // ���������� ����� fade-�
}

// fade - ���������/������� ��������
//----------------------------------------------------------------
// �����:
//  fade(el, <���������...>, <���������...>, ...);
//
//  el - ������� ��� ��� id
//  ��������� ��������� ���������� � �����: {��������: ��������, ��������: ��������, ...}
//  ����� ����� ����� ���� ��������� ��� �� ���� ������.
//
// ���������:
//  interval - �������� ����� ���������� � �������������.
//  time - ������������ fade-� � �������������, ���������� ����� ������ fade-� �� �������.
//  steps - ���������� ����� fade-�, ���������� ����� ������ fade-� �� ���������� �����.
//    ���� �� ����� �� time �� steps, ����� ������������ �� fadeDefaults.defTime ��� defSteps
//  action - ��������� (��������, ������, ����):
//    '+', 'show' - ��������;  '-', 'hide' - ������;
//    '', 'auto' - ���� ������� ����� - ������, ���� ����� - ��������.
//  fast - fade �� ���� ���, ��� ��������.
//  onFadeIterate - c������, ������������ ��� ������ ��������, ��. Animation.onCustomIterate
//  afterFade - �������, ��������������� � ���������� fade-�.
//    ������ ������: obj.afterFade(reason)
//    ��� reason - ������� ��������� fade-�:
//      'finished' - fade ���������� ���������,
//      'aborted' - fade ��� ������� ������ fade-��.
//
function fade(el, param1, param2/*...*/) {
  el = $l(el);
  var params = {
    obj: el,
    id: 'opacity',
    onCustomIterate: fade.onIterate,
    onEndAnimation: fade.onEndFade
  }

//�������� ��������� �� param1, param2, ...
  for (var i = arguments.length-1; i > 0; i--) {
    var arg = arguments[i];
    if (typeof(arg) == 'string') {
      if (arg == '+' || arg == '-') arg = {action: arg}
      else {
        warn('Invalid fade('+elInfo(el)+') argument: "'+arg+'"');
        continue;
      }
    } else if (typeof(arg) == 'number') {
      warn('Invalid fade('+elInfo(el)+') argument: '+arg);
      continue;
    }
    expandObj(params, arg);
  }
  expandObj(params, fadeDefaults);

//��������, ���� �� �������� ��������
  var prevAni = Animations.findObj(el, 'opacity');

//���������� �������� (show | hide)
  var show = 
    (!params.action || params.action == 'auto' ?
      (prevAni ? prevAni.action == 'hide' : el.offsetHeight == 0)
    :
      (params.action != '-' && params.action != 'hide'));
  var action = params.action = (show ? 'show' : 'hide');

  if (prevAni) {
    var sameAction = (prevAni.action == action);
    params.startValue = prevAni[(sameAction ? 'startValue' : 'finalValue')];
    params.finalValue = prevAni[(sameAction ? 'finalValue' : 'startValue')];
    params.t = (sameAction ? prevAni.t : 1 - prevAni.t);
  } else {
    params.startValue = (el.offsetHeight == 0 ? 0 : 1);
    params.finalValue = (show ? 1 : 0);
  }

  params.fadeProperty = ('opacity' in el.style ? 'opacity' : 
                        ('filter' in el.style ? 'filter' : null));

//���� ��� �������� ������������, �� ������ ��������� (��� ��������)
  if (!params.fadeProperty) params.fast = true;

//��������� ��������
  new Animation(params);
}


fade.onIterate = function() {
  if (this.action == 'show' && !this.visibilitySet) {
    if (this.obj.offsetHeight == 0) this.obj.style.display = 'block';
    this.obj.style.visibility = 'visible';
    this.visibilitySet = true;
  }
  var value = this.startValue + (this.finalValue - this.startValue)*this.equT;
  this.obj.style[this.fadeProperty] = 
    (this.fadeProperty == 'filter' ? 'alpha(opacity='+Math.round(value*100)+')' : value);
  if (this.onFadeIterate) this.onFadeIterate();
}

fade.onEndFade = function(reason) {
  if (!reason || reason == 'finished') {
    if (this.fadeProperty) this.obj.style[this.fadeProperty] = '';
    if (this.action == 'hide') {
      this.obj.style.display = 'none';
    } else if (!this.visibilitySet) {
      this.obj.style.display = 'block';
      this.obj.style.visibility = 'visible';
    }
  }
  if (this.afterFade) this.afterFade(reason);
}







// Animation common - �������� ����������� �������� �� sour � dest
function expandObj(dest, sour) {
  for (var i in sour) {
    if (!(i in dest)) dest[i] = sour[i];
  }
}

// ������ �������� ���������� ������� ��������
var stylePropEls = [];

// setStylePropFor(el, property, values) - ��������� �������� c���� ��������
//---------------------------------------------------------------------------
// �������� property ��� el.style ��������������� � �������� ������� (set-) ��������� values
// � ����������� �� ��������� ����������� ������� setStylePropFor()
// �� ���������������� ���������� ������ unsetStylePropFor()
//   el - c����� �� �������
//   property - ��� ��������
//   values - ������ �� ����������, ����������� �������.
//     ������ (set-) �������� ��������������� ��� ������ ������ setStylePropFor(),
//     ����������� ������ � ���� �� ���������� el � property �� ������ ��������,
//     � ���� ����������� ���������� �������. ����� unsetStylePropFor() ��������� ���� �������,
//     � ��� ���������� 0 c������� ��������������� �� ������ (unset-) �������� ��������� values.
//     ������: values = 'hidden,' - set-��������: 'hidden, unset-��������: ''
//       values = 'visible' - set-�������� � unset-��������: 'visible'
//
function setStylePropFor(el, property, values) {
  for (var i = 0, l = stylePropEls.length; i < l; i++) {
    var rec = stylePropEls[i];
    if (rec.el == el && rec.property == property) {
      rec.count++;
      return;
    }
  }
  values = values.toString().split(',');
  stylePropEls.push({el: el, property: property, values: values});
  el.style[property] = values[0];
}

function unsetStylePropFor(el, property) {
  for (var i = 0, l = stylePropEls.length; i < l; i++) {
    var rec = stylePropEls[i];
    if (rec.el == el && rec.property == property) {
      if ((--rec.count) == 0) {
        stylePropEls.removeItemByIndex(i);
        el.style[property] = rec.values[(rec.values.length > 0 ? 1 : 0)];
      }
      return;
    }
  }
}




function callEventHandler(method, object) {
  if (method == null)     return false;
  if (!object) object = window;
  if (isFunction(method)) return method.call(object);
  if (isArray(method))    return method[0].apply(object, method.slice(1));
  if (isString(method))   return eval(method);
  return false;
}

//-- body events handler --

var bodyEventHandlers = {};

function setupBodyEvent(eventType, handler) {
  eventType = 'on'+eventType;
  var info = bodyEventHandlers[eventType];
  if (!info) {
    bodyEventHandlers[eventType] = {defHandler: document.body.getAttribute(eventType), handlers: [handler]};
    document.body.setAttribute(eventType, (isIE ? bodyEventWrapper : 'bodyEventWrapper(event)'));
  } else {
    info.handlers.push(handler);
  }
}

function bodyEventWrapper(event) {
  if (!event) event = window.event;
  var info = bodyEventHandlers['on'+event.type];
  for (var i = 0, l = info.handlers.length; i < l; i++) {
    callEventHandler(info.handlers[i]);
  }
  if (info.defHandler) callEventHandler(info.defHandler);
}



function initZoom(zoomEl, toggleEl){
//warn('initZoom: Old zoom call!');
  var zEl = $l(zoomEl);
  if (zEl == null) throw 'initZoom('+zoomEl+'): element not found';
  zEl.afterZoom = function() {
    var isOpen = (zEl.offsetHeight > 0);
    if (toggleEl.tagName == 'IMG') {
      toggleEl.src = 'i/'+(isOpen ? 'close' : 'open')+'.gif';
    } else { 
      toggleEl.innerHTML = (isOpen ? '�������' : '��������');
    }
  }
  zoom(zEl);
  return false
}


/*
//-- Fade -----------------------------------------------

var DEF_FADE_TIME    = 20;

var DEF_FADE_STEPS   = 4;

function fadeIn(el, time, steps, displayMode) {
  fade(el, 'in', time, steps, displayMode);
}

function fadeOut(el, time, steps, displayMode) {
  fade(el, 'out', time, steps, displayMode);
}

var
  fadingElements = [];

function fade(el, how, time, steps, displayMode) {
  el = $l(el);
  if (time == undefined) time = DEF_FADE_TIME;
  if (steps == undefined) steps = DEF_FADE_STEPS; else if (steps <= 0) steps = 1;
  if (el.fadeIntervalId) {
    clearTimeout(el.fadeIntervalId);
    el.fadeIntervalId = null;
  }
  el.fadeStep = ((how == 'in' ? 1 : -1)/steps);
  if (!('fadeValue' in el)) el.fadeValue = (how == 'in' ? 0 : 1);
  el.fadeValue += el.fadeStep;
  el.fadeDisplayMode = displayMode; 
  if (hasAlpha(el)) setAlpha(el, el.fadeValue);
  if (!el.alphaMode || steps == 1) {
    setVisible(el, how == 'in', displayMode);
    if (el.afterFade) callEventHandler(el.afterFade, el);
    if (el.afterFadeEnd) {
      var i = fadingElements.addItem(el);
      setTimeout('callAfterFadeEnd('+i+')', 0);
    }
    return;
  }
  if (how == 'in') setVisible(el, true, displayMode);
  var i = fadingElements.addItem(el);
  el.fadeIntervalId = setInterval('stepFading('+i+')', time/(steps-1));
}

function stepFading(i) {
  var el = fadingElements[i];
  if (el == null) return;
  el.fadeValue += el.fadeStep;
  if (el.fadeValue > 1) el.fadeValue = 1; else if (el.fadeValue < 0) el.fadeValue = 0;
  setAlpha(el, el.fadeValue);
  if (el.fadeValue <= 0 || el.fadeValue >= 1) {
    clearInterval(el.fadeIntervalId);
    el.fadeIntervalId = null;
    if (el.fadeValue <= 0) setVisible(el, false, el.fadeDisplayMode);
    if (el.afterFade) callEventHandler(el.afterFade, el);
    if (el.afterFadeEnd) setTimeout('callAfterFadeEnd('+i+')', 0);
    else fadingElements.removeItemByIndex(i);
  }
}

function callAfterFadeEnd(i) {
  var el = fadingElements[i];
  fadingElements.removeItemByIndex(i);
  callEventHandler(el.afterFadeEnd, el);
}*/


var DEF_DISPLAY_MODE = 'blank';   // 'visible' / 'block' / 'blank' / false

function hasAlpha(el) {
  if (!('alphaMode' in el))
    el.alphaMode = ('opacity' in el.style ? 'opacity' : 
                     ('filter' in el.style ? 'filter' : false));
  return el.alphaMode;
}

function getAlpha(el) {
  return ('alphaValue' in el ? el.alphaValue : 1);
}

function setAlpha(el, value) {
  if (el.alphaValue != value) {
    if (value < 0.01) value = 0;
    else if (value > 0.99) value = 1;
    el.alphaValue = value;
    if (!('alphaMode' in el)) hasAlpha(el);
    if (el.alphaMode == 'opacity')
      el.style.opacity = el.alphaValue
    else if (el.alphaMode == 'filter') 
      el.style.filter = 'alpha(opacity='+Math.round(el.alphaValue*100)+')';
  }
}

function setVisible(el, value, displayMode) {
  if (displayMode != undefined) el.displayMode = displayMode;
  else if ('displayMode' in el) displayMode = el.displayMode;
  else displayMode = DEF_DISPLAY_MODE;
  if (displayMode != false) {
    if (displayMode == 'visible') el.style.visibility = (value ? 'visible' : 'hidden');
    else el.style.display = (value ? (displayMode == 'blank' ? '' : displayMode) : 'none');
  }
}

//-- Hint --

var
  HintContainerId = 'hint_container';

function Hint(type, defContent, w, h) {
  this.hintContainer = document.createElement('DIV');
  this.hintContainer.className = 'hint';
  this.type = type || 'text';
  this.defContent = defContent;
  this.width = w;
  this.height = h;
  this.zIndex = 2000;
  this.inContainer = false;
  this.visible = false;
  this.fastShow = true;
  this.show = Hint_show;
  this.hide = Hint_hide;
  this.updatePos = Hint_updatePos;
  if (mouseMoveListeners.length == 0) addMouseMoveListener(null);  // add null handler to know mouse pos
}

function Hint_show(content, w, h) {
  if (content == null) content = this.defContent;
  if (w == null) w = this.width;
  if (h == null) h = this.height;
  var hintCont = this.hintContainer;

  hintCont.innerHTML = 
   '<table border="0" cellspacing="0" cellpadding="0"><tr><td>'+
     (this.type == 'image' ?
       '<img src="'+content+'"'+(w ? ' width="'+w+'"' : '')+(h ? ' height="'+h+'"' : '')+'>' :
       '<b></b><div>'+content+'</div><b></b>') +
   '</td></tr></table>';
  if (w) hintCont.style.width = w;
  if (h) hintCint.style.height = h;

  if (this.visible) return;
  hintCont.hintObject = this;
  if (!this.mouseHandlerAdded) {
    addMouseMoveListener(Hint_updatePos, this);
    this.mouseHandlerAdded = true;
  }

  if (!this.inContainer) {
    (document.getElementById(HintContainerId) || document.body).appendChild(hintCont);
    this.inContainer = true;
  }
  if (this.zIndex) hintCont.style.zIndex = this.zIndex;
  if (this.width) hintCont.style.width = this.width;
  if (this.fastShow) 
    setVisible(hintCont, true)
  else
    fade(hintCont, '+');
  this.visible = true;
  var t = hintCont.getElementsByTagName('TABLE')[0];
  this.hintWidth = t.offsetWidth;
  this.hintHeight = t.offsetHeight;
  this.updatePos();
}

function Hint_hide(how) {
  if (!this.visible) return;
  this.visible = false;
  var hintCont = this.hintContainer;
  if (how == 'fast' || this.fastShow) {
    setVisible(hintCont, false);
    if (this.mouseHandlerAdded) {
      removeMouseMoveListener(Hint_updatePos, this);
      this.mouseHandlerAdded = false;
    }
    hintCont.hintObject = null;
  } else {
    if (this.mouseHandlerAdded) hintCont.afterFade = Hint_afterFadeOut;
    fade(hintCont, '-');
  }
}

function Hint_afterFadeOut() {
  this.afterFade = null;
  var obj = this.hintObject;
  this.hintObject = null;
  obj.mouseHandlerAdded = false;
  removeMouseMoveListener(Hint_updatePos, obj);
}

function Hint_updatePos() {
  var body = document.body;
  var d = (body.clientWidth + body.scrollLeft) - this.hintWidth;
  var x = Math.min(mouseAbsPosX, d);
  var y = mouseAbsPosY + 20;
//  alert(mouseAbsPosX +'--'+ x +'-'+ y);
  var h = this.hintHeight;
  var ch = body.clientHeight + body.scrollTop;
  if (y + h >= ch) y = Math.min(mouseAbsPosY, ch) - h;
  with (this.hintContainer.style) {
    left = x;
    top  = y;
  }
}

var
  hint = new Hint('text');

function hintHide() {
  hint.hide();
}

//-- Preload images --

var
  preloadedImgs = [];

function preloadImg(src, path) {
  if (path == null) path = '';
  if (isArray(src)) {
    var res = [];
    for (var i = 0, l = src.length; i < l; i++) {
      var img = new Image();
      img.src = path + src[i];
      preloadedImgs.push(img);
      res.push(img.src);
    }
    return res;
  }
  var img = new Image();
  img.src = path + src;
  preloadedImgs.push(img);
  return img.src;
}


//-- loadData / submitData --

function loadData(url, id, onCopyContent, resend, showIndicator) {
  sendRequest(id, onCopyContent, url, null, resend, showIndicator);
}

function submitData(form, id, event, onCopyContent, resend, showIndicator) {
  sendRequest(id, onCopyContent, form, event, resend, showIndicator);
}

var
  dataRequest = null,
  dataRequestResendDef = true;

function sendRequest(id, onCopyContent, urlForm, event, resend, showIndicator) {
  if (!dataRequest) {
    dataRequest = new RemoteFileLoader('dataRequest');
    dataRequest.onCopyContent = dataRequest_onCopyContent;
    dataRequest.onCopyContentEvents = {};
    dataRequest.requestDlgs = {};
    dataRequest.showIndicator = {};
    dataRequest.showRequestIndicator = true;
    dataRequest.onRequestIndicator = dataRequest_onRequestIndicator;
  }
  if (id in dataRequest.onCopyContentEvents) {
    if (resend != null ? resend : dataRequestResendDef) {
      dataRequest.cancel(id);
    } else {
      if (event) cancelEvent(event);
      return false;
    }
  }
  dataRequest.onCopyContentEvents[id] = onCopyContent;
  dataRequest.showIndicator[id] = showIndicator;
  if (event) {
   var dlg = dataRequest.requestDlgs[id] = (window.getWindowByElement ? getWindowByElement(urlForm) : null);
   if (dlg) dlg.dataRequestActive = true;
    dataRequest.submitInto(urlForm, id, event);
  } else {
    dataRequest.loadInto(urlForm, id);
  }
  return true;
}

function dataRequest_onCopyContent(doc, text, id) {
  if (!(id in dataRequest.onCopyContentEvents)) return false;
  var callback = dataRequest.onCopyContentEvents[id];
  delete dataRequest.onCopyContentEvents[id];
  if (id in dataRequest.requestDlgs) {
    var dlg = dataRequest.requestDlgs[id];
    delete dataRequest.requestDlgs[id];
    if (dlg) dlg.dataRequestActive = false;
  }
  return (callback ? callback(doc, text, id) : false);
}

function dataRequest_onRequestIndicator(uri, id, action) {
  return (dataRequest.showIndicator[id] != false);
}

function cancelDataRequest(id) {
  if (dataRequest && (id in dataRequest.onCopyContentEvents)) {
    delete dataRequest.onCopyContentEvents[id]
    dataRequest.cancel(id);
  }
}


//-- Favorites --

function addPageBookmark(title, url) {
  title = title || document.title; 
  url = url || location.href;
  if (window.sidebar) { // Firefox
    window.sidebar.addPanel(title, url, '');
  } else if (window.external) { // IE
    window.external.AddFavorite(url, title);
  } else if (window.opera) { // Opera
    var el = document.createElement('A');
    el.setAttribute('href', url);
    el.setAttribute('title', title);
    el.setAttribute('rel', 'sidebar');
    el.click();
  } else {
    alert('��� ������� �� ������������ �������������� ���������� � ���������. �������� ������ ������� ����� ����.')
    return false;
  }
  return true;
}

//-- Lipka, 18.02.08---------------------------------------------------------------

var ie = (/MSIE\s((5\.5)|[6789])/.test(navigator.userAgent)) && (navigator.platform == "Win32");
var ie5 = /MSIE 5\.0/.test(navigator.userAgent) && navigator.platform == "Win32";

function png(id, src_png, src_gif, sizingMethod){  
  var image = document.getElementById(id);
  if (isIE50) image.src = src_gif;
  else if (!isIE) image.src = src_png;
  else image.runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' +  src_png + '",sizingMethod="'+(sizingMethod || 'image')+'")';
  return 1;
}


function doUpdateColumns() {
  if (window.updateRightColumn && window.updateBottomColumn) {
    updateRightColumn();
    updateBottomColumn();
  } else setTimeout(doUpdateColumns, 250);
}

function doUpdateRightColumn() {
  if (window.updateRightColumn) updateRightColumn();
  else setTimeout(doUpdateRightColumn, 250);
}

//-- Comments block --

function formComment(id, toggle) {
  var r = $l('response'+id);
  if (!r.isFilled) {
    r.innerHTML = $l('form_comment').innerHTML;
    var subj = $l_('subj', r, 'INPUT');
    subj.id = 'subj'+id;
    subj.style.display = 'none';
    subj.value = '';
    var body = $l_('body', r, 'TEXTAREA');
    body.id = 'body'+id;
    var s = $l('msg'+id).innerHTML.replace(/<(.|\s)+?>/g, '').substr(0, 200);
    if (s.length == 200) s = s.replace(/\S+$/, '');
    body.value = '[cit]'+trim(s)+'[/cit]';
    var name = $l_('name', r, 'INPUT');
    name.id = 'name'+id;
    name.value = $l('name').value;
    initInputPlaceholder(name, '���� ���', '', 'empty');
    var submit = $l_('submit', r, 'INPUT');
    submit.id = 'submit'+id;
    var form = submit.form;
    form.commentId = id;
    r.isFilled = true;
  }
  initZoom($l('response'+id), toggle);
  return false
}

function chkSubmitCommentForm(form, event) {
  var id = form.commentId || '';
  var body = $l('body'+id);
  if (trim(body.value) == '') {
    alert('�� �� ����� ���������.');
    body.focus();
    cancelEvent(event);
    return;
  }
  var name = $l('name'+id);
  if (trim(name.value) == '' || name.className == 'empty') {
    alert('�� �� ����� ���.');
    name.focus();
    cancelEvent(event);
    return;
  }
  var subj = $l('subj'+id);
  if (trim(subj.value) == '' || subj.className == 'empty') subj.value = '';
  $l('submit'+id).disabled = true;
}

function toggle(suffix, current) {
  var itm = $l('toggle_'+suffix).getElementsByTagName('TD');
  var td = findParentNode(current, 'TD');
  var n = -1;
  for (var i = 0, l = itm.length; i < l; i++) { 
    itm[i].className = '';
    $l('box_'+suffix+i).style.display = 'none';
    $l('frm_'+suffix+i).style.display = 'none';
    if (itm[i] == td) n = i
  }
  td.className = 'current';
  $l('box_'+suffix+n).style.display = '';
  $l('frm_'+suffix+n).style.display = '';
  return false
}

//-- Glavred block --

function initGlavredForm() {
  var forms = document.body.getElementsByTagName('FORM');
  for (var i = forms.length-1; i >= 0; i--) {
    var form = forms[i];
    if (form.className != 'glavred_form' || form.glavredBylTut) continue;
    form.messageInput = findSubChild(form, 'TEXTAREA');
    var inps = form.getElementsByTagName('INPUT');
    for (var j = 0, l = inps.length; j < l; j++) {
      var inp = inps[j];
      if (inp.name == 'name') {
        initInputPlaceholder(inp, '���� ���', '', 'empty');
        form.nameInput = inp;
      } else if (inp.type == 'submit') {
        form.submitBtn = inp;
      }
    }
    setupEvent(form, 'submit', GlavredForm_onSubmit);
    form.glavredBylTut = true;
  }
}

function GlavredForm_onSubmit(event) {
  var form = (event.srcElement || event.target);
  var messageInput = form.messageInput;
  if (trim(messageInput.value) == '') {
    alert('�� �� ����� ���������.');
    messageInput.focus();
    cancelEvent(event);
    return;
  }
  var nameInput = form.nameInput;
  if (trim(nameInput.value) == '' || nameInput.className == 'empty') {
    alert('�� �� ����� ���.');
    nameInput.focus();
    cancelEvent(event);
    return;
  }
  form.submitBtn.disabled = true;
}

//-- More photos --

var 
  photoBlock,
  previewsBlock,
  containerBlock,
  moveIntervalId;

function showMorePhotos() {
  if (photoBlock) return;
  photoBlock = $l('photo_block');
  previewsBlock = $l('previews');
  containerBlock = photoBlock.parentNode;
  containerBlock.style.width = containerBlock.offsetWidth+'px';
  containerBlock.style.height = containerBlock.offsetHeight+'px';
  containerBlock.style.overflow = 'hidden';
  photoBlock.style.width = photoBlock.offsetWidth+'px';
  photoBlock.style.position = 'relative';
  photoBlock.curPos = 0;
  photoBlock.endPos = -(photoBlock.offsetWidth + getAbsPos(photoBlock).left);
  photoBlock.incVal = 2;
  moveIntervalId = setInterval(movingBlockIterator, 50);
  setTimeout(movingBlockIterator, 0);
}

function movingBlockIterator() {
  if (photoBlock.curPos != photoBlock.endPos) {
    photoBlock.incVal *= 2;
    photoBlock.curPos -= photoBlock.incVal;
    if (photoBlock.curPos < photoBlock.endPos) photoBlock.curPos = photoBlock.endPos;
    photoBlock.style.left = photoBlock.curPos+'px';
  } else if (previewsBlock.curPos == null) {
    previewsBlock.style.display = 'block';
    previewsBlock.style.width = previewsBlock.offsetWidth+'px';
    previewsBlock.style.position = 'relative';
    previewsBlock.style.left = (-previewsBlock.offsetWidth)+'px';
    previewsBlock.curPos = -previewsBlock.offsetWidth;
    previewsBlock.endPos = 0;
  } else if (previewsBlock.curPos != previewsBlock.endPos) {
    previewsBlock.curPos = Math.round(previewsBlock.curPos + previewsBlock.endPos)/2;
    if (Math.abs(previewsBlock.curPos - previewsBlock.endPos) <= 1) previewsBlock.curPos = previewsBlock.endPos;
    previewsBlock.style.left = previewsBlock.curPos+'px';
  } else if (containerBlock.curPos == null) {
    containerBlock.curPos = containerBlock.offsetHeight;
    containerBlock.endPos = previewsBlock.offsetHeight;
  } else if (containerBlock.curPos != containerBlock.endPos) {
    containerBlock.curPos = Math.round(containerBlock.curPos + containerBlock.endPos)/2;
    if (Math.abs(containerBlock.curPos - containerBlock.endPos) <= 1) containerBlock.curPos = containerBlock.endPos;
    containerBlock.style.height = containerBlock.curPos;
  } else {
    clearInterval(moveIntervalId);
    moveIntervalId = null;
    photoBlock.style.display = 'none';
    previewsBlock.style.width = '';
    previewsBlock.style.position = '';
    previewsBlock.style.left = '';
    containerBlock.style.width = '';
    containerBlock.style.height = '';
    containerBlock.style.overflow = '';
  }
}




/* highlight table row*/

var currentRow = null;

function mouseOverRow(event) {
  var el = (event.target || event.toElement);
  while (el) {
    if (el.tagName == 'TR') break;
    el = el.parentNode;
  }

  if (el != currentRow) {
    if (currentRow) currentRow.id = '';
    if (el) el.id = 'current';
    currentRow = el;
  }
}


//-- Input Placeholder --

function initInputPlaceholder(input, emptyText, filledClass, emptyClass, pwdBkg) {
  input.inputPlaceholderInfo = {emptyText: emptyText, filledClass: filledClass, emptyClass: emptyClass};  
  if(pwdBkg != null) input.inputPlaceholderInfo.pwdBkg = pwdBkg;
  setupEvent(input, 'focus', InputPlaceholder_onFocus);
  setupEvent(input, 'blur', InputPlaceholder_onBlur);
  var value = trim(input.value);
  if (value == '' || value == emptyText) {
    input.className = emptyClass;
    if(pwdBkg != null) input.style.backgroundImage = 'url(' + pwdBkg + ')';
    if (value == '') input.value = emptyText;
  } else {
    input.className = filledClass;
    if(pwdBkg != null) input.style.backgroundImage = 'none';
  }
}

function InputPlaceholder_onFocus(event) {
  var input = (event.srcElement || event.target);
  var info = input.inputPlaceholderInfo;
  if (input.className == info.emptyClass) {
    input.className = info.filledClass;
    input.value = '';
    if(info.pwdBkg != null) input.style.backgroundImage = 'none';
  }                                     
}

function InputPlaceholder_onBlur(event) {
  var input = (event.srcElement || event.target);
  var info = input.inputPlaceholderInfo;
  if (trim(input.value) == '') {
    input.className = info.emptyClass;
    input.value = info.emptyText;
    if(info.pwdBkg != null) input.style.backgroundImage = 'url(' + info.pwdBkg + ')';
  }
}


function getCookieValue(name) {
  name = name.toLowerCase();
  var cookies = document.cookie.split(';');
  for (var i = 0, l = cookies.length; i < l; i++) {
    if (cookies[i].match(/^\s?(.*?)\=(.*)/)) {
      var n = RegExp.$1.toLowerCase();
      if (n == name) return RegExp.$2;
    }
  }
  return null;
}

function setCookieValue(name, value) {
  var d = new Date();
  d.setFullYear(d.getFullYear()+10);
  var s = name+'='+value + '; path=/; domain=.' + location.hostname + '; expires='+d.toUTCString();
  document.cookie = s;
}


var curBodyPadding;

function bodyResized() {
  var body = document.body;
  var w = body.clientWidth;
  var p = (w < 1000 ? '2em' : (w < 1200 ? '3em' : '5em'));
  if (p != curBodyPadding) {
    body.style.paddingLeft = p;
    body.style.paddingRight = p;
    curBodyPadding = p;
  }
}

var mainMenu, mainMenuIfrm;

function initMainMenu() {
  mainMenu = $l('main_menu');   
  mainMenuIfrm = $l('main_menu_iframe');
  if (mainMenuIfrm) {
    mainMenu.style.visibility = 'hidden';
    mainMenu.style.display = '';
    mainMenuIfrm.zoomMaxSize = mainMenu.offsetHeight;
    mainMenuIfrm.style.width = mainMenu.offsetWidth + 'px';
    mainMenu.style.visibility = 'visible';
    mainMenu.style.display = 'none';
//  mainMenu.whileZoom = whileMenuZoom;
//  for (var i = 1; i < 5; i++) $l('sub'+i).whileZoom = whileMenuZoom;
  }
}

function zoomMainMenu() {
  if (mainMenuIfrm) {
    if (!mainMenu.afterZoom) {
      mainMenu.afterZoom = function() {
        var h = mainMenu.offsetHeight;
        if (h > 0) {
          mainMenuIfrm.style.height = mainMenu.offsetHeight + 'px';
          mainMenuIfrm.style.width = mainMenu.offsetWidth + 'px';
          mainMenuIfrm.style.display = '';
        } else {
          mainMenuIfrm.style.display = 'none';
        }
      }
    }
    zoom(mainMenuIfrm);
  }
  zoom(mainMenu);
}
  
//function whileMenuZoom() {
//  mainMenuIfrm.style.height = mainMenu.offsetHeight + 'px';
//}


function panelOver(el, txt_hint, w_hint) {
  /\/i\/ico\/panel\/light\/(.+)/.test(el.src);
  el.src = '/i/ico/panel/' + RegExp.$1;
  if (w_hint) hint.show(txt_hint, w_hint); else hint.show(txt_hint);
}

function panelOut(el) {
  /\/i\/ico\/panel\/(.+)/.test(el.src);
  el.src = '/i/ico/panel/light/' + RegExp.$1;
  hint.hide()
}


function showAlert(cookieName) {
  if (getCookieValue(cookieName) == '0') return true;
  var text = $l('alert').innerHTML;
  $l('alert').innerHTML = '';
  var wn = showWindow('w', '��������!', text, 340, 320, 'center');
  $l('alert_btn').focus();
  return true
}

function clickAlertBtn(cookieName, event) {
  alert($l('alert_ck').checked);
  if ($l('alert_ck').checked) { setCookieValue(cookieName, 0) }
  Window_closeBtnClick(event);
}


var ul_num = 0;
var ul_max_height;

function showUnitedLent() {
  var u = $l('ul' + ul_num);
  u.style.visibility = 'hidden';
  u.style.display = '';

  if (u.offsetTop + u.offsetHeight <= ul_max_height) {
    u.style.visibility = 'visible';
    ul_num++;
    setTimeout(showUnitedLent, 50);
  } else {
    u.style.display = 'none';
    $l('ul'+(ul_num-1)).className = 'last-in-lent';
  }
}
