/** Copyright (c) 2006 UPT Ltd. Версия $Id: xsight.cObject.js,v 1.8 2007/12/26 19:14:04 andy Exp $ */

/**
* Функция-обертка для создания новых классов и потомков
* с правильным вызовом конструктора базового класса
* @param {object} pParent родительский объект
* @param pProp реализация класса
*/
function newClass(pParent, pProp)
{
	// Динамический конструктор
	var clazz = function()
	{
    	// Stupid JS need exactly one "operator new" calling for parent
    	// constructor just after class definition.
    	if (clazz.preparing)
    		return delete(clazz.preparing);
    	// Call custom constructor.
    	if (clazz.constr)
    	{
			this.constructor = clazz; // we need it!
			clazz.constr.apply(this, arguments);
		}
	}

	clazz.prototype = {}; // no prototype by default
	if (pParent)
	{
		pParent.preparing = true;
		clazz.prototype = new pParent;
		clazz.prototype.constructor = pParent;
		clazz.constr = pParent; // BY DEFAULT - parent constructor
	}
	if (pProp)
	{
		var cname = "constructor";
		for (var k in pProp)
		{
			if (k != cname) clazz.prototype[k] = pProp[k];
		}
		if (pProp[cname] && pProp[cname] != Object)
		clazz.constr = pProp[cname];
	}
	return clazz;
}

/**
* Измененный прототип ф-ции, добавлен метод bind
* @param {object} pOpject объект, который биндится
*/
Function.prototype.bind = function(pObject)
{
	var method = this;
	return function()
	{
    	return method.apply(pObject, arguments);
	}
}


/**
 * Базовый класс
 * @class
 */
cObject = newClass(null, {
	/**
	* Конструктор класса
	* @constructor
	*/
	constructor: function() { },

	/**
	* Метод добавления хендлера события
	* @public
	* @param {object} pObject объект, к которому прикрепляется заданное событие
	* @param {string} pEvent имя события (без префикса on)
	* @param pHandler функция обработчика события
	*/
	fAddHandler:function(pObject, pEvent, pHandler)
	{
		if (!pObject || typeof(pObject) == 'undefined') return false;
  		if (typeof(pObject.addEventListener) != 'undefined')
			pObject.addEventListener(pEvent, pHandler, false);
  		else if (typeof(pObject.attachEvent) != 'undefined')
    		pObject.attachEvent('on' + pEvent, pHandler);
  		else
		{
			var handlersProp = '_handlerStack_' + pEvent;
			var eventProp = 'on' + pEvent;
			if (typeof(pObject[handlersProp]) == 'undefined')
			{
				pObject[handlersProp] = [];
      			if (typeof(pObject[eventProp]) != 'undefined')
        			pObject[handlersProp].push(pObject[eventProp]);
      				pObject[eventProp] = function(e)
      			{
        			var ret = true;
        			for (var i = 0; ret != false && i < pObject[handlersProp].length; i++)
						ret = pObject[handlersProp][i](e);
        			return ret;
				}
			}
			pObject[handlersProp].push(pHandler);
		}
	},

	/**
	* Метод удаления хендлера события
	* @public
	* @param {object} pObject объект, из которого удаляется заданное событие
	* @param {string} pEvent имя события (без префикса on)
	* @param pHandler функция обработчика события
	* @return {boolean} true, если удалось удалить handler, иначе false
	*/
	fRemoveHandler:function(pObject, pEvent, pHandler)
	{
		if (typeof(pObject) == 'undefined') return false;
		if (typeof(pObject.removeEventListener) != 'undefined')
    		pObject.removeEventListener(pEvent, pHandler, false);
  		else if (typeof(pObject.detachEvent) != 'undefined')
    		pObject.detachEvent('on' + pEvent, pHandler);
  		else
		{
			var handlersProp = '_handlerStack_' + pEvent;
			if (typeof(pObject[handlersProp]) != 'undefined')
			{
				for (var i = 0; i < pObject[handlersProp].length; i++)
				{
					if (pObject[handlersProp][i] == pHandler)
					{
						pObject[handlersProp].splice(i, 1);
          				return true;
					}
				}
			}
		}
		return false;
	},

	/**
	* Метод установки handler'а на событие onload документа
	* @public
	* @param pHandler функция обработчика события
	*/
	fSetOnloadHandler:function(pHandler)
	{
		var root = window.addEventListener ? window : document.addEventListener ? document : null;

		if (root)
		{
			this.fAddHandler(root, "load", pHandler);
		}
		else
		{
			if(typeof window.onload == 'function')
			{
				var existing = window.onload;
				window.onload = function()
				{
					existing();
					pHandler();
				}
			}
			else
			{
				window.onload = pHandler;
			}
		}
	},

	/**
	* Метод установки handler'а на событие onresize документа
	* @public
	* @param pHandler функция обработчика события
	*/
	fSetOnresizeHandler:function(pHandler)
	{
		var root = window.addEventListener || window.attachEvent ? window : document.addEventListener ? document : null;
		if (root)
		{
			if(root.addEventListener)
				root.addEventListener("resize", pHandler, false);
      		else if(root.attachEvent)
      			root.attachEvent("onresize", pHandler);
		}
		else
		{
			if(typeof window.onload == 'function')
			{
				var existing = window.onresize;
				window.onresize = function()
				{
					existing();
					pHandler();
				}
			}
			else
			{
				window.onresize = pHandler;
			}
		}
	},

	/**
	* Метод показа модального диалога
	* @public
	* Может принимать от двух до трех аргументов. Является прослойкой к
	* showModalDialog, по-умолчанию (без третьего аргумента) отрисовывает
	* окно заданной высоты и шириры
	* @return {object} результат выполнения показа модального диалога
	*/
	fShowModalDialog:function()
	{
		var url = this.fShowModalDialog.arguments[0];
		var action = this.fShowModalDialog.arguments[1];

		var init = "dialogWidth:700px;";
			init += "dialogHeight:500px;";
			init += "edge:Raised;";
			init += "center: Yes;";
			init += "help: No;";
			init += "resizable: No;";
			init += "status: No;";

		if (this.fShowModalDialog.arguments.length > 2)
			init = this.fShowModalDialog.arguments[2];

		if (typeof(window.showModalDialog) != 'undefined')
			return showModalDialog(url, action, init);
		else
		{
			alert(globals.fGet('ERR_MODAL_DIALOGS_NOT_SUPPORTED'));
			return false;
		}

	},
	
	/**
	* Метод показа модального диалога помощи
	* @public
	* Может принимать от двух до трех аргументов. Является прослойкой к
	* showModelessDialog, по-умолчанию (без третьего аргумента) отрисовывает
	* окно заданной высоты и шириры
	* @return {object} результат выполнения показа модального диалога
	*/
	fShowHelpDialog:function()
	{
		var url = this.fShowHelpDialog.arguments[0];
		var action = this.fShowHelpDialog.arguments[1];

		var init = "dialogWidth:400px;";
			init += "dialogHeight:500px;";
			init += "edge:Raised;";
			init += "center: Yes;";
			init += "help: No;";
			init += "resizable: No;";
			init += "status: No;";

		if (this.fShowHelpDialog.arguments.length > 2)
			init = this.fShowHelpDialog.arguments[2];

		if (typeof(window.showModelessDialog) != 'undefined')
			return showModelessDialog(url, action, init);
		else
		{
			alert(globals.fGet('ERR_MODELESS_DIALOGS_NOT_SUPPORTED'));
			return false;
		}

	},	

	/**
	* Метод получения объекта по заданному идентификатору / имени
	* @public
	* @param {string} pName имя (id) объекта
	* @return {object} найденный объект
	*/
	fGetObj:function(pName)
	{
		if (document.getElementById)
			return document.getElementById(pName);
		else if (document.all)
        	return document.all[pName];
		else if (document.layers)
			return this.fGetObjNN4(document, pName);
		else
			return;
	},

	/**
	* Метод получения объекта по заданному идентификатору / имени для NN4
	* @protected
	* @param {object} pObj объект, в котором искать
	* @param {string} pName имя (id) объекта
	* @return {object} найденный объект
	*/
	fGetObjNN4:function(pObj, pName)
	{
		var x = pObj.layers;
        var foundLayer;
        for (var i=0; i<x.length; i++)
        {
			if (x[i].id == pName)
				foundLayer = x[i];
			else if (x[i].layers.length)
				var tmp = this.fGetObjNN4(x[i], pName);
			if (tmp)
				foundLayer = tmp;
        }
        return foundLayer;
	},

	/**
	* Метод получения высоты клиентского окна
	* @public
	* @return {integer} высота в px
	*/
	fGetViewportHeight:function()
	{
		if (typeof(window.innerHeight) != 'undefined')
			return window.innerHeight;
		if (document.documentElement && document.documentElement.clientHeight)
			return document.documentElement.clientHeight;
		if (typeof(document.body) != 'undefined')
			return document.body.clientHeight;
		return window.undefined;
	},

	/**
	* Метод получения ширины клиентского окна
	* @public
	* @return {integer} ширина в px
	*/
	fGetViewportWidth:function()
	{
		if (typeof(window.innerWidth) != 'undefined')
			return window.innerWidth;
		if (document.documentElement && document.documentElement.clientWidth)
			return document.documentElement.clientWidth;
		if (typeof(document.body) != 'undefined')
			return document.body.clientWidth;
		return window.undefined;
	},

	/**
	* Метод получения смещения по высоте относительно top
	* @public
	* @return {integer} смещение Y в px
	*/
	fGetViewportOffsetY:function()
	{
		if (window.pageYOffset)
			return window.pageYOffset;
        else if (document.documentElement && document.documentElement.scrollTop)
			return document.documentElement.scrollTop;
        else if (document.body)
			return document.body.scrollTop;
		else
			return window.undefined;
	},

	/**
	* Метод получения смещения по высоте относительно left
	* @public
	* @return {integer} смещение X в px
	*/
	fGetViewportOffsetX:function()
	{
		if (window.pageXOffset)
			return window.pageXOffset;
        else if (document.documentElement && document.documentElement.scrollLeft)
			return document.documentElement.scrollLeft;
        else if (document.body)
			return document.body.scrollLeft;
		else
			return window.undefined;
	},

	/**
	* Метод замены всех вхождений подстроки в строку на новое значение
	* @public
	* @param string pString входная строка
	* @param string pSearchFor искомая фраза
	* @param string pReplaceWith заменять на
	* @return string измененная строка
	*/
	fStringReplace:function(pString, pSearchFor, pReplaceWith)
	{
		var pos;
		while (pString.indexOf(pSearchFor)>-1)
		{
			pos = pString.indexOf(pSearchFor);
			pString = "" + (pString.substring(0, pos) + pReplaceWith + pString.substring((pos + pSearchFor.length), pString.length));
		}
	 	return pString;
	},

	/**
	* Метод нахождения позиции строки в подстроке
	* @public
	* @param string pString входная строка
	* @param string pWhat искомая подстрока
	* @return integer позиция
	*/
	fStrPos:function(pString, pWhat)
	{
		for (var i = 0; i < pString.length; i++)
			if (pString.substring(i, i+pWhat.length) == pWhat)
				return i;
		return -1;
	},

	/**
	* Метод проверки принадлежности значения pValue на вхождение в плоский массив
	* @public
	* @param array pArray входной массив
	* @param string pValue проверяемое значение
	* @return boolean результат проверки
	*/
	fInArray: function(pArray, pValue)
	{
		if (pArray.length > 0)
		{
			for (var i=0; i<pArray.length; i++)
			{
				if (pArray[i].toLowerCase() == pValue.toLowerCase())
				return true;
			}
		}
		else return false;
	}

});