//--------------------------------------------------------------------------
// Проект:      Zoom - 2
//
// Copyright:   "Nota-PI group" 2000г.
//
//---------------------------------------------------------------------------
// Модуль:      Common.js
// Категория:   Вспомогательные процедуры
// Язык:        JavaScript
//
// Описание:    Общие функции
//
// Автор:       Алексей Конюхов
// Разработка:  29.08.2001 - ...
//---------------------------------------------------------------------------

// Отображение help'а

function help(p_nIndex, p_Lang)
{
    if (p_Lang == "") p_Lang = "e"
    mm_strURL = "help_"+p_Lang+".asp?id="+p_nIndex
    window.showHelp(mm_strURL)
}

// Окно с about'ом
function ShowAbout(p_Lang)
{
    mm_dWnd = open("about.asp?ln="+p_Lang, "about", "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=600,height=560")
}

// Внешнее окно
function ShowExternal(p_URL, p_Name, p_Tools)
{
    dWnd = open(p_URL, p_Name, "toolbar="+p_Tools+",location=no,status=no,menubar="+p_Tools+",scrollbars=yes,resizable=yes,width=600,height=400");
}



//---------------------------------------------------------------------------
// Переход по адресу...

function GoASP(p_strAddr)
{
    window.location.href = p_strAddr;
}

//---------------------------------------------------------------------------
// Отметка / сброс отметок всех checkbox'ов с одинаковым префиксом

function SelectAll(p_strBaseName, p_nQuant, p_bValue)
{
    for (var mm_I = 1; mm_I <= p_nQuant; mm_I++)
    if (document.all[p_strBaseName+mm_I])
            document.all[p_strBaseName+mm_I].checked = p_bValue;
}

//---------------------------------------------------------------------------

//Класс для работы с расширениями

function extensionsCat() {
var _list_extensions = new Array()

this.register = function(expr, id_extension, ext_point, order) {
    _list_extensions[_list_extensions.length] = [expr, id_extension, ext_point, order]
}

this.list = function(ext_point) {
    var point_extensions = new Array()
    var i
    for (i=0; i<_list_extensions.length; i++) {
        if (_list_extensions[i][2] == ext_point) {
            point_extensions[point_extensions.length] = _list_extensions[i]
        }
    }
    return point_extensions
}

this.unregister = function(id_extension) {
    var oneExt
    var startPortion
    var endPortion
    var slice_point = 0
    for (var i=0; i<_list_extensions.length; i++) {
        oneExt = _list_extensions[i]
        if (oneExt[1] == id_extension) {
            slice_point = i
            break
        }
    }
    startPortion = _list_extensions.slice(0, slice_point)
    endPortion = _list_extensions.slice(slice_point + 1, _list_extensions.length + 1)
    _list_extensions = startPortion.concat(endPortion)
}

this.doSort = function(self_extensions) {
    var aNewExtensions = new Array()
    var aNotOrdered = new Array()
    while (self_extensions.length) {
        oneExt = self_extensions[0]
        self_extensions = self_extensions.slice(1, self_extensions.length + 1)
        if (oneExt[3]) {
            aNewExtensions[oneExt[3]] = [oneExt[0],oneExt[1],oneExt[2],oneExt[3]]
        } else {
            aNotOrdered[aNotOrdered.length] = [oneExt[0],oneExt[1],oneExt[2],oneExt[3]]
        }
    }
    var num = aNewExtensions.length
    for (i=0; i < num; i++) {
        oneExt = aNewExtensions[0]
        aNewExtensions = aNewExtensions.slice(1, aNewExtensions.length + 1)
        if (oneExt) {self_extensions[self_extensions.length] = oneExt}
    }
    self_extensions.concat(aNotOrdered)
    return self_extensions
}

this.apply = function(ext_point, sorted) {
    var bRes = true
    var self_extensions = this.list(ext_point)
    if (!self_extensions.length) {return}
    if (sorted) {self_extensions = this.doSort(self_extensions)}
    for (num_extension=0; num_extension < self_extensions.length; num_extension++) {
        var ext = self_extensions[num_extension][0]
        if (typeof(ext) == "function")
        {
            ext()
        } else {
            eval(ext)
        }
    }
    return bRes
}

this.count = function(p_sExtPointID) {
    return this.list(p_sExtPointID).length
}
}

var extensions = new extensionsCat()

function bodyOnLoad() {
    extensions.apply("_body_load", false)
    bodyAfterLoad()
}

/**
 обработчик события body load
*/
function addOnLoadHandler(expr, order) {
    //автоматическое получение идентификатора для расширения - просто порядковый номер
    var nextID = extensions.count("_body_load")
    extensions.register(expr, nextID, "_body_load", order)
}

function bodyAfterLoad() {
    extensions.apply("_body_after_load", false)
}

/**
 обработчик события body load
*/
function addAfterLoadHandler(expr, order) {
    //автоматическое получение идентификатора для расширения - просто порядковый номер
    var nextID = extensions.count("_body_after_load")
    extensions.register(expr, nextID, "_body_after_load", order)
}

/**
 обработчик события вызова контекстного меню (нажатие правой кнопки мыши)
*/
function bodyOnContextMenu() {
    var res = true
    var self_extensions = extensions.list("_body_context_menu")
    if (!self_extensions.length) {return true}
    for (var num_ext=0; num_ext < self_extensions.length; num_ext++) {
        res = (res && eval(self_extensions[num_ext][0]))
    }
    return res
}

/**
 обработчик события нажатия клавишы клавиатуры
*/
function windowOnKeyPress(poEvent) {

    if (!poEvent) poEvent = window.event
    var res = true
    var self_extensions = extensions.list("_window_keypress")
    if (!self_extensions.length) {return true}
    for (var num_ext=0; num_ext < self_extensions.length; num_ext++) {
        res = (res && self_extensions[num_ext][0](poEvent))
    }
    return res
}

// привязка обработчика к событию нажатия клавиши клавиатуры
document.onkeypress = windowOnKeyPress


function addEventHandler(expr, eventName, order) {
    //автоматическое получение идентификатора для расширения - просто порядковый номер
    var nextID = extensions.count(eventName)
    extensions.register(expr, nextID, eventName, order)
}

function empty() {

}

document.write("<iframe id='bk_frame_for_popup' style='DISPLAY:NONE;Z-INDEX:5;WIDTH:250px;HEIGHT:28px;POSITION:absolute;LEFT:0;TOP:0; border-width: 0' ms_positioning='FlowLayout'></iframe>")

function syncBkFrame(p_sPopupID) {

    var document_body_scrollLeft
    try
    {
        document_body_scrollLeft = document.body.scrollLeft;
    }
    catch( e ) { document_body_scrollLeft = 0; }

    popup = document.getElementById(p_sPopupID)
    var bk_frame = document.getElementById("bk_frame_for_popup")
    bk_frame.style.width = popup.clientWidth + 2
    bk_frame.style.height = popup.clientHeight + 2
    bk_frame.style.left = popup.getBoundingClientRect().left - 2 + document_body_scrollLeft
    bk_frame.style.top = calcTop(popup)
    popup.style.zIndex = 2
    bk_frame.style.zIndex=popup.style.zIndex-1
}


function showPopupById(p_sPopupID, p_sAdjust, p_sParent, p_bClosePrev, top, left, currId)
{
    /*
    p_sAdjust =
        left, right - слева или справа от места клика
        parent - там же, где расположен предыдущий попап (из которого вызвали этот)
        abs - явно задаются координаты через параметры top и left
    usePopup - использование стандартного объекта Popup
    currId - дополнительный id, текущего открытого попапа - а
    */
    if (typeof(event) == "undefined") event = gl_FireFoxEvent
    var popup = document.getElementById(p_sPopupID) // popup, который нужно показать

    // iframe, который "подкладывается" под попап окно, что бы не просвечивали комбобоксы

    var document_body_scrollLeft = 0
    try
    {
        document_body_scrollLeft = document.body.scrollLeft;
    }
    catch( e ) { document_body_scrollLeft = 0; }

    var document_body_scrollTop = 0
    try
    {
        document_body_scrollTop = document.body.scrollTop;
    }
    catch( e ) { document_body_scrollTop = 0; }

    if (p_bClosePrev) closeCurrPopup()
    popup.currId = currId

    // отображение попап - а
    try {
        popup.style.display = "block";
    }
    catch( e ) {}

    // если не заданы явно координаты для попапа, то вычисляем на основе координат event - а
    if (p_sAdjust != "abs")
    {
	    var evnt = jsGetEvent()

        eventSender = getSrcElement(evnt)

        var ct = calcTop(eventSender) // document_body_scrollTop

        if( ct + popup.clientHeight < document.body.clientHeight)
        {
            popup.style.top = ct
        } else
        if( ct - popup.clientHeight < 0 )
        {
            popup.style.top = ct
        } else
            popup.style.top = ct - popup.clientHeight

        if (p_sAdjust == "right" || p_sAdjust == undefined)
            popup.style.left = event.clientX - popup.clientWidth + document_body_scrollLeft

        if (p_sAdjust == "left")
        {
            if (evnt.clientX + popup.clientWidth > document.body.clientWidth) {
                popup.style.left = evnt.clientX - popup.clientWidth + document_body_scrollLeft
            } else {
                popup.style.left = evnt.clientX
            }
        }

        if (p_sAdjust == "parent") {
            var oParent

            if ("string" == typeof(p_sParent))
            {
                oParent = document.getElementById(p_sParent)
            } else {
                oParent = p_sParent
            }
            popup.style.top = oParent.style.top
            popup.style.left = oParent.style.left
        }
    } // end if  p_sAdjust != "abs"

    // задание явно переданных координат
    if (p_sAdjust == "abs") {
        popup.style.top = top
        popup.style.left = left
    }
    /*
    if (usePopup) {
        var oPopup = window.createPopup()
        //oPopBody.style.border = "solid  1px"
        var oPopBody= oPopup.document.body
        oPopBody.innerHTML = popup.innerHTML
        oPopup.show(popup.getBoundingClientRect().left, calcTop(popup), popup.clientWidth, popup.clientHeight, document.body)
        popup.style.display = "none"
        return true
    }
    */
    if (isIe()) putBkFrame(popup)
    // "подкладывание" iframe под попап в качестве подложки
    /*
    bk_frame.style.width = popup.clientWidth + 2
    bk_frame.style.height = popup.clientHeight + 2
    bk_frame.style.left = popup.getBoundingClientRect().left - 2
    bk_frame.style.top = calcTop(popup)
    popup.style.zIndex = 2
    bk_frame.style.zIndex=popup.style.zIndex-1
    bk_frame.curr_popup = p_sPopupID
    bk_frame.style.display = "block"
    */
} // end pgm  showPopupById

function putBkFrame(poPopup)
{
    var document_body_scrollLeft
    try
    {
        document_body_scrollLeft = document.body.scrollLeft;
    }
    catch( e ) { document_body_scrollLeft = 0; }

    var bk_frame = document.getElementById("bk_frame_for_popup")

    bk_frame.style.width = poPopup.clientWidth + 2
    bk_frame.style.height = poPopup.clientHeight + 2
    bk_frame.style.left = poPopup.getBoundingClientRect().left - 2 + document_body_scrollLeft
    bk_frame.style.top = calcTop(poPopup)
    poPopup.style.zIndex = 2
    bk_frame.style.zIndex = poPopup.style.zIndex - 1
    bk_frame.curr_popup = poPopup.id
    bk_frame.style.display = "block"
}

function closeCurrPopup() {
    // закрытие предыдущего открытого попап - а, перед открытием нового
    //
    var currId = window.event.srcElement.num
    var bk_frame = document.getElementById("bk_frame_for_popup")
    if (currId == document.getElementById(bk_frame.curr_popup).currId) return true
    closePopupById(bk_frame.curr_popup)
} // end pgm

function closePopupById(p_sPopupID)
{
    var popup = document.getElementById(p_sPopupID)
    if (popup.style.display == "none") return
    popup.style.display = "none"
    var bk_frame = document.getElementById("bk_frame_for_popup")
    bk_frame.style.display = "none"
}


// функции для работы с объектом XMLHTTP
function xmlhttp_GetPage(p_sPage) {
    var xmlhttp=false

    try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP")
    } catch (e) {
        try {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
        } catch (E) {
            xmlhttp = false;
        }
    }

    if (!xmlhttp) {
        alert("Active X is disabled in browser options.")
        return
    }
    xmlhttp.open("GET", p_sPage, true)

    var bReady = false
    /*
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
            var sText = xmlhttp.responseText
            xmlhttp.send(null)
            return sText
        }
    }
    */

    //xmlhttp.onreadystatechange = None
    //while (xmlhttp.readyState != 4) {}
    var sText = xmlhttp.responseText
    xmlhttp.send(null)
    return sText
}

// добавление новой опции в указанный комбобокс
function addOptionTo( list, text, value )
{
    var len = list.length
    var opt

    opt = document.createElement("OPTION")

    opt = list.options[len] = opt
    opt.text  = text
    opt.value = value

    return opt
}

// удаление выделенной опции из комбобокса
function deleteSelectionFromList(dest_list)
{
    var len = dest_list.options.length;
    for(var i = (len-1); i >= 0; i--) {
        if ((dest_list.options[i] != null) && (dest_list.options[i].selected == true)) {
            dest_list.options[i] = null;
        }
    }
}

// удаление всех опций из комбобокса
function deleteOptions(dest_list)
{
    var len = dest_list.options.length;
    for(var i = (len-1); i >= 0; i--) {
        if (dest_list.options[i] != null) {
            dest_list.options[i] = null;
        }
    }
}

// найти первый родительский элемент, обладающий заданным свойством
function findParentElement(poFrom, p_sCond, nDepth) {
    // poFrom - элемент, с которого начинать поиск
    // p_sCond - условие вида "атрибут=='значение'"
    var x
    var currDepth = 0
    for (x = poFrom; (x != null) && (x != document.body); x = x.parentElement) {
        if (eval(p_sCond)) {
            return x
        }
        // защита от слишком глубокой рекурсии
        currDepth ++
        if (nDepth && currDepth >= nDepth) return null
    }
    return null
}

// удаление лишних пробелов в начала и с конца строки
function trim(p_sString) {
    if( p_sString == null ) return ""
    return p_sString.replace (/^\s+|\s+$/g, "");

    var re = /^\s*(\S*.*\S*)\s*$/
    return p_sString.replace(re, "$1")
    //return s.replace (/^([ ])+|([ ])+$/g, "");
}

function createXmlHttp() {
    var xmlhttp = false

    try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP")
    } catch (e) {
        try {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
        } catch (E) {
            try {
                xmlhttp = new XMLHttpRequest()
            } catch(e) {
                xmlhttp = false;
            }
        }
    }

    if (!xmlhttp) {
        alert("Active X is disabled in browser options.")
        return null
    }
    return xmlhttp
}

//---------------------------------------------------------
// вспомогательные функции для модуля FormEngine
//---------------------------------------------------------
// проверить соответствие введенных данных формату поля
function checkInputVal(poObj, poRegexp, poEvent)
{
    var sVal = trim(poObj.value)
    if (sVal == "" || poRegexp.test(sVal)) {
        elem(poObj.id + "_err").innerHTML = "";
        poObj.className = "manageDLinput"
        return true
    }
    elem(poObj.id + "_err").innerHTML = "<br>Некорректно введено значение поля"
    poObj.className = "manageDLinputError"
    try {poObj.focus()} catch (e) {}
    return false
}

// получить значение поля в зависимости от его типа
function getFieldVal(oFld)
{
    if (!oFld._fld_type) return oFld.value
    switch (oFld._fld_type)
    {
        case "checkBoxField":
            return oFld.checked ? oFld.value : oFld.off_value
        case "DateField":
            var sInFormat = document.getElementById(oFld.id + "_vis_format").value
            var sOutFormat = document.getElementById(oFld.id + "_out_format").value
            return convertDate(oFld.value, sInFormat, sOutFormat)
        default:
            return trim(oFld.value)
    }
}


function ShowProgressWindow(AspNameandParms,aParentWin,aMessage)
{

    var sAspNam = "Progresswin"
    if( isIe() ) sAspNam += "IE"

    var xParentWin = null;
    if( arguments.length > 1 )
        xParentWin = aParentWin;
    var sWinParm = "location=no,border=no,status=no,menubar=no,scrollbars=no,"
                 + "resizable=no,width = 400,height = 200"

    var progressWin
    if(xParentWin!=null)
    {
        progressWin = window.open( sAspNam + '.asp?target='
                                           + encodeURIComponent(AspNameandParms)
                                           + '&mess='+aMessage,null,
                                   sWinParm )
        try
        {
        progressWin.opener=aParentWin
        }
        catch( e ) { }
    }
    else
    {
        progressWin = window.open( sAspNam + '.asp?extern='
                                           + encodeURIComponent(AspNameandParms)
                                           + '&mess='+aMessage,null,
                                   sWinParm )
        try
        {
        progressWin.opener=null
        }
        catch( e ) { }
    }

} // end pgm

 // проверка текущих настроек времени для Enter.asp + tst.asp
 // и autoconnect
function testLocalTiming()
{
  var fld = document.getElementById( "LocalTiming" ) // .all
  if( fld == null ) return;
  //if( fld.length <= 0 ) return;

  var dtExpires = new Date();

  //var sT = dtExpires.toLocaleTimeString();
  var sD = dtExpires.toLocaleDateString();


  var k = sD.indexOf( "г" )
  if( k > 0 )
  {
      fld.value = "DD.MM.YYYY"
  } else
  {
      fld.value = "MM/DD/YYYY"
  }
} // testLocalTiming

function getLocalTiming()
{
  var dtExpires = new Date();

  var sT = dtExpires.toLocaleTimeString();
  var sD = ""; //dtExpires.toLocaleDateString();

  return sD + " " + sT
}




function highlightRow(objRow)
{
    var oTable = jsGetParentElement(objRow)
    var aRows = oTable.rows
    for (var i = 0; i < aRows.length; i++)
    {
        aRows[i].style.background = aRows[i].bgColor;
    }
    objRow.style.background = "#E7E6F7"; //"#ffffb9"
}

function inArray(paArr, psVal)
{
    var bRes = false
    for (var i = 0; i < paArr.length; i ++)
        if (paArr[i] == psVal) bRes = true
    return bRes
}

function findFirst(paArr, psVal)
{
    for (var i = 0; i < paArr.length; i ++)
        if (paArr[i] == psVal) return i
    return -1
}

var traceObj = null

try
{
    var traceObj = isIe() ? new ActiveXObject("Zaks.Trace") : new GeckoActiveXObject("{C0079703-E7F1-11D1-9220-000001136428}")
} catch(E) {}

trace("Tracing started.")

function trace(psMsg)
{
    if (traceObj != null) {
        try {
            traceObj.trace(psMsg)
        } catch (e) {}
    }
}

function isIe()
{
    var sVersion = navigator.appVersion
    return sVersion.indexOf("MSIE") > 0 ? true : false
}

function getSrcElement(event)
{
    if (!event) return null
    return isIe() ? event.srcElement : event.target
}

function objProps(obj, pnRet, psTitle)
{
    /*
    pnRet =
    0 - return
    1 - to debug stream
    2 - alert with paging
    */
    var aProps = []
    if (0 == pnRet)
    {
        var sProps = ""
        for (var prop in obj) sProps += prop + "<br>"
        return sProps
    }
    if (1 == pnRet)
    {
        for (var prop in obj) aProps.push(prop)
        aProps.sort()
        var sTitle
        if (psTitle) {sTitle = psTitle} else {sTitle = "object prop: "}
        for (var i in aProps) trace(sTitle + ": " + aProps[i])
        return
    }
}

//===== группа функций и переменных для обработки событий и тегов ====
//===== одновременно в MS IE и Firefox ===== Морозов В.Н. 20.07.06 ===

var gl_FireFoxScrElement = null ;
var gl_FireFoxEvent = null ;

//
function js_setScrElement(elm)
{
    gl_FireFoxScrElement = elm ;
} // end pgm

function jsReadEvent(xEvent)
{
  if( !isIe() )
  {
    gl_FireFoxEvent = xEvent;
    gl_FireFoxScrElement = xEvent.target;
  } else
  {
    gl_FireFoxEvent = window.event;
    gl_FireFoxScrElement = window.event.srcElement;
  }
} // end pgm

function jsReadEventFromParm(xEvent)
{
  if( !isIe() )
  {
    gl_FireFoxEvent = xEvent;
    gl_FireFoxScrElement = xEvent.target;
  } else
  {
    gl_FireFoxEvent = xEvent;
    gl_FireFoxScrElement = xEvent.srcElement;
  }
} // end pgm

function jsGetEvent_coord(nameCoord)
{
    if( isIe() )
    {
        gl_FireFoxEvent = window.event;
        gl_FireFoxScrElement = window.event.srcElement;
    }
    var retCoord = 0;
    if( nameCoord == 'X' )
    {
        try {
        retCoord = gl_FireFoxEvent.clientX
        }
        catch( e ) { }
    }
    else
    {
        try {
        retCoord = gl_FireFoxEvent.clientY
        }
        catch( e ) { }
    }

    return retCoord;
} // end pgm

// см. http://www.linkstraffic.net/programming/javascript/dragdrop.php от 1.08.07
/*function to get the mouse coordinates - browser detection*/
function getcoordinate(evt)
{
   /*
    var IE=false;
    if(navigator.appName == "Microsoft Internet Explorer")
    IE = true;

    if(IE)
    */
    var type = "Y"
    if( arguments.length > 1 )
        type = arguments[1];

    var x, y;

    if( isIe() )
    {
        x = evt.clientX + document.body.scrollLeft;
        y = evt.clientY + document.body.scrollTop;

    }
    else
    {
        x = evt.pageX;
        y = evt.pageY;
    }

    return (type == "Y") ? y : x ;
} // end pgm


function jsGetSrcElement()
{
    if( isIe() )
    {
        //try
        //{
        gl_FireFoxEvent      = window.event
        gl_FireFoxScrElement = window.event.srcElement;
        //}
        //catch(e) { }
    } else
    {
        gl_FireFoxScrElement = gl_FireFoxEvent.target;
    }
        return gl_FireFoxScrElement;
}

function jsGetEvent()
{
    if( isIe() )
        gl_FireFoxEvent = window.event;

    return gl_FireFoxEvent;
}

function my_jsObjProps(obj)
{
	if( gjs_nYesRussComputer <= 0 ) return;

	/*
	try
	{
		alert( "obj.tagName="+obj.tagName )
	}
	catch( e ) { }
	*/

	jsObjProps(obj)
} // end pgm

function jsObjProps(obj)
{

    var ss = "", k = 0, val
    for (var prop in obj)
    {
        ss = "prop=["+prop+"] "+ typeof(prop) ;
        try
        {
	        val = obj.getAttribute( prop )
        }
        catch( e ) { }

        if( val == null )
        {
          try
          {
	          if( isIe() )
	              val = eval( "obj."+prop )
	          else
	              val = evaluate( "obj."+prop )
          }
          catch( e ) {}
        }

        ss += " val=["+val+"]"

        ss += " k=" + k
        if( !confirm( ss ) ) break;
        k++;
    } // end for
}

function jsGetParentElement(elm)
{
    if (elm == null) return null
    if (typeof(elm) != "object") return null
    if( !isIe() )
    {
        return elm.parentNode;
    }
    else
    {
        return elm.parentElement;
    }
}

function jsGetTagName(elm)
{
    if( elm == null ) return "";
    if (typeof(elm) != "object") return "";
    if( !isIe() )
    {
        return elm.nodeName;
    }
    else
    {
        return elm.tagName;
    }
} // end pgm

function calcOffsetTop(beg)
{
    var k=-1, offset=0;
    var elm = beg ;

    var tagNameStop = "BODY"
    if( arguments.length > 1 )
        tagNameStop = arguments[1]

    var tagNameCurr = ""
    var tagNamePrior = ""
    var yesPlus = true


    if( elm != null )
    for(k=0;k<40;k++)
    {
        if( elm == null ) break;

            tagNameCurr = jsGetTagName( elm )
        if( tagNameCurr == tagNameStop ) break;

        yesPlus = true

        if( tagNameCurr == "TR" && tagNamePrior == "TD" ) yesPlus = false
        else
        if( tagNameCurr == "TBODY" && tagNamePrior == "TR" ) yesPlus = false

        if( yesPlus == true )
            offset += elm.offsetTop;

            elm = jsGetParentElement( elm )

        tagNamePrior = tagNameCurr
    } // end for(k;;)

    if( offset > 0 )
    {
        var mTop = document.body.topMargin
        if( typeof mTop == "undefined" ) mTop = 0

            offset -= mTop
    } // end if


    return offset;
} // end pgm  calcOffsetTop

function calcOffsetLeft(beg)
{
    var typ, offset=0;
    var elm = beg;


    var tagNameStop = "BODY"
    if( arguments.length > 1 )
        tagNameStop = arguments[1]

    var tagNameCurr = ""
    var tagNamePrior = ""
    var yesPlus = true

    var b_IsIe = isIe()

    if( elm != null )
    for(var k=0;k<40;k++)
    {
        if( elm == null ) break;

            tagNameCurr = jsGetTagName( elm )
        if( tagNameCurr == tagNameStop ) break;

        yesPlus = true

        if( tagNameCurr == "TR" && tagNamePrior == "TD" ) yesPlus = false
        else
        if( tagNameCurr == "TBODY" && tagNamePrior == "TR" ) yesPlus = false

        if( yesPlus == true )
            offset += elm.offsetLeft;

            elm = jsGetParentElement( elm )

            tagNamePrior = tagNameCurr
    } // end for(k;;)

    if( offset > 0 )
    {
        var mLeft = document.body.leftMargin
        if( typeof mLeft == "undefined" ) mLeft = 0

            offset -= mLeft
    } // end if

    return offset;
} // end pgm  calcOffsetLeft

function jsGetInnerText(elm)
{
    if( elm == null ) return "";
    if (typeof(elm) != "object") return ""
    if( !isIe() )
    {
        return elm.textContent;
    }
    else
    {
        return elm.innerText;
    }
} // end pgm

function jsSetInnerText(elm,val)
{
    if( !isIe() )
    {
        return elm.textContent = val;
    }
    else
    {
        return elm.innerText = val ;
    }
} // end pgm

// <%'вместо document.all( sName ) !!! - внимание не возвращает список%>
function jsNameFromAll(sName)
{
    var lst = document.getElementsByName( sName );
    if( lst == null ) return null;
    if( lst.length <= 0 ) return null;

    return lst[0];
} // end pgm

// <%'вместо document.all( sName ) !!! - внимание возвращает список%>
function jsListFromAll(sName)
{
    var lst = document.getElementsByName( sName );
    if( lst == null ) return null;
    if( lst.length <= 0 ) return null;

    return lst;
} // end pgm

// <% ' не распространять клавишу вверх %>
function stopKeyProp( event )
{
     if( isIe() )
        event.cancelBubble = true;
    else
        event.stopPropagation();

} // end pgm

function set_window_location_href( sloc )
{

    if( isIe() )
        window.event.cancelBubble = true;
    else
    {
        gl_FireFoxEvent.stopPropagation();
    }

    window.location.href = sloc
} // end pgm

function jsGetInxSelection( oSel, sVal )
{
    var inx = -1
    if( oSel == null ) return inx;
    if( oSel.length <= 0 ) return inx;

    for(var i=0; i<oSel.length; i++)
    {
        if( oSel[i].value == sVal ) { inx = i; break; }
    } // end for(;;)

    return inx;
} // end pgm

// <% ' поск под элемента %>
function findSubElement( elmBase, sId )
{
    if( isIe() )
    {
       if( elmBase == null ) return null;

       return elmBase.all.item( sId )
    }

    var yyy = document.getElementById( sId )
    if( yyy == null ) return null;

    var k = 200; // подстраховка от зацикливания

       var zzz = jsGetParentElement(yyy);
    while( true )
    {
        if( zzz == elmBase ) return yyy;
        if( zzz instanceof HTMLDocument == true ) break;
            zzz = jsGetParentElement(zzz);
        if( zzz == null ) break;
        k--;
        if( k <= 0 ) break;

    } // end while

    return findChildInTree( elmBase, sId );
} // end pgm

// <%'просмотр Childs-Tree и выбор элемента с нужным именем%>
function findChildInTree( elmBase, sChildId )
{

    if( isIe() )
    {
       if( elmBase == null ) return null;

       return elmBase.all.item( sChildId )
    }


    // FireFox

    if( elmBase == null ) return null;
    if( typeof( elmBase ) == "undefined" ) return null;
    if( typeof( elmBase ) != "object" ) return null;

    if( elmBase instanceof Text == true ) return null;

    var cld, i, xxx, xId;

    try
    {
        xId = elmBase.getAttribute( "id" )
    }
    catch( e ) { xId = null; }

    if( xId != null )
    if( typeof( xId ) == "string" )
    if( xId == sChildId ) return elmBase;

    if( !elmBase.hasChildNodes() ) return null;

    for(i=0;i<elmBase.childNodes.length;i++)
    {

         xxx =  elmBase.childNodes[i]

         cld = findChildInTree( xxx, sChildId )
     if( cld != null ) return cld;

    } // end for

    return null;
} // end pgm

// <%'просмтр Childs и выбор элемента с нужным именем или id %>
function getElementFromChild( elmBase, sNameChild )
{
   if(  elmBase == null ) return null;
   if( !elmBase.hasChildNodes() ) return null;

   var typ = "name";
   if( arguments.length > 2 )
       typ = arguments[2];

   var cld,i;

   if( typ == "name" )
    for(i=0;i<elmBase.childNodes.length;i++)
    {
     cld = elmBase.childNodes[i];
     if( typeof( cld.name ) == "undefined" ) continue;
     if( typeof( cld.name ) != "string" ) continue;
     if( cld.name == sNameChild ) return cld;
    } // end for
   else
   if( typ == "id" )
    for(i=0;i<elmBase.childNodes.length;i++)
    {
     cld = elmBase.childNodes[i];
     if( typeof( cld.id ) == "undefined" ) continue;
     if( typeof( cld.id ) != "string" ) continue;
     if( cld.id == sNameChild ) return cld;
    } // end for

   return null;
} // end pgm

//~~~~~ end List ~~~ for 'MS IE' | 'Firefox' ~~~~~

// формирование даты и строки и контроль заданных значений даты
function jsTestDate( sText, xLv )
{

    var new_Date = null; // <% ' null - ошибка в формате данных %>

    var txt = trim( sText )
    if( txt.length <= 0 ) return new_Date; // <%' нет данных %>

    var re0 = /\d/g;        // <% 'Create regular expression - цифры %>

    var res = txt.replace(re0, "");
    if( res.length != 2 )  // <% 'не два разделителя %>
        return new_Date;

    var rx = res.substring( 0, 1 )
    if( rx == "/" ) rx = "\\"+rx;
    var re1 = new RegExp( rx, "g" )

         res = res.replace( re1, "" );
     if( res.length != 0 )   // <% ' есть недопустимые разделители %>
         return new_Date;

       if( (xLv == 1 && rx != "." ) // <% ' не русский вариант %>
        || (xLv != 1 && rx != "/" ) // <% ' не американский вариант %>
         ) return new_Date;

       var ar = txt.split( rx )
       if( ar.length != 3 ) // <% ' разделители стоят не так %>
           return new_Date;

       if( rx == "/" )
       {
           var m = ar[0];
                   ar[0] = ar[1];
                           ar[1] = m ;
       }

       var k = parseInt( ar[1], 10 )
       if( k <= 0 || k > 12 ) // <% ' неверный месяц %>
           return null;
       else
           ar[1] = ("" + (k-1).toString(10))

           k = parseInt( ar[0], 10 )
       if( k <= 0 || k > 31 ) // <% ' неверное число месяца %>
           return null;

       try
       {
               new_Date = new Date( ar[2], ar[1], ar[0] )
       }
       catch( e )
       {
           new_Date = null;
           return new_Date; // <% ' ошибка в дате, не смотря на все проверки %>
       }

       return new_Date;
} // end pgm  jsTestDate

/**
 <%'получение текста выделения, работает и в Ms IE и в FireFox%>
*/
function getSelectionText()
{
    if (!isIe()) return document.getSelection()
    var oSel = document.selection
    var oRng = oSel.createRange()
    return oRng.text
}

function createActiveX(psAppName, psClsId, nLang)
{
	var obj = null
    try {
        obj = isIe() ? new ActiveXObject(psClsId) : new GeckoActiveXObject(psClsId)
    } catch(E)
    {
	    obj = null
    }
    if( obj == null )
    try {
        obj = isIe() ? new ActiveXObject(psAppName) : new GeckoActiveXObject(psAppName)
    } catch(E)
    {
	    obj = null
    }

    if( obj == null )
    {
	    var s = "Error: not create ActiveXObject";
		if (nLang == 1)
			s = "Невозможно загрузить компонент";
		s = s + " '"+psClsId+"', '"+psAppName+"'"
	    alert( s )
    }

    return obj;
} // end pgm

function elem(psId)
{
    return document.getElementById(psId)
}

function alr(psMsg)
{
    alert(psMsg)
}


//======================================================
//
//======================================================
/*
var cnt = 0
function getStyle_(el, styleProp)
{
    var x
    if (typeof(el) == "string")
    {
        x = document.getElementById(el);
    } else {
        x = el
    }
    if (cnt == 0)
    {
        alert("window.getComputedStyle: " + document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp))
    } else {
        cnt ++
    }
    if (x.currentStyle)
        var y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
    return y;
}
*/
function getStyle(elem, prop)
{
  if (typeof elem!="object") elem = document.getElementById(elem);

  // external stylesheet for Mozilla, Opera 7+ and Safari 1.3+
  if (document.defaultView && document.defaultView.getComputedStyle)
  {
    if (prop.match(/[A-Z]/)) prop = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
    return document.defaultView.getComputedStyle(elem, "").getPropertyValue(prop);
  }

  // external stylesheet for Explorer and Opera 9
  if (elem.currentStyle)
  {
    var i;
    while ((i=prop.indexOf("-"))!=-1) prop = prop.substr(0, i) + prop.substr(i+1,1).toUpperCase() + prop.substr(i+2);
    return elem.currentStyle[prop];
  }
  return "";
}
//--------------------------------------------------------------


// уведомитель о событиях
function cEventNotifier() {

    /**
     слушатели события
    */
    var m_aListeners = {}
    var m_aQueue = [] // возникшие события

    // подписаться на событие
    this.subscribe = function(psEventName, pfCallback)
    {
        if (typeof(m_aListeners[psEventName]) == "undefined")
        {
            m_aListeners[psEventName] = [pfCallback]
        } else {
            m_aListeners[psEventName].push(pfCallback)
        }
    }

    // если в асинхронном режиме - поставить в очередь, иначе - выполнить
    this.notify = function(psName, poObj, pbAsync)
    {
        if (pbAsync)
        {
            m_aQueue.push({"name": psName, "event": poObj})
        }
        else
            this.doNotify(psName, poObj)
    }

    // уведомить подписчиков о возникновении события
    this.processQueue = function()
    {
        if (m_aQueue.length == 0) return
        var oEvent
        for (var i = 0; i < m_aQueue.length; i++)
        {
            oEvent = m_aQueue[i]
            this.doNotify(oEvent["name"], oEvent["event"])
        }
        m_aQueue = []
    }


    // уведомить подписчиков о возникновении события
    this.doNotify = function(psName, poObj)
    {
        var aListeners = m_aListeners[psName]
        if (!aListeners) return
        for (var i = 0; i < aListeners.length; i ++)
        {
            aListeners[i](poObj)
        }
    }


    this.get = function()
    {
        return this.instance
    }
}

cEventNotifier.instance = new cEventNotifier()
var g_oNotifier = cEventNotifier.instance
//--------------------------------------------------------------

window.setInterval("g_oNotifier.processQueue()", 100)


/**
 проверить, есть ли в заданном экземпляре Object
 нужное поле
*/
function hasKey(poObj, psKey)
{
    if (!(poObj instanceof Object)) return false
    for (var sKey in poObj)
    {
        if (sKey == psKey) return true
    }
    return false
}

/**
 преобразовать массив в аналогичный по размеру,
 в котором ко всем элементам изначального массива
 применена заданная функция (или взято заданное свойство)
*/
function mapArray(psProp)
{
    var args = arguments
    if (args.length < 2) return null
    var aRes = []
    // второй аргумент должен быть массив. Если нет - возвращаем то что дали
    if (!(args[1] instanceof Array)) return args[1]
    if (typeof(psProp) == "string")
    {
        for (var i = 0; i < args[1].length; i ++){
            var aItem = []
            for (var j = 1; j < args.length; j ++) aItem.push(args[j][i][psProp])
            aRes.push(aItem.length == 1 ? aItem[0] : aItem)
        }
        return aRes
    }
    if (typeof(psProp) == "function")
    {
        for (var i = 0; i < args[1].length; i ++) {
            var aItem = []
            for (var j = 1; j < args.length; j ++) aItem.push(psProp(args[j][i]))
            aRes.push(aItem.length == 1 ? aItem[0] : aItem)
        }
        return aRes
    }
    return aRes
}

/*
 проверить, существует ли указанная функция
*/
function funcExists(poFuncName)
{
    if (typeof(poFuncName) == "function") return true
    if (typeof(poFuncName) == "string") return eval("typeof(" + poFuncName + ")=='function'")
    return false
}

// Сохранение параметров в режиме HTTP
function js_SaveParmWithHTTP( sParm, sFunc )
{
    var sHttpRegim = "GET"
    var xHttpSend  = null
    var sFirstParm = "?save_func=" + sFunc
    if( arguments.length > 2 )
    {
            sHttpRegim = "POST"
            xHttpSend  = arguments[2] // XML obj
    } // end if  arguments.length > 2
    var save_cursor = document.body.style.cursor
                      document.body.style.cursor="wait"
    var xmlhttp = createXmlHttp() // ??. common.js
    //throw(1)
    if( xmlhttp != null )
    {
	    var sRun = "opts_save.asp" + sFirstParm + sParm
        //my_alert( "Otl : sRun=["+sRun+"]" )
        xmlhttp.open( sHttpRegim, sRun, false ) // синхронный режм иначе true)
        xmlhttp.onreadystatechange = function ()
        {
                if (xmlhttp.readyState == 4) { js_SaveParmWithHTTP_End(); xmlhttp = null;}
        }
        xmlhttp.send(xHttpSend)
    }
        document.body.style.cursor=save_cursor
} // end pgm  js_SaveParmWithHTTP

/**
 сохранение переменных сессии.
 Принимает либо три параметра - имя переменной, тип (string || number)
 и значение. Или один параметр - массив структур формата
 {"name": name, "type": type, "value": value}
*/
function saveCurrObjects()
{
    if (arguments.length == 3)
    {
        var aParams = [{"name": arguments[0], "type": arguments[1], "value": arguments[2]}]
        var oXml = makeXmlForSaveCurrObjects(aParams)
        postRequest("saveCurrObjValue.asp", oXml.getNode(), false)
    }
    if (arguments.length == 1)
    {
        var oXml = makeXmlForSaveCurrObjects(arguments[0])
        postRequest("saveCurrObjValue.asp", oXml.getNode(), false)
    }
}

/**
 формирование xml для сохранения переменных currObjects через
 объект xmlhttp
*/
function makeXmlForSaveCurrObjects(paParams)
{
    var loXML = new xmlDoc(null, "<?xml version=\"1.0\" encoding=\"windows-1251\"?><SaveValues/>")
    for (var i = 0; i < paParams.length; ++i)
    {
        var loActionElem = loXML.getNode().createElement("Item");
        loActionElem.setAttribute("type", paParams[i]["type"]);
        loActionElem.setAttribute("name", paParams[i]["name"]);
        loActionElem.setAttribute("value", paParams[i]["value"]);
        loXML.getNode().documentElement.appendChild(loActionElem);
    }
    return loXML;
}

function js_SaveParmWithHTTP_End()
{
} // end pgm


function getByNameOrId(psId)
{
    var oElem = elem(psId)
    if (oElem) return oElem
    var aElems = document.getElementsByName(psId)
    if (aElems && aElems.length > 0) return aElems[0]
    return undefined
} // end pgm

function jsShowWndHTML( sId )
{
    //alert( "jsShowWndHTML '"+ sId +"'" )

    var sIdx = sId

    var elm = document.getElementById( sIdx )
    if( elm == null ) { alert( "Not Find sIdx = [" + sIdx + "]" ); return; }

    var html = "-?-"

    if( typeof elm.outerHTML == "string" )
     html = elm.outerHTML;
    else
    if( typeof elm.innerHTML == "string" )
     html = elm.innerHTML;

    //alert( "["+html+"]" );

    var frm = jsNameFromAll( "SaveShowWndHTML_form" ) // document.all
    if( frm == null )
    {
	    my_alert( "Not Find form = [SaveShowWndHTML_form]\n"
	              + "[" + html + "]" );
	    return;
	} // end if

	if( arguments.length > 1 )
	{
		frm[ "formReplace" ].value = arguments[1]
	}

    frm[ "formShow" ].value = html
    frm.submit();

} // end pgm  jsShowWndHTML

/**
 получить значение GET параметра по имени
*/
function GETParam(psParam)
{
	var sCurrHref = window.location.href;
    var aTmp = sCurrHref.split("?");
    var sQueryString = aTmp[1];
    aTmp = sQueryString.split("&");
    var oParams = {};
    for (var i in aTmp)
    {
		var aKeyAndValue = aTmp[i].split("=");
		oParams[aKeyAndValue[0]] = aKeyAndValue[1];
    }
    return oParams[psParam];
}


