function $l(el) {
  return (typeof(el) == 'string' ? document.getElementById(el) : el);
}

function $_(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 ? s.toString().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;
  }
}


// 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]]) - метод класса
//----------------------------------------------------------------
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])
//----------------------------------------------------------------
  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)
//----------------------------------------------------------------
  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);
    }
  },

  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          // интервал между итерациями (мс)
}


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 {
      this.t = (new Date().getTime() - this.startTime)/this.time;
    }
    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)
  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 {
        this.onEndIterate(reason);
      }
    }
  },

// event, вызывается при завершении итераций.
  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-а (мс)
  overflow: 'hidden,', // вначале zoom-а overflow: 'hidden', вконце overflow: ''
  dir: 'v'        // направление zoom-а (v - вертикальный, h - горизонтальный), обязательный
}

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, вызывается при завершении итераций.
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 = {
  defSteps: 4     // количество шагов 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 = [];

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
}


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');
  }
}

//-- 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;
}



//-- 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;
}

/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;


//-- Lipka, 18.02.08---------------------------------------------------------------

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;
}




//-- 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;
}


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) {
  if ($l('alert_ck').checked) { setCookieValue(cookieName, 0) }
  Window_closeBtnClick(event);
}



//-- bookmarks/favorites --

function addPageBookmark(title, url) {
  title = title || document.title; 
  url = url || location.href;
  try {
    if (window.sidebar) { // Firefox
      window.sidebar.addPanel(title, url, '');
      return true;
    } else if (window.external) { // IE
      window.external.AddFavorite(url, title);
      return true;
    } else if (window.opera) { // Opera
      var el = document.createElement('A');
      el.setAttribute('href', url);
      el.setAttribute('title', title);
      el.setAttribute('rel', 'sidebar');
      el.click();
      return true;
    }
  } catch(e) {}
  return false;
}


  

//============================================--- klerk ---===========================================

function setWidthPage() {
  var emBlock = window.emBlock;
  if (!emBlock) emBlock = window.emBlock = $l('em-block');
  var maxWidth = (emBlock ? emBlock.offsetWidth : 14)*87;
  $l('width').style.width = (document.body.clientWidth > maxWidth ? '87em' : (document.body.clientWidth < 990 ? '970px' : '100%'));
}

//--- toggle ---

function toggleToday(n) {
  var td = $l('toggle_today').getElementsByTagName('TD');
  for (var i = 0, l = td.length; i < l; i++) {
    var cell = td[i];
    var lbl = $l('toggle_today'+i);
    if (i != n) {
      cell.className = '';
      lbl.style.display = 'none'
    } else {
      cell.className = 'active';
      lbl.style.display = ''
    }
  }
  return false
}

function toggle(n) {
  var td = $l('toggle').getElementsByTagName('TD');
  for (var i = 0, l = td.length; i < l; i++) {
    var cell = td[i];
    var lbl = $l('zoom' + i);
    if (i != n) {
      cell.getElementsByTagName('DIV')[0].className = 'p05';
      cell.getElementsByTagName('IMG')[0].style.visibility = 'hidden';
      cell.getElementsByTagName('A')[0].className = 'mid dark';
      if (lbl) lbl.style.display = 'none';
    } else {
      cell.getElementsByTagName('DIV')[0].className = 'bg-purple p05';
      cell.getElementsByTagName('IMG')[0].style.visibility = 'visible';
      cell.getElementsByTagName('A')[0].className = 'mid no';
      if (lbl) lbl.style.display = 'block';
    }
  }
  return false
}

function toggleSeminar(n) {
  var a = $l('toggle_sem').getElementsByTagName('A');
  for (var i=0, l=a.length; i<l; i++) {
    var lnk = a[i];
    var lbl = $l('toggle_sem'+i);
    if (i != n) {
      lnk.className = '';
      lbl.style.display = 'none'
    } else {
      lnk.className = 'active';
      lbl.style.display = ''
    }
  }
}

function toggleSoft(n) {
	  
	var lbl0 = $l('toggle_soft0');
	var lbl1 = $l('toggle_soft1');
	var lbl2 = $l('toggle_soft2');
	
	if (n == 0)
	{						
		lbl0.className = 'active';				
		lbl1.className = '';				
		lbl1.className = '';
		
	}
	else if (n == 1)
	{		
		lbl0.className = '';			
		lbl1.className = 'active';			
		lbl1.className = '';
		
	}
	else
	{
	
		lbl0.className = '';			
		lbl1.className = '';			
		lbl1.className = 'active';
		
	}	
}


function toggleNews(n) {
  var a = $l('toggle_news').getElementsByTagName('A');
  for (var i=0, l=a.length; i<l; i++) {
    var lnk = a[i];
    var lbl = $l('toggle_news'+i);
    if (i != n) {
      lnk.className = '';
      lbl.style.display = 'none'
    } else {
      lnk.className = 'active';
      lbl.style.display = ''
    }
  }
}

//--- Menu ---

var
  activeSubmenu,
  isSubmenuMouseUpOnBodyActive = false;
 
function toggleSubmenu(id) {
  if (id) {
    var submenu = document.getElementById(id);
    var show = (submenu.offsetHeight == 0);
    submenu.style.display = (show ? 'block' : 'none');
  } else {
    submenu = null;
    show = false;
  }
  if (activeSubmenu && activeSubmenu != submenu) {
    activeSubmenu.style.display = 'none';
  }
  activeSubmenu = (show ? submenu : null);
  var body = document.body;
  if (show) {
    setupEvent(body, 'mousedown', Submenu_mouseDownOnBodyHandler)
  } else {
    removeEvent(body, 'mousedown', Submenu_mouseDownOnBodyHandler)
    if (isSubmenuMouseUpOnBodyActive) removeEvent(body, 'mouseup', Submenu_mouseUpOnBodyHandler);
  }
}
 
function Submenu_mouseDownOnBodyHandler(event) {
  var el = (event.target || event.srcElement);
  if (el) {
    if (el.id.indexOf('submenulink_') == 0) return true;
    while (el && (!el.id || el.id.indexOf('submenu_') != 0)) el = el.parentNode;
    if (el) {
      setupEvent(document.body, 'mouseup', Submenu_mouseUpOnBodyHandler);
      isSubmenuMouseUpOnBodyActive = true;
    } else {
      setTimeout(Submenu_close, 0);
    }
  }
  return true;
}
  
function Submenu_mouseUpOnBodyHandler(event) {
  setTimeout(Submenu_close, 0);
  return true;
}

function Submenu_close() {
  toggleSubmenu(null);
}

function CheckSearch() {
  if (document.getElementById('search')=='' || document.getElementById('search')=='найти на сайте') return false;
  return true;
}


