
var containerTag = 'DIV';
var operatingTag = 'INPUT';

var SUFFIX = '=';

var SHO = 'show';
var ENA = 'enab';
var READONLY = 'locked';
var FOCUS = 'autofocus';
var HIDE_EMPTY = 'hide_empty';

var canAutoFocus = false;

// используются для кеша
var containerTags = new Array();
var usableInputs  = new Array();

// дерево зависимостей.
// ну или "таблица поиска": задав инпут, получаем все зависящие от него дивы
var iTree = new Array();
iTree[SHO] = new Array();
iTree[ENA] = new Array();



// возвращает тэги-контейнеры всего документа
function getContainerTags()
{
    if (!containerTags || containerTags.length==0) {
        var tags = document.getElementsByTagName(containerTag);
        for (var i=0; i < tags.length; i++) {
            var tag = tags[i];
            if (tag.getAttribute(SHO) || tag.getAttribute(ENA)) {
                containerTags.push(tag);
            }
        }
    }
    return containerTags;
}
// ^^^ getContainerTags



// возвращает управляющие элементы внутри root (или document,если root не указан)
// если указан Attr, то возвращает только управляющие элементы с таким атрибутом 
function getUsableInputs(root, attr)
{
    root = $(root);
    if (!root) root = document;
    
    if (  (root != document) || !usableInputs || usableInputs.length==0) {
        var inputs = root.getElementsByTagName(operatingTag);
        var matching = new Array();
        for (var i=0; i < inputs.length; i++) {
            var input = inputs[i];
            if (  input.getAttribute(attr?attr:SHO)  ||  input.getAttribute(attr?attr:ENA)  ) {
                matching.push(input);
            }
        }
    }
    if (root == document) {
        if (matching) {
            usableInputs = matching ;
        } else {
            matching = usableInputs;
        }
    }
    return matching; 
}
// ^^^ getUsableInputs



// возвращает дерево зависимостей от управляющего тэга в котором attr=value
// параллельно, при обходе дерева элементов у них проставляются аттрибуты
// parentInput и parentDiv, указывающие на родительский инпут и див, соответственно
function findNested(attr, value, predInput) 
{
    var divs = getContainerTags();
    var result = new Array();
    
    for (var d=0; d<divs.length; d++) {
        // из всех дивов выбираем только те, что содержат атрибут attr, в котором есть занчение value
        if (!divs[d].getAttribute(attr) || !divs[d].getAttribute(attr).split(',').find(function(val){return val==value})) continue;
        var div = divs[d];
        
        if (predInput) {       
            if (!div.parentInput) {
                div.parentInput = new Array();
            }
            if (!div.parentInput[attr]) {
                div.parentInput[attr] = new Array();
            }
            div.parentInput[attr].push(predInput);
        }
        var inputs = getUsableInputs(div, attr);
        var nested = new Array();
        for (var i=0; i < inputs.length; i++) {
            var input = inputs[i];
            if (!input.parentDiv) {
                input.parentDiv = new Array();
            }
            if (!input.parentDiv[attr]) {
                input.parentDiv[attr] = new Array();
            }
            input.parentDiv[attr] = div;
            var nest = findNested(attr, input.getAttribute(attr));
            if (!(nest.length==0)) nested.push( nest );
        }
        div = [div];
        for (var n=0; n<nested.length; n++) {
            div.push( nested[n] );
        }
        result.push(div);
    }
    return result.length==1 ? result[0] : result;
}
// ^^^ findNested



// строит дерево зависимостей iTree
// проставляет зависимости внутри элементов
// вешает на события онклик и кейап функцию проверки элементов
function prepareForm()
{
    // обнуляем глобальные переменнные
    //
    iTree = new Array();
    iTree[SHO] = new Array();
    iTree[ENA] = new Array();
    containerTags = new Array();
    usableInputs  = new Array();


    var divs = getContainerTags();
    var inputs = getUsableInputs();

    for (var i=0; i<inputs.length; i++) {
        var input = inputs[i];
        var sho = input.getAttribute(SHO);
        var ena = input.getAttribute(ENA);

        if (sho || ena) { // сброс инпутов в файрфоксе
            if (input.checked && input.getAttribute('defChecked') != 'true') input.checked = false;
        }
            
        
        if (sho) {
            if (!iTree[SHO][sho])
                iTree[SHO][sho] = findNested(SHO, sho, input);
        }
        if (ena) {
            if (!iTree[ENA][ena])
                iTree[ENA][ena] = findNested(ENA, ena, input);
        }
    }
    
    for (var i=0; i<inputs.length; i++) {
        setChainState( SHO, iTree[SHO][inputs[i].getAttribute(SHO)], inputs[i].checked );
        setChainState( ENA, iTree[ENA][inputs[i].getAttribute(ENA)], inputs[i].checked );
    }
        
    addEvent(document,'click',showHideFields);
    addEvent(document,'keyup',showHideFields);
    if (typeof showAttention != "undefined") showAttention();
}
// ^^^ prepareForm



// 
function setChainState(attr, chain, bool)
{
    if (!chain) return;
    for (var i=0; i<chain.length; i++) {
        if (chain[i].length) {
            setChainState(attr, chain[i], bool);
        } else {
            elementState( chain[i], attr, bool );
        }
    }
}



function showHideFields(e)
{
    if (!e) var e = window.event;
    var tg = e.target || e.srcElement;

    if (
        !(tg.nodeName == 'INPUT' && tg.getAttribute(SHO))
        &&
        !(tg.nodeName == 'INPUT' && tg.getAttribute(ENA))
       ) return;

    
    canAutoFocus = true;
    var inputs = getUsableInputs();
    for (var i=0; i<inputs.length; i++) {
        setChainState( SHO, iTree[SHO][inputs[i].getAttribute(SHO)], inputs[i].checked );
        setChainState( ENA, iTree[ENA][inputs[i].getAttribute(ENA)], inputs[i].checked );
    }
    canAutoFocus = false;    

    // для оформления заказа
    if (typeof(iOnChange) != 'undefined') { 
        iOnChange('rOtherCity');
    
        // смотрим способ оплаты. если вариант один, то активируем его
        if (document.forms.paymentForm) {
            var elems = document.forms.paymentForm.elements;
            var count = 0, index = 0;
        
            for (var e=0; e<elems.length; e++) {
                if (elems[e].disabled) continue;
                count++;
                index = e;
            }
            if (count == 1) elems[index].checked = true;
        }
    
        // пересчитываем итоговую стоимость заказа
        //
        if (tg.name == 'delivType')
            recalcTotalPrice();
    }
}


function setOffOthers(attr, others, value)
{
    for (var i=0;i<others.length;i++)
    {
        var val = others[i].getAttribute(attr);
        if (val == value) continue;
        setChainState( attr, iTree[attr][val], false );
    }
}


function checkParents( attr, inputs )
{
    if (!inputs) return true;
    var result = false;
    for (var i=0; i<inputs.length; i++) {
        var input = inputs[i];
        result = result || ( input.checked && checkParents(attr, input.parentDiv && input.parentDiv[attr] && input.parentDiv[attr].parentInput[attr]) );
    }
    return result;
}
 

function elementState( elem, attr, checked )
{
    if (elem.parentInput) {
        checked = checkParents( attr, elem.parentInput[attr] );
    }
    var doFocus = false;
    if (attr == SHO) {
        if (checked && elem.style.display == 'none') doFocus = true; 
        elem.style.display = checked ? '':'none';
    }
    if (attr == ENA) {
        if (checked) {
            Element.removeClassName(elem, 'disable');
            if (elem.disabled) doFocus = true;
        } else {
            Element.addClassName(elem, 'disable');
        }
        elem.disabled = !checked;
    }
    
    // что-нибудь делаем со вложенными инпутами
    var inputs = elem.getElementsByTagName('input');
    for (var i=0; i<inputs.length; i++) {
        // дисаблим или энаблим инпут
        if (attr == ENA) { 
            if (!checked) {
                inputs[i].disabled = true;
                if (inputs[i].getAttribute(HIDE_EMPTY) == 'true') {
                    if (inputs[i].value == '') {
                        // если в одном диве будет много инпутов, то тут будет лажа;)
                        Element.hide(elem);
                    } else {
                        Element.show(elem);
                    }
                }
            } else {
                inputs[i].disabled = false;
                if (inputs[i].getAttribute(HIDE_EMPTY) == 'true') { // && inputs[i].value == '') {
                     Element.show(elem);
                }
            }
        }

        // обнуляем значения сбрасываемых инпутов
        if (!checked && inputs[i].getAttribute(READONLY)!='true') {
            switch (inputs[i].type.toLowerCase()) {
                case 'text':
                    inputs[i].value = '';
                break;
                case 'checkbox':  
                case 'radio':
                    inputs[i].checked = false;
                break;
            }
        }
        
        // переводим фокус на включаемый инпут
        if (canAutoFocus && doFocus && typeof(inputs[i].getAttribute(FOCUS))=='string' && inputs[i].getAttribute(FOCUS)=='true' && i==0) {
            if (inputs[i].focus) {
                inputs[i].focus();
                // заплатка для сраной оперы!!!!
                var fuckingopera = inputs[i];
                setTimeout( function() {fuckingopera.focus()}, 1 );
            }
        }
            
    }
    //alert();
}
// ^^^ elementState



// возвращает первый чекнутый элемент из списка
function getRadioChecked( elems )
{
    for (var i=0; i<elems.length; i++) {
        if (elems[i].checked) return elems[i];
    }
    return null;
}
// ^^^ getRadioChecked


/** ULTRA-SIMPLE EVENT ADDING **/

function addEvent(obj,type,fn)
{
    if (obj.addEventListener)
        obj.addEventListener(type,fn,false);
    else if (obj.attachEvent)
        obj.attachEvent("on"+type,fn);
}

//addEvent(window,"load",prepareForm);

(function(i) {
  var u = navigator.userAgent.toLowerCase();
  var ie = /*@cc_on!@*/false;
  if (/webkit/.test(u)) {
    // safari
    timeout = setTimeout(function(){
			if ( document.readyState == "loaded" || 
				document.readyState == "complete" ) {
				i();
			} else {
			  setTimeout(arguments.callee,10);
			}
		}, 10); 
  } else if ((/mozilla/.test(u) && !/(compatible)/.test(u)) ||
             (/opera/.test(u))) {
    // opera/moz
    document.addEventListener("DOMContentLoaded",i,false);
  } else if (ie) {
    // IE
    (function (){ 
      var tempNode = document.createElement('document:ready'); 
      try {
        tempNode.doScroll('left'); 
        i(); 
        tempNode = null; 
      } catch(e) { 
        setTimeout(arguments.callee, 0); 
      } 
    })();
  } else {
    window.onload = i;
  }
})(prepareForm);




/** PUSH AND SHIFT FOR IE5 **/

function Array_push() {
    var A_p = 0
    for (A_p = 0; A_p < arguments.length; A_p++) {
        this[this.length] = arguments[A_p]
    }
    return this.length
}

if (typeof Array.prototype.push == "undefined") {
    Array.prototype.push = Array_push
}

function Array_shift() {
    var A_s = 0
    var response = this[0]
    for (A_s = 0; A_s < this.length-1; A_s++) {
        this[A_s] = this[A_s + 1]
    }
    this.length--
    return response
}

if (typeof Array.prototype.shift == "undefined") {
    Array.prototype.shift = Array_shift
}

