// Функция определяющая размеры (длина, высота) клиентской части окна браузера.
function screenSize() {
      var w, h; // Объявляем переменные, w - длина, h - высота
      w = (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth));
      h = (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight));
      return {w:w, h:h};
}


function getOffsetSum(elem) {
    var top=0, left=0
    while(elem) {
        top = top + parseInt(elem.offsetTop)
        left = left + parseInt(elem.offsetLeft)
        elem = elem.offsetParent        
    }
    
    return {top: top, left: left}
}

function getOffsetRect(elem) {
    // (1)
    var box = elem.getBoundingClientRect()
    
    // (2)
    var body = document.body
    var docElem = document.documentElement
    
    // (3)
    var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
    var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft
    
    // (4)
    var clientTop = docElem.clientTop || body.clientTop || 0
    var clientLeft = docElem.clientLeft || body.clientLeft || 0
    
    // (5)
    var top  = box.top +  scrollTop - clientTop
    var left = box.left + scrollLeft - clientLeft
    
    return { top: Math.round(top), left: Math.round(left) }
}

function getOffset(elem) {
    if (elem.getBoundingClientRect) {
        // "правильный" вариант
        return getOffsetRect(elem)
    } else {
        // пусть работает хоть как-то
        return getOffsetSum(elem)
    }
}


//Функция для создания синхронизированных списков
function syncList()
 {
 }
  
 //Метод sync() - принимает список из значений атрибутов id элементов SELECT, образующих связанный список и запускает их синхронизацию
 syncList.prototype.sync = function()
 {
     //Перебираем аргументы (id элементов SELECT) и назначаем событиям onChange селектов, с соответствующими id, функцию-обработчик. 
     //В качестве обработчика выступает второй метод объекта syncList - _sync (напрямую его вызывать не нужно) 
     //Обработчик назначается всем элементам SELECT кроме последнего в списке аргументов, т.к. последний не влияет ни на какой другой элемент SELECT и с ним не нужно синхронизироваться.
     for (var i=0; i < arguments.length-1; i++)    document.getElementById(arguments[i]).onchange = (function (o,id1,id2){return function(){o._sync(id1,id2);};})(this, arguments[i], arguments[i+1]);
     document.getElementById(arguments[0]).onchange();//запускаем обработчик onchange первого селекта, чтобы при загрузке страницы заполнить дочерние селекты значениями.
 }
 
 function makeDefault(secondSelectId) {
/*  var secondSelect = document.getElementById(secondSelectId);
  var defSecond = document.getElementById(secondSelectId + '_def');
  alert(secondSelect.options[defSecond.value]);
  secondSelect.options[defSecond.value].selected = true;*/
 }
 
 //служебный метод _sync - срабатывает при смене выбранного элемента в текущем (старшем) элементе SELECT (по его событию onChange) и изменяет содержимое зависимого селекта на основании значения выбранного в старшем селекте.
 syncList.prototype._sync = function (firstSelectId, secondSelectId)
 {
     var firstSelect = document.getElementById(firstSelectId);
     var secondSelect = document.getElementById(secondSelectId);
     if ((firstSelectId == 'region_id') && (secondSelectId == 'city_id')) {
      var defFirst = document.getElementById(firstSelectId + '_def');
      var defSecond = document.getElementById(secondSelectId + '_def');
     }

     secondSelect.length = 0; //обнуляем второй (подчиненный) SELECT
     
     if (firstSelect.length>0)//если первый (старший) SELECT не пуст
     {
         //из свойства dataList, с данными для заполнения подчиненных селектов, берем ту часть данных, которая соответствует именно значению элемента, 
         //выбранного в первом селекте, и определяет содержимое подчиненного элемента SELECT.
         var optionValue = firstSelect.options[ firstSelect.selectedIndex==-1 ? 0 : firstSelect.selectedIndex].value; var optionData = this.dataList[optionValue]; if (!optionData) optionData = this.dataList[parseInt(optionValue)];
         //заполняем второй (подчиненный) селект значениями (создаем элементы option)
         for (var key in optionData || null) {
          secondSelect.options[secondSelect.length] = new Option(optionData[key], key);
          if ((firstSelect.value == defFirst.value) && (key == defSecond.value)) {
            secondSelect.options[secondSelect.length - 1].selected = true;
          }
        }
         
         //если в старшем SELECT-е нет выделенного пункта, выделяем первый
         if (firstSelect.selectedIndex == -1) setTimeout( function(){ firstSelect.options[0].selected = true;}, 1 );
         //если во втором списке нет выделенного пункта, выделяем первый его пункт
         if ((firstSelectId == 'region_id') && (secondSelectId == 'city_id')) {
/*          if (firstSelect.value == defFirst.value) {
            setTimeout('makeDefault(\'' + secondSelectId + '\')', 1 );
          }*/
          } else {
            if (secondSelect.length>0) setTimeout( function(){ secondSelect.options[0].selected = true;}, 1 );
          }
     }
     //если второй (подчиненный) селект имеет в свою очередь свои подчиненные селекты (те, для которых он главный), 
     //то запускаем его обработчик onchange, чтобы изменить его подчиненные селекты
     secondSelect.onchange && secondSelect.onchange();
 };
