﻿if(typeof(Bitrix) == "undefined"){
	var Bitrix = new Object();
}

Bitrix.TypeUtility = function Bitrix$TypeUtility(){
    if(typeof(Bitrix.TypeUtility.initializeBase) == "function")
        Bitrix.TypeUtility.initializeBase(this);
	this._initialized = false;
}

Bitrix.TypeUtility.prototype = {
	initialize: function(){
		this._initialized = true;
	},
	isString: function(item){
		return typeof(item) == "string" || item instanceof String;
	},
	isNotEmptyString: function(item){
		return typeof(item) == "string" || item instanceof String ? item.length > 0 : false;
	},
	isBoolean: function(item){
		return typeof(item) == "boolean" || item instanceof Boolean;
	},
	
	isNumber: function(item){
		return typeof(item) == "number" || item instanceof Number;
	},	
	
	isFunction: function(item){
		return typeof(item) == "function" || item instanceof Function;
	},
	isDomElement: function(item){
		return this.isElementNode(item);
	},
	isElementNode: function(item){
		return typeof(item) == "object" && "nodeType" in item && item.nodeType == 1; //document.body.ELEMENT_NODE
	},	
	tryConvertToString: function(item){
		if(typeof(item) == "string" || item instanceof String)
			return item;
		if(typeof(item.toString) == "function")
			return item.toString();
		if(item == null)
			return "null";
		if(item == undefined)
			return "undefined"
		return "<?>";
	}
}

Bitrix.TypeUtility._instance = null;
Bitrix.TypeUtility.getInstance = function(){
	if(this._instance == null){
		this._instance = new Bitrix.TypeUtility();
		this._instance.initialize();
	}
	return this._instance;
}
Bitrix.TypeUtility.isString = function(item){
	return this.getInstance().isString(item);
}
Bitrix.TypeUtility.isNotEmptyString = function(item){
	return this.getInstance().isNotEmptyString(item);
}
Bitrix.TypeUtility.isBoolean = function(item){
	return this.getInstance().isBoolean(item);
}
Bitrix.TypeUtility.isNumber = function(item){
	return this.getInstance().isNumber(item);
}
Bitrix.TypeUtility.isFunction = function(item){
	return this.getInstance().isFunction(item);
}

Bitrix.TypeUtility.isDomElement = function(item){
	return this.getInstance().isDomElement(item);
}

Bitrix.TypeUtility.isElementNode = function(item){
	return this.getInstance().isElementNode(item);
}

Bitrix.TypeUtility.tryConvertToString = function(item){
	return this.getInstance().tryConvertToString(item);	
}

Bitrix.TypeUtility.createDelegate = function(instance, method){
	return function() {
		return method.apply(instance, arguments);
	}
}

if(typeof(Bitrix.TypeUtility.registerClass) == "function")
    Bitrix.TypeUtility.registerClass("Bitrix.TypeUtility");

Bitrix.WebAppHelper = function Bitrix$WebAppHelper(){
    if(typeof(Bitrix.WebAppHelper.initializeBase) == "function")
        Bitrix.WebAppHelper.initializeBase(this);
	this._initialized = false;
}

Bitrix.WebAppHelper.prototype = {
	//initialize: function(){ this.this._initialized = true;},
	getPath: function(){
	    if(Bitrix.TypeUtility.isString(window["bitrixWebAppPath"]))
		    return window["bitrixWebAppPath"];
	    if(Bitrix.TypeUtility.isString(window["APPPath"]))
		    return window["APPPath"];
	    return "";
    }	
}

Bitrix.WebAppHelper._instance = null;
Bitrix.WebAppHelper.getInstance = function(){
	if(this._instance == null){
		this._instance = new Bitrix.WebAppHelper();
		//this._instance.initialize();
	}
	return this._instance;
}
Bitrix.WebAppHelper.getPath = function(){
	return this.getInstance().getPath();
}

Bitrix.NavigationHelper = function(){}
Bitrix.NavigationHelper.isOpera = function(){
	try{ return "opera" in window &&  navigator.userAgent.indexOf("Opera") >= 0; }
	catch(e){ return false;}
}

Bitrix.NavigationHelper.isSafari = function(){
    if(!("navigator" in window))
        return false;
    var nav = window.navigator;
    if("vendor" in nav && Bitrix.TypeUtility.isNotEmptyString(nav.vendor) && nav.vendor.indexOf("Apple") < 0)
        return false;
    return "userAgent" in nav && Bitrix.TypeUtility.isNotEmptyString(nav.userAgent) && nav.userAgent.indexOf("Safari") >= 0;
}

if(typeof(Bitrix.WebAppHelper.registerClass) == "function")
    Bitrix.WebAppHelper.registerClass("Bitrix.WebAppHelper");
    
Bitrix.GoodbyeWindow = function Bitrix$GoodbyeWindow(){
    if(typeof(Bitrix.GoodbyeWindow.initializeBase) == "function")
	    Bitrix.GoodbyeWindow.initializeBase(this);
	this._initialized = false;
	this._containerDivId = "bx_googbye_window_container";
	this._content = "";
	this._topPanelDivId = "bx_googbye_window_topPanel";
	this._contentDivId = "bx_googbye_window_content";
	this._contentSpanId = "bx_googbye_window_content_text";
	this._timeToLive = 1;
	this._layoutType = "";
	this._onShowClientScript = null;
	this._onHideClientScript = null;
	this._isVisible = false;
	
	this._containerDivCssClass = "";
	this._topPanelDivCssClass = "";	
	this._contentDivCssClass = "";	
	this._contentSpanCssClass = "";		
	this._layoutCssClassSuccess = "";	
	this._layoutCssClassError = "";
}	

Bitrix.GoodbyeWindow.prototype = {
    initialize: function(){
        if(this._initialized) return;
		this.reset();
        this._initialized = true;
    },
	
	getContent: function(){
		return this._content;
	},
	setContent: function(value){
		this._content = value;
	},	
	
	getLayoutType: function(){
		return this._layoutType;
	},
	setLayoutType: function(value){
		this._layoutType = value;
	},		
	
	getTimeToLive: function(){
		return this._timeToLive;
	},
	setTimeToLive: function(value){
		if(isNaN(value))
			throw String.concat("'",value, "'", " is not a number!");
			
		this._timeToLive = parseInt(value);
	},		
	
	getContainerDivCssClass: function(){
		return this._containerDivCssClass;
	},
	
	setContainerDivCssClass: function(val){
		this._containerDivCssClass = val;
	},	
	
	getTopPanelDivCssClass: function(){
		return this._topPanelDivCssClass;
	},
	
	setTopPanelDivCssClass: function(val){
		this._topPanelDivCssClass = val;
	},		
	
	getContentDivCssClass: function(){
		return this._contentDivCssClass;
	},
	
	setContentDivCssClass: function(val){
		this._contentDivCssClass = val;
	},	
	
	getContentSpanCssClass: function(){
		return this._contentSpanCssClass;
	},
	
	setContentSpanCssClass: function(val){
		this._contentSpanCssClass = val;
	},		
	
	getLayoutCssClassSuccess: function(){
		return this._layoutCssClassSuccess;
	},
	
	setLayoutCssClassSuccess: function(val){
		this._layoutCssClassSuccess = val;
	},	
	
	getLayoutCssClassError: function(){
		return this._layoutCssClassError;
	},
	
	setLayoutCssClassError: function(val){
		this._layoutCssClassError = val;
	},	
	
	getOnHideClientScript: function(){
		return this._onHideClientScript;
	},
	setOnHideClientScript: function(value){
		this._onHideClientScript = value;
	},		
	
	getOnShowClientScript: function(){
		return this._onShowClientScript;
	},
	setOnShowClientScript: function(value){
		this._onShowClientScript = value;
	},	
	
	getDefaultTimeToLive: function(){
		return 1800;
	},
	
	reset: function(){
		this._content = "Everything Is Fine...";
		this._timeToLive = this.getDefaultTimeToLive();
		this._layoutType = "SUCCESS";
		this._onShowClientScript = null;
		this._onHideClientScript = null;	
	},
	
	show: function(){
		if(this._isVisible)
			return;
		
		if(this._onShowClientScript != null && this._onShowClientScript.length > 0)
			window.eval(this._onShowClientScript);
			
		var containerDiv = document.getElementById(this._containerDivId);
		
		if(containerDiv == null){
			containerDiv = document.createElement("DIV");
			containerDiv.style.visibility = "hidden";
			containerDiv = document.body.appendChild(containerDiv);
			containerDiv.id = this._containerDivId;	
			if(Bitrix.TypeUtility.isNotEmptyString(this._containerDivCssClass))
				containerDiv.className = this._containerDivCssClass;
			else{
				containerDiv.style.backgroundColor = "#edf1f3";
				containerDiv.style.borderWidth = "1px";
				containerDiv.style.borderStyle = "solid";
				containerDiv.style.borderColor = "#ad9634";
				containerDiv.style.padding = "1px";
				containerDiv.style.margin = "0px";
				containerDiv.style.position = "absolute";
				containerDiv.style.textAlign = "left";
				containerDiv.style.fontFamily = "Tahoma";
				containerDiv.style.fontSize = "12px";
				containerDiv.style.fontWeight = "normal";
				containerDiv.style.zIndex = "1001";	
			}			
		}
	
		var topPanelDiv = document.getElementById(this._topPanelDivId);
		
		if(topPanelDiv == null){
			topPanelDiv = document.createElement("DIV");
			containerDiv.appendChild(topPanelDiv);
			topPanelDiv.id = this._topPanelDivId;
			if(Bitrix.TypeUtility.isNotEmptyString(this._topPanelDivCssClass))
				topPanelDiv.className = this._topPanelDivCssClass;
			else{
				topPanelDiv.onclick = function(){Bitrix.GoodbyeWindow.getInstance().hide();};
				topPanelDiv.style.width = "10px";
				topPanelDiv.style.height = "10px";
				topPanelDiv.style.margin = "0px";
				topPanelDiv.style.padding = "0px";
				topPanelDiv.style.position = "absolute";
				topPanelDiv.style.top = "1px";
				topPanelDiv.style.right = "1px";
				var imgUrl = Bitrix.PathHelper.combine(Bitrix.PathHelper.getApplicationPath(), "bitrix/images/close_window_mini_button.gif");
				topPanelDiv.style.background = "transparent url(" + imgUrl + ") no-repeat scroll 0% 0%";
				topPanelDiv.style.cursor = "pointer";
			}			
		}
				
		
		var contentDiv = document.getElementById(this._contentDivId);
		if(contentDiv == null){
			contentDiv = document.createElement("DIV");
			containerDiv.appendChild(contentDiv);
			contentDiv.id = this._contentDivId;
			if(Bitrix.TypeUtility.isNotEmptyString(this._contentDivCssClass))
				contentDiv.className = this._contentDivCssClass;
			else{
				contentDiv.style.padding = "0px";
				contentDiv.style.margin = "5px 10px 5px 10px";				
			}
		}
		
		
		var contentSpan = document.getElementById(this._contentSpanId);
		if(contentSpan == null){
			contentSpan = document.createElement("SPAN");
			contentDiv.appendChild(contentSpan);
			contentSpan.id = this._contentSpanId;
			if(Bitrix.TypeUtility.isNotEmptyString(this._contentSpanCssClass))
				contentSpan.className = this._contentSpanCssClass;
			else{
				contentSpan.style.padding = "0px";
				contentSpan.style.margin = "0px";
			}
		}
		
		contentSpan.innerHTML = "";
		contentSpan.innerHTML = this._content;
		
		if(Bitrix.TypeUtility.isNotEmptyString(this._layoutCssClassSuccess)){
			var rxSuccess = new RegExp(this._layoutCssClassSuccess, "gi");
			contentSpan.className = contentSpan.className.replace(rxSuccess, "");
		}
		
		if(Bitrix.TypeUtility.isNotEmptyString(this._layoutCssClassError)){
			var rxError = new RegExp(this._layoutCssClassError, "gi");
			contentSpan.className = contentSpan.className.replace(rxError, "");		
		}
		
		if(this._layoutType == "SUCCESS"){
			if(Bitrix.TypeUtility.isNotEmptyString(this._layoutCssClassSuccess))
				contentSpan.className = contentSpan.className.concat(" ", this._layoutCssClassSuccess);
			else
				contentSpan.style.color = "Green";
		}
		else if(this._layoutType == "ERROR"){
			if(Bitrix.TypeUtility.isNotEmptyString(this._layoutCssClassError))
				contentSpan.className = contentSpan.className.concat(" ", this._layoutCssClassError);
			else
				contentSpan.style.color = "Red";
		}
			
		var windowSize = jsUtils.GetWindowInnerSize();
		var windowScroll = jsUtils.GetWindowScrollPos();	

		containerDiv.style.visibility = "visible";
		
		var textWidth = parseInt(contentDiv.offsetWidth);
		if(textWidth > 250){
			var textHeight = parseInt(contentDiv.offsetHeight);
			var textWidth = Math.round(Math.sqrt(1.62 * textWidth * textHeight));
			contentDiv.style.width = textWidth + "px";
		}
		
		var left = parseInt(windowScroll.scrollLeft + windowSize.innerWidth/2 - containerDiv.offsetWidth/2);
		var top = parseInt(windowScroll.scrollTop + windowSize.innerHeight/2 - containerDiv.offsetHeight/2);
		
		containerDiv.style.top = top + "px";
		containerDiv.style.left = left + "px";		
		
		if(this._timeToLive >= 0)
			window.setTimeout(function(){ Bitrix.GoodbyeWindow.getInstance().hide(); }, this._timeToLive > 0 ? this._timeToLive : this.getDefaultTimeToLive());
						
		this._isVisible = true;
	},
	
	hide: function(){
		if(!this._isVisible)
			return;
			
		var containerDiv = document.getElementById(this._containerDivId);
		if(containerDiv == null) return;
		containerDiv.style.visibility = "hidden";
		
		var onHideScript = this._onHideClientScript;
		this.reset();
		
		if(onHideScript != null && onHideScript.length > 0)
			window.eval(onHideScript);	
			
		this._isVisible = false;
	},
	
	_getStyleAttributeValue: function(srcElem, attrName){
		if(!srcElem) throw "Source element is not defined!";
		if(Sys.Browser.agent === Sys.Browser.InternetExplorer){ // IE
			var elmStyle = srcElem.currentStyle;
			return elmStyle.getAttribute(attrName);
		}
		else{
			var elmCompStyle = document.defaultView.getComputedStyle(srcElem, '');
			return elmCompStyle.getPropertyValue(attrName);
		}	
	},
	
	_parseInt: function(sourceValue, defaultValue){
		if(!sourceValue || isNaN(sourceValue)) return defaultValue;
		return parseInt(sourceValue);
	}
}

Bitrix.GoodbyeWindow._instance = null;
Bitrix.GoodbyeWindow.getInstance = function(){
	if(this._instance == null){
        this._instance = new Bitrix.GoodbyeWindow();
		this._instance.initialize();
	}
    return this._instance;
}

Bitrix.GoodbyeWindow.show = function(content, layout, ttl){
    var instance = this.getInstance();
	instance.setContent(content);
	instance.setLayoutType(layout);
	instance.setTimeToLive(ttl);
	instance.show();
}

Bitrix.GoodbyeWindow.getContainerDivCssClass = function(){
	return this.getInstance().getContainerDivCssClass();
}
	
Bitrix.GoodbyeWindow.setContainerDivCssClass = function(val){
	this.getInstance().setContainerDivCssClass(val);
}
	
Bitrix.GoodbyeWindow.getTopPanelDivCssClass = function(){
	return this.getInstance().getTopPanelDivCssClass();
}
	
Bitrix.GoodbyeWindow.setTopPanelDivCssClass = function(val){
	this.getInstance().setTopPanelDivCssClass(val);
}	
	
Bitrix.GoodbyeWindow.getContentDivCssClass = function(){
	return this.getInstance().getContentDivCssClass();
}
	
Bitrix.GoodbyeWindow.setContentDivCssClass = function(val){
	this.getInstance().setContentDivCssClass(val);	
}	
	
Bitrix.GoodbyeWindow.getContentSpanCssClass = function(){
	return this.getInstance().getContentSpanCssClass();
}
	
Bitrix.GoodbyeWindow.setContentSpanCssClass = function(val){
	this.getInstance().setContentSpanCssClass(val);
}		
	
Bitrix.GoodbyeWindow.getLayoutCssClassSuccess = function(){
	return this.getInstance().getLayoutCssClassSuccess();
}
	
Bitrix.GoodbyeWindow.setLayoutCssClassSuccess = function(val){
	this.getInstance().setLayoutCssClassSuccess(val);
}	
	
Bitrix.GoodbyeWindow.getLayoutCssClassError = function(){
	return this.getInstance().getLayoutCssClassError();
}
	
Bitrix.GoodbyeWindow.setLayoutCssClassError =  function(val){
	this.getInstance().setLayoutCssClassError(val);
}

if(typeof(Bitrix.GoodbyeWindow.registerClass) == "function")
    Bitrix.GoodbyeWindow.registerClass("Bitrix.GoodbyeWindow");    

Bitrix.ObjectHelper = function Bitrix$ObjectHelper()
{
	this._initialized = false;
}

Bitrix.ObjectHelper.prototype = {
	initialize: function(){
		this._initialized = true;
	},
	tryGetBoolean: function(object, name, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";
		if(!(name in object))
			return def;
		var v = object[name];
		if(Bitrix.TypeUtility.isBoolean(v))
			return v;
		if(Bitrix.TypeUtility.isString(v))
			return v.toUpperCase() == "TRUE";
		return def;
	},
	tryGetString: function(object, name, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";
		return name in object && Bitrix.TypeUtility.isString(object[name]) ? object[name] : def;
	},	
	tryGetBooleanByNameArray: function(object, nameArr, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!(nameArr instanceof Array)) throw "nameArr is not valid!";
        if(nameArr.length == 0) 
            return def;
            
        var r = undefined;
        for(var i = 0; i < nameArr.length; i++ ){
		    if(!(nameArr[i] in object))
			    continue;  
		    var v = object[nameArr[i]];
		    if(Bitrix.TypeUtility.isBoolean(v)){
		        r = v;
		        break;
		    }
		    if(Bitrix.TypeUtility.isString(v)){
			    r = v.toUpperCase() == "TRUE";
			    break;
			}          
        }
		return r != undefined ? r : def;
	},	
	tryGetStringByNameArray: function(object, nameArr, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!(nameArr instanceof Array)) throw "nameArr is not valid!";
        if(nameArr.length == 0) 
            return def;
        var r = undefined;
        for(var i = 0; i < nameArr.length; i++ ){
		    if(!(nameArr[i] in object))
			    continue;  
		    var v = object[nameArr[i]];
		    if(Bitrix.TypeUtility.isString(v)){
		        r = v;
		        break;
		    }         
        }
		return r != undefined ? r : def;			
	},		
	tryGetIntByNameArray: function(object, nameArr, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!(nameArr instanceof Array)) throw "nameArr is not valid!";
        if(nameArr.length == 0) 
            return def;
        var r = undefined;
        for(var i = 0; i < nameArr.length; i++ ){
		    if(!(nameArr[i] in object))
			    continue;  
		    var v = object[nameArr[i]];
			if(Bitrix.TypeUtility.isNumber(v)){
		        r = v;
		        break;			
			}		
		    if(Bitrix.TypeUtility.isString(v)){
				var r = parseInt(v);
				if(!isNaN(r))
					break;
				r = undefined;
		    }         
        }
		return r != undefined ? r : def;				
	},
	tryGetInt: function(object, name, def){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";
		if(!(name in object))
			return def;
		var v = object[name];
		if(Bitrix.TypeUtility.isNumber(v))
			return v;
		if(Bitrix.TypeUtility.isString(v)){	
			var r = parseInt(v);
			if(!isNaN(r))
				return r;
		}
		return def;
	},	
	setStringIfNotEmpty: function(object, name, val){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";	
		if(Bitrix.TypeUtility.isNotEmptyString(val))
			object[name] = val;
	},
	setString: function(object, name, val){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";	
		if(Bitrix.TypeUtility.isString(val))
			object[name] = val;
	},	
	setBoolean: function(object, name, val){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";	
		if(Bitrix.TypeUtility.isNumber(val))
		    object[name] = val > 0;	
		else if(Bitrix.TypeUtility.isBoolean(val))
			object[name] = val;		
	},
	setNumber: function(object, name, val){
		if(typeof(object) != "object" || !object) throw "object is not valid!";
		if(!Bitrix.TypeUtility.isString(name)) throw "name is not valid!";	
		if(Bitrix.TypeUtility.isNumber(val))
			object[name] = val;		
	}
}


Bitrix.ObjectHelper._instance = null;
Bitrix.ObjectHelper.getInstance = function(){
	if(this._instance == null){
		this._instance = new Bitrix.ObjectHelper();
		this._instance.initialize();
	}
	return this._instance;
}

Bitrix.ObjectHelper.tryGetBoolean = function(object, name, def){
	return this.getInstance().tryGetBoolean(object, name, def);
}

Bitrix.ObjectHelper.tryGetBooleanByNameArray = function(object, nameArr, def){
    return this.getInstance().tryGetBooleanByNameArray(object, nameArr, def);
}

Bitrix.ObjectHelper.tryGetString = function(object, name, def){
	return this.getInstance().tryGetString(object, name, def);
}
Bitrix.ObjectHelper.tryGetStringByNameArray = function(object, nameArr, def){
	return this.getInstance().tryGetStringByNameArray(object, nameArr, def);
}
Bitrix.ObjectHelper.tryGetInt = function(object, name, def){
	return this.getInstance().tryGetInt(object, name, def);
}
Bitrix.ObjectHelper.tryGetIntByNameArray = function(object, nameArr, def){
	return this.getInstance().tryGetIntByNameArray(object, nameArr, def);
}
Bitrix.ObjectHelper.setStringIfNotEmpty = function(object, name, val){
	return this.getInstance().setStringIfNotEmpty(object, name, val);
}

Bitrix.ObjectHelper.setString = function(object, name, val){
	return this.getInstance().setString(object, name, val);
}

Bitrix.ObjectHelper.setBoolean = function(object, name, val){
	return this.getInstance().setBoolean(object, name, val);
}

Bitrix.ObjectHelper.setNumber = function(object, name, val){
	return this.getInstance().setNumber(object, name, val);
}

if(typeof(Bitrix.ObjectHelper.registerClass) == "function")
	Bitrix.ObjectHelper.registerClass("Bitrix.ObjectHelper");

Bitrix.PathHelper = function Bitrix$PathHelper(){
	this._initialized = false;
	this._isAbsoluteUrlRx = null;
	this._absoluteUrlPathRx = null;
}

Bitrix.PathHelper.prototype = {
	initialize: function(){
		this._initialized = true;
		this._isAbsoluteUrlRx = new RegExp("^[a-z][a-z,0-9]+([\.][a-z,0-9]+)?\:", "i");
		this._absoluteUrlPathRx = new RegExp("^([a-z\.0-9]+)\:(//)?([a-z_0-9\:\@\.]+)/(.+)", "i");
	},
	getApplicationPath: function(){
		return "bitrixWebAppPath" in window && Bitrix.TypeUtility.isNotEmptyString(window["bitrixWebAppPath"]) ? window["bitrixWebAppPath"] : "/";
	},
	isVirtual: function(path){
		if(!Bitrix.TypeUtility.isString(path)) return false;
		return path.length > 0 && path.charAt(0) == "~";
	},
	isAbsolute: function(path){
		if(!Bitrix.TypeUtility.isString(path)) return false;	
		return this._isAbsoluteUrlRx.test(path);
	},
	isRelative: function(path){
		return !this.isAbsolute(path);
	},
	parse: function(path){
		if(!Bitrix.TypeUtility.isString(path)) throw "path is not valid!";	
		
		if(this.isAbsolute(path)){
			var m = this._absoluteUrlPathRx.exec(path);
			if(m == null) return null;
			return { scheme:m[1], schemeSeparator:m[2], hostAndPort:m[3], path:m[4] };
		}

		if(this.isRelative(path))
			return { scheme:"", schemeSeparator:"", hostAndPort:"", path:path };

		if(this.isVirtual(path))
			throw "Virtual paths is not supported!";
			
		throw path + " could not be parsed!";
	},
	resolveVirtualPath: function(path){
		if(!this.isVirtual(path))
			return path;
		var appPath = this.getApplicationPath();
		appPath = this.appendTrailingSlash(appPath);
		
		path = path.substr(1);
		while(path.length > 0 && path.charAt(0)=="/")
			path = path.substr(1);
			
		return appPath.concat(path);
	},
	makeVirtual: function(path){
		if(!Bitrix.TypeUtility.isString(path)) throw "path is not valid!";	
		if(this.isVirtual(path))
			return path;	
		var appPath = this.getApplicationPath();
		appPath = this.appendTrailingSlash(appPath);
		if(path.indexOf(appPath) != 0)
			return path;
		return "~/" + path.substr(appPath.length);
	},
	appendTrailingSlash: function(path){
		if(!Bitrix.TypeUtility.isString(path)) throw "path is not valid!";	
		if(path.length == 0)
			return "/";
		if(path.charAt(path.length - 1) != "/")
			path += "/";
		return path;
	},
	combine: function(path1, path2){
		if(!path1 && !path2) return "";
		
		if(path1 && !Bitrix.TypeUtility.isString(path1)) throw "path1 is not valid!";
		if(path2 && !Bitrix.TypeUtility.isString(path2)) throw "path2 is not valid!";
		
		if(!path2) return path1;
		if(!path1) return path2;
		
		if(this.isVirtual(path2) || !this.isRelative(path2))
			return path2;
			
		var toUp = 0;
		if(path2.charAt(0) == "/")
			return path2;
		while(path2.length > 0){
			if(path2.indexOf("../") == 0){
				path2 = path2.substr(3);
				toUp++;
				continue;
			}
			if(path2.indexOf("./") == 0){
				path2 = path2.substr(2);
				continue;
			}
			if(path2.indexOf("/") == 0){
				path2 = path2.substr(1);
				continue;
			}					
			break;
		}
		
		
		
		if(toUp > 0){
			var path1IsVirtual = this.isVirtual(path1);
			if(path1IsVirtual)
				path1 = this.resolveVirtualPath(path1);
			
			var fragments = this.parse(path1);
			var path = fragments != null ? fragments.path : "";
			if(path.length > 0){
				while(toUp > 0){
					var partIndex = path.lastIndexOf("/");
					if(partIndex < 0){
						path = "";
						break;
					}
					path = path.substr(0, partIndex);
					toUp--;
				}
				path1 = fragments.scheme + ":" + fragments.schemeSeparator + fragments.hostAndPort + "/";
				if(path.length > 0)
					path1 += path;
			}
			
			if(path1IsVirtual)
				path1 = this.makeVirtual(path1);
		}
		
		var r = path1;
		if(path2.length > 0){
			r = this.appendTrailingSlash(r) + path2;
		}
		
		return r;
	},
	getFileExtension: function(path){
		if(!Bitrix.TypeUtility.isString(path)) throw "path is not valid!";
		var ext = "";
		var queryIndex = path.indexOf("?");
		if(queryIndex >= 0)
			path = path.substr(0, queryIndex);
		
		var dotIndex = path.lastIndexOf(".");
		if(dotIndex < 0) return "";
		return path.substr(dotIndex, path.length - dotIndex);		
	}
}

Bitrix.PathHelper._instance = null;
Bitrix.PathHelper.getInstance = function(){
	if(this._instance == null){
		this._instance = new Bitrix.PathHelper();
		this._instance.initialize();
	}
	return this._instance;
}

Bitrix.PathHelper.getApplicationPath = function(){
	return this.getInstance().getApplicationPath();
}

Bitrix.PathHelper.isVirtual = function(path){
	return this.getInstance().isVirtual(path);
}

Bitrix.PathHelper.resolveVirtualPath = function(path){
	return this.getInstance().resolveVirtualPath(path);
}

Bitrix.PathHelper.isRelative = function(path){
	return this.getInstance().isRelative(path);
}

Bitrix.PathHelper.getUrlPath = function(path){
	return this.getInstance().getUrlPath(path);
}

Bitrix.PathHelper.combine = function(path1, path2){
	return this.getInstance().combine(path1, path2);
}

Bitrix.PathHelper.getFileExtension = function(path){
	return this.getInstance().getFileExtension(path);
}

if(typeof(Bitrix.PathHelper.registerClass) == "function")
	Bitrix.PathHelper.registerClass("Bitrix.PathHelper");

Bitrix.EnumHelper = function Bitrix$EnumHelper(){
	this._initialized = false;
}

Bitrix.EnumHelper.prototype = {
	initialize: function(){
		this._initialized = true;
	},
	
	getName: function(values, id){
		if(!(values instanceof Object)) throw "Bitrix.EnumHelper.getName: values are not specified!";
		if(!(typeof(id) == "number" || id instanceof Number)) throw "Bitrix.EnumHelper.getName: id is not specified!";
		for(var key in values)
			if(values[key] === id) 
				return key;
		return null;
	},
	getId: function(values, name){
		if(!(values instanceof Object)) throw "Bitrix.EnumHelper.getId: values are not specified!";
		if(!(typeof(name) == "string" || name instanceof String)) throw "Bitrix.EnumHelper.getId: name is not specified!";	

		for(var key in values)
			if(key === name)
				return values[key];	
		return null;
	},
	checkPresenceById: function(values, id){
		return this.getName(values, id) != null;
	}
}

Bitrix.EnumHelper._instance = null;
Bitrix.EnumHelper.getInstance = function(){
	if(Bitrix.EnumHelper._instance == null){
		Bitrix.EnumHelper._instance = new Bitrix.EnumHelper();
		Bitrix.EnumHelper._instance.initialize();
	}
	return Bitrix.EnumHelper._instance;
}

Bitrix.EnumHelper.getName = function(values, id){
	return Bitrix.EnumHelper.getInstance().getName(values, id);
}

Bitrix.EnumHelper.getId = function(values, name){
	return Bitrix.EnumHelper.getInstance().getId(values, name);
}

Bitrix.EnumHelper.checkPresenceById = function(values, id){
	return Bitrix.EnumHelper.getInstance().checkPresenceById(values, id);
}

if(typeof(Bitrix.EnumHelper.registerClass) == "function")
	Bitrix.EnumHelper.registerClass("Bitrix.EnumHelper");
	
	
Bitrix.EventPublisher = function Bitrix$EventPublisher(){
    this._listeners = null;
}

Bitrix.EventPublisher.prototype.addListener = function(listener){
    if(!Bitrix.TypeUtility.isFunction(listener)) throw "listener is not valid!";
    if(this._listeners == null)
	    this._listeners = new Array();
    this._listeners.push(listener);	
}


Bitrix.EventPublisher.prototype.removeListener = function(listener){
    if(!Bitrix.TypeUtility.isFunction(listener)) throw "listener is not valid!";
    if(this._listeners == null) return;
    var index = -1;
    for(var i = 0; i < this._listeners.length; i++){
	    if(this._listeners[i] != listener) continue;
	    index = i;
	    break;
    }
    if(index < 0) return;
    this._listeners.splice(index, 1);	
}

Bitrix.EventPublisher.prototype.fire = function(){
    if(this._listeners == null) return;
    for(var i = 0; i < this._listeners.length; i++){
	    this._listeners[i].apply(this, arguments);
    }	
}

if(typeof(Bitrix.EnumHelper.registerClass) == "function")
    Bitrix.EventPublisher.registerClass("Bitrix.EventPublisher");
    
Bitrix.ElementPositioningUtility = function(){
    if(typeof(Bitrix.ElementPositioningUtility.initializeBase) == "function")
	    Bitrix.ElementPositioningUtility.initializeBase(this);
}

Bitrix.ElementPositioningUtility.prototype = {
	initialize: function(){
		this._isInitialized = true;
	},
	
	getElementRect : function(el){
		var r = { top: 0, right:0, bottom: 0, left: 0,  width:0, height:0 };
		if(!el) 
			return r;
		if(typeof(el.getBoundingClientRect) != "undefined"){
			var clientRect = el.getBoundingClientRect();
			var root = document.documentElement;
			var body = document.body;			
					
			r.top = clientRect.top + root.scrollTop + body.scrollTop;
			r.left = clientRect.left + root.scrollLeft + body.scrollLeft;
			r.width = clientRect.right - clientRect.left;
			r.height = clientRect.bottom - clientRect.top;
			r.right = clientRect.right + root.scrollLeft + body.scrollLeft;
			r.bottom = clientRect.bottom + root.scrollTop + body.scrollTop;	
		}
		else
		{
			var x=0, y=0, w=el.offsetWidth, h=el.offsetHeight;
			var first = true;
			for(; el!=null; el = el.offsetParent){
				x += el.offsetLeft;
				y += el.offsetTop;
				if(first){
					first = false;
					continue;
				}
				var elBorderLeftWidth = 0, elBorderTopWidth = 0;
				//if(typeof(document.all) == "undefined" || typeof(window.opera) != "undefined"){
				if(Sys.Browser.agent != Sys.Browser.InternetExplorer){
					var elCompStyle = document.defaultView.getComputedStyle(el, '');
					elBorderLeftWidth = parseInt(elCompStyle.getPropertyValue('border-left-width'));
					elBorderTopWidth = parseInt(elCompStyle.getPropertyValue('border-top-width'));								
				}
				else{
					var elStyle = el.currentStyle;
					elBorderLeftWidth = parseInt(elStyle.getAttribute('borderLeftWidth'));
					elBorderTopWidth = parseInt(elStyle.getAttribute('borderTopWidth'));				
				}
				if(!isNaN(elBorderLeftWidth) && elBorderLeftWidth > 0 )
					x += elBorderLeftWidth;	
				if(!isNaN(elBorderTopWidth) && elBorderTopWidth > 0 )
					y += elBorderTopWidth;										
			}			
			
			r.top = y;
			r.left = x;
			r.width = w;
			r.height = h;
			r.right = r.left+ w;
			r.bottom = r.top + h;			
		}
		return r;
	},
	getOffset: function(offsetEl, sourceEl){
		if(!offsetEl) throw "Bitrix.ElementPositioningUtility.getOffset: Offset element is not defined!";
		if(!sourceEl) throw "Bitrix.ElementPositioningUtility.getOffset: Source element is not defined!";
		
		var offsetElRect = this.getElementRect(offsetEl);
		var sourceElRect = this.getElementRect(sourceEl);
		
		return Bitrix.Point.create(offsetElRect.top - sourceElRect.top, offsetElRect.left - sourceElRect.left);					
	},
	
	_getNumberOrZero: function(val){
		return !isNaN(val) ? val : 0;
	},
	
	getElementMargins: function(el){
		var r = { top: 0, right:0, bottom: 0, left: 0 };
		if(!el) 
			return r;

		if(/*@cc_on!@*/false){ //IE	
			var elStyle = el.runtimeStyle;
			
			r.top = this._getNumberOrZero(parseInt(elStyle.getAttribute('marginTop')));
			r.right = this._getNumberOrZero(parseInt(elStyle.getAttribute('marginRight')));
			r.bottom = this._getNumberOrZero(parseInt(elStyle.getAttribute('marginBottom')));
			r.left = this._getNumberOrZero(parseInt(elStyle.getAttribute('marginLeft')));
		}
		else{
			var elCompStyle = document.defaultView.getComputedStyle(el, '');
			r.top = this._getNumberOrZero(parseInt(elCompStyle.getPropertyValue('margin-top')));
			r.right = this._getNumberOrZero(parseInt(elCompStyle.getPropertyValue('margin-right')));
			r.bottom = this._getNumberOrZero(parseInt(elCompStyle.getPropertyValue('margin-bottom')));
			r.left = this._getNumberOrZero(parseInt(elCompStyle.getPropertyValue('margin-left')));
		}
		return r;
	}
}
	
Bitrix.ElementPositioningUtility._instance = null;
Bitrix.ElementPositioningUtility.getInstance = function(){
	if(this._instance == null){
		this._instance = new Bitrix.ElementPositioningUtility();
		this._instance.initialize();
	}
	return this._instance;
}

Bitrix.ElementPositioningUtility.getElementRect = function(el){
	return this.getInstance().getElementRect(el);
}

Bitrix.ElementPositioningUtility.getElementMargins = function(el){
	return this.getInstance().getElementMargins(el);
}

if(typeof(Bitrix.ElementPositioningUtility.registerClass) == "function")
    Bitrix.ElementPositioningUtility.registerClass("Bitrix.ElementPositioningUtility");

