///======================================================================================================
/// Global constants (it MUST correspond with server side constants!) 
///======================================================================================================

// Constant sw_ArrayItemsDelimiter MUST correspond with server-side constant SWsoft.Ajax.AjaxCore.AjaxConverter.ArrayItemsDelimiter!!!
var sw_ArrayItemsDelimiter = ',\t';

// Constant sw_ArrayItemsDelimiter MUST correspond with server-side constant SWsoft.Ajax.AjaxCore.SWsoft.Ajax.AjaxCore.LOCAL_ID_ATTRIBUTE_NAME!!!
var LOCAL_ID_ATTRIBUTE_NAME = "LID";

// Global W3C DOM constants 
ELEMENT_NODE                   = 1;
ATTRIBUTE_NODE                 = 2;
TEXT_NODE                      = 3;
CDATA_SECTION_NODE             = 4;
ENTITY_REFERENCE_NODE          = 5;
ENTITY_NODE                    = 6;
PROCESSING_INSTRUCTION_NODE    = 7;
COMMENT_NODE                   = 8;
DOCUMENT_NODE                  = 9;
DOCUMENT_TYPE_NODE             = 10;
DOCUMENT_FRAGMENT_NODE         = 11;
NOTATION_NODE                  = 12;

///======================================================================================
/// Attention!!!
/// Functions below MUST correspond with SWsoft.Ajax.AjaxCore.JsLib class on server side!
///======================================================================================


//===================================================
//  Common functions ---
//===================================================

function sw_GetElement(id, d){
    if (id){
      if (!d) d = document;
      if (d.getElementById){
        return d.getElementById(id);
      } else if (d.all){
        return d.all[id];
      } else if (d.layers){
          return d.layers[id];   
      }
    }
    return false;
}

function sw_GetInnerHtml(el){
    if(el.rows){
        return el.rows[0].cells[0].innerHTML;
    }else{
        return el.innerHTML; 
    }
}
function sw_SetInnerHtml(el, html){
    if(el.rows){
        el.rows[0].cells[0].innerHTML = html;
    }else{
        el.innerHTML = html; 
    }
}

function sw_SetInnerText(el, str){
    if(!str)
        str = '';
    if(!el)
        return;
    if(el.innerText!=null){// IE
        el.innerText = str;
    }else{// Mozilla
        el.innerHTML='';
        var textNode = el.ownerDocument.createTextNode(str);
        el.appendChild(textNode);
    }
}

function sw_GetInnerText(el){
    if(!el)
        return '';
    if(el.innerText!=null){// IE
        return el.innerText;
    }else{// Mozilla
        return sw_GetInnerTextMZ(el);
    }
}

// For non IE browsers
function sw_GetInnerTextMZ(el){
    if(!el)
        return '';
    
    if(el.nodeType == ELEMENT_NODE){
        if(el.hasChildNodes()){
            var ret = '';
            var nodes = el.childNodes;
            for(var i=0; i<nodes.length; i++){
                ret += sw_GetInnerTextMZ(nodes[i]);
            }            
            return ret;
        }else{
            return '';
        }
    }
    
    if(el.nodeType == TEXT_NODE){
        return el.nodeValue;
    }
    
    return '';
}

// Parameter "t" is a name of target of navigating
function sw_Navigate(href, t, frameHolder){
    if(t && t!=''){ 
        return window.open(href, t);
    }else{
        return window.location = href;
    }
}

function sw_UpdateFrame(fName, urlParams)
{
    var oldUrl = new String(sw_GetFrameURL(fName));
    var baseUrl = sw_GetBaseUrlPart(oldUrl);
    var newUrl = baseUrl + '?' + urlParams;
    if(newUrl!=oldUrl)
        sw_Navigate(newUrl, fName);
}

function sw_ShowError(mess){
    alert(mess);
}

function sw_Display(id, arg){
    var el = sw_GetElement(id);
    if(!el || !el.style)
        return;
    if(el.style.display != arg)
        el.style.display = arg;
}

function sw_IsVisible(id){
    var el = sw_GetElement(id);
    return sw_IsElementVisible(el);
}

function sw_IsElementVisible(el){
    if(!el || !el.style){
        return false;
    }else{
        return (el.style.display != 'none' && el.style.visibility != "hidden");
    }
}

function sw_FormatStr(format){
    if(format==null)
        return '';
    var result = format;
    var re = null;
    for (var i=0; i <= arguments.length; i++){
      re = new RegExp("\\{"+i+"\\}","g");
      result = result.replace( re, arguments[i+1] );
    }
    return result;
}


//===================================================
// Browser type detection ---
//===================================================

function sw_BrowserIsIE(){
    if(document.all && window.ActiveXObject){
        return true;
    }else{
        return false;
    }
}

function sw_CheckIsNetscape(){
    if (window.XMLHttpRequest){
        var xhttp = new XMLHttpRequest();
        if( typeof(xhttp.onreadystatechange) == 'undefined' )
            return true;
    }    
    return false;
}
var _sw_IsNetscape = sw_CheckIsNetscape();
function sw_IsNetscape(){ return _sw_IsNetscape; }

var _sw_IsIE = sw_BrowserIsIE();
function sw_IsIE(){ return _sw_IsIE; }

//===================================================
// XmlHttpRequest utils ---
//===================================================

function sw_CreateXmlHttpRequest(){
    var xhttp;    
    if (window.XMLHttpRequest){
        xhttp = new XMLHttpRequest()
    }else if (window.ActiveXObject){
        xhttp = new ActiveXObject("Microsoft.XMLHTTP"); // xhttp = new ActiveXObject("Msxml2.XMLHTTP"); 
    }else{ 
        sw_ShowError("XMLHttpRequest is NOT SUPPORTED by current browser!");
        return null;
    }    
    return xhttp;
}

function sw_DoAsyncRequest(xhttp, callbackRef, query, serviceUrl, method, async, enforceNoCache){
    // Prepare params --
    if(!method) method = "GET";
    if(!serviceUrl) serviceUrl = "AjaxHttpHandler.aspx";
    if(async==null) async = true; //async=true; 
    if(!async) async = false;

    ///// DEBUG CODE: Capacity test for Opera
    //var longParam = '';
    //for(var i=0; i<1400; i++) longParam+='0000000000';
    //for(var i=0; i<100; i++) longParam+='1111111111';
    //query += "&longParam="+longParam;
    //alert('longParam ready. length = '+longParam.length);
    //// Max param length under Opera is ~15KB
    
    var requestStr = serviceUrl +"?";
    var antiCache = (""+Math.random()).replace('.','');
    if(query){
        requestStr += query + '&';
        sw_Debug("Ajax request start.\n\nQuery:\n\n " + query + "\n\n(This message generated by function sw_DoAsyncRequest in file PleskClientUtils.js)");
    }
    
    if(enforceNoCache)
        requestStr += antiCache; 
        
    if(requestStr.length>2000) 
        method = 'POST';
        
    // Do request ---    
    if(callbackRef!=null){
        xhttp.onreadystatechange = callbackRef; // Hook the event handler
    }
    // Prepare the call, http method=GET, true=asynchronous call. Netscape does not works with "false" - synchronous mode
    if( sw_IsNetscape() ){
        /// Under Netscape we use only synchronous GET request
        /// DOESN'T work under Netscape + HTTPS!!!
        //netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); // - it cannot help us.
        //requestStr = 'https://localhost:8443'+requestStr; // - it cannot help us. 
        
        xhttp.open('GET', requestStr, false); // Works well in all browsers
        xhttp.send(null); //We MUST use null parameter! Otherwise it does not works in Mozilla!
        if(callbackRef) callbackRef();
    }else{
        // Modern browsers
        if(method=="POST"){
            if(typeof(xhttp.setRequestHeader)!='undefined'){
                // IE, FireFox, Mozilla
                xhttp.open('POST', serviceUrl, async);
                xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;');
                xhttp.send(query);
            }else{
                // Opera less than 8.1
                xhttp.open('POST', requestStr, async);
                xhttp.send('');
            }
        }else{
            xhttp.open('GET', requestStr, async); // Works well in all browsers
            xhttp.send(null); //We MUST use null parameter! Otherwise it does not works in Mozilla!
        }
    }
}

function sw_IsAsyncRequestDone(xmlhttp){
    if(sw_IsNetscape())
        if (xmlhttp.status==200)
            return true;
    if (xmlhttp.readyState==4){
      //if (xmlhttp.status==200){
        return true;
      //}
    }
    return false;
}


//===================================================
// DOM utils ---
//===================================================
function sw_CloneNodeWithEvent(el, eventName){
    return sw_CloneNode(el);
}
function sw_CloneNode(el){
    if( sw_IsNetscape()){
        return sw_CloneNodeNetscape(el);
    }else{
        return sw_CloneNodeIE(el);
    }
}

function sw_CloneNodeNetscape(el){
    var clon = el.cloneNode(true);
    sw_PostCloneUpdate(clon, el);
    return clon;    
}

function sw_CloneNodeIE(el){
    //return el.cloneNode(true);    
    var clon = el.cloneNode(true);
    sw_PostCloneUpdate(clon, el);
    return clon;
}
function sw_PostCloneUpdate(clon, el){
    // Under IE6 cloned element have some problems!
    // - It loose event handlers (not always)!
    // - It loose INPUT-CHECKBOX checked state!
    // - It loose SELECT selection state!
    // This function fix this problems!
    if(el.nodeType != ELEMENT_NODE){
        return;
    }
    // Restore event handlers
    clon["onclick"] = el["onclick"];
    clon["onchange"] = el["onchange"];
    //clon["onmouseover"] = el["onmouseover"];
    //clon["onmouseout"] = el["onmouseout"];
    
    var nodeNameUC = el.nodeName.toUpperCase();
    if(nodeNameUC =='INPUT'){
        // INPUT element processing
        clon.defaultChecked = el.checked;
        clon.checked = el.checked;
    }else if(nodeNameUC =='SELECT'){
        // SELECT element processing (Keep old selection!)
        sw_SetSelectedValue(clon, sw_GetSelectedValue(el) );
    }
    var originalNodes = el.childNodes;
    var clonedNodes = clon.childNodes;
    if( originalNodes.length == clonedNodes.length ){
        var len = originalNodes.length;
        for(var i=0; i<len; i++){
            sw_PostCloneUpdate(clonedNodes[i], originalNodes[i]);
        }
    }        
}

// Remove "id" of child nodes of specified elements.
function sw_ClearChildIds(el){
    if(!el) 
        return;
    if(el.nodeType!=ELEMENT_NODE)
        return;
    if(el.id){
        el._OldId = el.id;
        el.id = null;
    }
    var nodes = el.childNodes;
    var len = nodes.length;
    for(var i=0; i<len; i++){
        sw_ClearChildIds(nodes[i]);
    }
}

function sw_RestoreChildIds(el){
    if(!el) 
        return;
    if(el.nodeType!=ELEMENT_NODE)
        return;
    if(el._OldId){
        el.id = el._OldId;
    }
    var nodes = el.childNodes;
    var len = nodes.length;
    for(var i=0; i<len; i++){
        sw_RestoreChildIds(nodes[i]);
    }
}

function sw_GetText(xmlNode, childTagName){
    var chNode = sw_Xml_GetChildNode(xmlNode, childTagName);
    if(chNode){
        var ret = '';
        var len = chNode.childNodes.length;
        for(var i=0; i<len; i++){
            ret += chNode.childNodes[i].nodeValue; // Get value of text node
        }
        return ret;
    }else{//node not found
      return null;
    }  
}

function sw_Xml_GetChildNode(xmlNode, childTagName){
    if(!xmlNode) return null;
    if(!childTagName) return null;
    var nset = xmlNode.getElementsByTagName(childTagName);
    if(nset){
        if(nset.length==1){ 
            return nset[0];
        }else if(nset.length>1){
            sw_Debug('Error in sw_Xml_GetChildNode. Multiple nodes with name "' + childTagName + '" was found (nset.length='+nset.length+').');
        }
    }
    return null;
}

// Find and return node by specified attribute value.
function sw_DOM_GetNodeByAttrValue(el, aName, aVal){
    if(!el || !aName || !aVal)
        return null;
    if(el.getAttribute)    
        if(el.getAttribute(aName)==aVal)
            return el;
    if(el.hasChildNodes)
        if(!el.hasChildNodes())
            return null;
    var node = null;
    for(var i=0; i<el.childNodes.length; i++ ){
        node = sw_DOM_GetNodeByAttrValue(el.childNodes[i], aName, aVal)
        if(node){ 
            //alert('found');
            return node;        
        }
    }
    return null;
}


// Operations with "LocalID" (begin) ---

// Find and return node by specified "local id".
// Use custom created index.
function sw_FindByLocalId(container, localId){
    sw_EnsureLocalIdsIndexed(container);
    return container._Index[localId];    // if not found then we return null
}

function sw_EnsureLocalIdsIndexed(container){
    if(container._Index == null){
        container._Index = new Object();
        sw_BuildLocalIdsIndex(container._Index, container, LOCAL_ID_ATTRIBUTE_NAME);
    }
}

function sw_BuildLocalIdsIndex(indexerObj, el, attrName){
    if(!indexerObj || !el)
        return null;
    if(el.getAttribute){
        var aVal = el.getAttribute(attrName);
        if(aVal!=null && aVal!=''){
            indexerObj[aVal] = el;                
        }
    }       
    if(el.hasChildNodes){
        if(el.hasChildNodes()){
            var len = el.childNodes.length;
            for(var i=0; i<len; i++ ){
                sw_BuildLocalIdsIndex(indexerObj, el.childNodes[i], attrName);
            }
        }
    }
    return;
}

function sw_ResetLocalIdsIndex(container, attrName){
    if(container._Index){
        container._Index = null;
    }    
}
// Operations with "LocalID" (end) ---

// Disable/Enable element and its descendants
function sw_SetDisable(el, val){
    if(!el) return;
    if(el.nodeType!=ELEMENT_NODE) 
        return;
    el.disabled = val;    
    if(el.hasChildNodes)
        if(!el.hasChildNodes())
            return null;
    for(var i=0; i<el.childNodes.length; i++ ){
        sw_SetDisable(el.childNodes[i], val)
    }
}    

// Disable/Enable element and its descendants
function sw_SetDisableById(id, val){
    sw_SetDisable(sw_GetElement(id), val)
}    

function sw_SetFocus(id){
    var obj = sw_GetElement(id);
	if (obj){
	    try{
		    obj.focus();
		}catch(ex){}
	}
}

function sw_SetSelect(id){
    var obj = sw_GetElement(id);
	if (obj)
		obj.select();
}


//===================================================
// DropDownList operations ---
//===================================================

function sw_AddOpt(id, val, text){
    var sel = sw_GetElement(id);
    if(!sel){ alert("SELECT element with id= '"+id+"' not fount"); return;}
    var pos = sel.options.length;
    var opt = document.createElement('OPTION');
    sel.options[pos] = opt;
    opt.text = text;
    opt.value = val;
}

function sw_ClrOpts(id){
    var sel = sw_GetElement(id);
    if(!sel){ alert("SELECT element with id= '"+id+"' not fount"); return;}
    for(; 0 < sel.options.length ;){ sel.options[0] = null; }
}

function sw_SetSelectedValue(obj, val){
    for(var i=0; i<obj.options.length; i++){
        if(obj.options[i].value==val){
            obj.selectedIndex = i; // for Netscape
            obj.options[i].selected = true;
        }else{
            obj.options[i].selected = false;
        }
    }
}

function sw_GetSelectedValue(obj){
    var i = obj.selectedIndex;
    if(i!=-1)
        return obj.options[i].value;
    else
        return null;
}

function sw_SetSelectsVisibility(visibile, selectsContainer){
    if(!selectsContainer) 
        selectsContainer = window.document;
    var select_arr = selectsContainer.getElementsByTagName("select");
    if(!select_arr) 
        return;        
    var visStr = (visibile!=false) ? "visible" : "hidden";    
    for (var i = 0; i < select_arr.length; i++){ 
        if(!select_arr[i].initialVisibility){
            select_arr[i].initialVisibility = select_arr[i].style.visibility;
        }
        if(select_arr[i].initialVisibility=="hidden") 
            continue;
        select_arr[i].style.visibility = visStr;
    }
}

function sw_SetOpacity(el, val){
    if(isNaN(val) || !el)
        return false;
   
    if(el.nodeName.toLowerCase()=="tr" && typeof(el.cells)!= 'undefined'){
        for(var i=0; i<el.cells.length ;i++){
            sw_SetOpacity(el.cells[i], val);
        }
    }else{
        val = new Number(val);
        var opacity = (val/100);
        if(typeof(el.runtimeStyle)!= 'undefined' && typeof(el.runtimeStyle.filter) != 'undefined'){
            // IE
            // (anti-bug)
            var needFix = ( 
                el.nodeName.toLowerCase()!="img" 
                && el.style.height=='' 
                && el.style.width==''
                );
            
            if(needFix){
                el.style.height = '0%';
            }
            
	        el.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + val + ")";
	        
            if(needFix){
                el.style.height = '';
            }
        }else if(typeof(el.style.filter)!= 'undefined' && typeof(el.style.filter.alpha) != 'undefined'){
            // Opera. (Some new version > 9.0?)
            el.style.filter.alpha.opacity = val;
        }else{
            // Mozilla && Safari
            if( typeof(el.style.MozOpacity) != 'undefined' ){
                el.style.MozOpacity = (val/100);
            }
            if( typeof(el.style.opacity) != 'undefined' ){
                el.style.opacity = (val/100);
            }
        }
        return true;
    }
}


//===================================================
// Converters and serializers utils ---
//===================================================

Array.prototype.toString = function(){
    var res = '';
    for(var i=0; i<this.length; i++){
        if(i!=0)
            res += sw_ArrayItemsDelimiter;
        res += this[i];
    }    
    return res;
}

Array.prototype.fromString = function(val){
    if(val instanceof Array)
    {
        for(var i=0; i<val.length; i++){
            this[i] = val[i];
        }
        this.length = val.length;
    }else{
        this.length = 0;
        var str = val.toString();
        var val = str.split(sw_ArrayItemsDelimiter);
        for(var i=0; i<val.length; i++){
            this[i] = val[i];
        }
        this.length = val.length;
    }
}

function sw_Serialize(val, delimiter){    
    //if(delimiter==null) delimiter = sw_ArrayItemsDelimiter;
    if(val==null)
        return null;
    if(val instanceof Array){
        return val.toString();
//        var str = '';
//        var arr = new Array();
//        for(var i=0; i<val.length; i++){
//            arr[i] = val[i];
//        }
//        return arr.join(delimiter);
    }else{
        return val;
    }
}

function sw_Deserialize(val, delimiter){
    if(delimiter==null) delimiter = sw_ArrayItemsDelimiter;
    var str = val.toString();
    var val = str.split(delimiter);
    if(val.indexOf(delimiter)!=-1){
        var arr = new Array();  
        arr.fromString(str);  
//        for(var i=0; i<val.length; i++){
//            arr[i] = val[i];
//        }    
        return arr;
    }else{
        return val;
    }
}



//===================================================
// Types utilities (converters, etc.) ---
//===================================================

function sw_NotNullAndNotEmpty(val){
    return (
            val 
            || 
            (
                val != null 
                && 
                typeof(val).toLowerCase()=='array' 
                && 
                (val).length > 0 
            ) 
           );
}

function sw_ToBool(val){
    // This function MUST corrspond with server-side methods from SWsoft.Ajax.AjaxCore namespace:
    //  - JsLib.ToBool(...)
    //  - JsBool.Equal(...)    
    //  - ScriptBuilder.ToJsBool(...)
    // Also we can take into account following methods:
    //  - AjaxConverter.ParseBool(...)
    //  - JsBool.IsTrueConstant(...)    
    //  - JsBool.IsFalseConstant(...)    
    return (val===true || val=='true' || val=='True' || val=='TRUE' || val=='1' ? true : false);
}

function sw_ToNumber(val){
    if(typeof(val)=='number')
        return val;
    if(val!=null){
        var vs = val.toString();
        vs = vs.replace(',', '.');
        var num = new Number(vs); 
        return num;
    }
    return null;
}

function sw_ToArray(val, delimiter){
    if(val instanceof Array)
        return val;
    var arr = new Array();    
    return arr.fromString(val);
}

function sw_ArrayContainsValue(arr, val){
    if(arr){
        for(var i=0; i<arr.length; i++)
            if(arr[i]==val)
                return true;
    }
    return false;
}

function sw_ArraysUnion(arr1, arr2){
    if(arr1==null && arr2==null)
        return new Array();
    if(arr1==null)
        return arr2;
    if(arr2==null)
        return arr1;
    for(var i=0; i<arr2.length; i++){
        if(!sw_ArrayContainsValue(arr1, arr2[i]))
            arr1[arr1.length] = arr2[i];
    }
    return arr1;
}

function sw_ArrayRemoveRange(mainArr, toRemove){
    var ret = new Array();
    for(var i=0; i<mainArr.length; i++){
        if(!sw_ArrayContainsValue(toRemove, mainArr[i]))
            ret[ret.length] = mainArr[i];
    }
    return ret;
}

function sw_ArrayIntersection(arr1, arr2){
    var ret = new Array();
    if(arr1==null || arr2==null)
        return ret;
    for(var i=0; i<arr1.length; i++){
        if(sw_ArrayContainsValue(arr2, arr1[i]))
            ret[ret.length] = arr1[i];
    }
    return ret;
}

/// Return array[index]. 
/// - If array is not object of Array type then empty string returns.
/// - If array.length is lesser or equal of zero then empty string returns.
/// - If array.length is lesser or equal of index then last array item returns.
function sw_TryGetArrayItem(array, index){
    if(
        array!=null 
        && array instanceof Array 
        && array.length > 0
      )
    {
        var ind = 0;
        if(!isNaN(index)){
            ind = new Number(index);
        }else if(typeof(index) == 'boolean'){
            ind = index ? 1 : 0;
        }else{
            ind = sw_ToBool(index) ? 1 : 0;
        }
        
        if(ind < 0)
            ind = 0;
        else if(ind >= array.length)
            ind = (array.length-1);
            
        return array[ind];
    }
    return '';
}

//===================================================
// Cookies utils ---
//===================================================

function sw_GetCookie(sName)
{
    var aCookie = document.cookie.split("; ");
    for (var i=0; i < aCookie.length; i++)
    {
    var aCrumb = aCookie[i].split("=");
    if (sName == aCrumb[0]) 
      return sw_UnEscapeCookie(aCrumb[1]);
    }
    return null;
}
function sw_SetCookie(sName, sValue, expMs)
{
    if(isNaN(expMs)) expMs = 24*3600000;
    var d = new Date( expMs + new Date().valueOf() );
    document.cookie = sName + "=" + sw_EscapeCookie(sValue) + "; expires=" + d.toUTCString() + ";";
}
function sw_DelCookie(sName)
{
    sw_SetCookie(sName, '', -1000000)
}

function sw_EscapeCookie(val){
    return sw_UrlEncode(val);
}
function sw_UnEscapeCookie(val){
    return sw_UrlDecode(val);
}


//===========================================================================================================
// MS Validators Utils. Functions is based on knowlege WebUIValidation.js (System.Web assembly resource file)
//===========================================================================================================

function sw_ValidateForm() {
    if (typeof(Page_ClientValidate) == "function" && Page_ClientValidate() == false) return false;
    return true;
}
function sw_ValidateGroup(validationGroup){
    if (typeof(Page_ClientValidate) == "function" && Page_ClientValidate(validationGroup) == false) return false;
    return true;
}

function sw_ValidateCtl(el){
    if(!el || typeof(ValidatorValidate)=='undefined' || typeof(ValidatorUpdateIsValid)=='undefined'){
        return true;
    }
    var vals = el.Validators;
    if(vals){
        try{
            for (i = 0; i < vals.length; i++) {
                ValidatorValidate(vals[i], null, null);
            }
            ValidatorUpdateIsValid();
        }catch(ex){}
    }
    return true;
}
function sw_ValidateCtlById(id){
    if(!id) 
        return false;
    var el = sw_GetElement(id);
    if(el){
        return sw_ValidateCtl(el);
    }else{
        return false;
    }
}

function sw_ResetValidators(validationGroup) {
    /// Anty Page_ClientValidate function
    Page_InvalidControlToBeFocused = null;
    if (typeof(Page_Validators) == "undefined") {
        return true;
    }
    var i;
    for (i = 0; i < Page_Validators.length; i++) {
        sw_ResetValidator(Page_Validators[i], validationGroup)
    }
    Page_IsValid = true;
    return Page_IsValid;
}

function sw_ResetValidator(val, validationGroup){
    /// val - validator control
    /// Anty ValidatorValidate function
    if(!val || typeof(ValidatorUpdateDisplay)=='undefined')
        return true;
    if (IsValidationGroupMatch(val, validationGroup)) {
        //var oldIsValid = val.isvalid;
        val.isvalid = true;
        ValidatorUpdateDisplay(val);
        //val.isvalid = oldIsValid;
    }        
//    var oldIsValid = val.isvalid;
//    val.isvalid = true;
//    ValidatorUpdateDisplay(val);
//    //val.isvalid = oldIsValid;
}

function sw_ResetValidatorsOfCtl(ctl){
    // ctl - control to validate
    if(!ctl)
        return;
        
    var vals = ctl.Validators;
    if(vals){
        try{
            for (i = 0; i < vals.length; i++) {
                sw_ResetValidator(vals[i]);
            }
        }catch(ex){}
    }
}
function sw_ResetValidatorsOfCtlById(id){
    sw_ResetValidatorsOfCtl(sw_GetElement(id));
}


//===================================================
// URL building ---
//===================================================

function sw_GetUrlParam(url, name){
    if(!name || !url) 
        return null;
    else
        return sw_GetPar(sw_ExtractQuery(url), name);
}        

function sw_SetUrlParam(url, name, value){
    // Return modified URL
    var baseUrl = sw_ExtractBaseUrl(url);
    var query = sw_SetPar( sw_ExtractQuery(url), name, value);
    var hash = sw_ExtractHash(url);
    return sw_CombineUrlParts(baseUrl, query, hash);
}

function sw_GetHashParam(url, name){
    if(!name || !url)
        return null;
    else
        return sw_GetPar(sw_ExtractHash(url), name);
}        

function sw_SetHashParam(url, name, value){
    // Return modified URL
    var baseUrl = sw_ExtractBaseUrl(url);
    var query = sw_ExtractQuery(url);
    var hash = sw_SetPar( sw_ExtractHash(url), name, value);
    return sw_CombineUrlParts(baseUrl, query, hash);
}

function sw_SetWholeHash(url){
    // Return modified URL
    var baseUrl = sw_ExtractBaseUrl(url);
    var query = sw_ExtractQuery(url);
    var hash = '';
    return sw_CombineUrlParts(baseUrl, query, hash);
}

function sw_CombineUrlParts(baseUrl, query, hash){
    var ret = (baseUrl ? baseUrl : '');
    if(query)
        ret+= '?'+query;
    if(hash)
        ret+= '#'+hash;
    return ret;
}

/// Return parameter value from query string like "Param1=Value1&Param2=Value2"
function sw_GetPar(query, name){
    if(!query || !name) 
        return null;
    query = '&'+query;        
    var ind = query.indexOf('&'+name+'=');
    if(ind==-1) 
        return null;
    var ind1 = ind + name.length + 2;
    var ind2 = query.indexOf('&' , ind +1);
    if(ind2==-1) 
        ind2 = query.length;
    return sw_UrlDecode(query.substring(ind1, ind2));
}  
      
/// Build new query string like "Param1=Value1&Param2=Value2" (with new parameter balue)
function sw_SetPar(query, name, value){
    // Return modified string
    if(query==null)    
        query = '';
    if(!name) 
        return query;
    var ret = '';
    query = '&'+query.toString();        
    var ind = query.indexOf('&'+name+'=');
    if(ind==-1){ 
        //Such parameter not exists yet
        if(value==null){
            ret = query;
        }else{
            ret = query + '&' + name + '=' + sw_UrlEncode(value);
        }
    }else{
        //Such parameter already exists
        var ind1 = ind + name.length + 2;
        var ind2 = query.indexOf('&' , ind +1);
        if(ind2==-1) 
            ind2 = query.length;
        if(value==null){ 
            // Remove whole parameter entry
            ret = query.substring(0, ind+1) + query.substr(ind2+1);
        }else{
            // Insert new value
            ret = query.substring(0, ind1) + sw_UrlEncode(value) + query.substr(ind2);
        }            
    }
    // Replace "&" from start and end!    
    return ret.replace(/(^&+)|(&+$)/g, '');
}        

function sw_ExtractBaseUrl(url){
    if(url==null) 
        return null;
    url = url.toString();
        
    // Remove part after '?'
    var qInd = url.indexOf('?');
    if(qInd!=-1){
        url = url.substring(0, qInd);
    }else{        
        // Remove part after '#'
        var hashInd = url.indexOf('#');
        if(hashInd!=-1){
            hash = url.substring(hashInd+1, url.length-1);
            url = url.substring(0, hashInd);
        }
    }    
    return url;
}

function sw_ExtractQuery(url){
    if(url==null) 
        return null;
    var query = url.toString();
    
    // Remove part after '#'
    var hashInd = query.indexOf('#');
    if(hashInd!=-1){
        hash = query.substring(hashInd+1, query.length-1);
        query = query.substring(0, hashInd);
    }
    
    // Remove part before '?'
    var qInd = query.indexOf('?');
    if(qInd!=-1){
        query = query.substring(qInd+1, query.length);
    }else{
        query = '';
    }
    return query;
}

function sw_ExtractHash(url){
    if(url==null) 
        return null;
    var hash = url.toString();
        
    // Remove part before '#'
    var ind = hash.indexOf('#');
    if(ind!=-1){
        hash = hash.substring(ind+1, hash.length);
    }else{
        hash = '';
    }
    return hash;
}

function sw_GetCurrentURL(t){
    return sw_GetFrameURL();
}

// Parameter "t" is a name of frame
function sw_GetFrameURL(t){
    if(t && t!=''){ 
        var w = sw_GetFrameWindow(t);
        if(w)
            return w.location;
    }else{
        return window.location;
    }
    return "";
}

function sw_GetBaseUrlPart(url){
    if(!url) return "";
    return url.replace(/\?.*/g, ''); 
}

// Serialize value as query parameter
function sw_QP(name, val){
    if(val instanceof Array)
        if(val.length==0)
            return '';    
    return (val==null ? '': '&'+name+'='+sw_UrlEncode( sw_Serialize(val) ));
}


//===================================================
// Escaping ---
//===================================================

sw_UrlEncode = function(value){ return encodeURIComponent(value); }
sw_UrlDecode = function(value){ return decodeURIComponent(value); }

sw_HtmlEncode = function(value){ return escape(value); }
sw_HtmlDecode = function(value){ return unescape(value); }

//Use it for building window.setTimeout(...) code
function sw_Esc4CodeGen(str){
    return (''+ str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\'/g, '\\\'');
}

//===================================================
// Widget: Draw image over HTML element  ---
//===================================================

function sw_ShowImageOverEl(el, imgUrl){
    sw_AddLoadingIndicator(el, imgUrl);
}
function sw_ShowImageOver(id, imgUrl){
    var el1 = document.getElementById(id);
    sw_ShowImageOverEl(el1, imgUrl);
}

function sw_HideImageOverEl(el){
    sw_RemoveLoadingIndicator(el);
}
function sw_HideImageOver(id){
    var el1 = document.getElementById(id);
    sw_HideImageOverEl(el1);
}

function sw_CreateLoadingIndicator(imgUrl){
    if(!imgUrl)
        return null;
    var img = document.createElement('img');
    img.src = imgUrl;
    img.style.borderWidth = '0px';
    img.style.position = 'absolute';
    img.style.display = '';
    img._IsLoadingIndicator = true;
    return img;
}

function sw_AddLoadingIndicator(target, imgUrl){
    //var holder = document.body;
    var holder = sw_GetChildrenOperatableElement(target);
    var img = sw_CreateLoadingIndicator(imgUrl);
    if(!holder || !img){
        return;
    }
    if(target._LoadingIndicator){
        sw_RemoveLoadingIndicator(target);
    }
    var x = sw_GetAbsoluteX(target);
    var y = sw_GetAbsoluteY(target);
    img.style.left = x;
    img.style.top = y;
    
    target._LoadingIndicator = img;
    holder.appendChild(img);
}

function sw_RemoveLoadingIndicator(target){
    //var holder = document.body;
    var holder = sw_GetChildrenOperatableElement(target);

    if(!target || !holder || !target._LoadingIndicator){
        return;
    }
    var img = target._LoadingIndicator;
    if(img.nodeType == ELEMENT_NODE
       && img.nodeName.toLowerCase() == 'img'
       && img._IsLoadingIndicator == true)
    {
        target._LoadingIndicator = null;
        if(img.parentNode)
            holder.removeChild(img);
    }
}

/// Return DOM element with well defined basic operations with children:
/// - appendChild(), 
/// - insertBefore()
/// - firstChild, 
/// - lastChild,
/// - childNodes, 
/// - innerHTML, 
/// - ... (etc.)
/// For some HTML-elements return null.
/// Those elements are <IMG>, <HR>, <BR>.
/// Elements <IMG>, <HR>, <BR> cannot have children therefore operations with children raise error!
function sw_GetChildrenOperatableElement(el){
    if(!el)
        return null;
    if(el.nodeType != ELEMENT_NODE)
        return null;
        
    var nodeName = el.nodeName.toLowerCase();
    
    // Exclude elements cannot have children
    if(
        nodeName == 'img' 
        || nodeName == 'hr' 
        || nodeName == 'br' 
       )
    {
        return null;
    }
    
    if(nodeName == 'table' && el.rows){ 
        if(el.rows.length>0 && el.rows[0].cells && el.rows[0].cells.length>0)
            return el.rows[0].cells[0];
        else
            return null;
    }else if(nodeName == 'tr' && el.cells){ 
        if(el.cells.length>0)
            return el.cells[0];
        else
            return null;
    }
    
    return el;
}


//function sw_CreateLoadingIndicator(imgUrl){
//    if(!imgUrl)
//        return null;
//    var img = document.createElement('img');
//    img.src = imgUrl;
//    img.style.borderWidth = '0px';
//    img.style.position = 'absolute';
//    img.style.display = '';
//    img._IsLoadingIndicator = true;
//    return img;
//}

//function sw_AddLoadingIndicator(target, imgUrl){
//    var holder = sw_GetChildrenOperatableElement(target);
//    if(!holder)
//        return;
//        
//    var img = sw_CreateLoadingIndicator(imgUrl);
//    if(!img)
//        return;
//    if(holder.firstChild!=null){
//        if(holder.firstChild._IsLoadingIndicator != true)
//            holder.insertBefore(img, holder.firstChild);
//    }else{
//        holder.appendChild(img);
//    }
//}

//function sw_RemoveLoadingIndicator(target){
//    if(!target)
//        return;        
//    var holder = sw_GetChildrenOperatableElement(target);
//    if(!holder)
//        return;
//    var img = holder.firstChild;
//    if(img.nodeType == ELEMENT_NODE
//       && img.nodeName.toLowerCase() == 'img'
//       && img._IsLoadingIndicator == true)
//    {
//        holder.removeChild(img);
//    }
//}

//===================================================
// Widget: Splash effect ---
//===================================================

function sw_Splash(el, duration, timespan){
    if(duration==null) 
        duration = 300;
    if(timespan==null) 
        timespan = 25;
    var dur = new Number(duration);
    var increment = Math.round(dur/timespan);
    
    if(el._opacTimeout) 
        window.clearTimeout(el._opacTimeout);
    sw_SetOpacity(el, 0);
    el._opac = 0;
    sw_IncreaseOpacityTo100(el, increment, timespan);
}

function sw_IncreaseOpacityTo100(el, increment, timespan){
    if(!el._opac)
        el._opac = 0;
    if(el._opac == 100){
        el._opacTimeout = null;
        return;
    }        
    el._opac += increment;
    if(el._opac > 100){
        el._opac = 100;
    }
    sw_SetOpacity(el, el._opac);
    el._opacTimeout = window.setTimeout(
        function(){ sw_IncreaseOpacityTo100(el, increment, timespan); },
        timespan
        );
}


//===================================================
// Delayed content rendering ---
//===================================================

var IMAGES_LOCK_ENABLED = true;

function sw_ImagesLock(container){
    var images = sw_GetImagesFrom(container);
    for (var i = 0; i < images.length; i++){ 
        sw_LockImg( images[i] );
    }
}
function sw_ImagesUnlock(container){
    var images = sw_GetImagesFrom(container);
    for (var i = 0; i < images.length; i++){ 
        sw_UnlockImg( images[i] );
    }
}
function sw_SetImgSrc(img, src){
    if(IMAGES_LOCK_ENABLED){
        if( !(img._Locked == true) ){
            img.src = src;
        }
        sw_StoreImgSrc(img, src);
    }else{
        img.src = src;
    }
}
function sw_GetImgSrc(img, src){
    if(IMAGES_LOCK_ENABLED){
        if( !(img._Locked == true) ){
            return img.src;
        }else{
            return sw_RestoreImgSrc(img);
        }
    }else{
        return img.src;
    }
}

function sw_GetImagesFrom(container){
    var result = new Array();
    
    var containerTagName = container.tagName.toLowerCase();
    if(containerTagName == 'img'){
        result[result.length] = container;
    }else if( containerTagName == 'input' && container.type == 'image'){
        result[result.length] = container;
    }
    
    var imgArr = container.getElementsByTagName("img");
    if(imgArr){
        for (var i = 0; i < imgArr.length; i++){ 
            result[result.length] = imgArr[i];
        }
    }
    
    var inputArr = container.getElementsByTagName("input");
    if(inputArr){
        for (var i = 0; i < inputArr.length; i++){ 
            var input = inputArr[i];
            if(input.type == 'image'){
                result[result.length] = input;
            }
        }
    }
    
    return result;
}

function sw_LockImg(img){
    img._Locked = true;
}
function sw_UnlockImg(img){
    img._Locked = false;
    var _StoredSrc = sw_RestoreImgSrc(img)
    if(_StoredSrc){
        img.src = _StoredSrc;
    }
}
function sw_StoreImgSrc(img, src){ img.setAttribute("_StoredSrc", src); }
function sw_RestoreImgSrc(img){ return  img.getAttribute("_StoredSrc"); }


//===================================================
// Events management ---
//===================================================

function sw_AttachEvent(obj, evType, fn){
    if (obj.addEventListener){
        obj.addEventListener(evType, fn, false);
        return true;
    } else if (obj.attachEvent){
        var r = obj.attachEvent("on"+evType, fn);
        return r;
    } else {
        var oldHanler = obj["on"+evType];
        if(oldHanler){
            obj["on"+evType] = function(e){
                oldHanler(e);
                fn(e);
            }
        }else{
            obj["on"+evType] = fn;
        }
        return true;
    }
}

function sw_StopEvent(evt){
    if(window.event){
        if(!evt)
            evt = window.event;
        evt.cancelBubble = true;
        evt.returnValue = false;
    }else{
        if(evt.preventDefault)
            evt.preventDefault();
        if(evt.stopPropagation)
            evt.stopPropagation();
    }
    return false;
}

//===================================================
// Debugging and performance counting ---
//===================================================

function sw_Trace(mess){
    if(window.SW_TRACE && window.SW_TRACE==true)
        alert(mess);
}
function sw_Debug(mess){
    if(window.SW_DEBUG && window.SW_DEBUG==true)
        alert(mess);
}

var _TimeRecord1 = new Date();
var _TimeRecord2 = null;

function sw_StartTimeRecording(){
    _TimeRecord1 = new Date();
}

function sw_StopTimeRecording(){
    _TimeRecord2 = new Date()
    //sw_Trace( 'TimeRecord = '+(_TimeRecord2.valueOf()-_TimeRecord1.valueOf()) + ' ms.' );
}

//function DebuggerConsole(){
//    var ELEMENT_NODE = 1;
//    
//    var _AreaEl = null;
//    
//    var _CreateArea = function(){
//        var area = document.createElement('div');
//        document.body.appendChild(area);

//        area.style.position = 'absolute';
//        area.style.posLeft = 0;
//        area.style.posTop = 0;
//        
//        area.innerHTML = "skdbvflbvhdzf";
//        
//        return area;
//    }
//    
//    var _EnsureAreaCreated = function(){
//        if(_AreaEl)
//            return;
//        _AreaEl = _CreateArea();
//    }
//    
//    this.WriteLine = function(mess){
//        _EnsureAreaCreated();
//        alert(mess);
//    }
//}
//var Debug = new DebuggerConsole();


//===================================================
// Positioning Functions ---
//===================================================

function sw_SetAbsolutePosition(el, dx, dy){
    if(el){
        var isIE = (document.all) ? false : true;
        if(el.style.position != 'absolute'){
            el.style.position = 'absolute';
        }
        if (isIE){
            el.style.pixelLeft = dx + document.body.scrollLeft;
            el.style.pixelTop = dy + document.body.scrollTop;
        }else{
            el.style.left = dx + document.body.scrollLeft;
            el.style.top = dy + document.body.scrollTop;
        }
    }
}

function sw_GetAbsoluteX(el){ return el.offsetLeft; }
function sw_GetAbsoluteY(el){ return el.offsetTop; }

//function sw_GetWidth(el){ return el.offsetWidth; }
//function sw_SetWidth(el, val){ el.style.width = val; }
//function sw_GetHeight(el){ return el.offsetHeight; }
//function sw_SetHeight(el, val){ el.style.height = val; }


/// Old unused functions ===================================================== 

function sw_GetElementOfFrame(id, fn){
  var fd = sw_GetFrameDocument(fn);
  if(fd) return sw_GetElement(id, fd);
  return null;
}

function sw_GetElementGlobal(id, d){
    if(!d) d = top.document;
    var el = sw_GetElement(id, d);
    if(el) return el;
    if(d.frames){
        for(var i=0;i<d.frames.length;i++){
            el = sw_GetElementGlobal(id, d.frames[i].document)
            if(el) return el;
        }
    }   
    return null;
}

function sw_GetFrameDocument(frameName, fh){
    // frameName can be NAME or ID of frame
    // search by ID doesn't work under Netscape 6
    // fh is a window object
    if(!fh) fh = top; 
    var frd = null;
    if(fh.frames){
        var i=0;e
        for(i=0;i<fh.frames.length;i++){
            var fr = fh.frames[i];
            if(fr.name==frameName)
                return fr.document;            
            if(fr.frameElement) // fr.frameElement doesn't work under Netscape 6
                if(fr.frameElement.id==frameName)
                    return fr.document;
            frd = sw_GetFrameDocument(frameName, fr)
            if(frd) return frd;
        }
    }
    return null;
}

function sw_GetFrameWindow(frameName, fh){
    if(!fh) fh = top; 
    if(fh.frames){
        var i=0;
        for(i=0;i<fh.frames.length;i++){
            var fr = fh.frames[i];
            if(fr.name==frameName) // We get trouble if fh.frames[i] loaded with site from other domain
                return fr;
            if(fr.id==frameName)
                return fr;
            var frw = sw_GetFrameWindow(frameName, fr)
            if(frw) return frw;
        }
    }
    return null;
}

function sw_SetTimeout(vCode, iMilliSeconds)
{
    setTimeout(vCode, iMilliSeconds);
}

//function sw_StartFunctionSequence(funcName, startValue, finishValue, timeLength, timeStep){
//    if(!timeStep) timeStep = 30;
//    if(!timeLength) timeLength = 200;
//    
//    var t = 0;
//    var x = startValue;
//    var iMax = Math.round(timeLength/timeStep);
//    var dx = (finishValue - startValue)/iMax;
//    var evalStr = "";
//    var i=0;
//    for(i=0; i<iMax; i++){
//        x += dx;
//        t += timeStep;
//        evalStr = funcName+"("+x+")";
//        sw_SetTimeout(evalStr, t);
//    }
//    evalStr = funcName+"("+finishValue+")";
//    sw_SetTimeout(evalStr, timeLength);          
//}

