/*global SISAL, window, self, $, TOOLTIP_CENTERTOP, TOOLTIP_CENTERLEFT, TOOLTIP_POSARROW, TOOLTIP_OFFSETTOP, TOOLTIP_OFFSETLEFT  */

SISAL.FX = (function FX() {

	var
		ListOfOverlay_array = [],
		ListOfPopup_array = [],
		zIndex = 0,
		className_makeDivLikeBody = "addFunction_makeDivLikeBody",
		className_removePaddingFromTd = "addFunction_removePaddingFromTd",
		bodyOnTop_zIndexOffset = 10000
		;
	
	/**
	 * Calcola la larghezza della SCROLLBAR
	 * @return larghezza della scrollbar
	 */
	function getScrollerWidth()
	{
	    var scr = null, inn = null, wNoScroll = 0, wScroll = 0;

	    // Outer scrolling div
	    scr = document.createElement('div');
	    scr.style.position = 'absolute';
	    scr.style.top = '-1000px';
	    scr.style.left = '-1000px';
	    scr.style.width = '100px';
	    scr.style.height = '50px';
	    // Start with no scrollbar
	    scr.style.overflow = 'hidden';

	    // Inner content div
	    inn = document.createElement('div');
	    inn.style.width = '100%';
	    inn.style.height = '200px';

	    // Put the inner div in the scrolling div
	    scr.appendChild(inn);
	    // Append the scrolling div to the doc

	    document.body.appendChild(scr);

	    // Width of the inner div sans scrollbar
	    wNoScroll = inn.offsetWidth;
	    // Add the scrollbar
	    scr.style.overflow = 'auto';
	    // Width of the inner div width scrollbar
	    wScroll = inn.offsetWidth;

	    // Remove the scrolling div from the doc
	    document.body.removeChild(
	    document.body.lastChild);

	    // Pixel width of the scroller
	    return (wNoScroll - wScroll);
	}
	
	function addToElementTd_removePadding()
	{
		// definizioni delle variabili
		var	i = 0, j = 0,
			numeroTrovati = 0,
			numeroTrTrovatiA = 0,
			numeroTrTrovatiB = 0,
			numeroTdTrovati = 0,
			objsWithClass = "",
			objsTr = "",
			childrenTr = ""
            ;
        
		// recupero tutti gli oggetti che hanno come classe quella stabilita
        objsWithClass = $('.' + className_removePaddingFromTd);
        // numero degli oggetti trovati
        numeroTrovati = objsWithClass.length;
		if (numeroTrovati > 0)
		{
			// al DIV recuperato cambio lo stile per non farlo più vedere
			objsWithClass.css('width', '0px');
			objsWithClass.css('height', '0px');
			objsWithClass.css('fontSize', '0px');
			objsWithClass.css('display', 'none');
			
			// aggiungo la classe al TD da "rimuovere" e setto larghezza e padding a 0
			objsWithClass.parent().css('padding', '0px').css('width', '0px').addClass('addFunction_removeThisObj');
				
			// recupero il TR che devo analizzare
			objsTr = objsWithClass.parentsUntil('tr').parent();
			
			// numero dei TR da utilizzare per effettuare i cambiamenti
			numeroTrTrovatiA = objsTr.get().length;
			for (i = 0; i < numeroTrTrovatiA; i += 1)
			{
				// recupero il numero totale dei TR della regione
				numeroTrTrovatiB = $(objsTr.get()[i]).parent().children().length;
				for (j = 0; j < numeroTrTrovatiB; j += 1)
				{
					// recupero i figli di ogni TR
					childrenTr = $(objsTr.get()[i]).parent().children().children();
					childrenTr.css('width', '0px');
					
					// i TD trovati si riferiscono SOLO a quelli che non posseggono la classe "addFunction_removeThisObj"
					numeroTdTrovati = childrenTr.not('.addFunction_removeThisObj').length;
					if (numeroTdTrovati > 0)
					{
						// se si tratta di tanti ITEM sulla stessa riga (colonne n)
						if (numeroTrTrovatiB === 1)
						{
							// setto a 0 il padding dell'ultimo ITEM della regione
							$(childrenTr.not('.addFunction_removeThisObj').get()[numeroTdTrovati - 1]).css('padding', '0px');
						} else
						{
							// se si tratta di tanti ITEM uno sotto l'altro (colonne 1)
							// setto a 0 il padding dell'ultimo ITEM della regione
							$(childrenTr.not('.addFunction_removeThisObj').get()[0]).css('padding', '0px');
						}
					}
				}
			}
		}
	}
	
	/**
	 * Rende tutti i div con una classe stabilita simili al BODY. Potranno quindi essere utilizzati dalla FX come se fossero dei BODY.
	 * @return null
	 */
	function addToElementDiv_makeLikeBody()
	{
		// definizioni delle variabili
		var numeroTrovati = 0,
			top = 0,
			left = 0,
			width = 0,
			height = 0,
			objsWithClass = ""
            ;
        
		// recupero tutti gli oggetti che hanno come classe quella stabilita
        objsWithClass = $('.' + className_makeDivLikeBody);
        // numero degli oggetti comperati
        numeroTrovati = objsWithClass.get().length;
		
        // imposto i settaggi predefiniti simili a quelli del BODY (top e left)
		top = 0;
		left = 0;
		// imposto a 0 l'altezza e larghezza dell'oggetto in questione.. così da non falsificare i dati successivi
		objsWithClass.css('width', 0 + 'px');
		objsWithClass.css('height', 0 + 'px');
		// recupero l'altezza e la larghezza della pagina del sito
		width = $(document).width();
		height = $(document).height();
		if ($.browser.msie === true)
		{
			width -= (getScrollerWidth() + 4);
		}
		
		objsWithClass.css('position', 'absolute');
		objsWithClass.css('top', top + 'px');
		objsWithClass.css('left', left + 'px');
		objsWithClass.css('width', width + 'px');
		objsWithClass.css('height', height + 'px');
		objsWithClass.css('zIndex', '-1000');
	}
	/**
	 * Controlla l'elemento passato verificando se deve esere considerato come un BODY
	 * @param element_id id dell'oggetto da verificare
	 * @return
	 * <ul>
	 * <li>TRUE: l'elemento è da considerare come se fosse un BODY</li>
	 * <li>FALSE: l'elemento non è da considerare come BODY</li>
	 * </ul>
	 */
	function elementLikeBody(element_id)
	{
		var obj = "";
		// controlla che non sia passato come id una stringa predefinita
		if (element_id !== "body" && element_id !== "document" && element_id !== "window")
		{
			// controlla se l'oggetto possiede la classe di "riconoscimento"
			if ($('#' + element_id).hasClass(className_makeDivLikeBody))
			{
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * Controlla l'elemento passato verificando se deve esere considerato come un BODY
	 * @param element_id id dell'oggetto da verificare
	 * @return
	 * <ul>
	 * <li>TRUE: l'elemento è da considerare come se fosse un BODY</li>
	 * <li>FALSE: l'elemento non è da considerare come BODY</li>
	 * </ul>
	 */
	function elementBody(element_id)
	{
		var obj = "";
		// controlla che non sia passato come id una stringa predefinita
		if (element_id === "body" || element_id === "document" || element_id === "window")
		{
			return true;
		}
		
		return false;
	}
	
	/**
	 * Cambia lo zIndex di tutti i popup e relaviti overlay del body e sui likeBody in modo che siano sempre on top
	 */
	function showBodyPopupOnTop()
	{
		var
			ii = 0,
			element_id = '',
			element_zIndex = 0,
			popupId = '',
			popupOptions = '';
		
		// scansiono l'array degli OVERLAY
		for (ii = 0; ii < ListOfOverlay_array.length; ii += 1)
		{
			element_id = ListOfOverlay_array[ii][0];
			popupId = 'overlay_' + ListOfOverlay_array[ii][0];
			popupOptions = ListOfOverlay_array[ii][1];
			
			if ((elementLikeBody(element_id)) || elementBody(element_id))
			{
				element_zIndex = $('#' + popupId).css('zIndex') * 1;
				if (element_zIndex < bodyOnTop_zIndexOffset)
				{
					$('#' + popupId).css('zIndex', (element_zIndex + 10000));
				}
			}
			
		}
		
		// scansiono l'array dei POPUP
		for (ii = 0; ii < ListOfPopup_array.length; ii += 1)
		{
			element_id = ListOfPopup_array[ii][0];
			popupId = 'popup_' + ListOfPopup_array[ii][0];
			popupOptions = ListOfPopup_array[ii][1];
			
			if ((elementLikeBody(element_id)) || elementBody(element_id))
			{
				element_zIndex = $('#' + popupId).css('zIndex') * 1;
				if (element_zIndex < bodyOnTop_zIndexOffset)
				{
					$('#' + popupId).css('zIndex', (element_zIndex + 10000));
				}
			}
			
		}
	}
	
	/**
	 * Esegue il refresh per quanto riguarda le dimensioni dell'OVERLAY selezionato
	 * @param element_id id dell'elemento di cui si vuole aggiornare il proprio dell'OVERLAY
	 * @return null
	 */
	function refresh_ListOfOverlay(element_id, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : options;
		
		var width = 0, height = 0, top = 0, left = 0;
		
		if (element_id !== "body" && element_id !== "document" && element_id !== "window" && !elementLikeBody(element_id))
		{
			width = $('#' + element_id).outerWidth();
			height = $('#' + element_id).outerHeight();
			
			//top = $('#' + element_id).position().top;
			//left = $('#' + element_id).position().left;
		} else
		{
			//width = getPageSize(document.body).pageWidth;
			//height = getPageSize(document.body).pageHeight;
			//alert($(document).width());
			width = '100%';
			if ($.browser.msie === true)
			{
				width = 0;
			}
			height = $(document).height();
			$('#' + 'overlay_' + element_id).css('width', width).css('height', height);
			
			width = $(document).width();
			if ($.browser.msie === true)
			{
				width -= (getScrollerWidth() + 4);
			}
			height = $(document).height();
		}

		$('#' + 'overlay_' + element_id).css('width', width).css('height', height);//.css('top', top).css('left', left);
	}
	/**
	 * Esegue il refresh per quanto riguarda le dimensioni e le coordinate del POPUP selezionato
	 * @param element_id id dell'elemento di cui si vuole aggiornare il proprio POPUP
	 * @param options
	 * <ul>
	 * <li>x: posizione x da settare come left predefinito</li>
	 * <li>y: posizione y da settare come top predefinito</li>
	 * </ul>
	 * @return null
	 */
	function refresh_ListOfPopup(element_id, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : options;
		
		var
			top = 0,
			left = 0,
			firstTime = true;
		
		if ($('#popup_' + element_id).css('display') === 'block')
		{
			firstTime = false;
		}
		
		// esegue il refresh della dimensione in modo da catturare i cambiamenti
		//alert(options.width);
		$('#' + 'popup_' + element_id).css('width', options.width).css('height', options.height);
		
		//alert(options.centered);
		// se CENTERED è false il posizionamento della popup verrà calcolato recuperando le informazioni
		// dal template del popup
		if (options.centered === false)
		{
			// con le coordinate specificate il posizionamento segue x e y imposte relativamente all'oggetto
			if (element_id !== "body" && element_id !== "document" && element_id !== "window" && !elementLikeBody(element_id))
			{
				if (firstTime) {
					$('#popup_' + element_id).css('display', 'block');
				}
				if (options.TOOLTIP_POSARROW === 'LEFT')
				{
					if (!SISAL.isNull($('#TOOLTIP_ARROWID_' + element_id).position()))
					{
						top = $('#' + element_id).offset().top + ($('#' + element_id).height() / 2) - ($('#TOOLTIP_ARROWID_' + element_id).position().top + options.TOOLTIP_CENTERTOP);
						left = $('#' + element_id).offset().left + $('#' + element_id).width() - ($('#TOOLTIP_ARROWID_' + element_id).position().left + options.TOOLTIP_CENTERLEFT) + options.TOOLTIP_OFFSETLEFT;
					}
				}
				
				if (options.TOOLTIP_POSARROW === 'RIGHT')
				{
					if (!SISAL.isNull($('#TOOLTIP_ARROWID_' + element_id).position()))
					{
						top = $('#' + element_id).offset().top + ($('#' + element_id).height() / 2) - ($('#TOOLTIP_ARROWID_' + element_id).position().top + options.TOOLTIP_CENTERTOP);
						left = $('#' + element_id).offset().left - ($('#TOOLTIP_ARROWID_' + element_id).position().left + options.TOOLTIP_CENTERLEFT) + options.TOOLTIP_OFFSETLEFT;
					}
				}
				if (firstTime) {
					$('#popup_' + element_id).css('display', 'none');
				}
			} else
			{
				top = 0 + options.y;
				left = 0 + options.x;
			}
		} else
		// se CENTERED è true il posizionamento è centrato o definito dall'utente tramite X e Y
		if (SISAL.isNullOrEmpty(options.x) && SISAL.isNullOrEmpty(options.y))
		{
			if (element_id !== "body" && element_id !== "document" && element_id !== "window" && !elementLikeBody(element_id)) {
				top = $('#' + element_id).offset().top + ($('#' + element_id).outerHeight() / 2) - ($('#' + 'popup_' + element_id).outerHeight() / 2);
				left = $('#' + element_id).offset().left + ($('#' + element_id).outerWidth() / 2) - ($('#' + 'popup_' + element_id).outerWidth() / 2);
			} else {
				top = $(window).scrollTop() + ($(window).height() / 2) - ($('#' + 'popup_' + element_id).outerHeight() / 2);
				left = $(window).scrollLeft() + ($(window).width() / 2) - ($('#' + 'popup_' + element_id).outerWidth() / 2);
			}
		} else
		{
			// con le coordinate specificate il posizionamento segue x e y imposte relativamente all'oggetto
			if (element_id !== "body" && element_id !== "document" && element_id !== "window" && !elementLikeBody(element_id))
			{
				top = $('#' + element_id).offset().top + options.y;
				left = $('#' + element_id).offset().left + options.x;
			} else
			{
				top = 0 + options.y;
				left = 0 + options.x;
			}
		}
		$('#' + 'popup_' + element_id).css('top', top).css('left', left);
	}
	/**
	 * Esegue l'aggiornamento di tutti gli OVERLAY creati
	 * @return null
	 */
	function refresh_AllListOfOverlay()
	{
		var ii = 0;
		// per tutti gli elementi dell'array OVERLAY esegue il refresh
		for (ii = 0; ii < ListOfOverlay_array.length; ii += 1)
		{
			refresh_ListOfOverlay(ListOfOverlay_array[ii][0], ListOfOverlay_array[ii][1]);
		}
	}
	/**
	 * Esegue l'aggiornamento di tutti i POPUP creati
	 * @return null
	 */
	function refresh_AllListOfPopup()
	{
		var ii = 0;
		// per tutti gli elementi dell'array POPUP esegue il refresh
		for (ii = 0; ii < ListOfPopup_array.length; ii += 1)
		{
			refresh_ListOfPopup(ListOfPopup_array[ii][0], ListOfPopup_array[ii][1]);
		}
	}
    /**
     * Esegue l'aggiornamento di tutti gli OVERLAY e di tutti i POPUP creati
     * @return null
     */
    function refresh_AllListOfFunctionality()
    {
        refresh_AllListOfOverlay();
        refresh_AllListOfPopup();
    }
	/***
	 * Trova all'interno della lista dei popup il popup cercato
	 * @param elementId_popup Nome dell'elemento a cui il popup fà riferimento
	 * @return Posizione dell'array riguardo l'elemento ricercato
	 */
	function searchPopup(elementId_popup)
	{
		var ii;
		// scansiona l'array dei popup è verifica se è presente l'id ricercato
		for (ii = 0; ii < ListOfPopup_array.length; ii += 1)
		{
			if (ListOfPopup_array[ii][0] === elementId_popup)
			{
				return ii;
			}
		}
		return -1;
	}
	/***
	 * Elimina tutti i popup aperti
	 */
	function removeOther_popup(options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		options.idToOpen = SISAL.isNullOrEmpty(options.idToOpen) ? '' : options.idToOpen;
		options.group = SISAL.isNullOrEmpty(options.group) ? '' : options.group;
		
		var
			ii = 0,
			popupId = '',
			popupOptions = '';
			
		// scansiona l'array dei popup è verifica se è presente l'id ricercato
		for (ii = 0; ii < ListOfPopup_array.length; ii += 1)
		{
			popupId = 'popup_' + ListOfPopup_array[ii][0];
			popupOptions = ListOfPopup_array[ii][1];
			
			if ('popup_' + options.idToOpen !== popupId)
			{
				if (SISAL.isNullOrEmpty(options.group)) // se non è specificato nessun gruppo chiudo tutto
				{
					$('#' + popupId).remove();
				} else
				{
					if (options.group === popupOptions.group) // rimuovi solo se il gruppo del popup analizzato è uguale al gruppo da voler chiudere
					{
						$('#' + popupId).remove();
					}
				}
			}
		}
		
		// scansiona l'array dei popup è verifica se è presente l'id ricercato
		for (ii = 0; ii < ListOfOverlay_array.length; ii += 1)
		{
			popupId = 'overlay_' + ListOfOverlay_array[ii][0];
			popupOptions = ListOfOverlay_array[ii][1];
			
			if ('overlay_' + options.idToOpen !== popupId)
			{
				if (SISAL.isNullOrEmpty(options.group)) // se non è specificato nessun gruppo chiudo tutto
				{
					$('#' + popupId).remove();
				} else
				{
					if (options.group === popupOptions.group) // rimuovi solo se il gruppo del popup analizzato è uguale al gruppo da voler chiudere
					{
						$('#' + popupId).remove();
					}
				}
			}
		}
	}
	/**
	 * TODO fare la funzione di merge per le options
	 * @param elementId_id
	 * @param options
	 * @return
	 */
	function mergeOptions(elementId_id, options)
	{
		var
			i,
			property;
		//ListOfPopup_array[elementId_id][1]
		                                
	    for (i in options)
		{
			if (options.hasOwnProperty(i))
			{
	            //resultProperty = "";
				property = options[i];
				//myDivHTML = myDivHTML.replace(i, property());
				//alert(i + ' | ' + property);
			}
		}
	}
	
	
	/**
	 * Ricava in base all'id passato se jQuery necessiterà del # o meno
	 * @param element_id id dell'elemento che si vuole elaborare
	 * @return # nel caso in cui l'id passato sia un vero id e non un TAG
	 */
	function getPreSharp(element_id)
	{
		var preObj = "#";
		if (element_id === "body" || element_id === "document" || element_id === "window")
		{
			preObj = "";
		}
		
		return preObj;
	}
	
	/**
	 * 
	 * @param element_id
	 * @return
	 */
	function addToElement_Disable(element_id, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		
		var
			preObj = getPreSharp(element_id),
			id = 'overlay_' + element_id,
			position = 'absolute',
			display = 'block',
			opacity = '0',
			top = 0,
			left = 0,
			width = 0,
			height = 0,
			myDiv = '',
			zIndexOK = zIndex;
		
		if (preObj === "#")
		{
			top = $(preObj + element_id).offset().top;
			left = $(preObj + element_id).offset().left;
			width = $(preObj + element_id).outerWidth();
			height = $(preObj + element_id).outerHeight();
		} else
		{
			top = 0;
			left = 0;
			width = $(document).width();
			height = $(document).height();
			if ($.browser.msie === true)
			{
				width -= (getScrollerWidth() + 4);
			}
			
			//width = getPageSize(document.body).pageWidth;
			//height = getPageSize(document.body).pageHeight;
		}
		
		if ((elementLikeBody(element_id)) || elementBody(element_id))
		{
			zIndexOK = zIndex + bodyOnTop_zIndexOffset;
		}

		myDiv = $("<div id='" + id + "'>");
		myDiv.css('zIndex', zIndexOK).css('background-color', '#cecece').css('position', 'absolute').css('display', 'none').css('opacity', '0').css('top', top).css('left', left).css('width', width).css('height', height);
		zIndex += 1;

		$('body').append(myDiv);
		
		ListOfOverlay_array[ListOfOverlay_array.length] = [];
		ListOfOverlay_array[ListOfOverlay_array.length - 1].push(element_id);	// posizione 0
		ListOfOverlay_array[ListOfOverlay_array.length - 1].push(options);		// posizione 1

	}
	/**
	 * Questa funzione crea il popup relativo all'elemento selezionato
	 * @param element_id è l'id dell'elemento a cui si vuole associare il popup
	 * @return null
	 */
	function addToElement_Popup(element_id, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		
		var
			preObj = getPreSharp(element_id),
			id = 'popup_' + element_id,
			position = 'absolute',
			display = 'block',
			opacity = '0',
			myDiv = '',
			zIndexOK = zIndex;
			
		
		if ((elementLikeBody(element_id)) || elementBody(element_id))
		{
			zIndexOK = zIndex + bodyOnTop_zIndexOffset;
		}
		
		myDiv = $("<div id='" + id + "'>");
		myDiv.css('zIndex', zIndexOK).css('position', 'absolute').css('display', 'none').css('opacity', '0');

		if (!SISAL.isNullOrEmpty(options.width)) {
			myDiv.css('width', options.width);
		}
		if (!SISAL.isNullOrEmpty(options.height)) {
			myDiv.css('height', options.height);
		}
		
		zIndex += 1;

		$('body').append(myDiv);
		
		ListOfPopup_array[ListOfPopup_array.length] = [];
		ListOfPopup_array[ListOfPopup_array.length - 1].push(element_id);	// posizione 0
		ListOfPopup_array[ListOfPopup_array.length - 1].push(options);		// posizione 1
	}
	
	
	/**
	 * Questa funzione crea il contenitore dell'overlay relativo all'elemento selezionato
	 * @param element_id id dell'elemento per cui si vuole creare l'overlay
	 * @return
	 */
	function showOnElement_Overlay(element_id, options)
	{
		$(document).ready(function ()
		{
			options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
			
			options.fading = SISAL.isNullOrEmpty(options.fading) ? 'slow' : options.fading;
			
			options.group = SISAL.isNullOrEmpty(options.group) ? '' : options.group;
			options.removeOther = SISAL.isNullOrEmpty(options.removeOther) ? false : options.removeOther;
			
			if (options.removeOther === true)
			{
				removeOther_popup({idToOpen: element_id, group: options.group});
			}
			
			// controlla se l'overlay sull'elemento esiste già
			if (SISAL.isNull(document.getElementById('overlay_' + element_id))) {
				addToElement_Disable(element_id, options);
			} else
			{
				// aggiorna il layer di stampa dell'oggetto
				$('#overlay_' + element_id).css('zIndex', zIndex);
				zIndex += 1;
			}
			
			$('#overlay_' + element_id).fadeTo('slow', 0.7, function () {
				$('#overlay_' + element_id).css('display', 'block');
			});
			
			addToElementDiv_makeLikeBody();
			//refresh_AllListOfFunctionality();
			refresh_AllListOfOverlay();
			showBodyPopupOnTop();
		});
	}
	
	/**
	 * Questa funzione crea il contenitore della popup relativa all'elemento selezionato
	 * @param element_id id dell'elemento per cui si vuole creare il popup
	 * @param options
	 * <ul>
     * <li> url: se passata nel popup verrà caricato il risultato della chiamata a questa url </li>
     * <li> html: se passata nel popup verrà visualizzato l'html richiesto </li>
     * </ul>
	 * @return
	 */
	function showOnElement_Popup(element_id, options)
	{
		$(document).ready(function ()
		{
			// gestione options
			options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
			options.method = options.method !== "GET" ? "POST" : options.method;
			options.async = options.async !== false ? true : options.async;
			options.softSync = options.softSync !== false ? true : options.softSync;
			options.javascript = options.javascript !== false ? true : options.javascript;
			options.nextStep = ((typeof options.nextStep !== "boolean") || (SISAL.isNull(options.nextStep))) ? false : options.nextStep;
			
			options.centered = SISAL.isNullOrEmpty(options.centered) ? true : options.centered;
			
			options.group = SISAL.isNullOrEmpty(options.group) ? '' : options.group;
			options.removeOther = SISAL.isNullOrEmpty(options.removeOther) ? false : options.removeOther;
			
			options.fading = SISAL.isNullOrEmpty(options.fading) ? 'slow' : options.fading;
			
			options.width = SISAL.isNullOrEmpty(options.width) ? null : options.width;
			options.height = SISAL.isNullOrEmpty(options.height) ? null : options.height;
			options.x = SISAL.isNullOrEmpty(options.x) ? null : options.x;
			options.y = SISAL.isNullOrEmpty(options.y) ? null : options.y;
			
			var
				elementId_id = -1;
			
			if (options.removeOther === true)
			{
				removeOther_popup({idToOpen: element_id, group: options.group});
			}
			
			// controlla se il popup sull'elemento esiste già
			if (SISAL.isNull(document.getElementById('popup_' + element_id)))
			{
				addToElement_Popup(element_id, options);
			} else
			{
				// aggiorna il layer di stampa della popup
				$('#popup_' + element_id).css('zIndex', zIndex);
				zIndex += 1;
			}
			
			if (!SISAL.isNull(options.url))
			{
				SISAL.ajax(options.url, {
					target: 'popup_' + element_id,
					method: options.method,
					async: options.async,
					softSync: options.softSync,
					javascript: options.javascript,
					response: true,
					success: function (html)
					{
						$('#popup_' + element_id).html(html);
						
						setTimeout(function ()
						{
						    if (!options.nextStep)
						    {
						        refresh_ListOfPopup(element_id, options);
						    }
							
						    $('#popup_' + element_id).fadeTo(options.fading, 1, function () {
						        $('#popup_' + element_id).css('display', 'block');
						    });
						}, '500');
					}
				});
				
			} else
			if (!SISAL.isNull(options.html))
			{
				$('#popup_' + element_id).html(options.html);
					
				setTimeout(function ()
				{
				    if (!options.nextStep)
				    {
				        refresh_ListOfPopup(element_id, options);
				    }

				    $('#popup_' + element_id).fadeTo(options.fading, 1, function () {
				        $('#popup_' + element_id).css('display', 'block');
				    });
				}, '500');
			}
			
			elementId_id = searchPopup(element_id);
			//mergeOptions(elementId_id, options);
			
			ListOfPopup_array[elementId_id][1].centered = options.centered;
			ListOfPopup_array[elementId_id][1].width = options.width;
			ListOfPopup_array[elementId_id][1].height = options.height;
			ListOfPopup_array[elementId_id][1].x = options.x;
			ListOfPopup_array[elementId_id][1].y = options.y;
			
			if (typeof(TOOLTIP_CENTERTOP) !== 'undefined')
			{
				ListOfPopup_array[elementId_id][1].TOOLTIP_CENTERTOP = TOOLTIP_CENTERTOP;
				options.TOOLTIP_CENTERTOP = TOOLTIP_CENTERTOP;
			}
			
			if (typeof(TOOLTIP_CENTERLEFT) !== 'undefined')
			{
				ListOfPopup_array[elementId_id][1].TOOLTIP_CENTERLEFT = TOOLTIP_CENTERLEFT;
				options.TOOLTIP_CENTERLEFT = TOOLTIP_CENTERLEFT;
			}
			
			if (typeof(TOOLTIP_POSARROW) !== 'undefined')
			{
				ListOfPopup_array[elementId_id][1].TOOLTIP_POSARROW = TOOLTIP_POSARROW;
				options.TOOLTIP_POSARROW = TOOLTIP_POSARROW;
			}
			
			if (typeof(TOOLTIP_OFFSETTOP) !== 'undefined')
			{
				ListOfPopup_array[elementId_id][1].TOOLTIP_OFFSETTOP = TOOLTIP_OFFSETTOP;
				options.TOOLTIP_OFFSETTOP = TOOLTIP_OFFSETTOP;
			}
			
			if (typeof(TOOLTIP_OFFSETLEFT) !== 'undefined')
			{
				ListOfPopup_array[elementId_id][1].TOOLTIP_OFFSETLEFT = TOOLTIP_OFFSETLEFT;
				options.TOOLTIP_OFFSETLEFT = TOOLTIP_OFFSETLEFT;
			}
			
			if (!SISAL.isNull($('#TOOLTIP_ARROWID').position()))
			{
				$('#TOOLTIP_ARROWID').attr('id', 'TOOLTIP_ARROWID_' + element_id); // sostituisco l'id del template caricato
			}
			
			//if (options.nextStep)
			//{
			addToElementDiv_makeLikeBody();
			refresh_ListOfPopup(element_id, options);
			showBodyPopupOnTop();
			//}
		});
	}
	
	function hideOnElement_Overlay(element_id) {
		if ($('#overlay_' + element_id).length !== 0)
		{
			if ($('#overlay_' + element_id).css('display') === 'block')
			{
				$('#overlay_' + element_id).fadeTo('slow', 0, function () {
					$('#overlay_' + element_id).css('display', 'none');
				});
			} else
			{
				window.setTimeout("SISAL.FX.hideOnElement_Overlay('" + element_id + "')", 50);
			}
		} else
		{
			window.setTimeout("SISAL.FX.hideOnElement_Overlay('" + element_id + "')", 50);
		}
	}
	function hideOnElement_Popup(element_id) {
		//alert('hideOnElement_Popup - element_id: |'+element_id+'|');
		if ($('#popup_' + element_id).length !== 0)
		{
			if ($('#popup_' + element_id).css('display') === 'block')
			{
				$('#popup_' + element_id).fadeTo('slow', 0, function () {
					$('#popup_' + element_id).css('display', 'none');
				});
			} else
			{
				window.setTimeout("SISAL.FX.hideOnElement_Popup('" + element_id + "')", 50);
			}
		} else
		{
			window.setTimeout("SISAL.FX.hideOnElement_Popup('" + element_id + "')", 50);
		}
	}
	
	function removeOnElement_Popup(element_id) {
		var elementId_id = searchPopup(element_id);
		//SISAL.logger.info(elementId_id);
		if (elementId_id !== -1 && !SISAL.isNull($('#popup_' + element_id).get()[0]))
		{
			//SISAL.logger.info($('#popup_' + element_id).get()[0]);
			ListOfPopup_array.splice(elementId_id);
			$('#popup_' + element_id).remove();
		} else
		{
			//SISAL.logger.info('nome:'+element_id+ '  | a:' + $('#popup_' + element_id).get()[0] + ' | b:'+elementId_id);
			if (!SISAL.isNull($('#popup_' + element_id).get()[0]) && elementId_id === -1)
			{
				$('#popup_' + element_id).remove();
			} else
			if (SISAL.isNull($('#popup_' + element_id).get()[0]) && elementId_id !== -1)
			{
				ListOfPopup_array.splice(elementId_id);
			} else
			{
				window.setTimeout("SISAL.FX.removeOnElement_Popup('" + element_id + "')", 100);
			}
		}
	}
	
	/**
	 * Mostra la popup dopo aver oscurato l'elemento richiesto (element_id)
	 * @param element_id Elemento su cui si vuole mostrare la popup
	 * @param options
	 * @return null
	 */
	function showOnElement_OverlayPopup(element_id, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		
		// funzioni da eseguire alla "load" della pagina
		showOnElement_Overlay(element_id, options);
		showOnElement_Popup(element_id, options);
	}
	/**
	 * Nasconde la popup sull'elemento selezionato
	 * @param element_id
	 * @return
	 */
	function hideOnElement_OverlayPopup(element_id)
	{
		hideOnElement_Overlay(element_id);
		hideOnElement_Popup(element_id);
	}
	
	function jsParse(property, element_id)
	{
		
		var
			i,
			resultProperty = "",
			resultData = "",
			splittedProperty;
	
		splittedProperty = property.split('|');
		//alert(property + " | " + splittedProperty);
		
		for (i = 0; i < splittedProperty.length; i += 1)
		{
			// <href:*>
			resultProperty = (splittedProperty[i].search("<href:") !== -1) ? (splittedProperty[i].substring("<href:".length, splittedProperty[i].search(">"))) : resultProperty;
			splittedProperty[i] = (splittedProperty[i].search("<href:") !== -1) ? "<_href>" : splittedProperty[i];
			
			// <hideThis:*>
			resultProperty = (splittedProperty[i].search("<hideThis:") !== -1) ? (splittedProperty[i].substring("<hideThis:".length, splittedProperty[i].search(">"))) : resultProperty;
			splittedProperty[i] = (splittedProperty[i].search("<hideThis:") !== -1) ? "<_hideThis>" : splittedProperty[i];
			
			// <hideOverlay:*>
			resultProperty = (splittedProperty[i].search("<hideOverlay:") !== -1) ? (splittedProperty[i].substring("<hideOverlay:".length, splittedProperty[i].search(">"))) : resultProperty;
			splittedProperty[i] = (splittedProperty[i].search("<hideOverlay:") !== -1) ? "<_hideOverlay>" : splittedProperty[i];
			
			// <hidePopup:*>
			resultProperty = (splittedProperty[i].search("<hidePopup:") !== -1) ? (splittedProperty[i].substring("<hidePopup:".length, splittedProperty[i].search(">"))) : resultProperty;
			splittedProperty[i] = (splittedProperty[i].search("<hidePopup:") !== -1) ? "<_hidePopup>" : splittedProperty[i];
			
			//alert("|" + splittedProperty[i] + "|");
			switch (splittedProperty[i])
			{
			// hideThis: sostuisce con javascript che nasconde il popup e l'overlay selezionato
			case "<hideThis>":
				resultData += "SISAL.FX.hideOnElement_OverlayPopup('" + element_id + "');";
				break;
			// _hideThis: sostuisce con javascript che nasconde il popup e l'overlay selezionato
			case "<_hideThis>":
				resultData += "SISAL.FX.hideOnElement_OverlayPopup('" + resultProperty + "');";
				break;
				
			// hideOverlay: sostuisce con javascript che nasconde l'overlay selezionato
			case "<hideOverlay>":
				resultData += "SISAL.FX.hideOnElement_Overlay('" + element_id + "');";
				break;
			// _hideOverlay: sostuisce con javascript che nasconde l'overlay selezionato
			case "<_hideOverlay>":
				resultData += "SISAL.FX.hideOnElement_Overlay('" + resultProperty + "');";
				break;
			
			// hidePopup: sostuisce con javascript che nasconde l'overlay selezionato
			case "<hidePopup>":
				resultData += "SISAL.FX.hideOnElement_Popup('" + element_id + "');";
				break;
			// _hidePopup: sostuisce con javascript che nasconde l'overlay selezionato
			case "<_hidePopup>":
				resultData += "SISAL.FX.hideOnElement_Popup('" + resultProperty + "');";
				break;
			
			// _url: sostuisce con javascript che esegue il reindirizzamento ad una url
			case "<_href>":
				resultData += "location.href='" + resultProperty + "';";
				break;
			
			// null: sostuisce con javascript che non esegue nulla
			case "<null>":
				resultData += "void(0);";
				break;
			
			// sostituisce con il testo inserito dallo sviluppatore
			default:
				resultData += splittedProperty[i];
				break;
			}
		}
		
		return resultData;
	}
	
	/**
	 * Questa funzione genera un popup a video a cui viene associato un template
	 * @param element_id Id dell'oggetto su cui si vuole realizzare il popup
	 * @param template_url Url del template che si vuole utilizzare
	 * @param options Tramite un'associazione di stringhe viene compilato il template (width e height definiscono le dimensioni minime del popup nel caso siano settate)
	 * @return null
	 */
	function showOnElement_TemplatePopup(element_id, urlTemplate, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		options.width = SISAL.isNullOrEmpty(options.width) ? null : options.width;
		options.height = SISAL.isNullOrEmpty(options.height) ? null : options.height;
		options.overlay = SISAL.isNullOrEmpty(options.overlay) ? true : options.overlay;
		options.folderTemplate = SISAL.isNull(options.folderTemplate) ? null : options.folderTemplate;
		options.nextStep = ((typeof options.nextStep !== "boolean") || (SISAL.isNull(options.nextStep))) ? false : options.nextStep;
		
		options.centered = SISAL.isNullOrEmpty(options.centered) ? true : options.centered;
		
		options.group = SISAL.isNullOrEmpty(options.group) ? '' : options.group;
		options.removeOther = SISAL.isNullOrEmpty(options.removeOther) ? false : options.removeOther;
		
		options.fading = SISAL.isNullOrEmpty(options.fading) ? 'slow' : options.fading;
		
		options.x = SISAL.isNullOrEmpty(options.x) ? null : options.x;
		options.y = SISAL.isNullOrEmpty(options.y) ? null : options.y;
		
		var 
			i,
			property,
			myDiv = "",
			myDivHTML = "",
			url_css = "",
			completeUrlTemplate = "/templates/" + urlTemplate;
		
		if (!SISAL.isNull(options.folderTemplate))
		{
			completeUrlTemplate = options.folderTemplate + urlTemplate;
		}
		
		$.ajax(
		{
			url: completeUrlTemplate,
			success: function (data)
			{
				var
					i,
					resultProperty = "";
				
				myDivHTML = data;
				
				if (!SISAL.isNull(options) && (typeof options === "object"))
		        {
					for (i in options)
					{
						if (options.hasOwnProperty(i))
						{
	                        resultProperty = "";
							property = options[i];
							
							if (i !== 'width' && i !== 'height' && i !== 'x' && i !== 'y' && i !== 'centered')
							{
								if (typeof property === "string")
								{
									myDivHTML = myDivHTML.replace(i, jsParse(property, element_id));
								} else
								{
									if (typeof property === "function")
									{
										myDivHTML = myDivHTML.replace(i, property());
									}
								}
							}
						}
					}
		        }
				
				// carica il CSS del template nell'HEAD del sito
				if (myDivHTML.search('<link type="text/css" rel="stylesheet" href="') !== -1)
				{
					url_css = myDivHTML.substring(myDivHTML.search('<link type="text/css" rel="stylesheet" href="') + '<link type="text/css" rel="stylesheet" href="'.length, myDivHTML.search('">'));
					if (SISAL.logger.isDebugEnabled())
					{
						SISAL.logger.debug("showOnElement_TemplatePopup - Controllo CSS (v0.1)");
						SISAL.logger.debug("showOnElement_TemplatePopup - CSSurl:" + url_css);
					}
					SISAL.loadCSS(url_css);
				}
				
				if (options.overlay === true)
				{
					showOnElement_OverlayPopup(element_id, {html: myDivHTML, width: options.width, height: options.height, centered: options.centered, x: options.x, y: options.y, nextStep: options.nextStep, fading: options.fading, removeOther: options.removeOther, group: options.group});
				} else
				{
					showOnElement_Popup(element_id, {html: myDivHTML, width: options.width, height: options.height, centered: options.centered, x: options.x, y: options.y, nextStep: options.nextStep, fading: options.fading, removeOther: options.removeOther, group: options.group});
				}
			}
		});
	}
	
	/**
	 * Aggiunge al tag input specificato la funzionalità di HELP (mostra il testo di help e lo cancella in caso di selezione)
	 * @param elementId Id dell'elemento input a cui si vuole applicare tale funzionalità
	 * @param verifyName Nome di verifica da controllare
	 * @param options Eventuali opzioni
	 * @return
	 */
	function addToInput_HelpText(elementId, verifyName, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		options.styleIn = SISAL.isNullOrEmpty(options.styleIn) ? null : options.styleIn;
		options.styleOut = SISAL.isNullOrEmpty(options.styleOut) ? null : options.styleOut;
		
		$('#' + elementId).focus(function () {
			if (this.value === verifyName)
			{
				this.value = "";
			}
		});
		
		$('#' + elementId).blur(function () {
			if (this.value === "")
			{
				this.value = verifyName;
			}
		});
	}
	
	/**
	 * Funzione che mostra o nasconde un oggetto (targetId)
	 * @param targetId Id dell'oggetto su cui viene eseguita la funzionalità
	 * @param options
	 * <ul>
	 * <li><b>velocity</b>: velocità di comparsa scomparsa (default: 'slow') SLOW || FAST</li>
	 * <li><b>complete</b>: funzione che viene eseguita al termine dell'operazione fatta</li>
	 * </ul>
	 * @return
	 */
	function slideToggle(targetId, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		options.velocity = SISAL.isNullOrEmpty(options.velocity) ? 'slow' : options.velocity;
		options.complete = (SISAL.isNullOrEmpty(options.complete) || (typeof options.complete !== "function")) ? function () {} : options.complete;
        
		options.rotate = SISAL.isNullOrEmpty(options.rotate) ? {} : SISAL.copy(options.rotate);
		options.rotate.target = (SISAL.isNullOrEmpty(options.rotate.target) || (typeof options.rotate.target !== "string")) ? null : options.rotate.target;
		options.rotate.angle = (SISAL.isNullOrEmpty(options.rotate.angle) || (typeof options.rotate.angle !== "number")) ? null : options.rotate.angle;
		options.rotate.whence = (SISAL.isNullOrEmpty(options.rotate.whence) || (typeof options.rotate.whence !== "string")) ? 'rel' : options.rotate.whence;
		
		var
			angle_cp = options.rotate.angle,
			preObj_targetId = getPreSharp(targetId),
			preObj_targetImg;
		
		$(preObj_targetId + targetId).slideToggle(options.velocity, function ()
		{
			// Animation complete.
			// eseguo la rotazione in caso sia necessaria
			if (!SISAL.isNullOrEmpty(options.rotate) && !SISAL.isNullOrEmpty(options.rotate.target) && !SISAL.isNullOrEmpty(options.rotate.angle))
			{
				/*
				 * http://code.google.com/p/jquery-rotate/wiki/Reference
				 */
				preObj_targetImg = getPreSharp(options.rotate.target);
				
				options.rotate.angle = angle_cp;
				
				if ($(preObj_targetImg + options.rotate.target).attr("used") === 'true')
				{
					if (options.rotate.angle < 0)
					{
						options.rotate.angle = Math.abs(options.rotate.angle);
					} else
					{
						options.rotate.angle -= angle_cp * 2;
					}
					
					$(preObj_targetImg + options.rotate.target).rotate(options.rotate.angle);
					$(preObj_targetImg + options.rotate.target).attr("used", 'false');
				} else
				{
					$(preObj_targetImg + options.rotate.target).rotate(options.rotate.angle);
					$(preObj_targetImg + options.rotate.target).attr("used", 'true');
				}
			}
			
			// eseguo la funzione che ha prestabilito lo sviluppatore
			options.complete();
		});
	}
	
	/**
	 * Funzione che mostra o nasconde un oggetto (targetId) in seguito al click su un secondo oggetto (buttonId)
	 * @param targetId Id dell'oggetto su cui viene eseguita la funzionalità
	 * @param buttonId Id del "pulsante" che deve essere cliccato per lanciare la procedura
	 * @param options
	 * <ul>
	 * <li><b>velocity</b>: velocità di comparsa scomparsa (default: 'slow') SLOW || FAST</li>
	 * <li><b>complete</b>: funzione che viene eseguita al termine dell'operazione fatta</li>
	 * </ul>
	 * @return
	 */
	function addToElement_slideToggle(targetId, buttonId, options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		
		var preObj_buttonId = getPreSharp(buttonId);
		
		$(preObj_buttonId + buttonId).click(function ()
		{
			slideToggle(targetId, options);
		});
	}
	
	/**
	 * TODO fare una funziona che permetta di risolvere i problemi relativi alle PNG per IE
	 * @return
	 */
	function pngFix()
	{
		if ($.browser.msie === true)
		{
			$(document).pngFix();
		}
	}
	
	/**
	 * permette di accedere al documento dell'iframe in base al browser utilizzato
	 * @param iframe Iframe di cui si vuole accere al documento
	 * @return documento dell'iframe passato
	 */
	function iframeDocument(iframe)
	{
		var doc = null;
		if (iframe.contentDocument) {
			doc = iframe.contentDocument;  // Firefox, Opera
		}
		else if (iframe.contentWindow) {
			doc = iframe.contentWindow.document; // Internet Explorer
		}
		else if (iframe.document) {  
			doc = iframe.document; // Others?  
		}
		return doc;
	}
	/**
	 * permette di accedere al documento dell'iframe in base al browser utilizzato
	 * @param iframe Iframe di cui si vuole accere al window
	 * @return window dell'iframe passato
	 */
	function iframeWindow(iframe)
	{
		var doc = null;
		if (iframe.contentWindow) {
			doc = iframe.contentWindow;  // Firefox, Opera  , Internet Explorer
		}
		else if (iframe.window) {  
			doc = iframe.document; // Others?  
		}
		return doc;
	}

	/**
	 * Funzione che permette la stampa della pagina o di un documento preciso
	 * @param options
	 * <ul>
     * <li> url: url della pagina che si desidera stampare </li>
     * <li> html: html che si vuole stampare </li>
     * </ul>
	 */
	function print(options)
	{
		options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
		options.url = SISAL.isNullOrEmpty(options.url) ? '' : options.url;
		options.html = SISAL.isNullOrEmpty(options.html) ? '' : options.html;
		
		var
			myIframe = '',
			rndNumber = Math.ceil(Math.random() * 1000000),
			id = 'iframePrint_' + rndNumber,
			width = 0,
			height = 0;
		
		// solo se URL o HTML sono settati può essere effettuata la stampa
		if (!(SISAL.isNullOrEmpty(options.url) && SISAL.isNullOrEmpty(options.html)))
		{
			// crea l'iframe che servirà per gestire la stampa
			myIframe = $("<iframe id='" + id + "' title='' frameborder='0' width='0' height='0'>");
			myIframe.css('opacity', '0').css('width', width).css('height', height);
			
			// se si tratta di un'URL da stampare
			if (!SISAL.isNullOrEmpty(options.url))
			{
				myIframe.attr('src', options.url); // definisco che url voglio stampare
				myIframe.load(function () {
					iframeWindow($('#' + id).get()[0]).focus(); // dò il focus all'iframe creato (per IE)
					iframeWindow($('#' + id).get()[0]).print(); // eseguo la stampa dell'iframe creato
					setTimeout("$('#" + id + "').remove()", '60000'); // dopo un minuto elimina l'iframe creato
				});
			}
			
			// se si tratta di un HTML da stampare
			if (!SISAL.isNullOrEmpty(options.html))
			{
				myIframe.load(function () {
					iframeDocument($('#' + id).get()[0]).body.innerHTML = options.html; // definisco l'html che voglio stampare
					iframeWindow($('#' + id).get()[0]).focus(); // dò il focus all'iframe creato (per IE)
					iframeWindow($('#' + id).get()[0]).print(); // eseguo la stampa dell'iframe creato
					setTimeout("$('#" + id + "').remove()", '60000'); // dopo un minuto elimina l'iframe creato
				});
			}
			
			// appendo al body l'iframe
			$('body').append(myIframe);
		} else
		{
			// se URL o HTML non sono settati chiamo la print standard del javascript
			window.print();
		}
	}
	
	/**
     * La funzione apre una finestra.
     * @param options
     * <ul>
     * <li> url la url della pagina da aprire (opzionale, default: null) STRING </li>
     * <li> name: "_blank"|"_parent"|"_self"|"_top"|name (l'attributo target o il nome della finestra) (opzionale, default: _blank) STRING </li>
     * <li> height: l'altezza della finestra in pixel, almeno 100 (opzionale, default: 100) NUMBER </li>
     * <li> left: la posizione da sinistra della finestra in pixel (opzionale, default: 0) NUMBER </li>
     * <li> location: "yes"|"no"|1|0 se mostrare la barra degli indirizzi (opzionale, default: "yes") STRING </li>
     * <li> menubar: "yes"|"no"|1|0 se mostrare la barra del menu (opzionale, default: "yes") STRING </li>
     * <li> resizable: "yes"|"no"|1|0 se la finestra è ridimensionabile (opzionale, default: "yes") STRING </li>
     * <li> scrollbars: "yes"|"no"|1|0 se mostrare le barre di scorrimento (opzionale, default: "yes") STRING </li>
     * <li> status: "yes"|"no"|1|0 se mostrare la barra dello stato (opzionale, default: "yes") STRING </li>
     * <li> titlebar: "yes"|"no"|1|0 se mostrare la barra del titolo (opzionale, default: "yes") STRING </li>
     * <li> toolbar: "yes"|"no"|1|0 se mostrare la barra degli strumenti (opzionale, default: "yes") STRING </li>
     * <li> top: la posizione dall'alto della finestra in pixel (opzionale, default: 0) NUMBER </li>
     * <li> width: la larghezza della finestra in pixel, almeno 100 (opzionale, default: 100) NUMBER </li>
     * <li> replace: true|false (per sostituire la voce corrente o crearne una nuova nello storico) (opzionale, default: false) BOOLEAN </li>
     * <li> centered: true|false se il popup deve essere centrato rispetto allora schermo (default: false) BOOLEAN </li>
     * </ul>
     * @return la finestra
     * @type object
     */
    function open(options)
    {
        var myWindow;
        try
        {
            if (SISAL.logger.isDebugEnabled())
            {
                SISAL.logger.debug("open - inizio");
                SISAL.logger.debug("open - options:\n" + SISAL.toStringAsLiteral(options));
            }

            // gestione options
            options = SISAL.isNullOrEmpty(options) ? {} : SISAL.copy(options);
            options.url = typeof options.url !== "string" ? null : options.url;
            options.name = typeof options.name !== "string" ? "_blank" : options.name;
            options.height = typeof options.height !== "number" ? 100 : options.height;
            options.left = typeof options.left !== "number" ? 0 : options.left;
            options.location = typeof options.location !== "string" ? "yes" : options.location;
            options.menubar = typeof options.menubar !== "string" ? "yes" : options.menubar;
            options.resizable = typeof options.resizable !== "string" ? "yes" : options.resizable;
            options.scrollbars = typeof options.scrollbars !== "string" ? "yes" : options.scrollbars;
            options.status = typeof options.status !== "string" ? "yes" : options.status;
            options.titlebar = typeof options.titlebar !== "string" ? "yes" : options.titlebar;
            options.toolbar = typeof options.toolbar !== "string" ? "yes" : options.toolbar;
            options.top = typeof options.top !== "number" ? 0 : options.top;
            options.width = typeof options.width !== "number" ? 100 : options.width;
            options.replace = options.replace !== true ? false : options.replace;
            
            options.centered = typeof options.centered !== "boolean" ? false : options.centered;
            if (options.centered === true)
            {
                options.left = (screen.width - options.width) / 2;
                options.top = 0;
            }
            
            options.fixed = typeof options.fixed !== "boolean" ? false : options.fixed;
            if (options.fixed === true)
            {
                options.location = 'no';
                options.menubar = 'no';
                options.resizable = 'no';
                options.status = 'no';
                options.titlebar = 'no';
                options.toolbar = 'no';
            }
            
            if (SISAL.logger.isTraceEnabled())
            {
                SISAL.logger.trace("open - options:\n" + SISAL.toStringAsLiteral(options));
                SISAL.logger.trace("open - specs:\n" + "height=" + options.height +
                        ",left=" + options.left +
                        ",location=" + options.location +
                        ",menubar=" + options.menubar +
                        ",resizable=" + options.resizable +
                        ",scrollbars=" + options.scrollbars +
                        ",status=" + options.status +
                        ",titlebar=" + options.titlebar +
                        ",toolbar=" + options.toolbar +
                        ",top=" + options.top +
                        ",width=" + options.width +
                        ",centered=" + options.centered
                );
            }
            
            myWindow = window.open(options.url,
                    options.name,
                    "height=" + options.height +
                    ",left=" + options.left +
                    ",location=" + options.location +
                    ",menubar=" + options.menubar +
                    ",resizable=" + options.resizable +
                    ",scrollbars=" + options.scrollbars +
                    ",status=" + options.status +
                    ",titlebar=" + options.titlebar +
                    ",toolbar=" + options.toolbar +
                    ",top=" + options.top +
                    ",width=" + options.width,
                    options.replace);
            
            if (SISAL.logger.isDebugEnabled())
            {
                SISAL.logger.debug("open - fine");
            }
        }
        catch (e)
        {
            if (SISAL.logger.isErrorEnabled())
            {
                SISAL.logger.error("open - ", e);
            }
        }
        return myWindow;
    }
    
    /**
     * Aggiunge la funzione "addToElementWithClass_slideToggle()" a tutti gli elementi che hanno come classe
     * "addFunction_slideToggle"
     * @return null
     */
    function addToElementWithClass_slideToggle_init()
    {
        var className = "addFunction_slideToggle",
			className_new = "addFunction_slideToggle_new",
            numeroTrovati = 0,
            i = 0,
            objWithClass = "",
            objsWithClass = "",
            div1 = "",
            div2 = "",
            div1HTML = "",
            div2HTML = ""
            ;
        
        objsWithClass = $('.' + className);
		objsWithClass.removeClass(className);
		objsWithClass.addClass(className_new);
		
        numeroTrovati = objsWithClass.get().length;
        
        // se almeno è stato trovato un oggetto con la classe richiesta
        if (numeroTrovati > 0)
        {
            for (i = 0; i < numeroTrovati; i += 1)
            {
                objWithClass = $(objsWithClass.get()[i]);
                // controllo che l'oggetto su cui è stata messa la classe sia un div
                if (objWithClass.is('div'))
                {
                    // controllo che l'oggetto selezionato contenga i due TAG P
                    if (objWithClass.children().length === 2)
                    {
                        div1 = $(objWithClass.children()[0]);
                        div2 = $(objWithClass.children()[1]);
                        
                        div2.hide();
                        
						//div1HTML  = div1.html();
                        //div2HTML = div2.html();
                        
                        //div1.css('margin-top', '12px');
                        //div1.css('margin-bottom', '12px');
                        //div1.css('cursor', 'pointer');
                        //$('*', div1).css('cursor', 'pointer');
                        
						//div2.css('margin-left', '10px');
						//div2.css('margin-right', '10px');
						
                        //div1.addClass('addFunction_slideToggle_div1');
                        //div2.addClass('addFunction_slideToggle_div2');
                        
                        //div2.html("<table style='width:100%;' cellspacing='0' cellpadding='0' border='0'><tr valign='top'><td>" + div2HTML + "</td></tr><tr><td align='right'><div class='addFunction_slideToggle_buttonChiudi' onclick='SISAL.FX.addToElementWithClass_slideUp(this);'>[ chiudi ]</div><div class='addFunction_slideToggle_bottomContent'>&nbsp;</div></td></tr></table>");
                        
                        //objWithClass.css('display', 'block');
                        
                        div1.click(function ()
                        {
                            //SISAL.FX.addToElementWithClass_slideDown($(this), $(this).next());
                            SISAL.FX.addToElementWithClass_slideToggle($(this), $(this).next());
                        });
                    }
                }
            }
        }
    }
	function addToElementWithClass_slideUp(obj)
    {
		var
			div1 = "",
			div2 = ""
			;
			
		div2 = $($(obj).parentsUntil(".addFunction_slideToggle_div2").parent().get()[0]);
		div1 = div2.prev();
		
		//div1.css('cursor', 'pointer');
		//$('*', div1).css('cursor', 'pointer');
		
		$(div2).slideUp('fast', function () {
			
		});
	}
	function addToElementWithClass_slideToggle(div1, div2)
    {
		//div1.css('cursor', 'default');
		//$('*', div1).css('cursor', 'default');
		$(div2).slideToggle('fast', function () {
			
		});
	}
	function addToElementWithClass_slideDown(div1, div2)
    {
		//div1.css('cursor', 'default');
		//$('*', div1).css('cursor', 'default');
		$(div2).slideDown('fast', function () {
			
		});
	}
	
	function addToElementInput_TextPasswordSwitch(obj)
	{
		var
			newObj = '',
			oldvalue = $(obj).attr('value'),
			id = $(obj).attr('id'),
			name = $(obj).attr('name'),
			maxlength = $(obj).attr('maxlength'),
			style = $(obj).attr('style'),
			onclick = obj.getAttribute('onclick'),
			onmouseover = obj.getAttribute('onmouseover'),
			onmouseout = obj.getAttribute('onmouseout'),
			onkeypress = obj.getAttribute('onkeypress'),
			onfocus = obj.getAttribute('onfocus'),
			onblur = obj.getAttribute('onblur'),
			oldfocus = $(obj).attr('oldfocus'),
			oldblur = $(obj).attr('oldblur')
			;
			
		if ($(obj).attr('type') === "text")
		{
			newObj = $("<input id='" + id + "' type='password' >");
			
			if (SISAL.isNull(oldfocus))
			{
				newObj.attr('oldfocus', onfocus);
			} else
			{
				newObj.attr('oldfocus', oldfocus);
			}
			
			if (SISAL.isNull(oldblur))
			{
				newObj.attr('oldblur', onblur);
			} else
			{
				newObj.attr('oldblur', oldblur);
			}
			
			newObj.attr('value', '');
			newObj.attr('oldvalue', oldvalue);
			
			if (!SISAL.isNullOrEmpty(name)) {
				newObj.attr('name', name);
			}
			if (!SISAL.isNullOrEmpty(maxlength)) {
				newObj.attr('maxlength', maxlength);
			}
			if (!SISAL.isNullOrEmpty(style)) {
				newObj.attr('style', style);
			}
			if (!SISAL.isNullOrEmpty(onclick)) {
				newObj.attr('onclick', onclick);
			}
			if (!SISAL.isNullOrEmpty(onmouseover)) {
				newObj.attr('onmouseover', onmouseover);
			}
			if (!SISAL.isNullOrEmpty(onmouseout)) {
				newObj.attr('onmouseout', onmouseout);
			}
			if (!SISAL.isNullOrEmpty(onkeypress)) {
				newObj.attr('onkeypress', onkeypress);
			}
			
			if (!SISAL.isNullOrEmpty(oldblur))
			{
				newObj.blur(
					function ()
					{
						eval(oldblur);
					}
				);
			} else
			{
				newObj.blur(
					function ()
					{
						SISAL.FX.addToElementInput_TextPasswordSwitch_auto(this);
					}
				);
				newObj.attr('oldblur', 'SISAL.FX.addToElementInput_TextPasswordSwitch_auto(this);');
			}
			
			$(obj).replaceWith(newObj);
			newObj.focus();
			newObj.select();
		}
	}
	function addToElementInput_TextPasswordSwitch_auto(obj)
	{
		var
			newObj = '',
			oldvalue = $(obj).attr('oldvalue'),
			id = $(obj).attr('id'),
			name = $(obj).attr('name'),
			maxlength = $(obj).attr('maxlength'),
			style = $(obj).attr('style'),
			onclick = obj.getAttribute('onclick'),
			onmouseover = obj.getAttribute('onmouseover'),
			onmouseout = obj.getAttribute('onmouseout'),
			onkeypress = obj.getAttribute('onkeypress'),
			onfocus = obj.getAttribute('onfocus'),
			onblur = obj.getAttribute('onblur'),
			oldfocus = $(obj).attr('oldfocus'),
			oldblur = $(obj).attr('oldblur')
			;
			
		if ($(obj).attr('type') === "password" && $(obj).attr('value') === "")
		{
			newObj = $("<input id='" + id + "' type='text' >");
			
			if (SISAL.isNull(oldfocus))
			{
				newObj.attr('oldfocus', onfocus);
			} else
			{
				newObj.attr('oldfocus', oldfocus);
			}
			
			if (SISAL.isNull(oldblur))
			{
				newObj.attr('oldblur', onblur);
			} else
			{
				newObj.attr('oldblur', oldblur);
			}
			
			newObj.attr('value', oldvalue);
			
			if (!SISAL.isNullOrEmpty(name)) {
				newObj.attr('name', name);
			}
			if (!SISAL.isNullOrEmpty(maxlength)) {
				newObj.attr('maxlength', maxlength);
			}
			if (!SISAL.isNullOrEmpty(style)) {
				newObj.attr('style', style);
			}
			if (!SISAL.isNullOrEmpty(onclick)) {
				newObj.attr('onclick', onclick);
			}
			if (!SISAL.isNullOrEmpty(onmouseover)) {
				newObj.attr('onmouseover', onmouseover);
			}
			if (!SISAL.isNullOrEmpty(onmouseout)) {
				newObj.attr('onmouseout', onmouseout);
			}
			if (!SISAL.isNullOrEmpty(onkeypress)) {
				newObj.attr('onkeypress', onkeypress);
			}
			
			if (!SISAL.isNullOrEmpty(oldfocus))
			{
				newObj.focus(
					function ()
					{
						eval(oldfocus);
					}
				);
			} else
			{
				newObj.focus(
					function ()
					{
						SISAL.FX.addToElementInput_TextPasswordSwitch(this);
					}
				);
				newObj.attr('oldfocus', 'SISAL.FX.addToElementInput_TextPasswordSwitch(this);');
			}
			
			$(obj).replaceWith(newObj);
		}
	}
    
    function addToElementInput_setPassword(inputId, password)
    {
        addToElementInput_TextPasswordSwitch($('#' + inputId).get()[0]);
        $('#' + inputId).attr('value', password);
    }
	
	/**
	* Gestione del css relativo all'utilizzo della libreria FX .. .questo CSS verrà importato nel sito per il corretto funzionamento e visualizzazione della libreria.
	*/
	function getStyleCSS()
	{
		var css = "";
		
		// addToElementWithClass_slideToggle_init()
		//css += "div.addFunction_slideToggle_new {display:none;} \n";
		//css += "div.addFunction_slideToggle_new div.addFunction_slideToggle_buttonChiudi {padding-right:10px;width:45px;text-align:right;cursor:pointer;font-family:Arial;font-size:11px;} \n";
		//css += "div.addFunction_slideToggle_new div.addFunction_slideToggle_bottomContent {font-size:1px;height:10px;width:100%;border-bottom:1px solid #dbdbdb;} \n";
		
		// addToElementTd_removePadding()
		css += "." + className_removePaddingFromTd + " {width:0px;height:0px;font-size:0px;display:none;} \n";
		// ritorna il css da stampare
		return css;
	}
	
    // funzioni da eseguire allo "scroll" della pagina
	$(window).bind('scroll', function () {
		addToElementDiv_makeLikeBody();
		//refresh_AllListOfFunctionality();
		refresh_AllListOfOverlay();
		showBodyPopupOnTop();
	});
	
	// funzioni da eseguire alla "resize" della pagina
	$(window).bind('resize', function () {
		addToElementDiv_makeLikeBody();
		refresh_AllListOfFunctionality();
		showBodyPopupOnTop();
	});
	
	// funzioni da eseguire alla "load" della pagina
	$(window).bind('load', function () {
		addToElementWithClass_slideToggle_init();
		addToElementDiv_makeLikeBody();
		addToElementTd_removePadding();
		showBodyPopupOnTop();
		
		//pngFix();
		
		// appende lo stile necessario per il funzionamento  utile delle funzionalità della FX
		$('head').append("<style type='text/css'>" + getStyleCSS() + "</style>");
	});
	
	return {
		showOnElement_Overlay : showOnElement_Overlay,
		hideOnElement_Overlay : hideOnElement_Overlay,
		showOnElement_Popup : showOnElement_Popup,
		hideOnElement_Popup : hideOnElement_Popup,
		removeOnElement_Popup : removeOnElement_Popup,
		showOnElement_OverlayPopup : showOnElement_OverlayPopup,
		hideOnElement_OverlayPopup : hideOnElement_OverlayPopup,
		showOnElement_TemplatePopup : showOnElement_TemplatePopup,
		addToInput_HelpText : addToInput_HelpText,
		slideToggle : slideToggle,
		addToElement_slideToggle : addToElement_slideToggle,
		print : print,
		open : open,
		addToElementWithClass_slideDown : addToElementWithClass_slideDown,
		addToElementWithClass_slideUp : addToElementWithClass_slideUp,
		addToElementWithClass_slideToggle : addToElementWithClass_slideToggle,
		addToElementInput_TextPasswordSwitch : addToElementInput_TextPasswordSwitch,
		addToElementInput_TextPasswordSwitch_auto : addToElementInput_TextPasswordSwitch_auto,
		addToElementInput_setPassword : addToElementInput_setPassword
	};

}());

if (SISAL.logger.isInfoEnabled())
{
    SISAL.logger.info("SISAL.FX - namespace creato");
}
