function fe(){}

/**
 * возвращает значение элемнта ввода
 * 
 * @param {String/HTMLInputElement} tcValue - ссылка на элемент ввода или его ID
 * @return {String} - значение элемента ввода
 */
function prepare_check(tcValue)
{
	if (tcValue.constructor == String)
	{
		var loElem = id(tcValue);
		return  (loElem) ? loElem.value : tcValue;
	}
	else
	{
		return (tcValue.value) ? tcValue.value : tcValue;
	}

	return tcValue;
}

/**
 * проверяет валидности адреса e-mail
 *
 * @param {String/HTMLInputElement} tcEmail - значение которое проверяем, ID элемента ввода,
 * значение которого будем проверять, или ссылка на этот элемент
 * @return {Boolean} - TRUE если с e-mail'ом все Ok, иначе FALSE
 */
function check_email_valid(tcEmail)
{
	tcEmail = prepare_check(tcEmail);

	return tcEmail.match(/^[0-9a-z_\-\.]+@[0-9a-z_\-\.]+\.[a-z]{2,4}$/i);
}

/**
 * проверка валидности адреса сайта
 * 
 * @param {String/HTMLInputElement} tcWWW - значение которое проверяем, ID элемента ввода,
 * значение которого будем проверять, или ссылка на этот элемент
 * @return {Boolean} - TRUE если адрес валиден, иначе false
 */
function check_url_valid(tcWWW)
{
	tcWWW = prepare_check(tcWWW);
	return tcWWW.match(/^[0-9a-z\_\.\-\/\:]+\.[a-z\/]{2,5}$/i);
}

function check_login_form(toForm)
{
    if (toForm.txtLogin.value == "") { alert('Не указан login!'); toForm.txtLogin.focus(); return false; }
    if (toForm.txtPass.value  == "") { alert('Не указан пароль!'); toForm.txtPass.focus(); return false; }

    if (!check_login_valid(toForm.txtLogin.value)) { alert("Login должен состоять из цифр и/или латинских букв, и быть длиной от четырех до десяти символов!"); toForm.txtLogin.focus(); return false; };
	if (!check_login_valid(toForm.txtPass.value)) { alert("Пароль должен состоять из цифр и/или латинских букв, и быть длиной от четырех до десяти символов!"); toForm.txtPass.focus(); return false; };

    return true;
}

/**
 * проверяет валидность логина/пароля 
 * только латиницы. и цифры, от 4х до 10 символов
 * 
 * @param {String/HTMLInputElement} tcLogin - значение которое проверяем, ID элемента ввода,
 * значение которого будем проверять, или ссылка на этот элемент
 * @return {Boolean} - TRUE если логин валиден, иначе false
 */
function check_login_valid(tcLogin)
{
	tcLogin = prepare_check(tcLogin);

	return tcLogin.match(/[a-z0-9_]{4,10}/i);
}

/**
 * проверяет чтобы бы в значении были только цифры
 * 
 * @param {String/HTMLInputElement} tcLogin - значение которое проверяем, ID элемента ввода,
 * значение которого будем проверять, или ссылка на этот элемент
 * @return {Boolean} - TRUE если значение валидно, иначе false
 */
function check_only_digits(tcValue)
{
	tcValue = prepare_check(tcValue);
	return tcValue.match(/[0-9]{1,20}/i);
}

/**
 * проверяет правильность аськового UIN'а'
 *  
 * @param {String/HTMLInputElement} tcLogin - значение которое проверяем, ID элемента ввода,
 * значение которого будем проверять, или ссылка на этот элемент
 * @return {Boolean} - TRUE - с UIN'ом все Ok
 */
function check_icq_valid(tcValue)
{
	tcValue = prepare_check(tcValue);
	return tcValue.match(/[0-9\-]{5,14}/i);
}

function check_phone_Valid(tcPhone)
{
	return tcPhone.match(/^[\s0-9\-\(\)]{7,20}$/i);
}

function check_nick_valid(tcNick)
{
    return tcNick.match(/[A-Za-z0-9\-\_]{2,20}/i);
}

function check_filename_valid(tcFName)
{
	var lcFName = get_filename_base(tcFName);

	return lcFName.match(/^[\A-Z0-9\_]{1,100}$/i);
}

/**
 * проверяет элемент формы на равенство ошибочному значению
 * 
 * @param {HTMLInputElement/String} toElem - ссылка на элемент формы или его ID
 * @param {String/Number} tcErrValue - ошибочное значение
 * @param {String} tcMessage - выводимое сообщение
 * @return {Boolean} - TRUE если в элементе ввода нет ошибочного значения
 */
function chk_fe(toElem, tcErrValue, tcMessage)
{
	if (toElem.constructor == String) toElem =  id(toElem);
	if (! tcMessage) tcMessage = 'Ошибочное значение';
	if (toElem.value == tcErrValue) { alert(tcMessage); toElem.focus(); return false; }
	return true;
}

/**
 * возвращает имя файла с расширением
 *
 * @param {String/HTMLInputElement} tcFName - имя файла,
 * или ссылка на элемент ввода типа FILE, или ID элемента ввода типа FILE
 * @return {String} - имя файла с расширением
 */
function get_file_name(tcFName)
{
	var lcFName = prepare_check(tcFName);
    var laFName = lcFName.split('\\');
	return laFName[laFName.length-1];
}

/**
 * возвращает расширение файла
 * 
 * @param {String/HTMLInputElement} tcFName - имя файла,
 * или ссылка на элемент ввода типа FILE, или ID элемента ввода типа FILE
 * @return {String} - расширение файла
 */
function get_file_ext(tcFName)
{
	var lcFName = get_file_name(tcFName);

    var laFName = lcFName.split('.');
	return laFName[laFName.length-1];
}

/**
 * возвращает имя файла без расширения
 * 
 * @param {String/HTMLInputElement} tcFName - имя файла,
 * или ссылка на элемент ввода типа FILE, или ID элемента ввода типа FILE
 * @return {} - имя файла без расширения
 */
function get_filename_base(tcFName)
{
	var lcFName = get_file_name(tcFName);

    var laFName = lcFName.split('.');
	var lcExt = laFName[laFName.length-1];
	return laFName[laFName.length-2];
}

/**
 * выводит popup-окно для просмотра картинки
 * 
 * @param {} toLink
 * @param {} tnW
 * @param {} tnH
 * @return {Boolean}
 */
function show_pic(toLink, tnW, tnH)
{
    window.open(toLink.href, "_blank", "width="+tnW+",height="+tnH+",resizable=no,location=no,titlebar=no,menubar=no,toolbar=no,status=no");
    return false;
}

/**
 * проверяет текстовое поле
 *  
 * @param {HTMLElement/String} toObj - ссылка на элемент формы или его ID
 * @param {String} tcFName - название поля 
 * @param {Number} tnMaxLen - максимальная длина
 * @param {Number} tnMinLen - минимальная длина
 * @return {Boolean} - TRUE - значит все Ok, иначе FALSE
 */
function check_text_field(toObj, tcFName, tnMaxLen, tnMinLen)
{
	if (toObj.constructor == String) toObj = id(toObj);
    var lcText = toObj.value;
    if (lcText == "") { alert('Не указано '+tcFName+'!'); toObj.focus(); return false;}
    if (lcText.length > tnMaxLen) { alert('Слишком длинное "'+tcFName+'!"\nДопустимо до '+tnMaxLen+' символов включительно'); toObj.focus(); return false;}
	if (tnMinLen  &&  lcText.length < tnMinLen) { alert('Слишком короткое "'+tcFName+'"'); toObj.focus(); return false;}
    return true;
}

/**
 * проверяет текстовое поле
 * синоним для check_text_field
 * @see check_text_field
 * 
 * @param {HTMLElement/String} toObj - ссылка на элемент формы или его ID
 * @param {String} tcFName - название поля 
 * @param {Number} tnMaxLen - максимальная длина
 * @param {Number} tnMinLen - минимальная длина
 * @return {Boolean} - TRUE - значит все Ok, иначе FALSE
 */
function CheckTextField(toObj, tcFName, tnMaxLen, tnMinLen) { return check_text_field(toObj, tcFName, tnMaxLen, tnMinLen); }

/**
 * переспрашивает заданный вопрос
 * 
 * @param {String} tcMess
 * @return {Boolean} - TRUE - ответ юзера был утвердительным
 */
function my_confirm(tcMess)
{
	if (confirm(tcMess))
	{
		if (confirm('Уверены?','')) return true;
		else return false;
	}
	else return false;
}

/**
 * лечит ИЭ от нелюбви к прозрачности в PNG
 * @param {} toObj
 */
function fixPNG_pic(toObj)
{
	fixPNG(toObj, 'crop');
}

/**
 * лечит ИЭ от нелюбви к прозрачности в PNG
 * @param {} toObj
 * @param {} tcMode
 */
function fixPNG(toObj, tcMode)
{
	tcMode = (tcMode == '' || tcMode == 'undefined') ? 'repeat' : tcMode;
	//Если браузер IE версии 5.5-6
	if (/MSIE (5\.5|6).+Win/.test(navigator.userAgent))
	{
		var tcSrc;

		if (toObj.tagName=='IMG') //Если текущий элемент картинка (тэг IMG)
		{
			if (/\.png$/.test(toObj.src)) //Если файл картинки имеет расширение PNG
			{
			tcSrc = toObj.src;
			toObj.src = "/blank.gif"; //заменяем изображение прозрачным gif-ом
		}
	}
    else //иначе, если это не картинка а другой элемент
    {
		//если у элемента задана фоновая картинка, то присваеваем значение свойства background-шmage переменной src
		tcSrc = toObj.currentStyle.backgroundImage.match(/url\("(.+\.png)"\)/i);
		if (tcSrc)
		{
			tcSrc = tcSrc[1]; //берем из значения свойства background-шmage только адрес картинки
			toObj.runtimeStyle.backgroundImage="none"; //убираем фоновое изображение
		}
	}
	//если, src не пуст, то нужно загрузить изображение с помощью фильтра AlphaImageLoader
	if (tcSrc) toObj.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + tcSrc + "',sizingMethod='"+tcMode+"')";
  }
}

function check_search_form(toForm, tnMaxLen, tnMaxWords, tnMinWord)
{
	var lcText = toForm.txtSearch.value

	if (lcText=="" || lcText=="я ищу ...")
	{
		alert('Не указано слово (слова) для поиска!');
		toForm.txtSearch.focus();
		return false;
	}

	if (lcText.length > tnMaxLen)
	{
		alert('Слишком длинный текст для поиска!\nРазрешено не более '+tnMaxLen+' символов.');
		toForm.txtSearch.focus();
		return false;
	}

	var laVal = lcText.split(' ');		//	режем на части
    if (laVal.length > tnMaxWords) { alert('За один раз можно искать не более '+tnMaxWords+' слов!'); toForm.txtSearch.focus(); return false; }

    for (var i=0; i < laVal.length; i++)
    {
    	var lcVal = laVal[i];
    	if (lcVal.length <= tnMinWord)
    	{
    		alert('Слова для поиска не могут быть короче '+tnMinWord+' символов (букв или цифр)!');
    		toForm.txtSearch.focus();
    		return false;
    	}
    }
	return true;
}

function clear_search_field(toObj, tcHelp)
{
	if (toObj.value == tcHelp) toObj.value = '';
}

function clear_ssscribe_field(toObj, tcHelp)
{
	if (toObj.value == 'ваш e-mail') toObj.value = '';
}

function CheckQuestionForm(toForm)
{
    if (toForm.txtQuestName.value == "")  { alert('Укажите пожалуйста как Вас зовут'); toForm.txtQuestName.focus(); return false;}
    if (toForm.txtQuestEmail.value== "")  { alert('Укажите свой e-mail, чтобы мы могли связаться с Вами'); toForm.txtQuestEmail.focus(); return false;}
    if (!Check_Email_Valid(toForm.txtQuestEmail.value))  { alert('Ошибочный e-mail!'); toForm.txtQuestEmail.focus(); return false;}
    if (!CheckTextField(toForm.edtQuestText, 'текст вопроса', 2000)) return false;
    return true;
}

/**
 * удаляет строку в tBody таблицы по ID строки (TR)
 * 
 * @param {HTMLTableRowElement/String} toRow - ссылка на строку или ее ID
 * @param {HTMLTableElement/String} toTable - ссылка на таблицу или ссылка на нее
 */
function del_row_by_id(toRow, toTable)
{
    var loTable = (toTable.constructor == String) ? id(toTable) : toTable;
    var loRow = (toRow.constructor == String) ? id(toRow) : toRow;
    if (!loTable  ||  !loRow  ||  loRow.tagName!='TR'  ||  loTable.tagName!='TABLE') { return false; }

    for (var i=loTable.tBodies[0].rows.length - 1; i>=0 ; i--)
    {
        var loCur = loTable.tBodies[0].rows[i];
        if(loCur == loRow)
        {
            loTable.tBodies[0].deleteRow(i);
            return true;
        }
    }

    return true;
}

/**
 * аналог РНР-шной in_array
 *
 * @param tuValue mixed - значение которое ищем
 * @param  taArray array - массив в котором ищем
 * @return boolean - TRUE если нашли
 */
function in_array(tuValue, taArray)
{
    for (var i=0; i < taArray.length; i++) if (taArray[i]==tuValue) return true;
    return false;
}

/**
 * ищеи значение tcValue в одномерном массиве taArray
 *  
 * @param {String/Number} tcValue - значение которое ищем
 * @param {Array} taArray - массив в котором ищем
 * @return {Number} - индекс найденного элемента или -1 если не нашли
 */
function get_index(tcValue, taArray)
{
    for (var i=0; i < taArray.length; i++) if (taArray[i]==tcValue) return i;
    return -1;
}

/**
 * правильно делает Escape для кириллицы
 *
 * @param {String} str - строка которую нужно отыскейпить
 * @return {String} - обработанная строка
 */
function escape1251(str)
{
	if (str.constructor != String  ||  str=='') return '';

    // Инициализируем таблицу перевода
    var trans = new Array();
    for (var i = 0x410; i <= 0x44F; i++)  trans[i] = i - 0x350; // А-Яа-я
    trans[0x401] = 0xA8;    // Ё
    trans[0x451] = 0xB8;    // ё

    var ret = [];
    // Составляем массив кодов символов, попутно переводим кириллицу
    for (var i = 0; i < str.length; i++)
    {
        var n = str.charCodeAt(i);
        if (typeof trans[n] != 'undefined') n = trans[n];
        if (n <= 0xFF) ret.push(n);
    }
    return escape(String.fromCharCode.apply(null, ret));
}

function win2unicode(str)
{
   var charmap   = unescape(
      "%u0402%u0403%u201A%u0453%u201E%u2026%u2020%u2021%u20AC%u2030%u0409%u2039%u040A%u040C%u040B%u040F"+
      "%u0452%u2018%u2019%u201C%u201D%u2022%u2013%u2014%u0000%u2122%u0459%u203A%u045A%u045C%u045B%u045F"+
      "%u00A0%u040E%u045E%u0408%u00A4%u0490%u00A6%u00A7%u0401%u00A9%u0404%u00AB%u00AC%u00AD%u00AE%u0407"+
      "%u00B0%u00B1%u0406%u0456%u0491%u00B5%u00B6%u00B7%u0451%u2116%u0454%u00BB%u0458%u0405%u0455%u0457");

   var code2char = function(code)
   {
               if(code >= 0xC0 && code <= 0xFF) return String.fromCharCode(code - 0xC0 + 0x0410);
               if(code >= 0x80 && code <= 0xBF) return charmap.charAt(code - 0x80);
               return String.fromCharCode(code);
   }

   var res = "";
   for (var i = 0; i < str.length; i++) res = res + code2char(str.charCodeAt(i));
   return res;
}

/**
 * xmlToArray() - преобразует все дочерние узлы документа XML в массив
 *
 * @param resultsXml -
 * @return {Array} - массив
 */
function xmlToArray(resultsXml)
{
    var resultsArray = new Array();  // инициализация массив resultsArray
    // обойти в цикле все узлы и извлечь их содержимое
    for(var i=0; i < resultsXml.length; i++) resultsArray[i] = resultsXml.item(i).firstChild.data;
    return resultsArray;    // вернуть содержимое узлов в виде массива
}

/**
 * устанавливает куки
 *
 * @param {String} tcName - имя куки
 * @param {String/Number} tcValue - значение куки
 * @param {Number} tnExpires - время жизни в секундах
 * @return void
 */
function setCookie(tcName, tcValue, tnExpires)
{
    var ldToday = new Date();
    ldToday.setTime(ldToday.getTime());
    if (tnExpires) tnExpires = tnExpires * 1000;

    var ldExpires = new Date(ldToday.getTime() + (tnExpires));
    document.cookie = tcName + '=' + tcValue +
        ( (tnExpires) ? ';expires=' + ldExpires.toGMTString() : '' );
}

/**
 * читает куку с указанным именем
 *
 * @param {String} tcName - имя нужной куки
 * @return {String} - значение нужной куки
 */
function getCookie(tcName)
{
	var lcArg = tcName + "=";
	var lnStartPos = document.cookie.indexOf(lcArg, 0);
	if (lnStartPos == -1) return "";
	else lnStartPos += lcArg.length;

	var lnEndPos = document.cookie.indexOf(';', lnStartPos);
	if (lnEndPos == -1) lnEndPos = document.cookie.length;

	return document.cookie.substring(lnStartPos, lnEndPos);
}

/**
 * удаляет куку с указанным именем
 * 
 * @param {String} tcName - имя удаляемой куки
 * @return void
 */
function delCookie(tcName)
{
	if (get_cookie(tcName)) document.cookie = tcName + '=; expires=Thu, 01-Jan-70 00:00:01 GMT';
}

/**
 * возвращает TRUE, если значение можно считать целочисленным 
 * 
 * @param {String/Number} tcValue
 * @return {Boolean} - TRUE, если значение можно считать целочисленным, иначе FALSE
 */
function is_int(tcValue)
{
	var lcValue = new String(tcValue);
	return lcValue.match(/^[0-9]{1,20}$/);
}

/**
 * возвращает TRUE, если значение tcValue можно считать датой
 * 
 * @param {String} tcValue - проверяемое значение
 * @return {Boolean} - TRUE, если значение tcValue можно считать датой
 */
function is_date(tcValue)
{
	var lcValue = new String(tcValue);
	return (is_dmy(tcValue)  ||  is_ymd(tcValue)) ? true : false;
}

/**
 * возвращает TRUE, если значение tcValue можно считать датой в формате DD-MM-YYYY
 *
 * @param {String} tcValue - проверяемое значение
 * @return {Boolean} - TRUE, если значение tcValue можно считать датой в формате DD-MM-YYYY
 */
function is_dmy(tcValue)
{
	var lcValue = new String(tcValue);
	if (lcValue.match(/^[0-9]{2}\.[0-9]{2}\.[0-9]{4}$/)) return true;
	if (lcValue.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)) return true;
	if (lcValue.match(/^[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/)) return true;

	return false;
}

/**
 * возвращает TRUE, если значение tcValue можно считать датой в формате YYYY-MM-DD
 * @param {String} tcValue - проверяемое значение в формате YYYY-MM-DD
 * @return {Boolean} - TRUE, если значение tcValue можно считать датой в формате YYYY-MM-DD
 */
function is_ymd(tcValue)
{
	var lcValue = new String(tcValue);
	if (lcValue.match(/^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$/)) return true;
	if (lcValue.match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/)) return true;
	if (lcValue.match(/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/)) return true;

	return false;
}

/**
 * для элемента toElem устанавливает CSS-свойство tcParam в значение tcValue
 * 
 * @param {HTMLElement/String} toElem - ссылка на элемент или его ID
 * @param {String} tcParam - CSS-свойство
 * @param {String/Number} tcValue - устаналиваемое значение
 * @return {String/Number} - текущее значение свойства tcParam
 */
function style(toElem, tcParam, tcValue)
{
	var loObj = (toElem.constructor == String) ? id(toElem) : toElem;
	if (loObj)
	{
		if (tcValue) loObj.style[tcParam] = tcValue;
		return loObj.style[tcParam];
	}
	else return false;
}

/**
 * возвращаетссылку на объект в ID равным tcID
 *
 * @param {String} tcID - ID нужного объекта
 * @return {HTMLElement/HTMLInputElement/HTMLTableElement/HTMLTableSectionElement} - ссылку на искомый объект или FALSE
 */
function id(tcID)
{
	var loObj = document.getElementById(tcID);
	return (loObj) ? loObj : false;
}

/**
 * показывает объект на экране
 *
 * @param {HTMLElement/String} toObj - ссылка на элемент или ID элемента  
 * @return void
 */
function show(toObj)
{
	if (toObj.constructor == String) toObj = id(toObj);

	if (toObj.$oldDisplay) toObj.style.display = toObj.$oldDisplay;
	else toObj.style.display = (toObj.tagName=='TABLE'  && document.all) ? 'table' : 'block';
}

/**
 * скрывает элемент, присваивания его style.display значение none
 * перед этим запоминает значение style.display в атрибут $oldDisplay
 * чтоб им могла воспользоваться функция show
 * @link show
 *
 * @param {HTMLElement/String} toObj - ссылка на элемент или ID элемента
 * @return void
 */
function hide(toObj)
{
	if (toObj.constructor == String) toObj = id(toObj);
	if (toObj)
	{
		toObj.$oldDisplay = toObj.style.display;
		toObj.style.display = 'none';
	}
}

/**
 * ищет элементы с CSS-классом tcClassName и если указано среди тэгов tcTagName
 * возвращает массив найденных элементов
 *
 * @param {String} tcClassName - имя CSS-класса который ищем
 * @param {String} tcTagName - имя тэга (среди каких будем искать)
 * @return {HTMLElement[]} - массив найденных элементов
 */
function hasClass(tcClassName, tcTagName)
{
  	var laRet = [];
    //	обнаружение имени класса (работает и в случае нескольких имен классов)
    var loRE = new RegExp("(^|\\s)" + tcClassName + "(\\s|$)");

	//	ограничение поиска элементами определенного типа или поиск по всем элементам
	var laElements = document.getElementsByTagName(tcTagName || "*");
	for (var j=0; j < laElements.length; j++)
	{
		//	если элемент относится к нужному классу, добавление его в возвращаемый массив
		if (laElements[j].className == tcClassName  ||  loRE.test(laElements[j]))
			laRet.push(laElements[j]);
	}

	return laRet;	//	возвращение списка соответствующих элементов
}

/**
 * ищет элементы с CSS-классом tcClassName и если указано среди тэгов tcTagName
 * возвращает массив найденных элементов
 * алиас для hasClass
 * @see hasClass
 *
 * @param {String} tcClassName - имя CSS-класса который ищем
 * @param {String} tcTagName - имя тэга (среди каких будем искать)
 * @return {Element[]} - массив найденных элементов
 */
function byClass(tcClassName, tcTagName)
{
    return hasClass(tcClassName, tcTagName);
}

/**
 * возвращает массив объектов у которых тэг tcTagName
 * если указан toRoot - то ищем только в этом элементе, иначе весь документ
 *
 * @param {String} tcTagName - имя тэга
 * @param {HTMLElement/String} toRoot - ссылка на объект или ID объекта в котором ищем
 * @return {Element[]} - массив найденных элементов
 */
function tag(tcTagName, toRoot)
{
	if (toRoot.constructor == String) toRoot = id(toRoot);
    return (toRoot || document).getElementsByTagName(tcTagName);
}

/**
 * attr() - получение и установка значений атрибута элемента
 *
 * @param mixed toObj - ссылка на объект или ID объекта
 * @param string tcAttrName - имя атрибуа
 * @param mixed tuValue -
 * @return mixed - значение указанного атрибута элемента
 */
function attr(toObj, tcAttrName, value)
{
    // гарантирование допустимости предоставленного имени
    if (!tcAttrName || tcAttrName.constructor != String) return '';

    // определение не относится ли это имя к тем самым "роковым" именам
    tcAttrName = { 'for': 'htmlFor', 'class': 'className' }[tcAttrName] || tcAttrName;

    // если пользователь устанавливает значение, то
    if (tuValue  &&  tuValue != null)
	{
        // сначала установить быстрый способ
        toObj[tcAttrName] = tuValue;

        // по возможности использовать setAttribute
        if (toObj.setAttribute) toObj.setAttribute(tcAttrName, tuValue);
    }

    // вернуть значение атрибута
    return toObj[tcAttrName] || toObj.getAttribute(tcAttrName) || '';
}

/**
 * возвращает координаты объекты относительно верхнего левого угла страницы
 *
 * @author взята из KLayers
 * @param {HTMLElement} o - ссылка на объект для которого нужно вернуть координаты
 * @return {Number[]} - массив с координатами, [0] = left, [1] - top
 */
function KL_getPageOffset(toObj)
{
	var KL_left =0, KL_top = 0;
	do
	{
		KL_left += toObj.offsetLeft;
		KL_top += toObj.offsetTop;

		toObj = toObj.offsetParent;
	}
	while (toObj);
	return [KL_left, KL_top];
}

var ru2en =
{
	ru_str : "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя",
	en_str : ['A','B','V','G','D','E','JO','ZH','Z','I','J','K','L','M','N','O','P','R','S','T',
    'U','F','H','C','CH','SH','SHH',String.fromCharCode(35),'I',String.fromCharCode(39),'JE','JU',
    'JA','a','b','v','g','d','e','jo','zh','z','i','j','k','l','m','n','o','p','r','s','t','u','f',
    'h','c','ch','sh','shh',String.fromCharCode(35),'i',String.fromCharCode(39),'je','ju','ja'],

	translit : function(org_str)
	{
		var tmp_str = "";
	    for (var i = 0, l = org_str.length; i < l; i++)
		{
			var s = org_str.charAt(i), n = this.ru_str.indexOf(s);
		    if(n >= 0) tmp_str += this.en_str[n];
			else tmp_str += s;
		}
		return tmp_str;
	}
}

/**
 * устанавливает значение tcValue для комбобокса toCBO
 * 
 * @param {HTMLElement/String} toCBO - ссылка на комбобокс или его ID
 * @param {Number/String} tcValue - устанавливаемое значение
 * @return {Number} - индекс установленного значения, или -1 если такого значения нет в списке комбобокса
 */
function cbo_set_value(toCBO, tcValue)
{
	if(toCBO.constructor == String) toCBO = id(toCBO);

	for (var i=0; i < toCBO.options.length; i++)
	{
		var loCur = toCBO.options[i];
		if (loCur.value == tcValue)
		{
			toCBO.selectedIndex = i;
			toCBO.value = tcValue;
			return i;
		}
	}
	return -1;
}

/**
 * вычисляет величину горизонтального скроллинга
 * (насколько юзер прокрутил страницу)
 * 
 * @return {Number} - величина скроллинга
 */
function getScrollX()
{
    // A shortcut, in case we're using Internet Explorer 6 in Strict Mode
    var de = document.documentElement;

    // If the pageXOffset of the browser is available, use that
    return self.pageXOffset ||

        // Otherwise, try to get the scroll left off of the root node
        ( de && de.scrollLeft ) ||

        // Finally, try to get the scroll left off of the body element
        document.body.scrollLeft;
}

/**
 * вычисляет величину вертикального скроллинга
 * (насколько юзер прокрутил страницу)
 * 
 * @return {Number} - величина скроллинга
 */
function getScrollY()
{
    // A shortcut, in case we're using Internet Explorer 6 in Strict Mode
    var de = document.documentElement;

    // If the pageYOffset of the browser is available, use that
    return self.pageYOffset ||

        // Otherwise, try to get the scroll top off of the root node
        ( de && de.scrollTop ) ||

        // Finally, try to get the scroll top off of the body element
        document.body.scrollTop;
}


/**
 * вычисляет ширину окна браузера (viewport)
 * 
 * @return {Number} - ширина окна в пикселах
 */
function windowWidth()
{
    // A shortcut, in case weХre using Internet Explorer 6 in Strict Mode
    var de = document.documentElement;

    // If the innerWidth of the browser is available, use that
    return self.innerWidth ||

        // Otherwise, try to get the width off of the root node
        (de && de.clientWidth) ||

        // Finally, try to get the width off of the body element
        document.body.clientWidth;
}

/**
 * вычисляет высоту окна браузера (viewport)
 * 
 * @return {Number} - высота окна в пикселах
 */
function windowHeight()
{
    // A shortcut, in case weХre using Internet Explorer 6 in Strict Mode
    var de = document.documentElement;

    // If the innerHeight of the browser is available, use that
    return self.innerHeight ||

        // Otherwise, try to get the height off of the root node
        ( de && de.clientHeight ) ||

        // Finally, try to get the height off of the body element
        document.body.clientHeight;
}

/**
 * вычисляет актуальную ширину элемента (используя CSS)
 * 
 * @param {HTMLElement/String} elem - ссылка на элемент или его ID
 * @return {Number} - ширина объекта в пикселах
 */
function getWidth(elem)
{
    // Gets the computed CSS value and parses out a usable number
    return parseInt(getStyle(elem, "width"));
}

/**
 * вычисляет актуальную высоту элемента (используя CSS)
 * 
 * @param {HTMLElement/String} toElem - ссылка на элемент или его ID
 * @return {Number} - высота объекта в пикселах
 */
function getHeight(toElem)
{
    // Gets the computed CSS value and parses out a usable number
    return parseInt(getStyle(toElem, "height"));
}

/**
 * устанавливаем элемент по горизонтали
 *
 * @param {HTMLElement/String} toElem - ссылка на элемент или ID нужного элемента
 * @param {Number} tnPos - отступ сверху
 * @return void
 */
function setX(toElem, tnPos)
{
    if (toElem.constructor == String) toElem = id(toElem);
    toElem.style.left = tnPos + "px";
}

/**
 * устанавливаем элемент по вертикали
 *
 * @param {HTMLElement/String} toElem - ссылка на элемент или ID нужного элемента
 * @param {Number} tnPos - отступ сверху
 * @return void
 */
function setY(toElem, tnPos)
{
    if (toElem.constructor == String) toElem = id(toElem);
    toElem.style.top = tnPos + "px";
}

/**
 * устанавливаем элемент по горизонтали и вертикали
 * 
 * @param {HTMLElement/String} toElem - ссылка на элемент или ID нужного элемента
 * @param {Number} tnX - отступ слева
 * @param {Number} tnY - отступ сверху
 * @return void
 */
function setXY(toElem, tnX, tnY)
{
	if (toElem.constructor == String) toElem = id(toElem);
	toElem.style.left = tnX + "px";
	toElem.style.top  = tnY + "px";
}

/**
 * возвращает высоту Web-страницы
 * @return {Number} - высота страницы в пикселах
 */
function pageHeight()
{
	return (self.innerHeight > document.body.scrollHeight) ? self.innerHeight : document.body.scrollHeight;
//	return document.body.scrollHeight;
}

/**
 * возвращает ширину Web-страницы
 * @return {Number} - ширина страницы в пикселах
 */
function pageWidth()
{
	return (self.innerWidth > document.body.scrollWidth) ? self.innerWidth : document.body.scrollWidth;
//	return document.body.scrollWidth;
}

function getClientWidth()
{
  return document.compatMode=='CSS1Compat' && !window.opera?document.documentElement.clientWidth:document.body.clientWidth;
}

function getClientHeight()
{
  return document.compatMode=='CSS1Compat' && !window.opera?document.documentElement.clientHeight:document.body.clientHeight;
}

/**
 * вычисляет отступ слева для псевдоокна
 *  
 * @param {Number} tnW - ширина "окна" в пикселах
 * @return {Number} - отступ слева 
 */
function calcPWindowX(tnW)
{
	var lnLeft = parseInt(getScrollX() + (windowWidth() / 2) - (tnW / 2));
	return (lnLeft < 0) ? 0 : lnLeft;
}

/**
 * вычисляет отступ сверху для псевдоокна
 *  
 * @param {Number} tnH - ширина "окна" в пикселах
 * @return {Number} - отступ сверху 
 */
function calcPWindowY(tnH)
{
	var lnTop = parseInt(getScrollY() + (windowHeight() / 2) - (tnH / 2));
	return (lnTop < 0) ? 0 : lnTop;
}

/**
 * возвращает значение свойства tcPropName для элемента toElem
 *  
 * @param {HTMLElement/String} toElem - ссылка на элемент или ID элемента
 * @param {String} tcPropName - имя свойства
 * @return {String/Number} - значение свойства
 */
function getStyle(toElem, tcPropName)
{
	if (toElem.constructor == String) toElem = id(toElem);

    // If the property exists in style[], then it's been set recently (and is current)
    if (toElem.style[tcPropName]) return toElem.style[tcPropName];
    // Otherwise, try to use IE's method
    else if (toElem.currentStyle) return toElem.currentStyle[tcPropName];

    // Or the W3C's method, if it exists
    else if (document.defaultView && document.defaultView.getComputedStyle)
		{
        // It uses the traditional text-align style of rule writing, instead of textAlign
        tcPropName = tcPropName.replace(/([A-Z])/g,"-$1");
        tcPropName = tcPropName.toLowerCase();

        // Get the style object and get the value of the property (if it exists)
        var s = document.defaultView.getComputedStyle(toElem,"");
        return s && s.getPropertyValue(tcPropName);
    // Otherwise, we're using some other browser
    }
	else return null;
}

/**
 * устанавливает прозрачность для элемента
 * 
 * @param {HTMLElement/String} toElem - ссылка на элемент или его ID
 * @param {Number} level - уровень прозрачности от 0 до 100
 * @return void
 */
function setOpacity(toElem, level)
{
    // If filters exist, then this is IE, so set the Alpha filter
    if (toElem.filters  &&  toElem.filters.alpha) toElem.filters.alpha.opacity = level;
    // Otherwise use the W3C opacity property
    else toElem.style.opacity = level / 100;
}


/**
 * выполняет постепенное проявление элемента
 *  
 * @param {HTMLElement/String} toElem - ссылка на элемент или его ID
 * @param {Number} tnEndOpcaity - конечный уровень прозрачности
 * @param {Number} tnSpeed - скорость проявления
 * @return void
 */
function fadeIn(toElem, tnEndOpcaity, tnSpeed)
{
    // Start the opacity at  0
    setOpacity(toElem, 0);

    // Show the element (but you can see it, since the opacity is 0)
    show(toElem);

    // We're going tnEndOpcaity do a 20 frameХ animation that takes place over one second
    for (var i=0; i <= 100; i += 5)
	{
        // A closure tnEndOpcaity make sure that we have the right ФiХ
        (
			function()
			{
				var lnOpacity = i;
				// Set the timeout tnEndOpcaity occur at the specified time in the future
				setTimeout(function()
				{
					// Set the new opacity of the element
					setOpacity(toElem, (lnOpacity / 100) * tnEndOpcaity);
				},
				(i + 1) * tnSpeed);
			}
		)();
    }
}

/**
 * выполняет постепенное скрытие элемента
 *  
 * @param {HTMLElement/String} toElem - ссылка на элемент или его ID
 * @param {Number} tnEndOpcaity - конечный уровень прозрачности
 * @param {Number} tnSpeed - скорость проявления
 * @return void
 */
function fadeOut(toElem, to, tnSpeed)
{
    //setOpacity( toElem, 1);	// Start the opacity at 1

    // We're going to do a 20 frameХ animation that takes place over one second
    for (var i=0; i < 100; i += 5)
	{
        // A closure to make sure that we have the right ФiХ
        (function()
		{
			var lnOpacity = i;
			// Set the timeout to occur at the specified time in the future
		    setTimeout(function()
			{
				// Set the new opacity of the element
		        setOpacity(toElem, 100 - lnOpacity);
		        if (lnOpacity == 95) hide(toElem);

			},
			(i + 1) * tnSpeed);
		}
		)();
    }
}

/**
 * возвращает ссылку на следующий элемент
 * 
 * @param {HTMLElement} toElem - ссылка на элемент для которого ищем следующий элемент
 * @return {HTMLElement} - ссылка на следующий элемент
 */
function next(toElem)
{
	if (toElem.constructor == String) toElem = id(toElem);

    do
    {
    	toElem = toElem.nextSibling;
    } while (toElem && toElem.nodeType != 1);
    return toElem;
}

/**
 * возвращает ссылку на предыдущий элемент
 * 
 * @param {HTMLElement} toElem - ссылка на элемент для которого ищем предыдущий элемент
 * @return {HTMLElement} - ссылка на предыдущий элемент
 */
function prev(toElem)
{
	if (toElem.constructor == String) toElem = id(toElem);

    do
	{
        toElem = toElem.previousSibling;
    } while (toElem && toElem.nodeType != 1);
    return toElem;
}

// определение позиции X (горизонтельной слева)
function pageX(toElem)
{
    var p = 0;

    // We need to add up all of the offsets for every parent
    while (toElem.offsetParent)
	{
        // Add the offset to the current count
        p += toElem.offsetLeft;

        // and continue on to the next parent
        toElem = toElem.offsetParent;
    }

    return p;
}

// определение позиции Y (вертикальной сверху)
function pageY(toElem)
{
    var p = 0;

    // We need to add up all the offsets for every parent
    while (toElem.offsetParent)
	{
        // Add the offset to the current count
        p += toElem.offsetTop;
        // and continue on to the next parent
        toElem = toElem.offsetParent;
    }

    return p;
}

function slideDown(toElem)
{
    // начало развертывания с 0
    toElem.style.height = '0px';

    // показываем элемент (но его не видно - высота нулевая)
    toElem.style.display = 'block';

    // определение всей потенциально доступной высоты
    var h = fullHeight(toElem);

    // собираемся за секунду показать  анимацию, состоящую из 20 "кадров"
    for (var i = 0; i <= 100; i += 5)
	{
        // замкнутое выражение, гарантирующее, что у нас в распоряжении
		// находится именно та переменная "i". которая нам нужна
        (
			function()
			{
				var pos = i;
				//	установка времени ожидания для совершения
				//	будущих действий в определенное время
				setTimeout(function()
				{
					//	установка новой высоты элемента
					toElem.style.height = ( pos / 100  * h ) + "px";

				}, (pos + 1) * 10);
			}
		)();
    }
}

// Find the full, possible, height of an element (not the actual, current, height)
function fullHeight(toElem)
{
    // If the element is being displayed, then offsetHeight
    // should do the trick, barring that, getHeight() will work

	if (getStyle(toElem, 'display') != 'none') return toElem.offsetHeight || getHeight(toElem);

    // Otherwise, we have to deal with an element with a display
    // of none, so we need to reset its CSS properties to get a more
    // accurate reading
    var old = resetCSS(toElem,
	{
        display: '',
        visibility: 'hidden',
        position: 'absolute'
    });

    // Figure out what the full height of the element is, using clientHeight
    // and if that doesn’t work, use getHeight
    var h = toElem.clientHeight || getHeight( toElem );

    // Finally, restore the CSS properties back to what they were
    restoreCSS(toElem, old);

    // and return the full height of the element
    return h;
}

/**
 * выводит отладочный текст в отладочном окне
 *
 * @param {String} tcText - текст который нужно вывести в отладочном окне
 * @param {Boolean} tlClear - если TRUE, то перед выводом значения отладночное окно очищается
 * @return {String} - весь текст который есть в отладочном окне
 */
function DebugOut(tcText, tlClear)
{
	var loOut = id('DebugOut');

	if (!loOut)
	{
		loOut = dce('div');
		loOut.id = 'DebugOut';
		loOut.style.display = 'block';
		loOut.style.position = 'absolute';
		loOut.style.zIndex = 100;
		loOut.style.width = '300px';
		loOut.style.height = '400px';
		loOut.style.padding = '5px';
		loOut.style.backgroundColor = 'white';
		loOut.style.color = 'red';
		loOut.style.overflowY = 'scroll';
		loOut.style.right = '10px';
		loOut.style.border = "1px solid red";

		dbac(loOut);

		loOut.innerHTML = '<table style="width: 100%; border: none;"><tr><td><b>Debug</b></td><td style="text-align: right;"><a href="javascript:CloseDebugOut();" style="font-weight: bold; color: red; border: none; text-decoration: none;">X</a></td></tr></table><div style="border-top: 1px solid red; padding-top: 5px;"></div>';
	}
	else
	{
		loOut.style.display = 'block';
	}
	loOut.style.top = parseInt(getScrollY() + 10) + 'px';
	
	if (tlClear) loOut.lastChild.innerHTML = tcText;
	else loOut.lastChild.innerHTML = tcText + '<hr /><br />' + loOut.lastChild.innerHTML;

	return loOut.innerHTML;
}

/**
 * CloseDebugOut() - закрывает окно отладочного вывода
 * @return void
 */
function CloseDebugOut()
{
	id('DebugOut').style.display = 'none';
}

/**
 * вычисляет параметры браузера
 * 
 * @return {browserInfo} - объект с инфой о браузере
 */
function browserInfo()
{
	this.ver = navigator.appVersion.toLowerCase();
	this.verNum = parseInt(this.ver);
	this.agent = navigator.userAgent.toLowerCase();
	this.dom = (document.getElementById ? 1 : 0);

	this.opera = (this.agent.indexOf("opera") > -1 && this.dom ? 1 : 0);
	this.opera7 = (this.opera && this.verNum >= 7);
	this.opera8 = (this.opera && this.verNum >= 8);
	this.opera9 = (this.opera && this.verNum >= 9);
	this.ie = (this.ver.indexOf("msie") > -1 && this.dom && !this.opera ? 1 : 0);
	this.webkit = this.ver.indexOf("applewebkit") > -1;
	this.chrome = this.ver.indexOf("chrome") > -1;
	this.safari = this.chrome ? false : this.ver.indexOf("safari") > -1;
	this.ieVer = 0;

	if (this.ie)
	{
		var pos = this.ver.indexOf("msie");
		if (pos != -1) this.ieVer = parseFloat(this.ver.substr(pos + 5));
	}

	this.ie6 = (this.ie && (this.ieVer >= 6));
	this.ie6only = (this.ie && (this.ieVer >= 6) && (this.ieVer < 7));
	this.ie7 = (this.ie && (this.ieVer >= 7));
	this.macOS = (this.agent.indexOf("mac") > -1);
	this.mac = (this.macOS && this.verNum >= 7 ? 1 : 0);
	this.moz = (this.agent.indexOf("gecko") > -1);
	this.ns6 = (this.dom && this.agent.indexOf("netscape") > -1 && this.verNum >= 5 ? 1 : 0);
	this.ff = (this.agent.indexOf("firefox") > -1);
	this.b = (this.ie || this.ns6 || this.opera7 || this.mac || this.moz || this.dom);

	return this;
}

/**
 * trim() - обрезает ведущие и конечные пробелы
 *
 * @param string tcString - строчка которой делаем обрезание
 * @return string - строчка у которой уже обрезали все что нужно
 */
function trim(tcString)
{
	if (typeof tcString != 'string') return tcString;

	return tcString.replace(/^\s*|\s*$/g, '');
}

/**
 * stripTags() -
 *
 * @param str -
 */
function stripTags(str)
{
	return str.replace(/(<([^>]*)>)/g, '');
}

/**
 * checkDate() - проверяет валидность даты
 *
 * @param integer month -
 * @param integer day -
 * @param integer year -
 * @return boolean - TRUE - если дата валидна, иначе FALSE
 */
function checkDate(month, day, year)
{
	if (month < 1 || month > 12) return false;
	if (day < 1 || day > 31) return false;
	switch (month)
	{
		case 4:
		case 6:
		case 9:
		case 11:
			if (day > 30) return false;
			break;
		case 2:
			if (year % 4) if (day > 28) return false;
			else if (day > 29) return false;
		break;
	}

	return true;
}

/**
 * алиас для document.createElement
 *
 * @param string tcTagName - имя тэга
 * @return {HTMLElement} - ссылку на созданный объект
 */
function dce(tcTagName)
{
	return document.createElement(tcTagName);
}

/**
 * добавляет элемент toElem в конец body
 * алиас для document.body.appendChild
 * 
 * @param {HTMLElement} toElem - ссылка на добавляемый элемент
 * @return void
 */
function dbac(toElem)
{
	if (document.body) document.body.appendChild(toElem);
}


// Compares str1 with str2, returns -1 (str1 lower), 0 (equal), +1 (str1 bigger)
function strCmp(str1, str2)
{
	if (str1 == str2) return 0;
	var arr = new Array(str1, str2);
	arr.sort();
	return (arr[0] == str1) ? -1 : 1;
}

/**
 * striCmp() - Compares str1 with str2, returns -1 (str1 lower), 0 (equal), +1 (str1 bigger)
 *
 * @param string str1 -
 * @param string str2 -
 * @return integer
 */
function striCmp(str1, str2)
{
	str1 = '' + str1;
	str2 = '' + str2;
	if (str1 == str2) return 0;
	str1 = str1.toLowerCase();
	str2 = str2.toLowerCase();
	var arr = new Array(str1, str2);
	arr.sort();
	return (arr[0] == str1) ? -1 : 1;
}

/**
 * formats string to be safe for GET method
 *
 * @param string st -
 * @return string
 */
function formatStToSafeGET(st)
{
	st = '' + st;
	st = st.replace(/%/g, '%25');
	st = st.replace(/\+/g, '%2B');
	st = st.replace(/ /g, '+');
	st = st.replace(/\?/g, '%3F');
	st = st.replace(/&/g, '%26');
	st = st.replace(/=/g, '%3D');
	st = st.replace(/'/g, '%27'); // st = st.replace(/'/, '%27'); comment for editor highlighting
	st = st.replace(/"/g, '%22'); // st = st.replace(/"/, '%22'); comment for editor highlighting
	st = st.replace(/\//g, '%2F');
	st = st.replace(/\\/g, '%5C');
	st = st.replace(/\x0d/g, '%0D');
	st = st.replace(/\x0a/g, '%0A');
	return st;
}

/**
 * показываем в правом нижнем углу экрана сообщение в "окошке" a-la QIP
 * @param {String} tcText - текст сообщения
 * @param {String} tcTitle - текст заголовка "окошка"
 * @param {Number} tnTime - время в секундах пока не спрячется "окошко"
 * @return void
 */
function aska(tcText, tcTitle, tnTime)
{
	var loOut = id('aska_shell');

	if (!loOut)
	{
		loOut = dce('div');
		loOut.id = 'aska_shell';
		loOut.className = 'aska';
		loOut.style.display = 'block';
		loOut.style.position = 'absolute';
		loOut.style.zIndex = 100;

		document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop
		loOut.style.top = parseInt(windowHeight() + getScrollY() - 160 - 10) + 'px';
		loOut.style.right = '2px';

		document.body.appendChild(loOut);

		loOut = id('aska_shell');

		loOut.innerHTML = '<div class="atitle"><h6>Сообщение</h6><a href="javascript:aska_hide()" title="закрыть окно сообщения">X</a></div><div class="clear"></div><div class="aska_content"></div>';
		loOut.onclick = aska_hide;
	}
	else loOut.style.display = 'block';

	loOut.firstChild.firstChild.innerHTML = (tcTitle) ? tcTitle : 'Сообщение';
	tnTime = (tnTime) ? parseInt(tnTime) : 10;
	loOut.lastChild.innerHTML = tcText;
	setTimeout(function() { aska_hide(); }, tnTime * 1000);
}

/**
 * скрывает сообщение созданное фунцией aska
 * @link aska
 * @return void
 */
function aska_hide()
{
	id('aska_shell').style.display = 'none';
}

/**
 * аналог PHP-шной, меняет местами ключи и значения массива
 * @author Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 *
 * @param array taArray - массив которому делаем ченч
 * @return array - массив после обмена
 */
function array_flip(taArray)
{
	var lcKey = '', laTempArr = {};

    for (lcKey in taArray) laTempArr[taArray[lcKey]] = lcKey;

    return laTempArr;
}

/**
 * аналог PHP-шной, возвращает массив из ключей массива
 * @author Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 *
 * @param array input -
 * @param search_value -
 * @param strict -
 */
function array_keys(input, search_value, strict)
{
    var tmp_arr = new Array(), llStrict = !!strict, llInclude = true, cnt = 0;

    for (key in input)
	{
        llInclude = true;
        if (search_value != undefined)
        {
            if (llStrict && input[key] !== search_value ) llInclude = false;
            else
            {
	            if (input[key] != search_value ) llInclude = false;
           }
        }

        if (llInclude)
        {
            tmp_arr[cnt] = key;
            cnt++;
        }
    }

    return tmp_arr;
}

/**
 * исправляет раскладку
 *
 * @param {String} tcStr - строка, которую правим
 * @param {String} tcNeedLanguage - нужный нам язык (ru, ua, en)
 * @return {String} - исправленная строка
 */
function punto(tcStr, tcNeedLanguage)
{
	if (!tcNeedLanguage) tcNeedLanguage = 'ru';
	var lcRet = new String(tcStr);

	var lcEn = "qwertyuiop[]asdfghjkl;'zxcvbnm,.`";
	var lcRu = "йцукенгшщзхъфывапролджэячсмитьбюё";
	var lcUa = "йцукенгшщзхїфівапролджєячсмитьбюё";

	if (tcNeedLanguage=='ua'  ||  tcNeedLanguage=='uk')	lcRu = lcUa;	//	немного подравляем для украинского языка

	if (tcNeedLanguage=='ru'  ||  tcNeedLanguage=='ua'  ||  tcNeedLanguage=='uk')
	{
		var lcFrom = lcEn;
		var lcTo = lcRu;
		lcRet = lcRet.replace('@', '"');
	}
	else
	{
		var lcFrom = lcRu;
		var lcTo = lcEn;
		lcRet = lcRet.replace('"', '@');
	}

	for (var i=0; i < lcFrom.length; i++)
 	{
 		var lcF = new String(lcFrom[i]);
		var lcT = new String(lcTo[i]);
 		lcRet = lcRet.replace(lcF, lcT);
		lcRet = lcRet.replace(lcF.toUpperCase(), lcT.toUpperCase());
 	}

 	return lcRet;
}

/**
 * punto_switcher() - исправление раскладки в поле ввода
 * вешаем на OnKeyUp или OnBlur
 *
 * @param {Event} e - ссылка на объект-событие
 * @return
 */
function punto_switcher(e)
{
    e = (e) ? e : window.event;    // получить ссылку на событие
    var loTarget = e.target || e.srcElement; // получить ссылку на приемник события

	var lcLang = (loTarget.lang) ? loTarget.lang : 'ru';
	loTarget.value = punto(loTarget.value, lcLang);
}

/**
 * возвращает список атрибутов объекта и значения
 * @param {Element/Object} toObj - ссылка на объект 
 * @param {String} tcSplit - строка разделитель строк
 * @return {String} - строку со списком атрибутов объекта и значениями атрибутов
 */
function getProps(toObj, tcSplit)
{
	if (!tcSplit) tcSplit = '\n';
	var lcRet = '';
	var lcTab = '    ';

    for (var i in toObj) // обращение к свойствам объекта по индексу
    	lcRet += lcTab + i + " : " + toObj[i] + tcSplit;

    lcRet = '{' + tcSplit + lcRet + '}';

	return lcRet;
}

/**
 * выполняет отложенную загрузку JS-скриптов
 * 
 * @param {String[]} taScripts - массив с именами скриптов
 * @param {String} tcPath - путь к папке со скриптами, если не указан то ./js/
 * @return void
 */
function post_load_scripts(taScripts, tcPath)
{
	var loHead = document.getElementsByTagName('head')[0];

	tcPath = (tcPath) ? tcPath : './js/';

	var lcCur = null, laCur = null, lfCallBack = null, laParams = null;

	for (var i=0; i < taScripts.length; i++)
	{
		var laCur = taScripts[i];
		if (laCur.constructor == Array)
		{
			lcCur = laCur[0];
			lfCallBack = laCur[1];
			laParams = (laCur[2]) ? laCur[2] : null;
		}
		else
		{
			lcCur = laCur;
			lfCallBack = laParams = false;
		}

		var loJS = dce('script');
		loJS.src = tcPath + lcCur;
		loJS.language = 'javascript';
		loJS.type = 'text/javascript';

		if (lfCallBack)
		{
			loJS.__ReadyState = false;
			loJS.onload = scriptOnloadCallBack(loJS, lfCallBack, laParams);
			if (! document.all) loJS.onreadystatechange = scriptOnloadCallBack(loJS, lfCallBack, laParams);
		}

		loHead.appendChild(loJS);
	}
}

/**
 * вызывается по факту загрузки скрипта
 * 
 * @param {HTMLElement} toScript - ссылка на элемент типа SCRIPT
 * @param {function} tfCallBack - ссылка на функцию которую нужно будет вызвать
 * @param {Array/Boolean} taParams - массив с параметрами вызываемой функции, FALSE если параметров нету
 * @return void
 */
function scriptOnloadCallBack(toScript, tfCallBack, taParams)
{
	if (toScript.__ReadyState) return true;

//	DebugOut('scriptOnloadCallBack 2');
//	DebugOut(toScript.readyState);
	if ((! toScript.readyState)  ||  toScript.readyState=='loaded'  ||  toScript.readyState=='complete')
	{
//		DebugOut('scriptOnloadCallBack 3');
		toScript.__ReadyState = true;
		tfCallBack.call(this, (taParams) ? taParams : []);
	}

	return true;
}

/**
 * выполняет отложенную загрузку стилей
 * 
 * @param {String[]} taStyles - массив с именами CSS-файлов
 * @param {String} tcPath - путь к папке со стилями, если не указан то ./css/
 * @return void
 */
function post_load_styles(taStyles, tcPath)
{
	var loHead = document.getElementsByTagName('head')[0];
	tcPath = (tcPath) ? tcPath : './css/';

	for (var i=0; i < taStyles.length; i++)
	{
		var loCSS = dce('link');
		loCSS.href = tcPath + taStyles[i];
		loCSS.type = 'text/css';
		loCSS.media = 'all';
		loCSS.rel = 'stylesheet';
		loHead.appendChild(loCSS);
	}
}

/**
 * аналог PHP-шной
 * 
 * @param {Array/HTMLElement/Object} taV
 */
function print_r(taV)
{
	alert(getProps(taV));
}

/**
 * узнает реальную длину строки в px
 * вычисляется размер строки с учетом стиля элемента obj
 * 
 * @param {HTMLElement} obj - ссылка на элемент
 * @param {String} str - 
 * @return {Number} - длина строки в px
 */
function stringSize(obj,str)
{
	var s = document.createElement("span")
	s.innerHTML=str;
	s.style.visibility="hidden";
	s.style.whiteSpace="nowrap";
	obj.appendChild(s);
	var res={width:s.offsetWidth,height:s.offsetHeight};
	obj.removeChild(s);
	return res;
}

/**
 * показывает сколько еще символов можно ввести
 *
 * @param {HTMLElement} toObj - ссылка на проверяемый элемент
 * @param {String} tcLeftOut - ID элемента в который выводим количество оставщихся символов
 * @param {Number} tnMax - сколько символов можно ввести в поле
 * @return void
 */
function check_text_field_len(toObj, tcLeftOut, tnMax)	//		проверяет длину поля "примечание"
{
    var lcText = toObj.value;
    if (lcText.length > tnMax) toObj.value = lcText.substring(0, tnMax);
    id(tcLeftOut).innerHTML = parseInt(tnMax - lcText.length);
}
