/*************************\
* ITALCOM S.p.A.          *
* Target:  IE 5.5, NE 6.0 *
* Library: Core.js        *
* Version: 1.0            *
* Require: none           *
* Objects: CQueryArgs     *
\*************************/

/* Definitions */
function EmptyFunction(){};
function NullFunction(){return null};

/*** IS FUNCTIONS ***/

var undefined;
function IsUndefined(v) { return (v == undefined); }
function IsEmptyString(v) { return (v == undefined || v === ""); }
//function IsEmpty(v) { try {	return (v == undefined || v == null || v === ""); } catch (e) {	return false; } }
function IsEmpty(o)
{
	if (o==null || o==="")
		return true;
	if (IsArray(o))
	{
		for(var i in o)
			return false;
		return true;
	}
	return false;
}
function IsBoolean(o){return typeof o=="boolean"}
function IsNumber(o){return typeof o=="number"}
function IsString(o){return typeof o=="string"}
function IsFunction(o){return typeof o=="function"}
function IsDate(o){return o instanceof Date}
function IsArray(o){return o instanceof Array}
function IsRegExp(o){return o instanceof RegExp}
function IsObject(o){return typeof o == "object"}
function IsStrictObject(o){return TypeOf(o) == "object"}
function TypeOf(o)
{
	if (o===null)
		return "null";
	var result = typeof o;
	if (result == "object")
	{
		if (o instanceof RegExp) return "regexp";
		if (o instanceof Date) return "date";
		if (o instanceof Array) return "array";
	}
	return result;
}
function IsInList(strItem, strListArray, sep)
{
	try
	{
		if (IsEmpty(strItem)) return false;
		if (IsEmpty(strListArray)) return false;
		if (IsEmpty(sep)) sep = ",";
		var l = IsArray(strListArray) ? strListArray : strListArray.toString().split(sep);
		strItem = Trim(strItem.toString());
		for (var i=0; i<l.length; i++)
			if (strItem == Trim(l[i].toString()))
				return true;
	}
	catch(e){Dump(e)}
	return false;
}


//==============
// CMessageList
//==============
// Esempio: ml = new CMessageList({key: {id: 1, msg: "message"}})
function CMessageList(entryList)
{
	if (IsEmpty(entryList)) entryList = {};

	this.all = entryList;
	return this;
}

CMessageList.prototype.isEmpty
=//===========================
function()
{
	for(var i in this.all) 
		return true;
	return false;
}

CMessageList.prototype.addMsgKey
=//=============================
// Es: add({key1: {id: 1, msg: ""}, key2: {id: 2, msg: ""}}, ["key1", "key2"])
function (messageList, keyList)
{
	var i;
	// Se non è specificato keyList si aggiungono tutti
	if (keyList==null)
	{
		for (i in messageList)
			this.all[i] = messageList[i];
	}
	else
	{
		for (var i=0; i<keyList.length; i++)
		this.all[keyList[i]] = messageList[keyList[i]];
	}
}

CMessageList.prototype.addMsgId
=//============================
// Es: add({key1: {id: 1, msg: ""}, key2: {id: 2, msg: ""}}, "1,2")
function (messageList, idList)
{
	// Se non è specificato keyList si aggiungono tutti
	for (var i in messageList)
		if (idList == null || IsInList(messageList[i].id, idList))
			this.all[i] = messageList[i];
}

CMessageList.prototype.getIdList
=//=============================
// Restituisce l'elenco degli id come stringa di interi separati da virgola es. "1,2"
function ()
{
	if (this.all.length == 0)
		return "";
	var result = [];
	for (var i in this.all)
		result[result.length] = this.all[i].id;
	return result.toString();
}

CMessageList.prototype.getMsgList
=//==============================
// Restituisce l'elenco dei messaggi come stringhe separate da \r
function (idList)
{
	if (this.all.length == 0)
		return "";
	var result = "";
	// Se non è specificato keyList si restituiscono tutti
	for (var i in this.all)
	{
		if (idList == null || IsInList(this.all[i].id, idList))
			result += this.all[i].msg + "\r";
	}
	return result;
}

function StringFormat(str, obj_args)
{
	// Es.:     StringFormat("{0}={1}", "v", 1) -> "v=1"
	// Oppure:  StringFormat("{a}={b}", {a: "v", b: 1}) -> "v=1"
	var arg = arguments;
	if (IsStrictObject(obj_args))
	{
		for (var i in obj_args)
			str = str.replace(new RegExp("{"+i+"}", "gi"), obj_args[i]);
		return str;
	}
	else
		return str.replace(StringFormat.regExp, function($0, $1){return arg[1+parseInt($1)]});
}
StringFormat.regExp = /\{(\d+)\}/g;

/* Macros */
function MacroReplace(str, list, flag)
{
	// Es.: MacroReplace(HTML, [["#id#", this.id], ["#cls#", this.cls]], "i")
	if (flag == null) flag = "g";
	var re = "("+ list[0][0] +")";
	var val = [];
	val[list[0][0]] = list[0][1]
	for (var i=1; i<list.length; i++)
	{
		re += "|("+ list[i][0] +")";
		val[list[i][0]] = list[i][1]
	}
	re = new RegExp(re, flag);
	return str.replace(re, function($0){return val[$0]});
}

function ErrorAlert(e, fName)
{
	try
	{
		var msg = "";
		if ( arguments.length > 1 )
			msg += fName;
		msg += "\n"+ e.name +" "+ e.number;
		msg += "\n"+ e.description;
		if ( e.description != e.message )
			msg += "\n"+ e.message;
		window.alert(msg);		
	}
	catch(e)
	{	
		window.alert("Unknown exception event");
	}
}


/*** BROWSER IDENTIFICATION ***/

/*
Per i nostri scopi il browser è:
Internet Explorer < 5.5
Internet Explorer >= 5.5
Netscape < 6.0
Netscape >= 6.0
*/

var IE = 0;
var NE = 0;
function BrowserIdentification()
{
	var pos, tmp;
    var userAgent = navigator.userAgent.toLowerCase();
    var majorVersion = parseInt(navigator.appVersion, 10);
    var minorVersion = parseFloat(navigator.appVersion);
    
    // Internet Explorer -> 5 o x.x
	var tmp = userAgent.match(/msie\s*(\d*)\D(\d*)/);
	if (tmp != null)
	{
		IE = parseInt(tmp[1], 10);
		if (IE==5)
			 IE = parseFloat(tmp[1]+"."+tmp[2]);
	}
	// Netscape Navigator -> 4 o 6
	else
	{
		NE = 4;
		if (majorVersion >= 5)
			NE = 6;
	}
}
try {BrowserIdentification()}catch(e){};

function BrowserAlert(verb)
{
	if (arguments.length<1) 
		verb = "knos dynweb cookie";
	else
		verb = verb.toLowerCase();

	if (verb.indexOf("knos")!=-1)
	{	
		if (IE<5.5)
		{
			window.alert("Funzionalità accessibile solo con Microsoft Internet Explorer ver. 5.5 o successive.");
			return false;
		}
		verb += "cookie";
	}

	if (verb.indexOf("dynweb")!=-1)
	{
		if (IE<5.5 && NE<6)
		{
			window.alert("Funzionalità accessibile solo con Microsoft Internet Explorer ver. 5.5 o successive o Netscape Navigator versione 6.0 o successive.");
			return false;
		}
	}

	if (verb.indexOf("cookie")!=-1)
	{
		if ( !navigator.cookieEnabled )
		{
			window.alert("Per accedere al servizio occorre abilitare i Cookie.");
			return false;
		}
	}
	
	return true;
}


function GetLicense(drvpath)
{
	var result = null;
	try
	{
		var fso, d, s, t;
		fso = new ActiveXObject("Scripting.FileSystemObject");
		if (IsEmpty(fso))
			result = "Error 1";
		d = fso.GetDrive(fso.GetDriveName(fso.GetAbsolutePathName("c:")));
		result = d.SerialNumber;
	}
	catch(e)
	{
		result = null;
	}
	return result;
}


//============
// CQueryArgs
//============
function CQueryArgs()
{
	this.args = [];
	this.init();
}

CQueryArgs.prototype.init
=//======================
function ()
{
try
{
	var str = document.location.search;
	if ( IsEmpty(str) )
		return [];
	var tmp = str.split(/[\?&]/);
	this.args = [];
	for (var i=0; i<tmp.length; i++)
	{
		var pos = tmp[i].indexOf("=");
		if (pos <0)
			continue;
		var arg = tmp[i].substr(0, pos);
		var val = tmp[i].substr(pos+1);
		this.args[this.args.length] = [unescape(arg), unescape(val)];
	}
}
catch(e)
{
	this.args = [];
}
}

CQueryArgs.prototype.getArg
=//========================
function (name, defValue)
{
	if (arguments.length < 2) defValue = null;

	var tmp = name.toLowerCase();
	for (var i=0; i<this.args.length; i++)
	{
		if ( this.args[i][0].toLowerCase() == tmp )
			return this.args[i][1];
	}		
	return defValue;
}


function GetPageName(url)
{
	if ( IsEmpty(url) )
		return "";
	url = unescape(url);
	var pos1 = url.lastIndexOf('/') + 1;
	var pos2 = url.lastIndexOf('\\') + 1;
	var pos = pos1 > pos2 ? pos1 : pos2;
	return url.slice(pos).toLowerCase();
}


function GetStyleAttribute(style, attribute, defValue)
{
try
{
	if ( IsEmpty(style) )
		return defValue;
	var tmp = style.split(/;/);
	for (var i=0; i<tmp.length; i++)
	{
		tmp[i] = tmp[i].split(":");
		if (tmp[i][0] == attribute)
			return tmp[i][1];
	}
}
catch(e)
{}
	return defValue;
}


/* CLIPBOARD */
function ClipboardGet(idClip)
{
	var result = "";
	try
	{
		var clip = window.clipboardData.getData("Text");
		if (!IsEmpty(idClip))
		{
			if ( clip.slice(0, idClip.length) == idClip )
				result = clip.slice(idClip.length);
		}
		else
			result = clip;
	}
	catch (e)
	{
		result = "";
	}
	return result;
}

function ClipboardSet(idClip, value)
{
	try
	{
		window.clipboardData.clearData("Text");
		if (arguments.length == 0)
		    return true;
		window.clipboardData.setData("Text", idClip+value);
		return true;
	}
	catch(e)
	{
		return false;
	}
}

 //////////
// Cookie
//
//	date = null: cookie di sessione
//	date = "":   scadenza di default 30/10/2029
function CookieSet(name, value, date, path, domain, bSecure) 
{
	var result = escape(name) + "=" + escape(value) + ";";	
	if (date !== null) // se null viene omessa, passare "" per il default
	{
		if (IsEmpty(date)) 
			date = new Date(2029,10,30);
		result += " expires=" + date.toGMTString() + ";";
	}
	if (path !== null)
	{
		if (IsEmpty(path)) 
			path = "/";
		result += " path=" + path + ";";
	}
	if (!IsEmpty(domain))
		result += " domain=" + domain + ";";
	if (!IsEmpty(bSecure) && bSecure)
		result += " secure;";
	document.cookie = result;
	return result;
}
function CookieGet(name) 
{
	if (IsEmpty(name)) return document.cookie;
	
	// cookies are separated by semicolons
	var aCookie = document.cookie.split(/;\s*/);
	var aCrumb;
	for (var i=0; i < aCookie.length; i++)
	{
		// a name/value pair (a crumb) is separated by an equal sign
		aCrumb = aCookie[i].split("=");
		if (name == aCrumb[0])
		{
			if (aCrumb.length > 1)
				return unescape(aCrumb[1]);
			else
				return "";
		}
	}
	// a cookie with the requested name does not exist
	return null;
}
function CookieDel(name) 
{
	var date=new Date(2000,10,30); 
	return CookieSet(name, "", date);
}


/*** DEBUGGING ***/

function Debug(expr)
{
	window.alert(expr);
}

function DebugPoint()
{
	if ( window.confirm("Debug?") )
		window.ale();
    // next statement	
}

function DebugProperties(target)
{
	var p;
	var str = "";
	for (p in target)
		if (typeof target[p] != "function")
			str += "\n" + p + " = " + target[p];
	return str;
}

function Dump(object_text)
{	
	var HTML = '<div style="font-size: 8pt;">'+ object_text +'</div>';
	if (IsObject(object_text))
		for (var i in object_text)
			if (!IsFunction(object_text[i]))
				HTML += '<div style="font-size: 8pt; padding-left: 20px;">'+ i +'='+ object_text[i] +'</div>';
	Response.Write(HTML);
}


/*** LOW LEVEL ***/
function ODD_INT(i)    	{ return (i & 0x01) ? true : false };
function EVEN_INT(i)    { return (i & 0x00) ? true : false };
var NIBBLE_TO_ESA =     "0123456789ABCDEF";
var ESA_CHAR =          ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];

function StringToEsa(str)
{
	var strEsa = "";
	for (i=0; i<str.length; i++)
	{
		h = (str.charCodeAt(i) & 0xf0) >> 4;
		l = (str.charCodeAt(i) & 0x0f);
		strEsa += ESA_CHAR[h];
		strEsa += ESA_CHAR[l];
	}
	return strEsa;
}


function EsaToString(esaChar)
{
	if (IsEmpty(esaChar)) return "";
	var str = "";
	var currByte = EsaToByte(esaChar, 0, esaChar.length);
	for (var i=0; i<currByte.length; i++)
		str += String.fromCharCode(currByte[i]);
	return str;
}


function ByteToEsa(byteArray, start, nLong)
{
	var h, l;
	var end = start+nLong;
	var strEsa = "";
	for (i=start; i<end; i++)
	{
		h = (byteArray[i] & 0xf0) >> 4;
		l = (byteArray[i] & 0x0f);
		strEsa += ESA_CHAR[h] + ESA_CHAR[l];
	}
	return strEsa;
}


function EsaToByte(esaChar, start, nChar)
{   
    var i, j, c;
    var low, high;    
    var outByte = new Array(nChar/2);
        
    esaChar = esaChar.toUpperCase();
    for (i=start, j=0; i<nChar; i++)
    {		
		c = esaChar.charAt(i);
        if ( (('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) )
        {
            if ( ODD_INT(i) )
                low = NIBBLE_TO_ESA.indexOf(c);
            else
                high = NIBBLE_TO_ESA.indexOf(c) << 4;
        }
        else 
        {
			return null;
        }
        if ( ODD_INT(i) )
            outByte[j++] = high | low;
    }    
    return outByte;
}


function StringPadding(str, padStr, mod)
{
	var n = str.length % mod;
	if ( n == 0 )
		n = str.length;
	else
		n = str.length + (mod - n);
	while ( str.length < n )
			str += padStr;
	return str.slice(0, n);
}



// Unione insiemistica degli elementi di due liste.
// Le due liste possono essere indifferentemente array oppure stringhe (con gli elementi separati da virgola).
// L'unione è restituita come array.
function Union(list1, list2)
{
	if (list1 == null) list1 = [];
	if (list2 == null) list2 = [];

	// Se list1 è una stringa non vuota la riconduco ad un array.
	if (IsString(list1))
		list1 = IsEmpty(list1) ? [] : list1.split(",");

	// Se list2 è una stringa lo riconduco ad un array.
	if (IsString(list2))
		list2 = IsEmpty(list2) ? [] : list2.split(",");

	// Se list1 è vuoto allora il risultato è list2.
	if (list1.length == 0)
		return list2;
	
	// (list1 non è vuoto) Se list2 è vuoto allora il risultato è list1.
	if (list2.length == 0)
		return list1;

	// Copio list1 in result.
	var result = list1.concat();

	// Merge di list1 e list2.
	for (var i = 0; i < list2.length; i++)
	{
		var found = false;
		for (var j = 0; j < list1.length; j++)
		{
			if (list2[i] == list1[j])
			{
				found = true;
				break;
			}
		}
		
		if (!found)
			result[result.length] = list2[i];
	}
	
	return result;
}

/*** TRIM ***/

function TrimLeft(s, c, nMax)
{
	s = s.toString();
	if (!IsEmpty(c))
	{
		var re;
		if (IsEmpty(nMax))
		{
			re = new RegExp("(^"+ c +"*)","");
			return s.replace(re, ""); 
		}
		else
		{
			var result = s;
			re = new RegExp("(^"+ c +")","");
			for (var i=0; i<nMax; i++)
				result = result.replace(re, "");
			return result;
		}
	}
	else
		return s.replace(/(^\s*)/, "");
}
function TrimRight(s, c, nMax) 
{
	s = s.toString();
	if (!IsEmpty(c))
	{
		var re;
		if (IsEmpty(nMax))
		{
			re = new RegExp("("+ c +"*$)","");
			return s.replace(re, "");
		}
		else
		{
			var result = s;
			re = new RegExp("("+ c +"$)","");
			for (var i=0; i<nMax; i++)
				result = result.replace(re, "");
			return result;
		}
	}
	else
		return s.replace(/(\s*$)/, "");
}
function Trim(s, c, nMax)
{
	if (!IsEmpty(c))
		return TrimRight(TrimLeft(s, c, nMax), c, nMax);
	else
		return TrimRight(TrimLeft(s));
}

function TrimSearchExpression(s)
{
	// Sostituzione di cr, tab, ecc. con spazi singoli
	s = s.replace(/(\f|\n|\r|\t|\v)+/g, " ");
	// Raddoppio degli apici e trim degli spazi
	return Trim(s.replace(/'/g, "''"));
}

function NormalizeString(s)
{
	// Semplificazione whitespace
	return s.replace(/\s+/g, " ");
}

function LikeSearchExpression(field, value)
{
	var s = ""+ value;
	return "["+ field +"] LIKE '%<!_CDATA_"+ s.replace(/'/g, "''") +"__>%'";
}

function WildDateExpression(colName, stdDateTime_Date)
{
	if (stdDateTime_Date === null || stdDateTime_Date === "")
		return "";
	var d = new Object();
	StdDateTimeObject(stdDateTime_Date, d);
	return "dbo.fn_ReplaceWildDate("+ colName +",'"+ d.year +"','"+ d.month +"','"+ d.day +"','"+ (parseInt(d.year, 10)+1) +"')";
}

function AppendSearchExpression(s1, s2)
{
	if (!IsEmpty(s1) && !IsEmpty(s2))
		s1 = "("+ s1 +") AND ";
	return s1 += s2;
}


/* ParseSearchText

Lo switch automatico su LIKE è ammesso solo su singoli attributi ed è attivato dalla
presenza di un % nella stringa di ricerca. 
Rispetto alla CONTAINS c'è la possibilità di specificare prefissi con % e caratteri jolly con _
Perchè la contains trovi anche sigle tipo S.p.A. bisogna svuotare il file:
(SQL SERVER 2000) C:\Program Files\Microsoft SQL Server\MSSQL\FTDATA\SQLServer\Config\noise.dat (lingua neutrale)
(SQL SERVER 2005) C:\Program Files\Microsoft SQL Server\MSSQL\FTDATA\SQLServer\Config\noiseneu.txt (lingua neutrale)
Il risultato del parsing ritorna l'oggetto:
{
	 result : <stringa di ricerca se ok>
	,error1 : <parte di str fino all'errore riscontrato>
	,error2 : <parte restante di str>
	,ok: <true se ok>
}
*/
function ParseSearchText(str, colName, bAlert)
{
	if (IsEmpty(colName)) colName = "*";
	if (IsEmpty(bAlert)) bAlert = true;
	
	var bLike = (colName != "*" && str.indexOf("%") >= 0) ? true : false;
	colName = "Object_Index."+colName;

	// Parsing dei token
	// item | + | - 
	var re = /("[^"]+")|(\+|\-)|([^ \f\n\r\t\v\+\-]+)/g
	var i, c, s, t, bFirst = true;
	var token = [];
	while ((t = re.exec(str)) != null)
	{
		for (i=0; i<t.length; t++)
			if (t[i] != "")
				token[token.length] = t[i];
	}

	function filterToken(t)
	{
		if (t.charAt(0) != '"')
			t = '"'+ t +'"';
		if (t.charAt(t.length-1) != '"')
			t = t + '"';
		if (bLike)
		{
			t = Trim(t, '"', 1);
			if (bFirst)
				bFirst = false;
			else
				t = "%"+t+"%";
		}
		t = t.replace(/'/g, "''");
		return t;
	}

	var status =
	{
		item : 0,
		near : 1,
		end : -1,
		error : -2
	}
	var result = "";
	var error1 = "";
	var error2 = "";
	s = status.item;
	i = 0;
	while (s != status.end && i<token.length)
	{		
		lookahead = token[i+1] == null ? null : token[i+1].charAt(0);
		switch (s)
		{
			case status.item:
				switch (token[i].charAt(0))
				{
					case '+':
						s = status.error;
						break;
					case '-':
						if (result == "")
						{
							result = bLike 
								? "("+ colName +" NOT LIKE '" 
								: "NOT CONTAINS("+ colName +", '";
							s = status.item;
							i++;
						}
						break;
					default:
						if (result == "")
						{
							result = bLike
								? "("+ colName +" LIKE '"
								: "CONTAINS("+ colName +", '";
						}
						switch (lookahead)						
						{
							case null:
								result += filterToken(token[i]) + "')";
								s = status.end;
								break;
							case '-':
								result += bLike
									? filterToken(token[i]) + "%') AND ("+ colName +" NOT LIKE '" 
									: filterToken(token[i]) + "') AND NOT CONTAINS("+ colName +", '";
								s = status.item;
								i += 2;
								break;
							case '+':
								result += bLike
									? filterToken(token[i]) + "%"
									: filterToken(token[i]) + " NEAR ";
								s = status.near;
								i += 2;
								break;
							default:
								result += bLike 
									? filterToken(token[i]) + "%') AND ("+ colName +" LIKE '" 
									: filterToken(token[i]) + "') AND CONTAINS("+ colName +", '";
								s = status.item;
								i += 1;
								break;
						}
				}
				break;

			case status.near:
				switch (token[i].charAt(0))
				{
					case '+':
					case '-':
						s = status.error;
						break;
					default:
						switch (lookahead)
						{
							case null:
								result += filterToken(token[i]) + "')";
								s = status.end;
								break;
							case '-':
								result += bLike
									? filterToken(token[i]) + "%') AND ("+ colName +" NOT LIKE '"
									: filterToken(token[i]) + "') AND NOT CONTAINS("+ colName +", '";
								s = status.item;
								i += 2;
								break;
							case '+':
								result += bLike
									? filterToken(token[i]) + "%"
									: filterToken(token[i]) + " NEAR ";
								s = status.near;
								i += 2;
								break;
							default:
								result += bLike
									? filterToken(token[i]) + "%') AND ("+ colName +" LIKE '"
									: filterToken(token[i]) + "') AND CONTAINS("+ colName +", '";
								s = status.item;
								i += 1;
								break;
						}
				}
				break;
			
			case status.error:
			default:
				var j;
				for (j=0; j<i; j++)
					error1 += token[j] + " ";
				for (j=i; j<token.length; j++)
					error2 += token[j] + " ";	
				s = status.end;
				break;
		}
	}
	result = { result : result, error1 : error1, error2 : error2, ok : (error1 == "" && error2 == "") }
	if (!result.ok && bAlert)
		try { window.alert("Errore nell'espressione di ricerca:\n  ..."+ result.error2) }catch(e){}
	if (result.ok && bLike)
	{
		result.result = result.result.replace(/\*+/g, "%");
		result.result = result.result.replace(/\%+/g, "%");
	}
	return result;
}

function OpenUrl(url, target, features)
{
	if ( IsEmpty(url) )
		return;
	
	switch ( target )
	{
		case "_same": 
			window.location = url;
			break;
		
		case "_replace":
			window.location.replace(url);
			break;
		
		default:	
			if ( IsEmpty(features) )
				window.open(url, target);
			else
				window.open(url, target, features);
	}	
}


/* CHECKED INPUT */

function ParseInt(v, def, radix)
{
	if (radix==null) radix = 10;
	var result = parseInt(v, radix);
	if (isNaN(result) && arguments.length > 1)
		return def;
	return result;
}

function ParseFloat(v, def)
{
	var result = parseFloat(v)
	if (isNaN(result) && arguments.length > 1)
		return def;
	return result;
}

// Ottenimento di un valore intero
// Ritorna:
//	"" se il valore e' in bianco
//	null se non è un intero valido
//	
function GetCheckedInteger(target, bAlert)
{
	if (IsEmpty(bAlert)) bAlert = true;
	
	target.value = Trim(target.value+"");
	if (IsEmptyString(target.value))
		return "";
	if (isNaN(target.value) || parseInt(target.value,10) != target.value)
	{
		if (bAlert)
		{
			window.alert("Inserire un'espressione numerica intera valida");
			target.focus();
		}
		return null;
	}
	return target.value;
}


// Ottenimento di un valore float
// Ritorna:
//	"" se il valore e' in bianco
//	null se non è un float valido
//
function GetCheckedFloat(target, bAlert)
{
	if (IsEmpty(bAlert)) bAlert = true;	
	target.value = Trim(target.value);
	if (IsEmptyString(target.value))
		return "";
	if (isNaN(target.value))
	{
		if (bAlert)
		{
			window.alert("Inserire un'espressione numerica valida (come separatore decimali usare il punto '.')");
			target.focus();
		}
		return null;
	}
	return target.value;
}


/* ARROTONDAMENTO */

// Arrotondamento di un numero con nDecimali specificati
// se sono indicati cPoint o bZero ritorna una stringa
function Round(value, nDecimal, cPoint, bZero)
{
try
{
	var defZero = false;
	if (IsEmpty(nDecimal)) nDecimal = 4;
	if (IsEmpty(cPoint)) { cPoint = null; } else { defZero = true; }
	if (!IsEmpty(bZero)) defZero = bZero;
	bZero = defZero;
	
	var dec = Math.pow(10, nDecimal);
	var result = Math.round(value * dec) / dec;
	if ( !bZero && cPoint === null )
		return result;

	strResult = result.toString();
	if (bZero)
	{
		var z = strResult.lastIndexOf(".");
		if (z < 0 && nDecimal > 0)
		{
			strResult += ".";
			z = nDecimal;
		}
		else
			z = z + nDecimal + 1 - strResult.length;
		for (var i=0; i<z; i++)
			strResult += "0";
	}

	if (!IsEmpty(cPoint))
		strResult = strResult.replace(/\./g, cPoint);

	return strResult;
}
catch(e)
{
	return 0;
}
}


/*** FORMATI STANDARD ***/

// Format
var Format_bool_x = ["", "x", "", "x"];
var Format_bool_1 = ["0", "1", "0", "1"];
var Format_bool_t = ["F", "V", "F", "T"];
var Format_bool_T = ["Falso", "Vero", "False", "True"];
var Format_bool_y = ["N", "S", "N", "Y"];
var Format_bool_Y = ["No", "Si", "No", "Yes"];
var Format_month = ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

function Format(str, fmt)
{
	var val, result;

	// Formato		
	if ( IsEmptyString(fmt) )
		return str;
	var result = fmt.match(/\s*([^:]*):([^|]*)\|*([^$]*)/);
	if ( result == null )
		return "?";
	var tipo = result[1].toLowerCase();
	var campi = result[2];
	var opzioni = result[3].toLowerCase();

	// Lettura Opzioni
	
	// lang + separatori decimali e migliaia
	var o_lang = opzioni.match(/\S*lang=([^ ,]*)/);
	var o_dsep = ",";
	var o_tsep = ".";
	if ( o_lang == null )
		o_lang = "it";
	else
	{
		o_lang = o_lang[1];
		if ( o_lang == "en" )
		{
			o_dsep = ",";
			o_tsep = ".";
		}
	}
	// case
	var o_case = opzioni.match(/\S*case=([^ ,]*)/);
	if ( o_case == null )
		o_case = "c";
	else
		o_case = o_case[1];
	// curr
	var o_curr = opzioni.match(/\S*curr=([^ ,]*)/);
	if ( o_curr == null )
		o_curr = "";
	else
		o_curr = o_curr[1];
	
	// Costruzione del risultato
	switch (tipo)
	{
		case "bool":	// Es. "bool:%Y|lang=it"
			val = parseInt(str, 10);
			if ( !isNaN(val) )
				val = val ? 1 : 0;
			else
				val = ( str.search(/^t|v|s|y/i) >= 0 )? 1 : 0;
			// Opzione lang
			if ( o_lang == "en" )
				val += 2;
			result = campi.replace(/%x/, Format_bool_x[val]);
			result = result.replace(/%1/, Format_bool_1[val]);
			result = result.replace(/%t/, Format_bool_t[val]);
			result = result.replace(/%T/, Format_bool_T[val]);
			result = result.replace(/%y/, Format_bool_y[val]);
			result = result.replace(/%Y/, Format_bool_Y[val]);
			// Opzione case
			switch ( o_case )
			{
				case "l": result = result.toLowerCase(); break;
				case "u": result = result.toUpperCase(); break;
			}
			break;
						
		case "dt":
			// Il valore da rappresentare e' in formato fisso:
			//	YYYY-MM-DDThh:mm:ss 
			//	1    2  3  4  5  6
			var val = str.match(/(\d*)-(\d*)-(\d*)T(\d*):(\d*):(\d*)/);			
			if ( val == null )
				return "";
			result = campi.replace(/%Y/, val[1]);
			result = result.replace(/%y/, val[1].slice(-2));
			result = result.replace(/%mm/, Format_month[val[2]-1+(o_lang=="en"?12:0)]);
			result = result.replace(/%m/, val[2]);
			result = result.replace(/%d/, val[3]);			
			result = result.replace(/%H/, val[4]);
			result = result.replace(/%M/, val[5]);
			result = result.replace(/%S/, val[6]);
			// Opzione case
			switch ( o_case )
			{
				case "l": result = result.toLowerCase();
				case "u": result = result.toUpperCase();
			}
			break;

		case "enum":
			// L'elenco si suppone in formato Vs V
			result = GetCollectionList(str, campi == "li");
			break;

		case "int":
			result = str;
			break;
			
		case "dec":
			var nDecimal = parseInt(campi, 10);
			if (isNaN(nDecimal))
				result = str;
			else
				result = Round(str, nDecimal, o_dsep, true);
			break;
		
		default:
			result = "?";
	}		
	return result;
}

// Funzione utilizzata per l'estrazione dei riferimenti al glossario
function GetCollectionList(arg, bList)
{
	if ( arguments.length < 2 ) bList = true;
	
	var HTML = "";
	var l = GetCollectionValue(arg);
	if ( bList )
	{
		for (var i=0; i<l.length; i++)
		{
			if ( Trim(l[i]) != "" )
				HTML += "{_<_}LI{_>_}" + l[i] + "{_<_}/LI{_>_}";
		}
		if (!IsEmpty(HTML))
			HTML = "{_<_}UL{_>_}"+ HTML +"{_<_}/UL{_>_}";
		else
			HTML = "";
	}
	else
	{
		for (var i=0; i<l.length; i++)
		{
			if ( Trim(l[i]) != "" )
			{
				if ( HTML != "" )
					HTML += ", ";
				HTML += l[i];
			}
		}
	}	
	return HTML;
}

// Ritorna un array con i valori della collection
// Se non c'e' nulla ritorna un array con un solo elemento stringa vuota
function GetCollectionValue(arg)
{
	var i, s; 
	if ( !IsEmptyString(arg) )
	{
		s = arg.match(/<Vs>([^$]*)<\/Vs>/g);
		if ( s != null )
		{
			s = arg.split("<!\[CDATA\[");
			if ( s != null )
			{
				if ( s.length > 1 )
				{ 
					s = s.slice(1);
					for (i=0; i<s.length; i++)
						s[i] = s[i].replace(/\]\]>.*/, "");
					return s;
				}
			}
		}
	}
	return [""];
}


/* Text conversion */

function TextToHTML(text)
{
	if (IsEmpty(text)) return "&nbsp;";
	
	var result = "" + text;
	result = result.replace(/&/g, "&amp;");
	result = result.replace(/\s\s/g, " &nbsp;");
	result = result.replace(/"/g, "&quot;");
	result = result.replace(/</g, "&lt;");
	return result.replace(/>/g, "&gt;");
}

function TextToXHTML(text)
{
	var result = "" + text;
		if (result==null) return "";
	// ' vs &apos; non è necessario
	return result.replace(/(&)|(")|(<)|(>)/g, 
	function(c)
	{
		switch (c)
		{
			case "&": return "&amp;";
			case '"': return "&quot;";
			case "<": return "&lt;";
			case ">": return "&gt;";
		}
		return c;
	});
}

function XHTMLToText(text)
{
	var result = "" + text;
		if (result==null) return "";
	return result.replace(/(&amp;)|(&quot;)|(&lt;)|(&gt;)/g, 
	function(c)
	{
		switch (c)
		{
			case "&amp;": return "&";
			case "&quot;": return '"';
			case "&lt;": return "<";
			case "&gt;": return ">";
		}
		return c;
	});
}

/* XML */

function XMLAttributeValue(attr, def){if (arguments.length<2) def = ""; try {return attr.text;} catch(e) {return def}}

function XMLAttributeValueToHTML(attr)
{
	var result;
	try
	{
		result = attr.xml.replace(/[^"]*"/, "");
		result = result.replace(/\"[^$]*/, "");
	} 
	catch(e)
	{
		result = ""
	} 
	if (IsEmpty(result))
		result = "&nbsp;";
	return result;
}

function XMLCreateNode(dom, name, data, attributes)
{
try
{
	var node = dom.createElement(name);
	if (data !== null)
		node.appendChild(dom.createCDATASection(data));
	if (!IsEmpty(attributes))
		for (var i=0; i<attributes.length; i++)
			node.setAttribute(attributes[i][0], attributes[i][1]);
	return node;
}
catch(e)
{
	return null;
}
}

function XMLAppendNode(dom, parentName, childName, data, attributes)
{
try
{
	var parent = dom.selectSingleNode(parentName);
	var node = XMLCreateNode(dom, childName, data, attributes);
	parent.appendChild(node);
	return node;
}
catch(e)
{
	return null;
}
}

function XMLGetNodeText(dom, nodeName, defaultResult)
{
	if (arguments.length<3) defaultResult = null; 
	try
	{
		return dom.selectSingleNode("//"+nodeName).text
	}
	catch(e)
	{
		return defaultResult;
	}
}

function XMLGetAttributeText(node, attrName, defaultResult)
{
	if (arguments.length<3) defaultResult = null; 
	try
	{
		return node.attributes.getNamedItem(attrName).text;
	}
	catch(e)
	{
		return defaultResult;
	}
}

function XMLGetNodeAttributeText(dom, nodeName, attrName, defaultResult)
{
	if (arguments.length<4) defaultResult = null; 
	try
	{		
		return dom.selectSingleNode("//"+nodeName).attributes.getNamedItem(attrName).text;
	}
	catch(e)
	{
		return defaultResult;
	}
}

function XMLEnumString(list, colValue)
{
	if (IsEmpty(colValue)) colValue = null;

	var result = "<Vs>";
	for (i=0; i<list.length; i++)
		result += "<V><![CDATA["+ ((colValue==null) ? list[i] : list[i][colValue]) +"]]></V>";
	result += "</Vs>";
	return result;
}

function XMLEnumValues(enumString)
{
	var result = [];
	var t, s = enumString.split("]]></V>");
	for (var i=0; i<s.length-1; i++)
	{
		t = s[i].split("<![CDATA[");
		if (t.length>1)
			result[result.length] = t[1];
	}
	return result;
}


function ArrayListToRow(arrayList, propList, def)
{
	if (IsEmpty(def)) def = "";

	var result = [];
	var v, row;
	for (var i in arrayList)
	{
		row = [];
		for (var j=0; j<propList.length; j++)
		{
			v = arrayList[i][propList[j]];
			if (v != null)
				row[row.length] = v;
			else
				row[row.length] = def;
		}
		result[result.length] = row.slice(0);
	}
	return result;
}

/* DATETIME */

function StdDateString(y, m, d) { y = "0000"+ y; m = "00"+ m; d = "00"+ d; return y.slice(-4) +"-"+ m.slice(-2) +"-"+ d.slice(-2); }
function StdTimeString(h, m, s) { h = "00"+ h; m = "00"+ m;	s = "00"+ s; return h.slice(-2) +":"+ m.slice(-2) +":"+ s.slice(-2); }
function StdDateTimeString(year, month, day, hour, min, sec) { if (IsEmpty(hour)) hour = 0; if (IsEmpty(min)) min = 0; if (IsEmpty(sec)) sec = 0; return StdDateString(year, month, day) +" "+ StdTimeString(hour, min, sec) }
function DateToStdDateString(date) { return StdDateString(date.getFullYear(), 1+date.getMonth(), date.getDate()) };
function DateToStdTimeString(date) { return StdTimeString(date.getHours(), date.getMinutes(), date.getSeconds()) };
function DateToStdDateTimeString(date) { return StdDateTimeString(date.getFullYear(), 1+date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()) };
function StdDateTimeObject(stdDateTime_Date, object)
{
	var d = stdDateTime_Date;
	if (IsEmpty(object)) object = new Object();
	if (IsEmpty(d)) 
	{
		object.year = "";
		object.month = "";
		object.day = "";
		object.hour = "";
		object.min = "";
		object.sec = "";
	}
	else
	{		
		if (IsEmpty(d.getDate))
		{
			object.year = d.slice(0,4);
			object.month = d.slice(5,7);
			object.day = d.slice(8,10);
			object.hour = d.slice(11,13);
			object.min = d.slice(14,16);
			object.sec = d.slice(17,19);
		}
		else
		{
			var d = new Date();
			object.year = d.getFullYear();
			object.month = 1+d.getMonth();
			object.day = d.getDate();
			object.hour = d.getHours();
			object.min = d.getMinutes();
			object.sec = d.getSeconds();
		}
	}
	return object;
}

/* OBJECT */

function ObjectClone(obj)
{
	var result = {};
	for (var i in obj)
		result[i] = obj[i];
	return result;
}

function ObjectCompare(partial, complete)
{
	for (var i in partial)
		if (partial[i] != complete[i])
			return false;
	return true;
}

function ObjectSerialize(obj, defObj)
{
	var sep = "";
	var result = "";
	for (var i in obj)
	{		
		if (defObj != null && obj[i] != null && obj[i] == defObj[i])
			continue;
		if (IsObject(obj[i]))
		{
			var sub = ObjectSerialize(obj[i]);
			var defSub = ObjectSerialize(defObj[i]);
			if (sub == defSub)
				continue;
			result += sep + i +':'+ sub;
		}
		else if (parseInt(obj[i]) == obj[i] || parseFloat(obj[i]) == obj[i])
			result += sep + i +':'+ obj[i];
		else
			result += sep + i +':"'+ obj[i] +'"';
		sep = ','
	}
	if (result != "")
		result = "{"+ result +"}";
	return result;
}

function ObjectNormalize(obj, defObj)
{
	try
	{
		if (IsString(obj))
			eval("obj="+obj);
		if (IsEmpty(obj))
			return ObjectClone(defObj);
		for (var i in defObj)
			if (obj[i] == null)
				obj[i] = defObj[i];
		return obj;
	}
	catch(e)
	{
		return defObj;
	}
}


//===========
// CSelection
//===========
function CSelection()
{
	this.all = [];
	this.get = function(id){return this.all[id]};
	this.add = function(id, object)
	{
		if (IsEmpty(id)) return;
		if (object == null) object = true;
		var tmp = id.toString().split(",");
		for (var i=0; i<tmp.length; i++)
			this.all[tmp[i]] = object
	};
	this.del = function(id){delete this.all[id]};
	this.reset = function(id, object){this.all=[]; this.add(id, object)};
	this.serialize = function(emptyDef)
	{
		var result = "";
		for (var i in this.all)
		{
			if (result != "")
				result += ",";
			result += i;
		}
		if (IsEmpty(result))
			result = emptyDef;		
		return result;
	}
}

/*** Serialization ***/

var __reString1 = /(&)|(<)|(>)|(')|(")|(\b)|(\t)|(\n)|(\v)|(\f)|(\r)/gm;
var __reString2 = /(&x0008;)|(&x0009;)|(&x000A;)|(&x000B;)|(&x000C;)|(&x000D;)|(&quot;)|(&apos;)|(&gt;)|(&lt;)|(&amp;)/gm;
var __reTag = /(<(?:\s|\S)*?>)/gm;
var __reType = /<(\/?\S*)(\s|>)/m;
var __reName = /\sn="([^"]*)"/m;
var __reValue = /\sv="([^"]*)"/m;
var __reOwner = /(<owner(?:\s|\S)*?>(?:\s|\S)*?<\/owner>)/gi;
var __reClient = /(<client(?:\s|\S)*?>(?:\s|\S)*?<\/client>)/m;
var __reServer = /(<server(?:\s|\S)*?>(?:\s|\S)*?<\/server>)/m;
function SerializeString(s)
{
	return (""+s).replace
	(
		__reString1,
		function($0)
		{
			switch($0)
			{
				case "&": return "&amp;";
				case "<": return "&lt;";
				case ">": return "&gt;";
				case "'": return "&apos;";
				case '"': return "&quot;";
				case "\b": return "&x0008;";
				case "\t": return "&x0009;";
				case "\n": return "&x000A;";
				case "\v": return "&x000B;";
				case "\f": return "&x000C;";
				case "\r": return "&x000D;";
				default: return $0;
			}
		}
	)
}
function DeserializeString(s)
{
	if (s==null)
		return "";
	return s.replace
	(
		__reString2,
		function($0)
		{
			switch($0)
			{
				case "&amp;": return "&";
				case "&lt;": return "<";
				case "&gt;": return ">";
				case "&apos;": return "'";
				case "&quot;": return '"';
				case "&x0008;": return "\b";
				case "&x0009;": return "\t";
				case "&x000A;": return "\n";
				case "&x000B;": return "\v";
				case "&x000C;": return "\f";
				case "&x000D;": return "\r";
				default: return $0;
			}
		}
	)
}

function SerializeDate(d) { return d.getFullYear() +'-'+ ('0'+(d.getMonth()+1)).slice(-2) +'-'+ ('0'+d.getDate()).slice(-2) +' '+ ('0'+d.getHours()).slice(-2) +':'+ ('0'+d.getMinutes()).slice(-2) +':'+ ('0'+d.getSeconds()).slice(-2) +':'+ ('00'+d.getMilliseconds()).slice(-3) }
function DeserializeDate(s) { return new Date(parseInt(s.slice(0,4), 10), parseInt(s.slice(5,7), 10)-1, parseInt(s.slice(8,10), 10), parseInt(s.slice(11,13), 10), parseInt(s.slice(14,16), 10), parseInt(s.slice(17,19), 10), parseInt(s.slice(20,22), 10)) }

/* Serialize
***************
	Funzione ricorsiva utilizzata per la serializzazione di un oggetto JavaScript in una stringa XML. 
	La funzione opera interamente in JavaScript per aumentare la compatibilità con i browser. 
	Possono essere serializzati solo: Number, String, Boolean, Date, RegExp, Array e Object. 
	Non vengono ad esempio serializzati oggetti di tipo Function, ActiveX, Applet, ecc.  
__o  
	Oggetto da serializzare.  
__id  
	Identificativo dell'oggetto serializzato. Normalmente si tratta dell'identivicativo di __o (cioè: eval(__id)==__o) ma può essere usato un identificativo qualunque. In fase di deserializzazione l'oggetto serializzato verrà ripristinato con il nome __id.  
Nota:  
	Per motivi di implementazione l'oggetto serializzato, l'identificativo specificato e le sue eventuali proprietà enumerabili non possono avere nomi che iniziano con "__" come ad esempio __o oppure __id.  
*/
function Serialize(__o, __id)
{
	var __xml = arguments[2] == undefined ? "" : arguments[2];
	var __result = "";
	var __i;
	switch (TypeOf(__o))
	{
		case "number": return '<n n="'+ __id +'" v="'+ __o +'"/>';
		case "string": return '<s n="'+ __id +'" v="'+ SerializeString(__o) +'"/>';
		case "boolean": return '<b n="'+ __id +'" v="'+ (__o?1:0) +'"/>';
		case "date": return '<d n="'+ __id +'" v="'+ SerializeDate(__o) +'"/>';
		case "regexp": return '<r n="'+ __id +'" v="'+ SerializeString(__o.toString()) +'"/>';
		case "array": for (__i in __o) __result += Serialize(__o[__i], __i, __xml); return __xml += '<a n="'+ __id +'">'+ __result +'</a>';
		case "object": for (__i in __o) __result += Serialize(__o[__i], __i, __xml); return __xml += '<o n="'+ __id +'">'+ __result +'</o>';
		default: return "";
	}
}

/* Deserialize
*****************
	Funzione ricorsiva utilizzata per la serializzazione di un oggetto JavaScript in una stringa XML. 
	La funzione opera interamente in JavaScript per aumentare la compatibilità con i browser. 
	Possono essere serializzati solo: Number, String, Boolean, Date, RegExp, Array e Object. 
	Non vengono ad esempio serializzati oggetti di tipo Function, ActiveX, Applet, ecc.  
__xml  
	Stringa xml contenente l'oggetto da deserializzare.  
__parentObjectId optional  
	Identificativo opzionale di un oggetto al di sotto del quale collocare l'oggetto da deserializzare. 
	Se omesso l'oggetto viene deserializzato come oggetto globale sovrascrivendo un eventuale oggetto già presente con lo stesso identificativo. 
	Se indicato l'oggetto deserializzato verrà appeso come property all'oggetto indicato. L'oggetto con identificativo parentObjectId viene creato solo se non è già esistente e non viene mai sovrascritto (mentre vengono sovrascritte eventuali property conincidenti con quelle deserializzate).  
Nota:  
	Per motivi di implementazione __parentObject non può iniziare con "__".  
*/
function Deserialize(__xml, __parentObjectId)
{
	__parentObjectId = __parentObjectId == null ? "" : __parentObjectId;
	var __i, __j, __k, __node;
	var __r = __xml.match(__reTag);
	for (__i=0; __i<__r.length; __i++)
	{
		__node = new Object();
		__node.type = __reType.exec(__r[__i]);
		if (__node.type)
			__node.type = __node.type[1];
		__node.name = __reName.exec(__r[__i]);
		if (__node.name)
			__node.name = __node.name[1];
		__node.value = __reValue.exec(__r[__i]);
		if (__node.value)
		{
			__node.value = __node.value[1];
			switch (__node.type)
			{
				case "n": __node.value = parseFloat(__node.value); break;
				case "s": __node.value = DeserializeString(__node.value); break;
				case "b": __node.value = __node.value = '1' ? true : false; break;
				case "d": __node.value = DeserializeDate(__node.value); break;
				case "r": __node.value = __node.value.toString(); break;
			}
		}
		__r[__i] = __node;
	}
	for (__i=0; __i<__r.length; __i++)
	{
		switch (__r[__i].type)
		{
			case "a":
				for (__j=__i+1, __k=0; __j<__r.length; __j++)
				{
					if (__r[__j].type == "/a" || __r[__j].type == "/o")
					{
						__k--;
						if (__k<=0 && __r[__j].type == "/a") break;
						continue;
					}
					if (__k==0)
					{
						if (isNaN(parseInt(__r[__j].name, 10)))
							__r[__j].name = __r[__i].name +'["'+ __r[__j].name +'"]';
						else
							__r[__j].name = __r[__i].name +'['+ __r[__j].name +']';
					}
					if (__r[__j].type == "a" || __r[__j].type == "o")
						__k++;
				}
				break;
			case "o":
				for (__j=__i+1, __k=0; __j<__r.length; __j++)
				{
					if (__r[__j].type == "/a" || __r[__j].type == "/o")
					{
						__k--;
						if (__k<=0 && __r[__j].type == "/o") break;
						continue;
					}
					if (__k==0)
						__r[__j].name = __r[__i].name +'.'+ __r[__j].name;
					if (__r[__j].type == "a" || __r[__j].type == "o")
						__k++;
				}
				break;
		}
	}
	if (__parentObjectId !== "")
	{
		if ( eval("typeof "+__parentObjectId) != "object" )
			eval( __parentObjectId +"= new Object()");
		__parentObjectId += ".";
	}
	for (__i=0; __i<__r.length; __i++)
	{
		switch (__r[__i].type)
		{
			case "n":
			case "s":
			case "b":
			case "d":
			case "r":
				eval(__parentObjectId + __r[__i].name +'= __r[__i].value'); 
				break;
			case "a":
				eval(__parentObjectId + __r[__i].name +"=[]");
				break;
			case "o":
				eval(__parentObjectId + __r[__i].name +"= new Object()");
				break;
		}
	}
}

/* PLACE HOLDER */

function OpenInnerLink(){}
function OpenInnerRef(){}
function OpenExternal(url)
{
    if (url.indexOf("file:") == 0)
    {
        try
        {
        	var fileName = url.replace("file:", "");
        	fileName = fileName.replace(/\\/g, "\\");
            fileEditObj = new ActiveXObject("FileEditCtrl.FileEdit");
            fileEditObj.OpenFile(url);
        }
        catch(e)
        {
            if (e.number == -2146827859)
            {
                // ActiveX can't create object.
                if (!window.confirm("Questa funzionalità richiede l'installazione di un componente ActiveX.\nProcedere con l'installazione?"))
                    return null;

                // Download del setup.
                window.open("/knos/plugin/FileEditSetup2.msi", "_blank");
            }
            else
                throw e;
        }
    }
	else
		window.open(url, "External").focus()
}

