/**
 * @file
 * Файл с утилитами.
 *
 * Функции начинающиеся со знака "_" являются внутренними и не предназначены для использования.
 */

// Переменные, определяющие версии браузера.
var isIE = /MSIE/.test(window.navigator.userAgent);
var isIE6 = /MSIE 6.0/.test(window.navigator.userAgent);
var isIE7 = /MSIE 7.0/.test(window.navigator.userAgent);
var isIE8 = /MSIE 8.0/.test(window.navigator.userAgent);
var isFF = /Firefox/.test(window.navigator.userAgent);
var isOpera = /Opera/.test(window.navigator.userAgent);
var isChrome = /Chrome/.test(window.navigator.userAgent);

//Глобальный массив для установки и сброса таймеров.
var timer = new Array;

// Внутренний счётчик количества вызовов функции.
var count = new Array; 

// Этот массив приведён для примера.
/*var func = {
  alert: function (any_array) {
    alert('This' + any_array);
  }
}*/
// Ассоциативный массив, предназначенный для вызова функций по их названию. 
// Например, приведённое описание массива func(см. до комментария),
// повзволит пользователю вызвать фукцию таким образом:
// func['alert']('Hello!');
// Для того, чтобы иметь возможность вызывать функции после завершения каких-либо эффектов
// (например opacityVisible()), необходимо объявить глобально этот массив у себя в скрипте.
// Например, если вы хотите, чтобы после завершения какого-либо эффекта вызывалась функция 
// с именем funcGo, нужно будет сделать такое объявление массива:
// var func = {
// funcGo: function(in_array) {
//    funcGo(in_array);  
//  }
// };
// Массив in_array принимает и передаёт параметры.
// Первый элемент массива всегда должен называться 'name'. В нём содержится имя вызываемой функции.
// Если у вас есть несколько функций необходимых для возврата,
// то перечислите их в массиве через запятую, например:
// var func = {
//   funcGo: function(in_array) {
//    funcGo(in_array);  
//  },
//   funcSome: function(in_array) {
//    funcSome(in_array);  
//  },
//   SimpleFunc: function(in_array) {
//    SimpleFunc(in_array);  
//  },
//  ...
// };
//   
// Для того, чтобы была вызвана ваша функция после завершения эффекта, вам необходимо
// передать в функцию (которую вы вызываете для создания эффекта) массив со следующией структурой:
// var funcAnyArray = {
//   name: 'funcGo',  // это поле содержит имя вашей функции
//   name_param1: value_of_parametr1, // эти поля могут называться как вам угодно
//   next_param2: value_of_parametr2, // это могут быть даже объекты
//   ...
// };
// Теперь можно вызвать функцию для создания эффекта, например так:
// opacityVisible(element, 10, 1, 100, 1, 'id-timer', funcAnyArray);
// Когда эффект закончится, функция передаст управление нашей функции funcGo,
// которая может выглядеть так:
// function funcGo(our_array) {
//   ...
// }
// Массив our_array получит переданный вами массив funcAnyArray (с названием 
// этой же функции и параметрами для неё).




/************************************************************************
 *                Функции для работы с DOM и XML                        *
 ************************************************************************/

/**
 * Возвращаем элемент по указанному id.
 * Используется вместо длинной записи через document...
 *
 * id
 * id элемента.
 * 
 * return
 * элемент.
 */
function gebi(id) {
  return document.getElementById(id);
}

/**
 * Возвращаем массив элементов с определённым именем.
 * Используется вместо длинной записи через document...
 *
 * in_name
 * Имя элемента.
 * 
 * return
 * Массив элементов.
 */
function gebtn(in_name) {
  return document.getElementsByTagName(in_name);
}

/**
 * Создаём элемент с именем name.
 * Используется вместо длинной записи через document...
 *
 * name
 * имя создаваемого элемента.
 * 
 * return
 * созданный элемент.
 */
function ce(name) {
  return document.createElement(name);
}

/**
 * Создаём текстовый узел.
 * Используется вместо длинной записи через document...
 *
 * text
 * текст узла.
 * 
 * return
 * созданный текстовый узел.
 */
function ctn(text) {
  return document.createTextNode(text);
}

/**
 * Удаляем узел.
 * Используется вместо длинной записи.
 *
 * node
 * узел.
 */
function rn(node) {
  node.parentNode.removeChild(node);
}

/**
 * Заменяет в узле старый потомок узел-1 на новый потомок узел-2.
 * Используется вместо длинной записи.
 * in_node
 * родительский узел, в котором необходимо произвести замену.
 * in_node1
 * заменяемый узел.
 * in_node2
 * заменяющий узел.
 */
function rc(in_node, in_node1, in_node2) {
  in_node.replaceChild(in_node2, in_node1);
}

/**
 * Преобразует XML-элемент в HTML.
 * Данная функция особенно актуальна при получении данных с сервера в формате XML (ajax),
 * которые необходимо вставить в объектную модель документа как есть.
 * 
 * 
 * in_XMLElement
 * XML-элемент.
 *
 * return
 * преобразованный HTML-элемент.
 */
function XMLtoDocument(in_XMLElement) {
  var el = in_XMLElement;  
  var node = _nextChild(el);
  return node;
}

/**
 * Вспомогательная рекурсивная функция, вызывается из XMLtoDocument().
 * Функция перебирает всех потомков элемента.
 * Внимание! Между элементов не должно быть пробелов!
 *
 * in_el
 * XML-элемент.
 *
 * return
 * преобразованный HTML-элемент.
 */
function _nextChild(in_el) {
  // Создаём элемент.
  if (in_el.nodeValue == null) {
    var nodeName = in_el.nodeName;
    var node = ce(nodeName);  
    // Копируем атрибуты.
    if (in_el.attributes != null) {
      var nodeAttrs = in_el.attributes;
      for (var i = 0; i < nodeAttrs.length; i++) {
        var attrName = nodeAttrs[i].nodeName;
        var attrValue = nodeAttrs[i].nodeValue;
        node.setAttribute(attrName, attrValue);
      }
    }
  } else {  // Создаём текстовый узел.
    var nodeValue = in_el.nodeValue;
    var node = ctn(nodeValue);
  }
      
  // Перебираем всех потомков.    
  if (in_el.hasChildNodes()) {
    while (in_el.firstChild) {
      var child = _nextChild(in_el.firstChild);
      // Добавляем узел к родителю.
      node.appendChild(child);
    }
    // Удаляем XML-элемент, не имеющий потомков.
    in_el.parentNode.removeChild(in_el);    
  } else {
    // Удаляем XML-элемент, не имеющий потомков.
    in_el.parentNode.removeChild(in_el);    
  }
  
  return node;  
}






/************************************************************************
 *                 Функции для работы с эфектами                        *
 ************************************************************************/

/**
 * Плавное изменение прозрачности элемента.
 * При завершении может вызывать функцию,
 * определённую пользователем, если это необходимо.
 * 
 * elem
 * элемент.
 * 
 * dOp
 * шаг изменения прозрачности (от 1 до 100).
 * 
 * beginOp
 * начальное значение прозрачности (1-100).
 * 
 * finishOp
 * конечное значение прозрачности.
 * 
 * interTime
 * временной интервал изменения прозрачности на величину dOp (в мс).
 * Этот параметр сильно зависит от используемого браузера.
 * 
 * in_t
 * уникальный таймер.
 * 
 * in_func
 * ассоциативный массив, содержащий в себе имя функции 
 * (которая будет вызвана после изменения прозрачности) и её параметры.
 * Первый элемент массива всегда должен называться 'name'.
 * Пример структуры массива:
 * var funcArray = {
 *   name: 'simpleFuncName',
 *   img: in_img,
 *   time: in_time
 * };
 * Данный параметр не обязателен, если вы не хотите вызывать какую-либо функцию
 * после изменения прозрачности.
 */
function opacityVisible(elem, dOp, beginOp, finishOp, interTime, in_t, in_func) {
  setOpacity(elem, beginOp);
  clearInterval(timer[elem.id]);
  timer[in_t] = setInterval(function() {_opacity(elem, dOp, finishOp, in_t, in_func);}, interTime);
}

/**
 * Установка прозрачности элемента.
 * 
 * in_el
 * элемент.
 * 
 * in_op
 * значение прозрачности (от 1 до 100).
 */
function setOpacity(in_el, in_op) {
  if (in_op > 100) {
    in_op = 100;
  }
  if (in_op < 1) {
    in_op = 1;
  }
  in_el.style.filter = 'alpha(opacity = ' + in_op + ')';
  in_el.style.opacity = in_op / 100;  
}

/**
 * Получение прозрачности элемента.
 * Данный метод работает только для элементов, 
 * у которых явно установленно значение прозрачности в стилях.
 * 
 * in_el
 * элемент.
 * 
 * return
 * значение прозрачности (от 1 до 100) или false в случае неудачи.
 */
function getOpacity(in_el) {
  if (in_el != null) {
    var op = null;
    if (in_el.style.opacity) {
      op = in_el.style.opacity * 100;
    } else if (in_el.filters.alpha.opacity) {
        op = in_el.filters.alpha.opacity;
      } else {
        return false;
      }
    return Math.round(op);
  }
}

/**
 * Перемещает элемент по заданным координатам с возможностью ондовременного изменения размеров.
 * Данный метод работает только для элементов, 
 * у которых явно установленно значение прозрачности в стилях.
 * При завершении может вызывать функцию,
 * определённую пользователем, если это необходимо.
 * 
 * in_el
 * элемент.
 * 
 * in_t
 * уникальный таймер.
 * 
 * in_time
 * время перемещения (в мс).
 * Этот параметр сильно зависит от используемого браузера.
 *
 * in_left
 * горизонтальная позиция элемента, в которую необходимо его переместить.
 * Позиция задаётся относительно родительского элемента.
 * 
 * in_top
 * вертикальная позиция элемента, в которую необходимо его переместить.
 * Позиция задаётся относительно родительского элемента.
 * 
 * in_width
 * ширина элемента в конце перемещения.
 * 
 * in_height
 * высота элемента в конце перемещения.
 *
 * in_func
 * ассоциативный массив, содержащий в себе имя функции 
 * (которая будет вызвана после перемещения) и её параметры.
 * Первый элемент массива всегда должен называться 'name'.
 * Пример структуры массива:
 * var funcArray = {
 *   name: 'simpleFuncName',
 *   img: in_img,
 *   time: in_time
 * };
 * Данный параметр не обязателен, если вы не хотите вызывать какую-либо функцию
 * после изменения прозрачности.
 *
 * return
 * ничего  или false.
 */
function moveResizeElement(in_el, in_t, in_time, in_left, in_top, in_width, in_height, in_func) {
  if (in_el == null) {
    return false;
  }
  var interTime = 1;
  var k = (in_time);
  timer[in_t] = setInterval(function() {_moveResize(in_el, in_t, k, in_left, in_top, in_width, in_height, in_func);}, interTime);
}

/**
 * Создаёт передний слой на всю страницу с определённым цветом.
 * color (string) цвет в формате #RRGGBB или цветовые константы red, blue, green и т.д.
 */
function foreground(color) {
  var divEl = ce('div');
  divEl.setAttribute('id', '');
  divEl.style.position = 'absolute';
  divEl.style.top = '0px';
  divEl.style.left = '0px';
  var body = documentSize();
  divEl.style.width = body[0] + 'px';
  divEl.style.height = body[1] + 'px';
  divEl.style.backgroundColor = color;
  gebtn('body')[0].appendChild(divEl);
  return divEl;
}

/**
 * Определяет позицию left элемента относительно <body>.
 * 
 * in_el
 * элемент.
 * 
 * return
 * значение left (только число, без постфикса 'px') или false.
 */
function getLeft(in_el) {
  if (in_el == null) {
    return false;
  }
  var left = in_el.offsetLeft;
  var leftParent = in_el;
  while (leftParent = leftParent.offsetParent) {
    left = left + leftParent.offsetLeft;
  }
  return left - gebtn('body')[0].offsetLeft;
}

/**
 * Определяет позицию top элемента относительно <body>.
 * 
 * in_el элемент.
 * return значение top (только число, без постфикса 'px')  или false.
 */
function getTop(in_el) {
  if (in_el == null) {
    return false;
  }
  var topParent = in_el;
  var top = in_el.offsetTop - 1;
  while (topParent = topParent.offsetParent) {
    top = top + topParent.offsetTop;
  }
  return top - gebtn('body')[0].offsetTop;
}

/**
 * Возвращает левую и верхнюю позицию элемента относительно тела документа.
 * 
 * @param element object - элемент.
 * @return array - координаты элемента.
 */
function offsetPosition(element) {
  var offsetLeft = 0, offsetTop = 0;
  do {
      offsetLeft += element.offsetLeft;
      offsetTop  += element.offsetTop;
  } while (element = element.offsetParent);
  return [offsetLeft, offsetTop];
}

/**
 * Возвращает размеры документа.
 */
function documentSize() {
  //var dxScroll = (window.scrollX != null) ? window.scrollX : document.documentElement.scrollLeft; // для Chrome, IE
  var scroll = offsetScroll();
  var w = gebtn('body')[0].offsetWidth + scroll.left;
  var h = gebtn('body')[0].offsetHeight;
  return [w, h];
}

/**
 * Возвращает левую и верхнюю позицию скролла в окне.
 */
function offsetScroll() {
  var dxScroll = (window.scrollX != null) ? window.scrollX : document.documentElement.scrollLeft; // для Chrome, IE
  var dyScroll = (window.scrollY != null) ? window.scrollY : document.documentElement.scrollTop; // для Chrome, IE
  var scroll = {
    left: dxScroll,
    top: dyScroll
  }
  return scroll;
}

/**
 * Возвращает размеры элемента или рабочей области.
 * el (object) элемент, если не указан, то вся рабочая область.
 */
function elementSize(el) {
  if (el) {
    var size = [el.offsetWidth, el.offsetHeight];
  } else {
    var h = window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight);
    var w = window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth);
    var size = [w, h];
  }
  return size;
}

/**
 * Центрует элемент в окне браузера.
 * el (object) элемент.
 */
function centeringElementWindow(el) {
  var win = elementSize();
  var el_size = elementSize(el);
  var scroll = offsetScroll();
  setLeft(el, (win[0] - el_size[0]) / 2 + scroll.left);
  setTop(el, (win[1] - el_size[1]) / 2 + scroll.top);
}

/**
 * Возвращает внешние размеры браузера.
 */
function winSize() {
  var w = window.outerWidth ? window.outerWidth : (document.documentElement.offsetWidth);
  var h = window.outerHeight ? window.outerHeight : (document.documentElement.offsetHeight);
  return [w, h];
}

/**
 * Устанавливает размеры браузера (IE, FF).
 */
function setWinSize(w, h) {
  window.resizeTo(w, h);
}

/**
 * Устанавливает высоту элемента в пикселах.
 */
function setH(el, h) {
  el.style.height = h + 'px';
}

/**
 * Устанавливает ширину элемента в пикселах.
 */
function setW(el, w) {
  el.style.width = w + 'px';
}

/**
 * Устанавливает левую позицию элемента в пикселах.
 */
function setLeft(el, l) {
  el.style.left = l + 'px';
}

/**
 * Устанавливает верхнюю позицию элемента в пикселах.
 */
function setTop(el, t) {
  el.style.top = t + 'px';
}

/**
 * Определяет позицию top элемента, необходимую для его вырвнивания по вертикали относительно родительского элемента.
 * Внимание! Данная функция работает коректно, если для элемента и его родителя явно заданы свойства CSS:
 * position(relative/absolute), height(%/px/...).
 * Также необходимо элементу body задавать параметр CSS - position: absolute.
 *
 * in_el
 * элемент.
 * 
 * in_relative
 * true или false, в зависимости от того как позиционирован элемент (absolute/relative).
 * Если элемент позиционирован абсолютно, то необходимо передать этому параметру false.
 * Если элемент позиционирован относительно и вы хотите, чтобы он выравнивался по вертикали относительно родителя,
 * но с учётом верхних элементов (если такие есть), которые тоже позиционированы относительно родителя,
 * то передайте true.
 *
 * return
 * вертикальная позиция элемента (только число, без постфикса 'px') или false.
 */
function getCenterVertical(in_el, in_relative) {
  if (in_el == null) {
    return false;
  }
  var parentHeight = in_el.parentNode.offsetHeight;
  var elHeight = in_el.offsetHeight;
  var elTop = 0;
  if (in_relative == true) {
    elTop = in_el.offsetTop;
  }
  
  // Высота родительского элемента не должна быть меньше высоты дочернего, определяем истинную высоту
  // родительского элемента. DOCTYPE XHTML 1.1 определяет высоту родительского элемента не коректно.
  if (parentHeight + elTop < elHeight) {
    var parentEls = in_el.parentNode.childNodes;
    var height = 0;
    if (in_relative == true) {
      for (var i = 0; i < parentEls.length; i++) {
        if ((parentEls[i].nodeValue == null)) {
          height = height + parentEls[i].offsetHeight;
        }
      }
      parentHeight = height;
    } else {
      parentHeight = elHeight;
    }
  } 
  
  elTop = (parentHeight - elHeight - elTop) / 2;
  return elTop; 
}

/**
 * Определяет позицию left элемента, необходимую для его вырвнивания по горизонтали
 * относительно родительского элемента.
 * Внимание! Данная функция работает коректно, если для элемента и его родителя явно заданы свойства CSS:
 * position(relative/absolute), width(%/px/...).
 * Также необходимо элементу body задавать параметр CSS - position: absolute.
 *
 * in_el
 * элемент.
 * 
 * return
 * горизонтальная позиция элемента (только число, без постфикса 'px') или false.
 */
function getCenterHorizontal(in_el) {
  if (in_el == null) {
    return false;
  }
  var parentWidth = in_el.parentNode.offsetWidth;
  var elWidth = in_el.offsetWidth;
  var elLeft = in_el.offsetLeft;
  elLeft = (parentWidth - elWidth) / 2;
  return elLeft; 
}

/**
 * Устанавливает элемент по центру вертикально.
 * Внимание! Данная функция работает коректно, если для элемента и его родителя явно заданы свойства CSS:
 * position(relative/absolute), width(%/px/...).
 * Также необходимо элементу body задавать параметр CSS - position: absolute.
 *
 * in_el
 * элемент.
 * 
 * in_relative
 * true или false, в зависимости от того как позиционирован элемент (absolute/relative).
 * Если элемент позиционирован абсолютно, то необходимо передать этому параметру false.
 * Если элемент позиционирован относительно и вы хотите, чтобы он выравнивался по вертикали относительно родителя,
 * но с учётом верхних элементов (если такие есть), которые тоже позиционированы относительно родителя,
 * то передайте true.
 */
function setCenterVertical(in_el, in_relative) {
  var topEl = getCenterVertical(in_el, in_relative);
  in_el.style.top = topEl + 'px';
}

/**
 * Устанавливает элемент по центру вертикально.
 * Внимание! Данная функция работает коректно, если для элемента и его родителя явно заданы свойства CSS:
 * position(relative/absolute), width(%/px/...).
 * Также необходимо элементу body задавать параметр CSS - position: absolute.
 *
 * in_el
 * элемент.
 */
function setCenterHorizontal(in_el) {
  var leftEl = getCenterHorizontal(in_el);
  in_el.style.left = leftEl + 'px';
}

/**
 * Разворачивает слой по вертикали.
 * id - айди слоя, который необходимо развернуть.
 */
function rollYOn(id) {
  var el = gebi(id);
  el.style.height = 'auto';
}

/**
 * Сворачивает слой по вертикали.
 * id - айди слоя, который необходимо свернуть.
 * dy - шаг изменения высоты в пикселях.
 * return - таймер.
 */
function rollYOff(id, dy) {
  var el = gebi(id);
  var height = el.offsetHeight;
  timer[el.id + "_roll"] = setInterval(function() {_roll(el, dy, height);}, 1);
  return timer[el.id + "_roll"];
}

/**
 * Скрывает все select на странице.
 * ignore_arr - массив элементов, которые игнорируются при скрытии.
 */
var hidden_selects = new Array();
function hiddenSelects(ignore_arr) {
  var selects = gebtn('select');
  for (var i = 0; i < selects.length; i++) {
    if (selects[i].style.visibility != 'hidden' && !in_array(selects[i], ignore_arr)) {
      hidden_selects.push(selects[i]);
      selects[i].style.visibility = 'hidden';
    }
  }
} 

/**
 * Показывает все скрытые select на странице.
 */
function visibleSelects() {
  for (var i = 0; i < hidden_selects.length; i++) {
    hidden_selects[i].style.visibility = 'visible';
  }
} 

/**
 * Скрывает все object на странице.
 */
function hiddenObjects() {
  var objs = gebtn('object');
  for (var i = 0; i < objs.length; i++) {
    objs[i].style.visibility = 'hidden';
  }
}

/**
 * Показывает все скрытые object на странице.
 */
function visibleObjects() {
  var objs = gebtn('object');
  for (var i = 0; i < objs.length; i++) {
    objs[i].style.visibility = 'visible';
  }
}

/**
 * Вспомогательная функция для сворачивания и разворачивания слоёв.
 * Не используйте её!
 */
function _roll(el, dy, height) {
  var y = el.offsetHeight;
  if (((y >= 0) && (dy > 0) && (y + dy <= height)) || ((y >= 0) && (dy < 0) && (y + dy >=0))) {
    y = y + dy;
    el.style.height = y + 'px';
  } else {
    if (dy > 0) {
      el.style.height = height + 'px';//'100%';
      clearInterval(timer[el.id + "_roll"]);  
    } else {
      if (dy < 0) {
        el.style.height = 0 + 'px';
        clearInterval(timer[el.id + "_roll"]);  
      } else {
        clearInterval(timer[el.id + "_roll"]);  
      }
    }
  }
}

/**
 * Вызывается из opacityVisible() и является вспомогательной.
 * Функция изменяет прозрачность элемента и по завершении вызывает функцию,
 * определённую пользоателем, если это необходимо.
 * Не используйте её!
 *
 * elem
 * элемент.
 * 
 * dOp
 * шаг изменения прозрачности (от 1 до 100).
 * 
 * finishOp
 * конечное значение прозрачности.
 * 
 * in_t
 * уникальный таймер.
 * 
 * in_func
 * ассоциативный массив, содержащий в себе имя функции 
 * (которая будет вызвана после изменения прозрачности) и её параметры.
 * Первый элемент массива всегда должен называться 'name'.
 * Пример структуры массива:
 * var funcArray = {
 *   name: 'simpleFuncName',
 *   img: in_img,
 *   time: in_time
 * };
 * Данный параметр не обязателен, если вы не хотите вызывать какую-либо функцию
 * после изменения прозрачности.
 * 
 * return
 * false в случае невозможности изменения прозрачности элемента, либо ничего не возвращает.
 */
function _opacity(elem, dOp, finishOp, in_t, in_func) {
  var curOp = getOpacity(elem);
  if (curOp == false) {    
    clearInterval(timer[in_t]);
    timer[in_t] = null;
    return false;
  }
  curOp = Math.round(curOp + dOp);
  if (((curOp >= finishOp) && (dOp > 0)) || ((curOp <= finishOp) && (dOp < 0))) {
    curOp = finishOp;
    clearInterval(timer[in_t]);
    timer[in_t] = null;
    if (in_func != null) {
      _gotoFunc(in_func);
    }
  } else if (curOp <= 1) {
    curOp = 1;
    clearInterval(timer[in_t]);
    timer[in_t] = null;
    if (in_func != null) {
      _gotoFunc(in_func);
    }
  }
  setOpacity(elem, curOp);
}

/**
 * Вызывается из moveResizeElement() и является вспомогательной.
 * Функция изменяет прозрачность элемента и по завершении вызывает функцию,
 * определённую пользоателем, если это необходимо.
 * Не используйте её!
 *
 * in_el
 * элемент.
 * 
 * in_t
 * уникальный таймер.
 * 
 * in_time
 * время перемещения (в мс).
 * Этот параметр сильно зависит от используемого браузера.
 *
 * in_left
 * горизонтальная позиция элемента, в которую необходимо его переместить.
 * Позиция задаётся относительно родительского элемента.
 * 
 * in_top
 * вертикальная позиция элемента, в которую необходимо его переместить.
 * Позиция задаётся относительно родительского элемента.
 * 
 * in_width
 * ширина элемента в конце перемещения.
 * 
 * in_height
 * высота элемента в конце перемещения.
 * 
 * in_func
 * ассоциативный массив, содержащий в себе имя функции 
 * (которая будет вызвана после изменения прозрачности) и её параметры.
 * Первый элемент массива всегда должен называться 'name'.
 * Пример структуры массива:
 * var funcArray = {
 *   name: 'simpleFuncName',
 *   img: in_img,
 *   time: in_time
 * };
 * Данный параметр не обязателен, если вы не хотите вызывать какую-либо функцию
 * после изменения прозрачности.
 */
count['_moveResize'] = 0; // внутренний счётчик количества вызовов функции
function _moveResize(in_el, in_t, in_k, in_left, in_top, in_width, in_height, in_func) {
  // Если счётчик обращений к функции равен переданному временному интервалу, то завершаем работу функции.
  if (count['_moveResize'] == in_k) {
    count['_moveResize'] = 0;
    in_el.style.left = in_left + 'px'; 
    in_el.style.top = in_top + 'px'; 
    in_el.style.width = in_width + 'px'; 
    in_el.style.height = in_height + 'px';
    clearInterval(timer[in_t]);
    // Передача управления следующей функции.
    if (in_func != null) {
      _gotoFunc(in_func);
    }
  } 
  // Коэфициент деления.
  var k = in_k - count['_moveResize'];
  // Вычисление интервалов для изменения позиции и размера элемента.
  var dL = (in_left - getLeft(in_el)) / k;
  var dT = (in_top - getTop(in_el)) / k;
  var dW = (in_width - in_el.offsetWidth) / k;
  var dH = (in_height - in_el.offsetHeight) / k;
  // Изменение позиции и размера элемента.
  in_el.style.left = getLeft(in_el) + dL + 'px'; 
  in_el.style.top = getTop(in_el) + dT + 'px'; 
  in_el.style.width = in_el.offsetWidth + dW + 'px'; 
  in_el.style.height = in_el.offsetHeight + dH + 'px';
  // Увиличием счётчик обращений к функции.
  count['_moveResize']++;
}

/**
 * Вызывает функцию пользователя и передаёт ей параметры. Является вспомогательной.
 * Не используйте её! 
 * 
 * in_func
 * ассоциативный массив, содержащий в себе имя функции 
 * (которая будет вызвана после изменения прозрачности) и её параметры.
 * Первый элемент массива всегда должен называться 'name'.
 * Пример структуры массива:
 * {
 *   name: 'simpleFuncName',
 *   img: in_img,
 *   time: in_time
 * };
 */
function _gotoFunc(in_func) {
  func[in_func['name']](in_func);
}











/************************************************************************
 *                              События                                 *
 ************************************************************************/

/**
 * Возвращает массив данных произошедшего собятия.
 * e - объект события.
 * return (array) - событие, элемент.
 */
/*function event(e) {
  return event = (e ? e : (window.event ? window.event : null));
  //var elem = event.target ? event.target : (event.srcElement ? event.srcElement : null);
  //return [event, elem];
}*/

/**
 * Возвращает координаты мыши относительно документа.
 * evt - объект события.
 * return (array) - координаты x,y.
 */
function getCoords(evt) {
  var coords = {x: 0, y: 0};
  if (evt.pageX) {
    coords.x = evt.pageX;
    coords.y = evt.pageY;
  } else if (evt.clientX) {
    coords.x = evt.clientX + document.body.scrollLeft - document.body.clientLeft;
    coords.y = evt.clientY + document.body.scrollTop - document.body.clientTop;
    if (document.body.parentElement && document.body.parentElement.clientLeft) {
      var bodPar = document.body.parentElement;
      coords.x += bodPar.scrollLeft + bodPar.clientLeft;
      coords.y += bodPar.scrollTop + bodPar.clientTop;
    }
  }
  return coords;
}

/**
 * Возвращает координаты мыши относительно экрана.
 * evt - объект события.
 * return (array) - координаты x,y.
 */
function getCoordsScreen(evt) {
  var coords = {x: evt.screenX, y: evt.screenY};
  return coords;
}







/************************************************************************
 *               Формирование сложных элементов на экране               *
 ************************************************************************/

/**
 * Создаёт окошко с текстом.
 *
 * @param in_mes (string):
 * выводимое сообщение.
 *
 * @param in_class (string):
 * класс CSS для окна.
 *
 * @return (object):
 * элемент div, представляющий собой окошко с текстом.
 */
function getMessageBox(in_mes, in_class) {
  var newDiv = ce('div');
  newDiv.className = in_class;
  var textDiv = ce('div');
  var newText = ctn(in_mes);
  textDiv.appendChild(newText);
  newDiv.appendChild(textDiv);
  return newDiv;
}

/**
 * Создаёт слой на всю страницу, который затеняет её.
 *
 * @param in_beg_op (int):
 * начальная прозрачность от 1 до 100.
 *
 * @param in_fin_op (int):
 * конечная прозрачность от 1 до 100.
 *
 * @param in_class (string):
 * класс CSS , в котором определены цвет фона, координаты и прозрачность. Например:
 * .shadowpage {
 *  position: absolute;
 *  left: 0px;
 *  top: 0px;
 *  background: #000000;
 *  opacity: 0.01;
 *  filter: alpha(Opacity = 1);
 * }
 *
 * @param in_func (string):
 * название функции, которой необходимо передать управление после показа слоя.
 */
function showShadowPage(in_beg_op, in_fin_op, in_class, in_func) {
  var newDiv = ce('div');
  gebtn('body')[0].appendChild(newDiv);
  newDiv.className = in_class;
  newDiv.style.width = gebtn('body')[0].offsetWidth + 'px';
  newDiv.style.height = gebtn('body')[0].offsetHeight + 'px';
  var dOp = 10;
  var beginOp = in_beg_op;
  var finishOp = (in_fin_op >= in_beg_op) ? in_fin_op : in_beg_op;
  var interTime = 2;
  var timer = 'shadow';
  var funcArr = {
    name: in_func,
    div: newDiv
  };
  opacityVisible(newDiv, dOp, beginOp, finishOp, interTime, timer, funcArr);
}

/**
 * Создаёт слой с прогрессбаром и возвращает его.
 * 
 * @param in_class_back (string):
 * класс CSS , в котором определены параметры фона прогрессбара и его размеры.
 * 
 * @param in_class_bar (string):
 * класс CSS , в котором определены параметры самого прогрессбара и его размеры (ширина динамическая).
 *
 * @return (object):
 * элемент div, представляющий собой прогрессбар.
 */
var prBarDiv = null; // Слой, который отображает шкалу прогрессбара.
var prPcentDiv = null; // Слой, который отображает цифры прогрессбара.
function createProgressBar(in_class_back, in_class_bar) {
  var newDiv = ce('div');
  newDiv.className = in_class_back;
  prBarDiv = ce('div');
  prBarDiv.className = in_class_bar;
  prPcentDiv = ce('div');
  newDiv.appendChild(prBarDiv);
  var prBarText = ctn('0%');
  prPcentDiv.appendChild(prBarText);
  newDiv.appendChild(prPcentDiv);
  return newDiv;
}

/**
 * Задаёт в процентах текущее значение прогрессбара.
 *
 * @param in_percent (int):
 * значение прогрессбара от 0 до 100.
 */
function setProgressBar(in_percent) {
  prBarDiv.style.width = in_percent + '%';
  prPcentDiv.innerHTML = in_percent + '%';
}








/************************************************************************
 *                 Функции для работы с элементами HTML                 *
 ************************************************************************/

/**
 * Устанавливает или снимает галочку в чекбоксе.
 * 
 * @param in_id (string):
 * айди чекбокса.
 *
 * @return (bool):
 * true в случае успеха и false, если чекбокс не существует.
 */
function checkBox(in_id) {
  if (gebi(in_id)) {
    gebi(in_id).checked = (gebi(in_id).checked == true) ? false : true;
    // Для чекбокса, в котором галочка отображается не стандартными средствами,
    // а с помощью картинки с айди 'img_' + айди чекбокса. 
    if (gebi('img_' + in_id)) {
      gebi('img_' + in_id).style.visibility = (gebi(in_id).checked == true) ? 'visible' : 'hidden';
    }
    
    // Передаём управление пользовательской функции, которая будет обслуживать клик по чекбоксу.
    // Эта функция должна быть определена в вашем скрипте.
    // С помощью неё вы сможете произвести дополнитльную обработку при клике по чекбоксу.
    // Если в ней нет необходимости, то просто создайте пустую функцию.
    // function onclickCheckbox(in_id) {}.
    onclickCheckbox(in_id);
    return true;
  } else {
    return false;
  }
}




/************************************************************************
 *                     Функции для работы с массивами                   *
 ************************************************************************/

/**
 * Ищет значение в массиве и возвращает true, если находи, иначе false.
 * search - элемент поиска.
 * stakc_arr - массив в котором происходит поиск.
 */
function in_array(search, stack_arr) {
  for (val in stack_arr) {
    if (stack_arr[val] == search) {
      return true;
    }
  }
  return false;
}
