﻿/**
 * @project Paredes de Vitoria
 * @filename admin.js
 * @version 2.0 (06/11/2009)
 * @creationdate 06/11/2009
 * @author 1001 Acessos - Telecomunicacoes e Informatica, Lda
 * @description Utils file.  
 */

 /**
  * Common object with utility functions.
  */
 Ext.namespace('utils');
 
 utils = new function() {
 
 	 //private
 	 var scope = this;
 	
 	 /* NAMESPACES */

 	 /**
 	  * Namespaces hashTable.
 	  * @type HashTable
 	  */
	 this.namespaces = new HashTable();
	 
	 /**
	  * Gets a namespace, given its prefix
	  * @param {string} prefix The namespace prefix.
	  * @return {string} The full name with which the namespace was initially registered.
	  */
	 this.getNs = function(prefix) {
	 
	 	return this.namespaces.get(prefix);
	
	 }
	 
	 /**
	  * Creates a namespace and registers its prefix.
	  * @param {string} name The namespace name.
	  * @param {string} prefix The namespace prefix.
	  */ 
	 this.setNs = function(name, prefix) {
	 	
	 	if (!this.namespaces.hasItem(prefix)) {
	 		var aux = name.replace(/\./g,'_');
		 	this.namespaces.add(prefix, aux);
		 	Ext.namespace(name);
	 	} 	
	 	
	 }
	 
	 
	 
	 /* STRINGS */
	 
	 /**
	  * Verifies if a string starts with the given pattern.
	  * @param {string} value The string to test.
	  * @param {string} pattern The testing pattern.
	  * @return {boolean} Boolean value indicating if the string starts with the given pattern or not.
	  */
	 this.stringStartsWith = function(value, pattern) {
	 
	 	if (!pattern) return false;
	 	if (!value) return false;
	 	value = value + ''; //Guarantees that we have a string, when values are numbers...
		return value.indexOf(pattern) === 0;
	 
	 }
	
	 /**
	  * Checks if the given value contains the specified pattern.
	  * @param {string} value The string in which we are going to search. 
	  * @param {string} pattern The string we are searching for.
	  * @return {Boolean} True if the given value contains the specified pattern. False otherwise.
	  */
	 this.stringContains = function(value, pattern) {
	 
	 	if (!pattern) return false;
	 	if (!value) return false;
	 	value = value + ''; //Guarantees that we have a string, when values are numbers...
	 	return (value.indexOf(pattern) > 0); 
	 	
	 }
	 
	 /**
	  * Verifies if a string ends with  the given pattern.
	  * @param {string} value The string to test.
	  * @param {string} pattern The testing pattern.
	  * @return {boolean} Boolean value indicating if the string ends with the given pattern or not.
	  */
	 this.stringEndsWith = function(value, pattern) {
	 
	 	if (!pattern) return false;
	 	if (!value) return false;
	 	value = value + ''; //Guarantees that we have a string, when values are numbers...
		var d = value.length - pattern.length;
	 
		return d >= 0 && value.lastIndexOf(pattern) === d;
	 
	 } 
	 
	 /**
	  * Verifies if the given object is a string.
	  * @param {Object} value The object to test.
	  * @return {boolean} Boolean value indicating if the object is a string or not.
	  */
	 this.isString = function(value) {
	 
		return typeof(value) == 'string';
	 
	 }	 
	 
	 /**
	  * Funcion que resuelve el valor ASCII 2 de un caracter. Caso se pase una cadena con mas de un caracter, 
	  * la funcion devolvera el valor ASCII 2 del primero caracter de esa misma cadena.
	  * @param {string} value El caracter a obtener el valor.
	  * @return {int} Valor numerico del caracter pasado en la tabla de ASCII 2.
	  */
	 this.getAsciiValue = function(value) {
	 
		value = value.charAt(0);
		
		var i;
		
		for(i=0;i<256;++i) {
			var h = i.toString(16);
			if (h.length == 1) h = '0' + h;
			h = '%' + h;
			h = unescape(h);
			if (h == value) break;
		}
	 
		return i;
	 
	 }
	
	 /**
	  * Funcion que devuelve un caracter ASCII 2 en funci�n de su codigo numerico.
	  * @param {int} value Valor numerico del caracter en ASCII 2 
	  * @return {string} El caracter en texto.
	  */
	 this.getAsciiChar = function(value) {
	 
	 	return String.fromCharCode(value);
	 
	 }	 
	 
	 
	 
	 /* ARRAYS */
	 
	 /**
	  * Copies the given array positions to a new array, from the given start position to the given end position. 
	  * @param {int} start The start position.
	  * @param {int} end The end position.
	  * @param {Array} array The initial array.
	  * @return {Array} Returns the copy array.
	  */
	 this.copyArray = function(start, end, array) {
	 
	 	var copyArray = new Array();
	 	for (var i=start; i<=end; i++) copyArray[copyArray.length] = array[i];
	 	
	 	return copyArray;
	 	
	 }
	 
	 /**
	  * Checks if the given obect is an array.
	  * @param {Object} obj The object to test.
	  * @return {boolean} True if the given object is an array. False otherwise.
	  */
	 this.isArray = function(obj) {
	 	return (obj.constructor.toString().indexOf('function Array()') != -1);
	 }	 
	 
	 /**
	  * Convierte un Json en un array de objetos.
	  * @param {String} json El json a convertir.
	  * @return {Object} El objecto que contiene el array de objetos. 
	  */
	 this.jsonToArray = function(json) {
	 
	 	return eval('(' + json + ')');
	 	
	 }
	 

	 
	 /* IMAGES */
	 
	 /**
	  * Funcion responsable de corregir el fondo de las imagenes PNG en Internet Explorer 6.
	  * Esta correccion solo se aplica a Internet Explorer 6 y a imagenes PNG dentro de una tag
	  * IMG. No funciona para imagenes PNG cargadas en background.
	  */
	 this.fixPng = function() {
		if (Ext.isIE6){
			for(var i=0; i<document.images.length; i++) {
				var img = document.images[i]
				var imgName = img.src.toUpperCase()
	
				if (imgName.substring(imgName.length-3, imgName.length) == "PNG") {
					
					var imgID = (img.id) ? "id='" + img.id + "' " : "";
					var imgClass = (img.className) ? "class='" + img.className + "' " : "";
					var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
					var imgStyle = "display:inline-block;" + img.style.cssText;
					
					if (img.align == "left") imgStyle = "float:left;" + imgStyle;
					if (img.align == "right") imgStyle = "float:right;" + imgStyle;
					if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
					
					var strNewHTML = "<span " + imgID + imgClass + imgTitle
					+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
					+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
					+ "(src=\'" + img.src + "\');\"></span>" ;
					img.outerHTML = strNewHTML;
					i--; //= i - 1;
				}
			}
		}
	 }	 

	 
	 
	 /* NUMBERS */
	 
	 /**
	  * Checks if the given value is numeric.
	  * @param {Object} value The object to verify
	  * @return {boolean} True if the given object is numeric. False otherwise.
	  */
	 this.isNumber = function(value) {
		
	 	//TODO: Cambiar la validacion para realizar mediante una expresion regular.
	 	
		var ValidChars = '-0123456789.';
		var IsNumber = true;
		
		try {
			//Rule excaptions
			if ((value == '-') || (value == '.') || (value == '-.') || (value == '.-'))
				IsNumber = false;
			
			for (var i = 0; i < (value.length && IsNumber == true); i++)
				if (ValidChars.indexOf(value.charAt(i)) == -1) IsNumber = false;
		
			return IsNumber;
		}
		catch (ex) {
			return false;
		}
		
	 } 
	 
	 /**
	  * Parses the given object into a float.
	  * @param {Object} value The object to parse.
	  */
	 this.parseFloat = function(value) {
	  	
	 	if (value && this.isNumber(value)) value = parseFloat(value);
	 	else value = 0;
	 	
	 	return value;
	 	
	 }
	 
	 /**
	  * Converts a number to the spanish number format (21002.23 -> 21.002,23).
	  * @param {Number} number The number to convert.
	  * @return {String} The string with the formated number.
	  */
	 this.spanishFormat = function(number) {
	 
	 	number += '';
	 	var x = number.split('.');
	 	var x1 = x[0];
	 	var x2 = x.length > 1 ? ',' + x[1]: '';
	 	var regExp = /(\d+)(\d{3})/;
	 	while (regExp.test(x1)) x1 = x1.replace(regExp, '$1' + '.' + '$2');
	 	return x1 + x2;
	 	
	 }
	 
	 /**
	  * Converts a number to JavaScript number format (21.002,23 -> 21002.23).
	  * @param {Number} number The number to convert.
	  * @return {String} The string with the formated number.
	  */
	 this.decimalFormat = function(number) {
	 
	 	number = number.replace(/\./g, '');
	 	number = number.replace(/,/g, '.');
	 	return number;
	 	
	 }
	 
	 /**
	  * Converts a number to the raw spanish number format (21002.23 -> 21002,23).
	  * @param {Number} number The number to convert.
	  * @return {String} The string with the formated number.
	  */
	 this.rawSpanishFormat = function(number) {
	 
	 	number = number.replace(/\./g, ',');
	 	return number;
	 	
	 } 	 

	 
	 
	 /* DATES */
	 
	 /**
	  * Funcion que formatea una fecha al formato espanol.
	  * @param {String} Fecha a formatear.
	  * @return {String} Devuelve la fecha formateada.
	  */
	 this.spanishFormatDateTime = function(value) {
	 	utils.log(value);
	 	value = value.split('.');
	 	date = Date.parseDate(value[0], 'Y-m-d H:i:s').format('d/m/Y H:i:s');
	 	return date;
	 	
	 }
	 
	 /**
	  * Funcion que formatea una fecha al formato ingles.
	  * @param {String} value Fecha a formatear.
	  * @return {String} Devuelve la fecha formateada.
	  */
	 this.englishFormatDateTime = function(value) {
	 
	 	value = value.split('.');
	 	date = Date.parseDate(value[0], 'd/m/Y H:i:s').format('Y-m-d H:i:s');
	 	return date;
	 	
	 }
	 
	 /**
	  * Funcion que transforma una cadena de texto indicada, de un formato dado a otro formato dado.
	  * @param {String} value Fecha a formatear.
	  * @param {String} iniFormat Formato inicial.
	  * @param {String} finFormat Formato final.
	  * @return {String} Devuelve la fecha formateada.
	  */
	 this.formatDate = function(value, iniFormat, finFormat) {
	 
	 	return Date.parseDate(value, iniFormat).format(finFormat);
	 	
	 }
	 
	 /**
	  * Constructs a string of characters representing the clock time. 
	  * It then returns that construction to whatever JavaScript code 
	  * calls the function. If you don't want the construction to include 
	  * the "AM" or "PM" part, remove the last two lines from the code 
	  * that constructs the clock time. 
	  */
	 this.getClockTime = function() {
		 var now = new Date();
		 var hour = now.getHours();
		 var minute = now.getMinutes();
		 var second = now.getSeconds();
		 var ap = "AM";
		 
		 if (hour > 11) { ap = "PM"; }
		 if (hour > 12) { hour = hour - 12; }
		 if (hour == 0) { hour = 12; }
		 if (hour < 10) { hour = "0" + hour; }
		 if (minute < 10) { minute = "0" + minute; }
		 if (second < 10) { second = "0" + second; }
		 
		 var timeString = hour + ':' + minute + ':' + second + " " + ap;
		 
		 return timeString;
	 }

	 
	 
	 /* OTHER */
	 
	 /**
	  * Funcion que devuelve un componente a partir de su id.
	  * @param {string} id id del componente que deseamos obtener.
	  * @return {Component} Devuelve el componente especificado.
	  */
	 this.getCmp = function(id) {
	 	
	 	return Ext.getCmp(id);
	 	
	 }
	 
	 /**
	  * Funcion de carga de un fichero JavaScript.
	  * @param {string} completePath Ruta completa para el fichero, incluiendo el nombre del fichero.
	  */
	 this.includeJs = function(completePath) {
	
	    var body = document.getElementsByTagName('body').item(0);
	    
	    script = document.createElement('script');
	    script.src = completePath;
	    script.type = 'text/javascript';
	    body.appendChild(script);
		
	 };
	 
	 /**
	  * Funcion de carga de una pestana. Comprueba si una pesta�a esta ya abierta y si se ha llegado 
	  * al limite de pestanas abiertas de manera simultanea.
	  * @param {string} panel Id del panel.
	  * @param {string} completePath Ruta completa para el fichero, incluiendo el nombre del fichero.
	  */
	 this.checkTab = function(panel, completePath) {
		
		if (typeof(Ext.getCmp(panel)) != 'undefined') {
			Ext.getCmp(this.getNs('MAIN') + 'CenterPanel').activate(Ext.getCmp(panel));
		} else {
			if (Ext.getCmp(this.getNs('MAIN') + 'CenterPanel').items.length >= application.MAIN_NUM_MAX_TAB) {
				factory.getDialogToast(lang.TOAST_WARNING_MSG_BEGIN + lang.MAX_TABS_REACHED + lang.TOAST_MSG_END);
			} else {
				this.includeJs(completePath);
			}
		}		
		
	 };
	 
	 /**
	  * Retrieves an array with the all the properties of a given object.  
	  * @param {Object} object The object from which to retrieve the properties. 
	  * @return {Array} An array with all the object's properties.
	  */
	 this.getPropertyNames = function(object) {
	 
	 	var propArray = new Array();
	 	for (var propName in object) {
	 		propArray[propArray.length] = propName;
	 	}
	 	
	 	return propArray;
	 	
	 }
	 
	 /**
	  * Funcion responsable de lanzar una traza. Solo funciona para Firefox / Firebug.
	  * @param {Object} obj Objeto a mostrar en consola.
	  */
	 this.log = function(obj) {
		 try { if (application.DEBUG_MODE) console.log(obj); } 
		 catch (ex) { /* Silence the error */ }
	 }
	  	
	/**
	 * Method that copies all the properties of config to obj.
	 * @param {Object} obj The receiver of the properties.
	 * @param {Object} config The source of the properties.
	 * @param {Object} defaults A different object that will also be applied for default values.
	 * @return {Object} The resulting object.
	 */
	this.apply = function(obj, config) {

		return Ext.apply(obj, config);
		
	}
	 /**
	  * Adds a page to the browser bookmarks. This function is cross-browser.
	  * @param {string} pageTitle The page title.
	  * @param {string} pageUrl The page URL.
	  */
	this.addToBookmarks = function(pageTitle, pageUrl){
		if (window.sidebar) { /* FireFox */
			window.sidebar.addPanel(pageTitle, pageUrl, "");
		}
		else if (window.opera && window.print){ /* Opera */
			var mbm = document.createElement("a");
			mbm.setAttribute("rel", "sidebar");
			mbm.setAttribute("href", pageUrl);
			mbm.setAttribute("title", pageTitle);
			mbm.click();
		}
		else if (document.all) { /* Internet Explorer */
			window.external.AddFavorite(pageUrl, pageTitle);
		}
		if (window.chrome) { /* Google Chrome */
			//Not supported
			alert("O Google Chrome não permite adicionar esta página automaticamente aos seus favoritos.\r\nPedimos desculpa pela inconveniência.");
		}
	}
	
	/**
	 *
	 */
	this.utf8Encode = function(s) {
		return unescape(encodeURIComponent(s));
	}

	/**
	 *
	 */
	this.utf8Decode = function(s) {
		return decodeURIComponent(escape(s));
	}

	/**
	 * Method responsible for disabling the mouse right click on the page body.
	 */
	this.disableBodyRightClick = function() {
		var message = "";
		var clickIEFn = function() {
			if (document.all) { (message); return false; }
		}
		var clickNSFn = function(e) {
			if (document.layers || (document.getElementById &&! document.all)) {
				if (e.which == 2 || e.which == 3) { (message); return false; }
			}
		}

		if (document.layers) {
			document.captureEvents(Event.MOUSEDOWN);
			document.onmousedown = clickNSFn;
		} else {
			document.onmouseup = clickNSFn;
			document.oncontextmenu = clickIEFn;
		}
		
		document.oncontextmenu = new Function("return false");
	}
 	
	/**
	  * Crea una JsonStore con la configuracion pasada por parametro
	  * @param {Object} config Objeto de configuracion del store
	  * @return {Ext.data.JsonStore} Devuelve un Ext.data.JsonStore configurado
	  */
	this.getJsonStore = function(config) {

		if ((config.url == '') || (typeof(config.url) == 'undefined') || (config.url == null)) {throw 'Propiedad urlStore en el metodo "factory.getJsonStore" no definida.'};		
		if ((config.root == '') || (typeof(config.root) == 'undefined') || (config.root == null)) {throw 'Propiedad rootStore en el metodo "factory.getJsonStore" no definida.'};		
		if ((config.fields == '') || (typeof(config.fields) == 'undefined') || (config.fields == null)) {throw 'Propiedad fieldsStore en el metodo "factory.getJsonStore" no definida.'};		
		if ((typeof(config.totalProperty) == 'undefined') || (config.totalProperty == null)) { config.totalProperty = 'totalCount' };		
		if ((config.baseParams == '') || (typeof(config.baseParams) == 'undefined') || (config.baseParams == null)) { config.baseParams = {} };		
		
		var store = new Ext.data.JsonStore({
			url: config.url,
			root: config.root,
			baseParams: config.baseParams,
			totalProperty: config.totalProperty,
			fields: config.fields,
			listeners: {
				loadexception: function() {
					alert('Ocorreu um erro de carga de dados para a tabela "' + config.root + '"');
				}
			}
		});	
		store.load();
		
		return store;

	}
	
 };
