/*
 * liwe.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */

/*
 *
 *	2009-04-16:	- Added the ``strong_debug`` flag to the liwe base class (default to ``false``).
 *
 *
 *	2009-03-06:	- $() and $v() are now here and not in utils.js
 *			- $() now can have a second optional argument to set the innerHTML.
 */

// PUBLIC: liwe
var liwe = {};
liwe.utils = {};
liwe.fx = {};

liwe.strong_debug = false;

// Library base
liwe._libbase = "";

liwe.ajax_url = "/ajax.php";

// Try to be compatible with other browsers
// Only use firebug logging when available
// (this code is a modified version of firebugx.js, written
// by Joe Hewitt)
if ( ! window [ "console" ] ) window.console = {};

try
{
	liwe._console = window.console [ "debug" ];
} catch ( e ) {
	window.console = {};
	liwe._console = null;
}

if ( ! liwe._console )
{
	var names = [ "log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", 
		      "timeEnd", "count", "trace", "profile", "profileEnd" ];

	for ( var i = 0; i < names.length; ++i )
		window.console [ names [ i ] ] = function() {};
}

liwe.set_libbase = function ( libbase_url )
{
	if ( libbase_url )
	{
		liwe._libbase = libbase_url;
		return;
	}

	var scripts = document.getElementsByTagName ( "script" );
	var l = scripts.length;
	var t, s, pos, path = "";

	for ( t = 0; t < l; t ++ )
	{
		s = scripts [ t ].src;

		if ( ! s ) continue;

		if ( s.match ( /liwe.*js/ ) )
		{
			s = s.replace ( /.*os3phplib.send_gzip.php.fname=/, "" );
			pos = s.lastIndexOf ( "/" );
			if ( pos != -1 ) path = s.slice ( 0, pos + 1 );
		}
	}

	if ( path ) liwe._libbase = path;
	else liwe._libbase = "/os3jslib";
};

liwe.set_libbase ();

// =============================================================================
// UTILS
// =============================================================================
liwe.utils.WAIT_TIMEOUT = 2000; // Milli seconds
liwe.utils.WAIT_TIME = 50; // Milli seconds

liwe.utils.wait_def = function ( name, cback, vars, time )
{
	if ( ! liwe.utils.is_def ( name ) ) 
	{
		if ( ! time ) time = 0;
		if ( time > liwe.utils.WAIT_TIMEOUT )
		{
			if ( liwe.strong_debug ) alert ( "Failed: " + name );
			return;
		}

		setTimeout ( function () { liwe.utils.wait_def ( name, cback, vars, time + liwe.utils.WAIT_TIME ); }, liwe.utils.WAIT_TIME );
        } else {
		if ( typeof ( cback ) != 'object' ) cback ( vars );
	}
};

liwe.utils.append_js = function ( script_file )
{
        var head = document.getElementsByTagName ( "head" ) [ 0 ];
        var new_script = document.createElement ( "script" );

        new_script.src = script_file;
        new_script.type = "text/javascript";
        head.appendChild ( new_script );
};


liwe.utils.is_def = function ( name )
{
	var is_def = false;
	var l;

	if ( typeof name == "string" )
	{
		var items = name.split ( "." );
		var s = '';

		s = items [ 0 ];
		l = items.length;

		for ( t = 0; t < l; t ++ )
		{
			// console.debug ( "Check for: " + s );
			eval ( "is_def = ( typeof ( " + s + " ) != 'undefined' );" );
			if ( ! is_def ) return false;
			if ( ! items [ t + 1 ] ) break;

			s += "." + items [ t + 1 ];
		}
		return true;
	}

	var t;
	var n;

	l = name.length;

	for ( t = 0; t < l; t ++ )
	{
		n = name [ t ];
		eval ( "is_def = ( typeof ( " + n + " ) != 'undefined' );" );

		if ( ! is_def ) return false;
	}

	return true;
};

liwe.browser = {};

liwe.browser.version = navigator.appVersion;
liwe.browser.has_dom = document.getElementById ? 1 : 0;
liwe.browser.ie = ( typeof window [ "ActiveXObject" ] != "undefined" ); //window.ActiveXObject != null );
liwe.browser.gecko = ( navigator.userAgent.toLowerCase().indexOf ( "gecko" ) != -1 ) ? 1 : 0;
liwe.browser.opera = ( navigator.userAgent.toLowerCase().indexOf ( "opera" ) != -1 ) ? 1 : 0;

// =============================================================================
// POSTLOADER
// =============================================================================

liwe.postload = {};

// The time (in millis) before a specified file is timedout
liwe.postload.WAIT_TIMEOUT = 30000; // 30 seconds (time is in millis)

// Millis to check for a specified file
liwe.postload.WAIT_TIME = 50; // 50 milli seconds
liwe.postload.events = {};

// This event is fired when a SINGLE SCRIPT has been loaded
// cback: script_loaded ( script_name )
liwe.postload.events [ 'script_load' ] = null;	

// This event is fired whenever PostLoader thinks it is good to
// update your load status info
// cback: script_update ( items_loaded, tot_items )
liwe.postload.events [ 'update' ] = null;

// This event is fired when PostLoader has finished to load
// ALL scripts defined.
// cback: script_completed ()
liwe.postload.events [ 'completed' ] = null;

/* FILES fields values:
#
#	0 - priority
#	1 - file name
#	2 - check_for
#	3 - cback
#	4 - vars
#	5 - is loaded
*/
liwe.postload._files = [];
liwe.postload._loaded_files = 0;

liwe.postload.add = function ( fname, check_for, pri, cback, vars )
{
	if ( ! pri ) pri = 1;

	if ( liwe.utils.is_def ( check_for ) ) return;

	liwe.postload._files.push ( [ pri, fname, check_for, cback, vars, 0 ] );
};

liwe.postload.load = function ()
{
	var t, l, itm;

	liwe.postload._files.sort ();

	l = liwe.postload._files.length;

	// keep count of loaded files
	liwe.postload._loaded_files = 0;

	for ( t = 0; t < l; t ++ )
	{
		itm = liwe.postload._files [ t ];
		// Files already in memory are skipped
		if ( itm [ 5 ] ) liwe.postload._loaded ( t ); 

		liwe.utils.append_js ( itm [ 1 ] );
		liwe.utils.wait_def ( itm [ 2 ], liwe.postload._loaded, t );
	}
};

liwe.postload._loaded = function ( pos )
{
	liwe.postload._loaded_files += 1;

	var itm = liwe.postload._files [ pos ];

	itm [ 5 ] = 1;

	if ( liwe.postload.events [ 'script_loaded' ] )
		liwe.postload.events [ 'script_loaded' ] ( itm [ 1 ] );

	if ( itm [ 3 ] ) itm [ 3 ] ( itm [ 4 ] );

	if ( liwe.postload.events [ 'update' ] )
		liwe.postload.events [ 'update' ] ( liwe.postload._loaded_files, liwe.postload._files.length );

	if ( ! ( liwe.postload._files.length - liwe.postload._loaded_files ) )
		if ( liwe.postload.events [ 'completed' ] ) liwe.postload.events [ 'completed' ] ();
};


liwe._clear_dom = function ( e )
{
	var i, l = e.childNodes.length;
	for ( i = 0; i < l; i ++ )
	{
		var el = e.childNodes [ i ];

		//PULIZIA
		var v;
		for ( v in el )
		{
			if ( v.charAt ( 0 ) != "_" ) continue;

			console.debug ( v );

			if ( v == "_listeners" )
			{
				var listeners = [].concat ( el [ v ] );
				var vi, vl = listeners.length;
				for ( vi = 0; vi < vl; vi ++ )
				{
					var lid = listeners [ vi ];
					var rec = _all [ lid ];
					if ( rec ) liwe.events.del ( rec.target, rec.type, rec.listener );
				}
			}

			try
			{
				el [ v ] = null;
			}
			catch (e)
			{
			}
		} 

		liwe._clear_dom ( el );
	}
};


function $ ( name, inner_html, warn )
{
	var e = document.getElementById ( name );

	if ( ! e ) 
	{
		if ( warn ) console.warn ( "Element: %s not found", name );
		return null;
	}

	if ( typeof inner_html == "undefined" )
		return e;

	// liwe._clear_dom ( e );

	e.innerHTML = inner_html;
	return e;
}

function $v ( name, def_val )
{
	var d = document.getElementById ( name );
	if ( ! d ) return def_val;

	return d.value;
}



/*
 * object_enh.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */
// PUBLIC: iterate
Object.prototype.iterate = function ( cback )
{
	var k;

	for ( k in this )
	{
		if ( typeof ( this [ k ] ) == 'function' ) continue;
		cback ( this [ k ], k );
	}
};

Object.prototype.keys = function ()
{
	var res = [];

	this.iterate ( function ( v, k ) { res.push ( k ); } );

	return res;
};

Object.prototype.values = function ()
{
	var res = [];

	this.iterate ( function ( v ) { res.push ( v ); } );

	return res;
};

// PUBLIC: debugDump
Object.prototype.debugDump = function ( dump_funcs, lvl )
{
	var s = '';
	var k;

	if ( ! lvl ) lvl = '';

	for ( k in this )
	{
		if ( typeof ( this [ k ] ) == 'function' ) 
		{
			if ( dump_funcs ) s += lvl + 'function ' + k + ' ()\n';
		} else {
			if ( typeof ( this [ k ] ) == 'object' )
			{
				s += lvl + k + ":\n" + this [ k ].debugDump ( dump_funcs, lvl + "-----  " );
			} else {
				s += lvl + k + ": " + this [ k ] + "\n";
			}
		}
	}

	return s;
};

// PUBLIC: count
Object.prototype.count = function ()
{
	var k;
	var res = 0;
	
	for ( k in this )
	{
		if ( ( typeof ( this [ k ] ) == 'function' ) ) continue;
		res ++;
	}

	return res;
};

// PUBLIC: get
Object.prototype.get = function ( name, def_val )
{
	var res = this [ name ];

	if ( typeof ( res ) == 'undefined' ) return def_val;

	return res;
};

// PUBLIC: getName
Object.prototype.getName = function ()
{
	if ( this.name ) return this.name;

	var s = "" + this;
	var v = s.match ( /^function  *([_a-zA-Z$][_a-zA-Z0-9$]*)  *.*/ ); //new RegExp ( "^function  *(.*) *\(" ) )

	if ( ! v ) return '';

	return v [ 1 ];
};

// PUBLIC: inherits
Object.prototype.inherits = function ( p )
{
	var name;

	this.parent = p;
	for ( name in p )
	{
		if ( typeof this [ name ] == 'undefined' ) this [ name ] = p [ name ];
	}
};


// PUBLIC: clone
Object.prototype.clone = function ()
{
        var res ={};
        var name;

        for ( name in this ) res [ name ] = this [ name ];

        return res;
};




/*
 * array_enh.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */
// PUBLIC: toSourceString
Array.prototype.toSourceString = function ( include_funcs )
{
	var s = '{';
	var k, v;
	var is_first = true;

	for ( k in this )
	{
		if ( ( typeof ( this [ k ] ) == 'function' ) && ( ! include_funcs ) ) continue;

		if ( ! is_first ) s += ", ";
		s += "'" + k + "' : '" + this [ k ] + "'";
		is_first = false;
	}

	s += "}";

	return s;
};

// PUBLIC: count
Array.prototype.count = function ()
{
	var k;
	var res = 0;
	
	for ( k in this )
	{
		if ( ( typeof ( this [ k ] ) == 'function' ) ) continue;
		if ( k == '__arr' ) continue;
		res ++;
	}

	return res;
};

// PUBLIC: fromObject
Array.fromObject = function ( a, include_funcs )
{
	var arr = new Array ();
	var k, v;

	for ( k in a ) 
	{
		if ( ( ! include_funcs ) && ( typeof ( a [ k ] ) == 'function' ) ) continue;

		arr [ k ] = a [ k ];
	}

	return arr;
};

// PUBLIC: fromForm
Array.fromForm = function ( form_id, max_depth )
{
	var arr = new Array ();
	var f = document.getElementById ( form_id );
	
	if ( ! max_depth ) max_depth = 0;

	_form_add_elems ( f, arr, max_depth, 0 );

	return arr;
};

// PUBLIC: find
Array.prototype.find = function ( key, case_sens, include_funcs )
{
	var k;
	var c = 0;

	if ( ! case_sens ) key = key.toLowerCase ();

	for ( k in this )
	{
		if ( ( typeof ( this [ k ] ) == 'function' ) && ( ! include_funcs ) ) continue;

		k = this [ k ];
		if ( ! case_sens ) k = k.toLowerCase ();
		if ( k == key ) return c;
			
		c++;
	}

	return -1;
};

// PUBLIC: toObject
Array.toObject = function ( arr )
{
	var res = {};
	var k;

	for ( k in arr )
	{
		if ( ( typeof ( arr [ k ] ) == 'function' ) ) continue;
		
		res [ k ] = arr [ k ];
	}

	return res;
};

// PUBLIC: del
Array.prototype.del = function ( pos, how_many )
{
	if ( ! how_many ) how_many = 1;

	var to_del = Array();

	var start = pos;
	var stop = pos + how_many;

	var k, count = -1, i;
	for ( k in this )
	{
		count++;

		if ( count < start ) 	  continue;
		else if ( count >= stop ) break;

		to_del.push ( k );
	}

	for ( i = 0; i < to_del.length; i++ )
	{
		delete this [ to_del [ i ] ];
	}
};

// PUBLIC: delKey
Array.prototype.delKey = function ( k )
{
	delete this [ k ];
};


if ( Array.prototype.indexOf == null )
{
	Array.prototype.indexOf = function ( item )
	{
		var t, l = this.length;
		for ( t = 0; t < l; t ++ )
			if ( this [ t ] == item ) return t;
		return -1;
	};
}


function _form_add_elems( node, arr, max_depth, curr_depth )
{
	var inps, sels, txts, t, n;

	inps = node.getElementsByTagName ( "input" );
	sels = node.getElementsByTagName ( "select" );
	txts = node.getElementsByTagName ( "textarea" );

	for ( t = 0; t < inps.length; t ++ )
	{
		n = inps [ t ];
		if ( ( ( n.type == 'radio' ) || ( n.type == 'checkbox' ) ) && ( n.checked == false ) ) continue;
		arr [ n.name ] = n.value;
	}

	for ( t = 0; t < sels.length; t ++ ) arr [ sels [ t ].name ] = sels [ t ].value;
	for ( t = 0; t < txts.length; t ++ ) arr [ txts [ t ].name ] = txts [ t ].value;
}


/* Implement array.push for browsers which don't support it natively. 
   Copyright 2005 Mark Wubben 
*/
if ( Array.prototype.push == null )
{
	Array.prototype.push = function() 
	{
		for( var i = 0; i < arguments.length; i++ )
			this [ this.length ] = arguments [ i ];

		return this.length;
	};
}



/*
 * string_enh.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 *
 *  2009-07-09: Fix htmlEntities now skips ";" "="
 *  2009-06-16: Fix htmlEntities now works again and skips "<" ">", '"', "'", "\r", "\n"
 *  2009-04-16: Fix htmlEntities RegExp to skip "-", "(" and ")"
 *  2009-01-14:	Added the String.buffer class
 */

// PUBLIC: startsWith
String.prototype.startsWith = function ( str )
{
	if ( this.substr ( 0, str.length ) == str ) return ( true );
	
	return ( false );
};

// PUBLIC: endsWith
String.prototype.endsWith = function ( str )
{
	if ( this.substr ( this.length - str.length ) == str ) return ( true );
	
	return ( false );
};

// PUBLIC: buffer
String.buffer = function ()
{
	this._buf = [];

	this.add = function ()
	{
		var t, l = arguments.length;

		for ( t = 0; t < l; t ++ )
			this._buf.push ( arguments [ t ] );

		return this;
	};

	this.get = function ( sep )
	{
		if ( ! sep ) sep = "";

		return this._buf.join ( sep );
	};

	this.toString = function () { return this.get ( "" ); };
};

String._re_htmlentities_invalid = /([^a-zA-Z0-9,.:;=!?+\/_ |@-\\(\\)<>\n\r'"&#-])/g;
String.prototype.htmlEntities = function ()
{
        function _ch ( m )
        {
                return ( "&#" + m.charCodeAt ( 0 ) + ";" );
        }

        return this.replace ( String._re_htmlentities_invalid, _ch );
};

String._re_entities_decl = /&#([^;]*);/g;
String.prototype.entities2char = function ()
{
	function _ch ( m, p1 )
	{
		return String.fromCharCode ( parseInt ( p1, 10 ) );
	}

	return this.replace ( String._re_entities_decl, _ch );
};


// PUBLIC: join
String.prototype.join = function ( arr )
{
	var l = arr.length;
	var k, t;
	var s = '';
	var is_first = true;

	for ( t = 0; t < l; t ++ )
	{
		if ( typeof ( arr [ t ] ) == 'function' ) continue;
		if ( ! is_first ) s += this;
		s += arr [ t ];
		is_first = false;
	}

	return s;
};

// PUBLIC: LStrip
String.prototype.LStrip = function ()
{
	return this.replace ( /^\s+/, "" );
};

// PUBLIC: RStrip
String.prototype.RStrip = function ()
{
	return this.replace ( /\s+$/, "" );
};

// PUBLIC: Strip
String.prototype.Strip = function () { return this.replace ( /^\s+|\s+$/,"" ); };

// PUBLIC: isUpper
String.prototype.isUpper = function () 
{
	var l = this.length;
	var c, t;

	if ( ! l ) return false;

	for ( t = 0; t < l; t ++ )
	{
		c = this [ t ].toUpperCase ();
		if ( c != this [ t ] ) return false;
	}

	return true;
	
};

// PUBLIC: isLower
String.prototype.isLower =  function () 
{
	var l = this.length;
	var c, t;

	if ( ! l ) return false;

	for ( t = 0; t < l; t ++ )
	{
		c = this [ t ].toLowerCase ();
		if ( c != this [ t ] ) return false;
	}

	return true;
	
};

String.basename = function ( s, sep )
{
	if ( ! sep ) sep = "/";

	return s.split ( sep ).slice ( -1 );
};

String.dirname = function ( s, sep )
{
	if ( ! sep ) sep = "/";

	return sep.join ( ( s.split ( sep ) ).slice ( 0, -1 ) );
};

// PUBLIC: format
String.format = function ()
{
	function re_replace ( v )
	{
		var m = v.match ( _re_replace );
		var val = args [ ++count ];

		return _string_re_replace ( m, val );
	}

	var _re_replace = /%([0+#-]*)([0-9]*)(\.{0,1})([0-9]*)([dsqm])/;
	var re = /%[0+#-]*[0-9]*\.{0,1}[0-9]*[dsqm]/gi;
	var fmt = arguments [ 0 ];	// The first param is the string format
	var count = 0;
	var args = arguments;

	return fmt.replace ( re, re_replace );
};

// PUBLIC: formatDict
String.formatDict = function ( fmt, dict )
{
	function re_replace ( v )
	{
		var m = v.match ( _re_replace );
		var val = dict [ m [ 1 ] ];
		var p1 = m.shift ();

		m.shift ();
		m.unshift ( p1 );
		return _string_re_replace ( m, val );
	}

	var _re_replace = /%\(([^)]*)\)([0+#-]*)([0-9]*)(\.{0,1})([0-9]*)([dsqm])/;
	var re = /%\([a-z0-9_-]+\)[0+#-]?[0-9]*\.?[0-9]*[dsqm]/gi;

	if ( fmt == "" ) return "";

	if ( ! fmt )
	{
		console.warn ( "No FMT for the following dict: %o", dict );

		return "";

		// fmt = "";
	}
	
	return fmt.replace ( re, re_replace );
};

function _string_re_replace ( matches,  value )
{
	var flags = matches [ 1 ];
	var width = ( matches [ 2 ] ? parseInt ( matches [ 2 ] ) : 0 );
	var precision = ( matches [ 4 ] ? parseInt ( matches [ 4 ] ) : 0 );
	var type = matches [ 5 ];
	var res = '';
	var pad_char = ' ';
	var pad_left = false;
	var show_sign = false;

	if ( flags.indexOf ( '-' ) >= 0 ) pad_left = true;
	if ( flags.indexOf ( '0' ) >= 0 ) pad_char = '0';
	if ( flags.indexOf ( '+' ) >= 0 ) show_sign = true;

	if ( pad_char == '0' && pad_left ) pad_char = ' ';

	switch ( type )
	{
		case 'm':	// Money
			if ( typeof ( Money ) != 'undefined' )
			{
				res = Money.fromLongInt ( value );
			} else
				res = value;

			break;
			
		case 'd':
			res  = _string_mkpad ( true, value, precision, width, pad_char, false, pad_left, show_sign );
			break;

		case 'q':
			value = value.replace ( /'/g, "\\'" );
			// Non mettere break, deve finire al case 's'

		case 's':
			res  = _string_mkpad ( false, value, precision, width, pad_char, true, pad_left, false );
			break;
	}

	return res;
}

function _string_mkpad ( is_num, v, prec, width, pad_char, trunc, pad_left, show_sign )
{
	var sign = '';

	if ( is_num )
	{
		v = parseInt ( v );
		if ( v < 0 ) sign = '-';
		else if ( show_sign ) sign = '+';

		v = Math.abs ( v );
	}

	v = String ( v );

	if ( ! width && ! prec ) return v;

	var len, t, i;

	if ( is_num )
	{
		len = prec - v.length;
		if ( len > 0 ) for ( t = 0; t < len; t ++ ) v = "0" + v;
	}

	v = sign + v;

	len = width - v.length;
	if ( len > 0 )
	{
		for ( t = 0; t < len; t ++ )
			v = ( pad_left ? v + pad_char : pad_char + v );
	}

	if ( ! is_num && prec )
	{
		return v.slice ( 0, prec );
	}

	return  v;
}



/*
 * ajax_manager.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 *
 *       2009-05-04:	ADD: new static function AJAXManager.handle_easy
 *
 *       2009-01-24:	ADD: this.cbacks for:
 *
 *       			- serialize	serialize data
 *       			- req-start	request start
 *       			- req-end	request end
 *       			- req-error	request error
 *
 *       		ENH: AJAX Manager is now more "liwe"ized
 *       		ENH: removed String and Array enhancement dependencies
 *
 *       		DEP: error_handler has been DEPRECATED
 *       		DEP: start_req_handler has been DEPRECATED
 *       		DEP: end_req_handler has been DEPRECATED
 *
 */

// PUBLIC: ajax_response

// PUBLIC: AJAXManager
// PUBLIC  easy
// PUBLIC: request
function AJAXManager ()
{
	this._reqs = [];
	this._in_list = 0;
	this._in_abort = false;

	this.url = liwe.ajax_url;

	this.cbacks = {	"serialize" : null, 
			"req-start" : null, 
			"req-end" : null, 
			"req-error" : null 
		      };

	// {{{ request ( url, vars, callback, easy, sync )
	this.request = function ( url, vars, callback, easy, sync ) 
	{
		var req = null;
		var id = '';
		var t;
		var res = '';
		var self = this;
		var s;

		if ( ! url ) url = this.url;

		if ( vars ) 
		{
			for ( t in vars ) 
			{
				if ( typeof ( vars [ t ] ) == 'undefined' ) continue;
				if ( typeof ( vars [ t ] ) == 'function' ) continue;
				if ( ( typeof ( vars [ t ] ) == 'object' ) && ( vars [ t ] == null ) ) continue;

				/*
					This is a hack for IE, since it considers functions as objects (!!!)
				*/
				if ( typeof ( vars [ t ] ) == 'object' )
				{
					s = vars [ t ].toString ();
					if ( s.match ( /^function/ ) ) continue;
				}

				if ( vars [ t ] == '__arr' ) continue;

				if ( ( typeof ( vars [ t ] ) == 'string' ) || ( typeof ( vars [ t ] ) == 'number' ) )
				{
					res += t + "=" + this._ajax_escape ( vars [ t ] ) + "&";
				} else {
					try 
					{
						res += t + "=" + this._ajax_escape ( vars [ t ].toJSONString() ) + "&";
					} catch ( e ) {
						res += t + "=" + this._ajax_escape ( vars [ t ] ) + "&";
					}
				}
			}

			res = res.substr ( 0, res.length - 1 ); //  + "&";
		}

		req = this._build_req_obj ();


		// The request callback
		var _obj = this;
		if ( this.error_handler )
		{
			console.warn ( "AJAXManager.error_handler is DEPRECATED. Use cbacks [ 'req-error' ] instead." );
			req.onreadystatechange = function () { _obj._req_change ( req, callback, easy, _obj.error_handler ); };
		} else
			req.onreadystatechange = function () { _obj._req_change ( req, callback, easy, _obj.cbacks [ 'req-error' ] ); };

		var async = true;
		if ( sync ) async = false;

		// if (erroneously) the url starts with two "//", Firefox throws a security error
		url = url.replace ( /^\/\//g, "/" );

		req.open ( "POST", url, async );
		req.setRequestHeader ( 'Content-Type', 'application/x-www-form-urlencoded' );
		req.send ( res );

		if ( easy )
		{
			if ( this.start_req_handler ) 
			{
				console.warn ( "AJAXManager.start_req_handler is DEPRECATED. Use cbacks [ 'req-start' ] instead." );
				this.start_req_handler ( req );
			}

			if ( this.cbacks [ 'req-start' ] ) this.cbacks [ 'req-start' ] ( req );
		}
	};
	// }}}
	// {{{ easy ( arr, cback )
	this.easy    = function ( arr, cback ) { this.request ( null, arr, cback, true ); };
	// }}}
	// {{{ _build_req_obj ()
	this._build_req_obj = function ()
	{
		var req;

		/*@cc_on @*/
		/*@if (@_jscript_version >= 5)
		try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			} catch ( E ) {
				req = false;
			}
		}
		@end @*/

		if ( ! req && typeof XMLHttpRequest != 'undefined' ) 
		{
			try {
				req = new XMLHttpRequest();
			} catch (e) {
				req=false;
			}
		}

		if ( ! req && window.createRequest ) 
		{
			try {
				req = window.createRequest();
			} catch (e) {
				req=false;
			}
		}

		/*
		if ( window.XMLHttpRequest )		// Mozilla, Safari, Konqueror, Netscape...
		{
			req = new XMLHttpRequest ();
		} else {
			try {
				req = new ActiveXObject("Msxml2.XMLHTTP");
			} catch(e) {
				try {
					req = new ActiveXObject("Microsoft.XMLHTTP");
				} catch ( e ) {
					req = null;
					console.error ( "XMLHTTP Request object not available." );
				}
			}
		}

		*/

		this._reqs.push ( req );

		return req;
	};
	// }}}
	// {{{ _req_change ( req, callback, easy, err_handler )
	this._req_change = function ( req, callback, easy, err_handler )
	{
		if ( ! easy ) 
		{
			if ( callback ) callback ( req );
		} else {
			var in_abort = this._in_abort;

			// Remove the req from the Request Pool
			if ( req.readyState == 4 ) 
			{
				if ( this.end_req_handler ) 
				{
					console.warn ( "AJAXManager.end_req_handler is DEPRECATED. Use cbacks [ 'req-end' ] instead." );
					this.end_req_handler ( req );
				}

				if ( this.cbacks [ 'req-end' ] ) this.cbacks [ 'req-end' ] ( req );


				this._remove_req ( req );

				if ( in_abort ) return;

				AJAXManager.handle_easy ( req.responseText, callback, err_handler );
			}
		}
	};
	// }}}

	

	this.error_handler = null;		// DEPRECATED
	this.start_req_handler = null;		// DEPRECATED
	this.end_req_handler = null;		// DEPRECATED

	// {{{ _remove_req ( req )
	this._remove_req = function ( req )
	{
		var t, l = this._reqs.length;

		if ( this._in_list ) 
		{
			var obj = this;

			setTimeout ( function () { obj._remove_req ( req ); }, 100 );
			return;
		}

		this._in_list = 1;

		for ( t = 0; t < l; t ++ )
		{
			if ( this._reqs [ t ] == req ) break;
		}
		if ( t < l )
			this._reqs.splice ( t, 1 );

		this._in_list = 0;
	};
	// }}}
	// {{{ abort ( cback )
	this.abort = function ( cback )
	{
		var t, l = this._reqs.length;

		if ( this._in_list ) 
		{
			var obj = this;

			//console.debug ( "In list: " + this._in_list );
			setTimeout ( function () { obj.abort (); }, 100 );
			return;
		}

		this._in_list = 2;
		this._in_abort = true;

		for ( t = 0; t < l; t ++ )
		{
			try
			{
				this._reqs [ t ].abort ();
			} catch ( e ) {
			}
		}

		this._in_abort = false;
		this._in_list = 0;

		if ( cback ) cback ();
	};
	// }}}
	
	this._ajax_escape = function ( s )
	{
		if ( this.cbacks [ 'serialize' ] )
			s = this.cbacks [ 'serialize' ] ( s );

		s = escape ( s );
		s = s.replace ( /\+/g, "%2B" );
		return s;
	};
}

AJAXManager.handle_easy = function ( responseText, callback, err_handler )
{
	var resp_txt = responseText.replace ( /^\s+/, "" );

	if ( resp_txt.substr ( 0, "var ajax".length ) == 'var ajax' )
	{
		try {
			eval ( resp_txt );
			if ( ajax_response [ 'err_code' ] )
			{
				if ( ! err_handler )
				{
					if ( ajax_response [ 'err_descr' ] )
					{
						console.error ( ajax_response [ 'err_descr' ] );
						alert ( ajax_response [ 'err_descr' ] );
					} else {
						console.error ( "Generic Request error. Error code: " + ajax_response [ 'err_code' ] );
					}
				} else
					err_handler ( ajax_response );

				return;
			}
		} catch ( e ) {
			console.error ( "ERROR IN EVAL: %s - (except: %o)", responseText, e );
			return;
		}

		if ( callback && typeof ( callback ) == 'function' ) callback ( ajax_response );
	} else
		console.error ( "Request ERROR: " + responseText );
};

liwe.AJAX = new AJAXManager ();

liwe.AJAX._multi = {};
liwe.AJAX._multi_data = {};

liwe.AJAX.add = function ( name, action, dict, cback )
{
	var multi;
	var data;

	if ( ! name   ) name = "AJAX";
	if ( ! action ) action = null;


	multi = this._multi [ name ];
	if ( ! multi ) 
	{
		multi = [];
		data  = {};
	} else {
		data = this._multi_data [ name ];
	}

	if ( data [ 'running' ] ) 
	{
		console.error ( "Requests are already running for: %s", name );
		return;
	}

	multi.push ( [ action, dict, cback ] );
	this._multi [ name ] = multi;
	this._multi_data [ name ] = data;

	console.debug ( "Multi: %s - Len: %d", name, multi.length );
};

liwe.AJAX.start = function ( name, cback )
{
	var multi, data, t, l, req, func;

	multi = this._multi [ name ];
	if ( ! multi ) 
	{
		console.error ( "There is no multi group called: %s", name );
		return;
	}

	data = this._multi_data [ name ];
	data [ 'running' ] = true;
	data [ 'len' ] = multi.length;
	data [ 'count' ] = 0;

	l = multi.length;
	var i;
	for ( t = 0; t < l; t ++ )
	{
		req = multi [ t ];

		liwe.AJAX._send ( name, req, cback );
	}
};

liwe.AJAX._send = function ( name, req, cback ) 
{
	this.request ( req [ 0 ], req [ 1 ], function ( v ) { liwe.AJAX._req_cback ( name, v, req, cback ); }, true );
};

liwe.AJAX._req_cback = function ( name, v, req, cback )
{
	var multi = liwe.AJAX._multi [ name ];
	var data = liwe.AJAX._multi_data [ name ];

	if ( req [ 2 ] ) req [ 2 ] ( v );
	

	data [ 'count' ] += 1;

	if ( data [ 'count' ] == data [ 'len' ] ) 
	{
		if ( cback ) cback ();
		liwe.AJAX._multi [ name ] = null;
		liwe.AJAX._multi_data [ name ] = null;
	}
};


liwe.events = {};

if ( document.addEventListener )
{
	// W3C DOM 2 Events model
	liwe.events.add 	= function ( target, type, listener ) { target.addEventListener ( type, listener, false ); };
	liwe.events.del 	= function ( target, type, listener ) { target.removeEventListener ( type, listener, false ); };
	liwe.events.prevent 	= function ( e ) { e.preventDefault (); };
	liwe.events.stop 	= function ( e ) { e.stopPropagation(); };

	liwe.events.source  	= function ( e ) { return e.target; };
	liwe.events.keycode 	= function ( e ) { return e.which; };
} else if ( document.attachEvent ) {
	// Internet Explorer Events model

	liwe.events.add		= function ( target, type, listener )
	{
		// prevent adding the same listener twice, since DOM 2 Events ignores
		// duplicates like this
		if ( liwe.events._find ( target, type, listener) != -1 ) return;

		// _cback calls listener as a method of target in one of two ways,
		// depending on what this version of IE supports, and passes it the global
		// event object as an argument
		var _cback = function ()
		{
			var e = window.event;

			if ( Function.prototype.call )
				listener.call ( target, e );
			else {
				target._curr_listener = listener;
				target._curr_listener ( e )
				target._curr_listener = null;
			}
		};

    		// add _cback using IE's attachEvent method
    		target.attachEvent ( "on" + type, _cback );

    		// create an object describing this listener so we can clean it up later
    		var rec =
    		{
      			target: target,
      			type: type,
      			listener: listener,
      			_cback: _cback
    		};

    		// get a reference to the window object containing target
    		var targetDocument = target.document || target;
    		var targetWindow = targetDocument.parentWindow;

    		// create a unique ID for this listener
    		var listenerId = "l" + liwe.events._list_counter++;

    		// store a record of this listener in the window object
    		if ( !targetWindow._all ) targetWindow._all = {};
    		targetWindow._all [ listenerId ] = rec;

    		// store this listener's ID in target
    		if ( ! target._listeners ) target._listeners = [];
    		target._listeners [ target._listeners.length ] = listenerId;

    		if ( ! targetWindow._unload_added )
    		{
      			targetWindow._unload_added = true;
      			targetWindow.attachEvent ( "onunload", liwe.events._del_all );
    		}
  	};

  
	liwe.events.del = function ( target, type, listener )
	{
		// find out if the listener was actually added to target
		var listenerIndex = liwe.events._find ( target, type, listener );
		if ( listenerIndex == -1 ) return;

		// get a reference to the window object containing target
		var targetDocument = target.document || target;
		var targetWindow   = targetDocument.parentWindow;

		// obtain the record of the listener from the window object
		var listenerId = target._listeners [ listenerIndex ];
		var rec = targetWindow._all [ listenerId ];

		// remove the listener, and remove its ID from target
		target.detachEvent ( "on" + type, rec._cback );
		target._listeners.splice ( listenerIndex, 1 );

		// remove the record of the listener from the window object
		delete targetWindow._all [ listenerId ];
	};

	liwe.events.prevent = function ( e ) { e.returnValue = false; };
	liwe.events.stop = function ( e ) { e.cancelBubble = true; };
	liwe.events.source   = function ( e ) { return event.srcElement; };
	liwe.events.keycode  = function ( e ) { return event.keyCode; };

	liwe.events._find = function ( target, type, listener )
	{
		// get the array of listener IDs added to target
		var listeners = target._listeners;
		if ( !listeners ) return -1;

		// get a reference to the window object containing target
		var targetDocument = target.document || target;
		var targetWindow   = targetDocument.parentWindow;

		// searching backward ( to speed up onunload processing ), find the listener
		for ( var i = listeners.length - 1; i >= 0; i-- )
		{
			// get the listener's ID from target
			var listenerId = listeners [ i ];

			// get the record of the listener from the window object
			var rec = targetWindow._all [ listenerId ];

			// compare type and listener with the retrieved record
			if (rec.type == type && rec.listener == listener) return i;
		}

		return -1;
	};

	liwe.events._del_all = function()
	{
		var targetWindow = this;

		for ( id in targetWindow._all )
		{
			var rec = targetWindow._all [ id ];
			if ( typeof ( rec ) == "function" ) continue;

			rec.target.detachEvent ( "on" + rec.type, rec._cback );
			delete targetWindow._all[id];
		}
	};

  	liwe.events._list_counter = 0;
}


liwe.events.add_by_id = function ( id, event_name, func )
{
	liwe.events.add ( document.getElementById ( id ), event_name, func );
};

/*
EXAMPLES

liwe.events.add ( window, 'load', on_load, false );
*/


/*
 * dom.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */
 
/*
 * 	2009-09-07:	Added the $c() function is like a getAllElementsByClassName ( element, class_name, [ starting_container == document ] )
 */

liwe.dom = {};

// PUBLIC: get_offset_top
liwe.dom.get_offset_top = function ( elm )
{
  	var o_top    = elm.offsetTop;
  	var o_parent = elm.offsetParent;

  	while ( o_parent && o_parent.tagName != "HTML" )
	{
		// if ( o_parent.style.position == 'absolute' ) return o_top;
    		o_top += o_parent.offsetTop;
    		o_parent = o_parent.offsetParent;
  	}
 
  	return o_top;
};

// PUBLIC: get_offset_left
liwe.dom.get_offset_left = function ( elm )  
{
	var o_left = elm.offsetLeft;
  	var o_parent = elm.offsetParent;

  	while ( o_parent )
	{
		// if ( o_parent.style.position == 'absolute' ) return o_left;
		// console.debug ( "parent: %o - o_parent: %s - left: %s", o_parent, o_parent.offsetParent, o_left );
		// if ( ! o_parent.offsetParent.offsetParent ) break;
    		o_left += o_parent.offsetLeft;
    		o_parent = o_parent.offsetParent;
  	}
 
  	return o_left;
};

// PUBLIC: append_css
liwe.dom.append_css = function ( css_file, id, as_first )
{
	var head = document.getElementsByTagName ( "head" ) [ 0 ];
	var new_css = document.createElement ( "link" );

	new_css.href = css_file;
	new_css.type = "text/css";
	new_css.rel  = "stylesheet";
	if ( id ) new_css.id = id;

	if ( as_first )
		head.insertBefore ( new_css, head.firstChild );
	else
		head.appendChild ( new_css );
};


// PUBLIC: get_padding_width
liwe.dom.get_padding_width = function ( el )
{
	var oldw = el.clientWidth;
	var neww;

	el.style.width = "0px";
	neww = el.clientWidth;

	el.style.width = ( oldw - neww ) + "px";

	return neww;
};

// PUBLIC: get_padding_height
liwe.dom.get_padding_height = function ( el )
{
	var oldh = el.clientHeight;
	var newh;

	el.style.height = "0px";
	newh = el.clientHeight;

	el.style.height = ( oldh - newh ) + "px";

	return newh;
};

liwe.dom.get_size = function ( el )
{
	return [ el.clientWidth, el.clientHeight ];
};

// PUBLIC: os3_get_window_size
liwe.dom.get_window_size = function ()
{
	var s = document.createElement ( "div" );
	s.style.position = "absolute";
	s.style.bottom = "0px";
	s.style.right  = "0px";
	s.style.width  = "1px";
	s.style.height  = "1px";
	s.style.visibility = "hidden";
	document.body.appendChild ( s );

	var w, h;
	w = os3_get_offset_left ( s ) + s.clientWidth;
	h = os3_get_offset_top ( s ) + s.clientHeight;

	document.body.removeChild ( s );

	return { "width": w, "height": h };
};

// PUBLIC: create_element
liwe.dom.create_element = function ( tag, name, parent )
{
	if ( ! parent ) parent = document.body;

	// if ( document.ActiveXObject ) tag = '<' + tag + ' name="' + name + '">';
	if ( document.all ) tag = '<' + tag + ' name="' + name + '">';

	var e = document.createElement ( tag );
	e.style.position = 'absolute';
	e.style.top = "0px";
	e.style.right = "0px";
	e.id = name;
	e.name = name;
	parent.appendChild ( e );
	
	return e;
};

liwe.dom.remove_element = function ( e, parent )
{
	if ( ! parent ) parent = document.body;

	parent.removeChild ( e );
};

liwe.dom.get_event_pos = function ( e )
{
	var posx = 0, posy = 0;

	if ( e == null ) e = window.event;
	if ( e.pageX || e.pageY )
	{
		posx = e.pageX; 
		posy = e.pageY;
	} else if ( e.clientX || e.clientY ) {
	 	if ( document.documentElement.scrollTop )
		{
	 		posx = e.clientX + document.documentElement.scrollLeft;
	 		posy = e.clientY + document.documentElement.scrollTop;
	 	} else {
	 		posx = e.clientX + document.body.scrollLeft;
	 		posy = e.clientY + document.body.scrollTop;
	 	}
	 }

	return [ posx, posy ];
};

liwe.dom.has_class = function ( el, class_name )
{
	var pattern = new RegExp ( "(^| )" + class_name + "( |$)" );

	if ( pattern.test ( el.className ) ) return true;

	return false;
};

liwe.dom.add_class = function ( target, class_name )
{
	if ( liwe.dom.has_class ( target, class_name ) ) return;

	if ( target.className == "" ) 
		target.className = class_name;
	else
		target.className += " " + class_name;
};

liwe.dom.del_class = function ( target, class_name )
{
	var pattern = new RegExp ( "(^| )" + class_name + "( |$)" );

	target.className = target.className.replace ( pattern, "$1" ).replace ( / $/, "" );
};

Object.prototype.hide = function ()
{
	if ( ! this.style || this.style.display == 'none' ) return;

	this._old_display = this.style.display;
	this.style.display = 'none';
};

Object.prototype.show = function ()
{
	if ( ! this.style ) return;

	if ( this._old_display )
		this.style.display = this._old_display;
	else
		this.style.display = 'block';

	this._old_display = null;
};

liwe.dom.tableize = function ()
{
	if ( ( ! liwe.browser.ie ) && ( ! liwe.browser.version < 8 ) ) return;
	
	function _replace ( table_start, table )
	{
		var parent = table_start.parentNode;
		var next_sibling = table_start.nextSibling;
		parent.removeChild ( table_start );
		parent.insertBefore ( table, next_sibling );
	}

	function _add_cell ( row, div )
	{
		var c;
		cell = document.createElement ( "td" );
		cell.setAttribute ( "vAlign", "top" );
		cell.className = div.className;

		c = cell.appendChild ( div.firstChild.cloneNode ( true ) );
		c.style.display = "block";

		row.appendChild ( cell );
	}

	var divs = document.getElementsByTagName ( "div" );
	var t, l = divs.length, div;
	var table = null, tbody = null;
	var row = null, cell = null;
	var table_start = null;

	for ( t = 0; t < l; t ++ )
	{
		div = divs [ t ];
		if ( ! div.className ) continue;

		if ( div.className.indexOf ( 'table' ) != -1 )
		{
			if ( table_start )
			{
				_replace ( table_start, table );
				table = null;
			}

			table_start = div;
			table = document.createElement ( "table" );
			tbody = document.createElement ( "tbody" );
			table.appendChild ( tbody );
			table.className = div.className;
			table.style.border = "1px dotted black";
		} else if ( div.className.indexOf ( "cell-first" ) != -1 ) {
			row = document.createElement ( "tr" );
			tbody.appendChild ( row );
			_add_cell ( row, div );
		} else if ( div.className.indexOf ( "cell" ) != -1 ) {
			_add_cell ( row, div );
		}
	}

	if ( table )
		_replace ( table_start, table );
};

function $c ( element, class_name, base )
{
	if ( ! base ) base = document;
	var elements = base.getElementsByTagName ( element );
	var t, l = elements.length;
	var res = [], el;

	for ( t = 0; t < l; t ++ )
	{
		el = elements [ t ];
		if ( el.className.indexOf ( class_name ) == -1 ) continue;

		res.push ( el );
	}

	return res;
}


/*
 * utils.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */

/*
 *
 *
 */

// PUBLIC: max
liwe.utils.max = function ()
{
	if ( ! arguments.length ) return 0;

	var m = 0;
	var t;

	for ( t = 0; t < arguments.length; t ++ )
		if ( m < arguments [ t ] ) m = arguments [ t ];

	return m;
};

// PUBLIC: min
liwe.utils.min = function ()
{
	if ( ! arguments.length ) return 0;

	var m = arguments [ 0 ];
	var t;

	for ( t = 1; t < arguments.length; t ++ )
		if ( m > arguments [ t ] ) m = arguments [ t ];

	return m;
};

// PUBLIC: date2str
// Mode:
//
//	0 - YYYY MM DD	( default )
//	1 - DD MM YYYY
// 	2 - MM DD YYYY
liwe.utils.date2str = function ( date, mode )
{
	var s = new String ( date );
	var v = s.match ( new RegExp ( "([0-9]{4}).([0-9]{1,2}).([0-9]{1,2})" ) );

	if ( ! mode ) mode = 0;

	switch ( mode )
	{
		case 1:
			s = v [ 3 ] + "-" + v [ 2 ] + "-" + v [ 1 ];
			break;
		case 2:
			s = v [ 2 ] + "-" + v [ 3 ] + "-" + v [ 1 ];
			break;

		default:
			s = v [ 1 ] + "-" + v [ 2 ] + "-" + v [ 3 ];
	}

	return s;
};

// PUBLIC: call
// Chiama una funzione passando un array di parametri
liwe.utils.call = function ( func_name, this_arg, arg_array )
{
	var i, l = arg_array.length;
	var s = "this_arg." + func_name + " ( ";
	
	for ( i = 0; i < l; i++ )
	{
		if ( i > 0 ) s += ", ";
		s += "arg_array[" + i + "]";
	}

	s += " );";

	return eval ( s );
};

// Formats a result list iterating on the list ``lst`` and using String.formatDict with
// the three templates str_row [mandatory], str_start [optional] and str_end [optional]
// Returns the formatted string
liwe.utils.format_list = function ( lst, str_row, str_start, str_end )
{
	var s = new String.buffer ();
	var t, l = lst.length;

	if ( ! l ) return '';

	if ( str_start ) s.add ( str_start );
	for ( t = 0; t < l; t ++ )
		s.add ( String.formatDict ( str_row, lst [ t ] ) );

	if ( str_end ) s.add ( str_end );

	return s.toString ();
};

liwe.utils._ents = null;

liwe.utils.map_entities = function ( txt )
{
	if ( ! liwe.utils_ents )
	{
		liwe.utils._ents = {
			 "&#8217;": "'",
			 "&#224;": "&agrave;",
			 "&#232;": "&egrave;",
			 "&#233;": "&eacute;",
			 "&#242;": "&ograve;",
			 "&#249;": "&ugrave;",
			 "&#8220;": '"',
			 "&#8221;": '"',
			 "&#8211;": "-",
			 "%u2013" : "-",
			 "%u2019" : "'",
		         "%u201C" : '"',
		         "%u201D" : '"'
		};

		var reg_exp = "";
		var ents = [];

		liwe.utils._ents.iterate ( function ( v, k ) { ents.push ( k ); } );
		reg_exp = "(" + "|".join ( ents ) + ")";

		liwe.utils._ents_re = RegExp ( reg_exp, "g" );
	}

	txt = txt.replace ( /&#37;/g, "%" );

	return txt.replace ( liwe.utils._ents_re, function ( k ) { return liwe.utils._ents [ k ]; } );
};


/*
 *
 * 	2009-04-05:	NEW: get_current_obj() - returns an object of the current history hash
 *
 */
liwe.history = {};

liwe.history.listener_callback = {};

liwe.history.cbacks = {
	"before-add" : null,
	"before-module" : null
};

liwe.history._load = function ()
{
	liwe.history._is_ie = ( document.all && navigator.userAgent.toLowerCase().indexOf ( 'msie' ) != -1 );

	liwe.history._blank_page = liwe._libbase + "/data/history_blank.html";

	liwe.history._data_storage = [];
	
	if ( liwe.history._is_ie )
		liwe.history._int_create_iframe ();

	document.write ( '<form style="display: none;"><input id="historyDataText" type="text" value="" \/><\/form>' );
};

liwe.history.init = function ()
{
	liwe.history._saved_location = liwe.history.get_current_location();

	setInterval ( liwe.history._int_check_location, 100 );

	setTimeout ( liwe.history._init_done, 200 );
};


liwe.history._init_done = function ()
{
	var hdt = document.getElementById ( "historyDataText" );
	
	if ( hdt.value )
		liwe.history._data_storage  = hdt.value.parseJSON();

	liwe.history._int_call_listener();
};


liwe.history._int_create_iframe = function ()
{
	var loc = liwe.history.get_current_location();
	
	liwe.history._adding = true;
	
	document.write ( "<iframe style='border: 2px; width: 1px; "
                               + "height: 1px; position: absolute; bottom: 0px; "
                               + "right: 0px; display: none;' "
                               + "name='liwe.historyFrame' id='liwe.historyFrame' src='" + liwe.history._blank_page + "?" + loc + "'>"
                               + "<\/iframe>" );

	liwe.history._iframe = document.getElementById ( "liwe.historyFrame" );

	window._os3_history_cb = liwe.history._int_iframe_location_changed;
};


liwe.history.get_current_location = function ()
{
	var loc = window.location.hash;
	if ( loc.length > 0 && loc.charAt ( 0 ) == '#' )
		loc = loc.slice ( 1 );
	return loc;
};

liwe.history.get_current_obj = function ()
{
	var loc = liwe.history.get_current_location ().split ( "," );
	var t, l = loc.length;
	var res = {}, p;

	for ( t = 0; t < l; t ++ )
	{
		p = loc [ t ].split ( "=" );
		res [ p [ 0 ] ] = p [ 1 ];
	}

	return res;
};


liwe.history._int_call_listener = function ()
{
	if ( ! liwe.history.listener_callback ) return;

	var id = liwe.history.get_current_location ();
	var dict = liwe.history._str2dict ( id );
	var data, module;

	if ( typeof dict [ "__dk" ] != "undefined" )
	{
		var key = parseInt ( dict [ "__dk" ] );
		data = liwe.history._data_storage [ key ];
		delete dict [ "__dk" ];
	}

	if ( typeof dict [ "__m" ] != "undefined" )
		module = dict [ "__m" ];
	else
		module = "__DEFAULT__";

	if ( ! liwe.history.listener_callback [ module ] ) return;

	liwe.history._listener_call = true;
	try
	{
		liwe.history.listener_callback [ module ] ( dict, data );
	}
	finally
	{
		liwe.history._listener_call = false;
	}
};


liwe.history.set_listener = function ( listener, module )
{
	if ( ! module ) module = "__DEFAULT__";
	liwe.history.listener_callback [ module ] = listener;
};


liwe.history.add = function ( dict, data )
{
	return liwe.history.add_module ( null, dict, data );
};


liwe.history.add_module = function ( module, dict, data )
{
	if ( ! dict ) dict = {};

	if ( liwe.history._listener_call ) return;
	if ( dict.get ( "__nh" ) == 1 ) return;

	if ( liwe.history.cbacks [ 'before-add' ] )
	{
		// NOTE: function should return TRUE to block event propagation
		var block = liwe.history.cbacks [ 'before-add' ] ( module, dict, data );

		if ( block ) return;
	}

	if ( data )
	{
		var key = liwe.history._data_storage.length.toString();
		liwe.history._data_storage.push ( data );
		dict [ "__dk" ] = key;

		var s = liwe.history._data_storage.toJSONString();
		var is = document.getElementById ( "historyDataText" );
		is.value = s;
	}

	if ( module ) dict [ "__m" ] = module;

	var id = liwe.history._dict2str ( dict );
	window.location.hash = id;
	liwe.history._saved_location = id;

	if ( liwe.history._is_ie )
	{
		liwe.history._adding = true;
		liwe.history._iframe.src = liwe.history._blank_page + "?" + id;
	}
};


liwe.history.replace = function ( module, dict, data )
{
	if ( liwe.history._listener_call ) return;

	if ( dict.get ( "__nh" ) == 1 ) return;

	var key = (liwe.history._data_storage.length - 1).toString();
	liwe.history._data_storage [ liwe.history._data_storage.length - 1 ] = data;
	dict [ "__dk" ] = key;

	var s = liwe.history._data_storage.toJSONString();
	var is = document.getElementById ( "historyDataText" );
	is.value = s;

	if ( module ) dict [ "__m" ] = module;

	var loc = String ( location ).split ( '#' ) [ 0 ];
	var id = liwe.history._dict2str ( dict );
	window.location.replace ( loc + "#" + id );
	liwe.history._saved_location = id;

	if ( liwe.history._is_ie )
	{
		liwe.history._adding = true;
		liwe.history._iframe.src = liwe.history._blank_page + "?" + id;
	}
};


liwe.history._dict2str = function ( dict )
{
	var str = "";
	var is_first = true;
	
	var k, v;
	for ( k in dict )
	{
		v = dict [ k ];
		if ( typeof ( v ) == 'function' ) continue;

		if ( is_first ) is_first = false;
		else str += ",";
		
		str += k;
		if ( v != null && v != undefined )
		{
			v = v.toString();
			str += "=" + liwe.history._escape_value ( v );
		}

	}

	return str;
};


liwe.history._str2dict = function ( str )
{
	var tok;

	var dict = {};

	str = liwe.history._lstrip ( str );

	while ( str.length > 0 )
	{
		// cerco la virgola divisoria
		var cpos = str.indexOf ( "," );
		while ( cpos < str.length - 1 && str.charAt ( cpos + 1 ) == ',' )
			cpos = str.indexOf ( ",", cpos + 2 );

		if ( cpos == -1 )
		{
			tok = str;

			str = "";
		} else {
			tok = str.slice ( 0, cpos );

			str = str.slice ( cpos + 1 );
			str = liwe.history._lstrip ( str );
		}

		// splittiamo sull'uguale
		var splt = tok.split ( "=" );
		var k = splt [ 0 ];
		var v = liwe.history._join ( "=", splt.slice ( 1 ) );
		v = v.replace ( ",,", "," );

		dict [ k ] = unescape(v);
	}

	return dict;
};


liwe.history._escape_value = function ( v )
{
	return v.replace ( ",", ",," );
};


liwe.history._lstrip = function ( s )
{
	while ( s.length > 0 && s.charAt ( 0 ) == ' ' )
		s = s.slice ( 1 );

	return s;
};


liwe.history._join = function ( sep, arr )
{
	var l = arr.length;
	if ( l == 0 ) return "";
	
	var s = arr [ 0 ];
	for ( var i = 1; i < l ; i++ )
		s += sep + arr [ i ];

	return s;
};


liwe.history._int_iframe_location_changed = function ( id )
{
	if ( liwe.history._adding )
	{
		liwe.history._adding = false;
		return;
	}

	if ( id.length > 0 && id.charAt ( 0 ) == '?' )
		id = id.slice ( 1 );

	window.location.hash = id;
	liwe.history._saved_location = id;

	liwe.history._int_call_listener ();
};


liwe.history._int_check_location = function ()
{
	var loc = liwe.history.get_current_location();
	if ( loc == liwe.history._saved_location )
		return;

	liwe.history._saved_location = loc;

	if ( liwe.history._is_ie )
		liwe.history._iframe.src = liwe.history._blank_page + "?" + loc;
	else
		liwe.history._int_call_listener();
};

liwe.history._load();


/*
    json.js
    2007-01-10

    This file adds these methods to JavaScript:

        array.toJSONString()
        boolean.toJSONString()
        date.toJSONString()
        number.toJSONString()
        object.toJSONString()
        string.toJSONString()
            These methods produce a JSON text from a JavaScript value.
            It must not contain any cyclical references. Illegal values
            will be excluded.

            The default conversion for dates is to an ISO string. You can
            add a toJSONString method to any date object to get a different
            representation.

        string.parseJSON(filter)
            This method parses a JSON text to produce an object or
            array. It can throw a SyntaxError exception.

            The optional filter parameter is a function which can filter and
            transform the results. It receives each of the keys and values, and
            its return value is used instead of the original value. If it
            returns what it received, then structure is not modified. If it
            returns undefined then the member is deleted.

            Example:

            // Parse the text. If a key contains the string 'date' then
            // convert the value to a date.

            myData = text.parseJSON(function (key, value) {
                return key.indexOf('date') >= 0 ? new Date(value) : value;
            });

    It is expected that these methods will formally become part of the
    JavaScript Programming Language in the Fourth Edition of the
    ECMAScript standard in 2007.
*/

if (!Object.prototype.toJSONString) {
    Array.prototype.toJSONString = function () {
        var a = ['['], b, i, l = this.length, v;

        function p(s) {
            if (b) {
                a.push(',');
            }
            a.push(s);
            b = true;
        }

        for (i = 0; i < l; i += 1) {
            v = this[i];
            switch (typeof v) {
            case 'undefined':
            case 'function':
            case 'unknown':
                break;
            case 'object':
                if (v) {
                    if (typeof v.toJSONString === 'function') {
                        p(v.toJSONString());
                    }
                } else {
                    p("null");
                }
                break;
            default:
                p(v.toJSONString());
            }
        }
        a.push(']');
        return a.join('');
    };

    Boolean.prototype.toJSONString = function () {
        return String(this);
    };

    Date.prototype.toJSONString = function () {

        function f(n) {
            return n < 10 ? '0' + n : n;
        }

        return '"' + this.getFullYear() + '-' +
                f(this.getMonth() + 1) + '-' +
                f(this.getDate()) + 'T' +
                f(this.getHours()) + ':' +
                f(this.getMinutes()) + ':' +
                f(this.getSeconds()) + '"';
    };

    Number.prototype.toJSONString = function () {
        return isFinite(this) ? String(this) : "null";
    };

    Object.prototype.toJSONString = function () {
        var a = ['{'], b, i, v;

        function p(s) {
            if (b) {
                a.push(',');
            }
            a.push(i.toJSONString(), ':', s);
            b = true;
        }

        for (i in this) {
            if (this.hasOwnProperty(i)) {
                v = this[i];
                switch (typeof v) {
                case 'undefined':
                case 'function':
                case 'unknown':
                    break;
                case 'object':
                    if (v) {
                        if (typeof v.toJSONString === 'function') {
                            p(v.toJSONString());
                        }
                    } else {
                        p("null");
                    }
                    break;
                default:
                    p(v.toJSONString());
                }
            }
        }
        a.push('}');
        return a.join('');
    };


    (function (s) {
        var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

        s.parseJSON = function (filter) {
            try {
                if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)) {
                    var j = eval('(' + this + ')');
                    if (typeof filter === 'function') {
                        function walk(k, v) {
                            if (v && typeof v === 'object') {
                                for (var i in v) {
                                    if (v.hasOwnProperty(i)) {
                                        v[i] = walk(i, v[i]);
                                    }
                                }
                            }
                            return filter(k, v);
                        }
                        return walk('', j);
                    }
                    return j;
                }
            } catch (e) {
            }
            throw new SyntaxError("parseJSON");
        };

        s.toJSONString = function () {
            if (/["\\\x00-\x1f]/.test(this)) {
                return '"' + this.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                    var c = m[b];
                    if (c) {
                        return c;
                    }
                    c = b.charCodeAt();
                    return '\\u00' +
                        Math.floor(c / 16).toString(16) +
                        (c % 16).toString(16);
                }) + '"';
            }
            return '"' + this + '"';
        };
    })(String.prototype);
}


/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
	Modified version by Fabio Rotondo for the LiWE project	
*/

var MD5 = {};

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
MD5.hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
MD5.b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
MD5.chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
MD5.hex_md5 = function ( s ) 
{ 
	return MD5._binl2hex ( MD5._core_md5 ( MD5._str2binl ( s ), s.length * MD5.chrsz ) ); 
};

MD5.b64_md5 = function ( s )
{ 
	return MD5._binl2b64 ( MD5._core_md5 ( MD5._str2binl ( s ), s.length * MD5.chrsz ) );
};

MD5.str_md5 = function ( s )
{ 
	return MD5._binl2str ( MD5._core_md5 ( MD5._str2binl ( s ), s.length * MD5.chrsz ) );
};

MD5.hex_hmac_md5 = function ( key, data ) 
{ 
	return MD5._binl2hex ( MD5._core_hmac_md5 ( key, data ) ); 
};

MD5.b64_hmac_md5 = function ( key, data ) 
{ 
	return MD5._binl2b64 ( MD5._core_hmac_md5 ( key, data ) ); 
};

MD5.str_hmac_md5 = function ( key, data ) 
{ 
	return MD5._binl2str ( MD5._core_hmac_md5 ( key, data ) ); 
};

/*
 * Perform a simple self-test to see if the VM is working
 */
MD5.test = function ()
{
  return MD5.hex_md5 ( "abc" ) == "900150983cd24fb0d6963f7d28e17f72";
};

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
MD5._core_md5 = function ( x, len )
{
  /* append padding */
  x [ len >> 5 ] |= 0x80 << ( ( len ) % 32 );
  x [ ( ( ( len + 64 ) >>> 9 ) << 4 ) + 14 ] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var i, l = x.length;

  for ( i = 0; i < l + 32; i ++ )
	  if ( typeof ( x [ i ] ) == "undefined" )
		  x [ i ] = 0;

  for ( i = 0; i < l; i += 16 )
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;

    a = MD5._ff ( a, b, c, d, x [ i + 0 ], 7 , -680876936 );
    d = MD5._ff ( d, a, b, c, x [ i + 1 ], 12, -389564586 );
    c = MD5._ff ( c, d, a, b, x [ i + 2 ], 17,  606105819 );
    b = MD5._ff ( b, c, d, a, x [ i + 3 ], 22, -1044525330 );
    a = MD5._ff ( a, b, c, d, x [ i + 4 ], 7 , -176418897 );
    d = MD5._ff ( d, a, b, c, x [ i + 5 ], 12,  1200080426 );
    c = MD5._ff ( c, d, a, b, x [ i + 6 ], 17, -1473231341 );
    b = MD5._ff ( b, c, d, a, x [ i + 7 ], 22, -45705983 );
    a = MD5._ff ( a, b, c, d, x [ i + 8 ], 7 ,  1770035416 );
    d = MD5._ff ( d, a, b, c, x [ i + 9 ], 12, -1958414417 );
    c = MD5._ff ( c, d, a, b, x [ i + 10 ], 17, -42063 );
    b = MD5._ff ( b, c, d, a, x [ i + 11 ], 22, -1990404162 );
    a = MD5._ff ( a, b, c, d, x [ i + 12 ], 7 ,  1804603682 );
    d = MD5._ff ( d, a, b, c, x [ i + 13 ], 12, -40341101 );
    c = MD5._ff ( c, d, a, b, x [ i + 14 ], 17, -1502002290 );
    b = MD5._ff ( b, c, d, a, x [ i + 15 ], 22,  1236535329 );

    a = MD5._gg ( a, b, c, d, x [ i+ 1 ] , 5 , -165796510 ) ;
    d = MD5._gg ( d, a, b, c, x [ i+ 6 ] , 9 , -1069501632 ) ;
    c = MD5._gg ( c, d, a, b, x [ i+11 ] , 14,  643717713 ) ;
    b = MD5._gg ( b, c, d, a, x [ i+ 0 ] , 20, -373897302 ) ;
    a = MD5._gg ( a, b, c, d, x [ i+ 5 ] , 5 , -701558691 ) ;
    d = MD5._gg ( d, a, b, c, x [ i+10 ] , 9 ,  38016083 ) ;
    c = MD5._gg ( c, d, a, b, x [ i+15 ] , 14, -660478335 ) ;
    b = MD5._gg ( b, c, d, a, x [ i+ 4 ] , 20, -405537848 ) ;
    a = MD5._gg ( a, b, c, d, x [ i+ 9 ] , 5 ,  568446438 ) ;
    d = MD5._gg ( d, a, b, c, x [ i+14 ] , 9 , -1019803690 ) ;
    c = MD5._gg ( c, d, a, b, x [ i+ 3 ] , 14, -187363961 ) ;
    b = MD5._gg ( b, c, d, a, x [ i+ 8 ] , 20,  1163531501 ) ;
    a = MD5._gg ( a, b, c, d, x [ i+13 ] , 5 , -1444681467 ) ;
    d = MD5._gg ( d, a, b, c, x [ i+ 2 ] , 9 , -51403784 ) ;
    c = MD5._gg ( c, d, a, b, x [ i+ 7 ] , 14,  1735328473 ) ;
    b = MD5._gg ( b, c, d, a, x [ i+12 ] , 20, -1926607734 ) ;

    a = MD5._hh ( a, b, c, d, x [ i+ 5 ] , 4 , -378558 ) ;
    d = MD5._hh ( d, a, b, c, x [ i+ 8 ] , 11, -2022574463 ) ;
    c = MD5._hh ( c, d, a, b, x [ i+11 ] , 16,  1839030562 ) ;
    b = MD5._hh ( b, c, d, a, x [ i+14 ] , 23, -35309556 ) ;
    a = MD5._hh ( a, b, c, d, x [ i+ 1 ] , 4 , -1530992060 ) ;
    d = MD5._hh ( d, a, b, c, x [ i+ 4 ] , 11,  1272893353 ) ;
    c = MD5._hh ( c, d, a, b, x [ i+ 7 ] , 16, -155497632 ) ;
    b = MD5._hh ( b, c, d, a, x [ i+10 ] , 23, -1094730640 ) ;
    a = MD5._hh ( a, b, c, d, x [ i+13 ] , 4 ,  681279174 ) ;
    d = MD5._hh ( d, a, b, c, x [ i+ 0 ] , 11, -358537222 ) ;
    c = MD5._hh ( c, d, a, b, x [ i+ 3 ] , 16, -722521979 ) ;
    b = MD5._hh ( b, c, d, a, x [ i+ 6 ] , 23,  76029189 ) ;
    a = MD5._hh ( a, b, c, d, x [ i+ 9 ] , 4 , -640364487 ) ;
    d = MD5._hh ( d, a, b, c, x [ i+12 ] , 11, -421815835 ) ;
    c = MD5._hh ( c, d, a, b, x [ i+15 ] , 16,  530742520 ) ;
    b = MD5._hh ( b, c, d, a, x [ i+ 2 ] , 23, -995338651 ) ;

    a = MD5._ii ( a, b, c, d, x [ i+ 0 ] , 6 , -198630844 ) ;
    d = MD5._ii ( d, a, b, c, x [ i+ 7 ] , 10,  1126891415 ) ;
    c = MD5._ii ( c, d, a, b, x [ i+14 ] , 15, -1416354905 ) ;
    b = MD5._ii ( b, c, d, a, x [ i+ 5 ] , 21, -57434055 ) ;
    a = MD5._ii ( a, b, c, d, x [ i+12 ] , 6 ,  1700485571 ) ;
    d = MD5._ii ( d, a, b, c, x [ i+ 3 ] , 10, -1894986606 ) ;
    c = MD5._ii ( c, d, a, b, x [ i+10 ] , 15, -1051523 ) ;
    b = MD5._ii ( b, c, d, a, x [ i+ 1 ] , 21, -2054922799 ) ;
    a = MD5._ii ( a, b, c, d, x [ i+ 8 ] , 6 ,  1873313359 ) ;
    d = MD5._ii ( d, a, b, c, x [ i+15 ] , 10, -30611744 ) ;
    c = MD5._ii ( c, d, a, b, x [ i+ 6 ] , 15, -1560198380 ) ;
    b = MD5._ii ( b, c, d, a, x [ i+13 ] , 21,  1309151649 ) ;
    a = MD5._ii ( a, b, c, d, x [ i+ 4 ] , 6 , -145523070 ) ;
    d = MD5._ii ( d, a, b, c, x [ i+11 ] , 10, -1120210379 ) ;
    c = MD5._ii ( c, d, a, b, x [ i+ 2 ] , 15,  718787259 ) ;
    b = MD5._ii ( b, c, d, a, x [ i+ 9 ] , 21, -343485551 ) ;

    a = MD5._safe_add ( a, olda ) ;
    b = MD5._safe_add ( b, oldb ) ;
    c = MD5._safe_add ( c, oldc ) ;
    d = MD5._safe_add ( d, oldd ) ;
  }

  return Array ( a, b, c, d ) ;
}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
MD5._cmn = function ( q, a, b, x, s, t )
{
  return MD5._safe_add ( MD5._bit_rol ( MD5._safe_add ( MD5._safe_add ( a, q ), MD5._safe_add ( x, t ) ), s ), b );
};

MD5._ff = function ( a, b, c, d, x, s, t )
{
  return MD5._cmn ( ( b & c ) | ( ( ~b ) & d ), a, b, x, s, t );
};

MD5._gg = function  ( a, b, c, d, x, s, t )
{
  return MD5._cmn ( ( b & d ) | ( c & ( ~d ) ), a, b, x, s, t );
};
MD5._hh = function  ( a, b, c, d, x, s, t )
{
  return MD5._cmn ( b ^ c ^ d, a, b, x, s, t );
};
MD5._ii = function  ( a, b, c, d, x, s, t )
{
  return MD5._cmn ( c ^ ( b | ( ~d ) ), a, b, x, s, t );
};

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
MD5._core_hmac_md5 = function ( key, data )
{
  var bkey = str2binl ( key );

  if ( bkey.length > 16 ) bkey = _core_md5 ( bkey, key.length * MD5.chrsz );

  var ipad = Array ( 16 ), opad = Array ( 16 );

  for ( var i = 0; i < 16; i++ )
  {
    ipad [ i ] = bkey [ i ] ^ 0x36363636;
    opad [ i ] = bkey [ i ] ^ 0x5C5C5C5C;
  }

  var hash = MD5._core_md5 ( ipad.concat ( MD5._str2binl ( data ) ), 512 + data.length * MD5.chrsz );
  return MD5._core_md5 ( opad.concat ( hash ), 512 + 128 );
};

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
MD5._safe_add = function ( x, y )
{
  var lsw = ( x & 0xFFFF ) + ( y & 0xFFFF );
  var msw = ( x >> 16 ) + ( y >> 16 ) + ( lsw >> 16 );

  return ( msw << 16 ) | ( lsw & 0xFFFF );
};

/*
 * Bitwise rotate a 32-bit number to the left.
 */
MD5._bit_rol = function ( num, cnt )
{
  return ( num << cnt ) | ( num >>> ( 32 - cnt ) );
};

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
MD5._str2binl = function ( str )
{
  var bin = Array();
  var mask = ( 1 << MD5.chrsz ) - 1;

  for ( var i = 0; i < str.length * MD5.chrsz; i += MD5.chrsz )
  {
    if ( typeof ( bin [ i >> 5 ] ) == "undefined" )
	bin [ i >> 5 ] = 0;

    bin [ i >> 5 ] |= ( str.charCodeAt ( i / MD5.chrsz ) & mask ) << ( i % 32 );
  }

  return bin;
};

/*
 * Convert an array of little-endian words to a string
 */
MD5._binl2str = function ( bin )
{
  var str = "";
  var mask = ( 1 << MD5.chrsz ) - 1;

  for ( var i = 0; i < bin.length * 32; i += MD5.chrsz )
    str += String.fromCharCode ( ( bin [ i >> 5 ] >>> ( i % 32 ) ) & mask );

  return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
MD5._binl2hex = function ( binarray )
{
  var hex_tab = MD5.hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";

  for ( var i = 0; i < binarray.length * 4; i++ )
  {
    str += hex_tab.charAt ( ( binarray [ i >> 2 ] >> ( ( i % 4 ) * 8 + 4 ) ) & 0xF ) +
           hex_tab.charAt ( ( binarray [ i >> 2 ] >> ( ( i % 4 ) * 8 ) ) & 0xF );
  }

  return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
MD5._binl2b64 = function ( binarray )
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";

  for ( var i = 0; i < binarray.length * 4; i += 3 )
  {
    var triplet = ( ( ( binarray [ i >> 2 ] >> 8 * ( i   %4 ) ) & 0xFF ) << 16 )
                | ( ( ( binarray [ i + 1 >> 2 ] >> 8 * ( ( i + 1 ) % 4 ) ) & 0xFF ) << 8 )
                | ( ( binarray [ i + 2 >> 2 ] >> 8 * ( ( i + 2 ) % 4 ) ) & 0xFF );

    for ( var j = 0; j < 4; j++ )
    {
       if ( i * 8 + j * 6 > binarray.length * 32 ) str += b64pad;
       else str += tab.charAt ( ( triplet >> 6 * ( 3 - j ) ) & 0x3F );
    }
  }
  return str;
}


var Paginator = function ()
{
	var self = this;

	self._tot_rows = 0;		// Total number of rows
	self._rows_per_page = 0;	// Rows for each page
	self._page = 0;			// Current Page
	self._tot_links = 10;		// Number of links to show
	self._tot_pages = 0;		// Total number of pages

	self._dest_id = null;

	self.templates = {};
	self.templates [ 'pag-first' ] = "&lt;&lt;&lt;";
	self.templates [ 'pag-first-lnk' ] = 'javascript:self._go(0)';
	self.templates [ 'pag-last' ] = "&gt;&gt;&gt;";
	self.templates [ 'pag-last-lnk' ] = 'javascript:self._go(%(_TOT_PAGES)s)';
	self.templates [ 'pag-prev' ] = "&lt;";
	self.templates [ 'pag-prev-lnk' ] = 'javascript:self._go(%(_PREV)s)';
	self.templates [ 'pag-next' ] = '&gt;';
	self.templates [ 'pag-next-lnk' ] = 'javascript:self._go(%(_CURR_PAGE)s+1)';
	self.templates [ 'pag-pos' ] = '%(_PAGE)s';
	self.templates [ 'pag-pos-lnk' ] = 'javascript:self._go(%(_NUM)s)';
	self.templates [ 'pag-sep' ] = '|';
	self.templates [ 'pag-link-space' ] = '';
	self.templates [ 'pag-left-info' ] = '';
	self.templates [ 'pag-right-info' ] = '';

	// _TOT_PAGES 
	// _CURR_PAGE
	// _NUM
	// _PAGE

	self.init = function ( tot_rows, rows_per_page, tot_links )
	{
		self._tot_pages = Math.ceil ( tot_rows / rows_per_page );
		self._tot_rows = tot_rows;
		self._rows_per_page = rows_per_page;
		self._tot_links = ( tot_links ? tot_links : 10 );

		self.templates [ '_TOT_PAGES' ] = self._tot_pages;
		self.set_page ( 0 );
	};

	self.set_page = function ( page )
	{
		if ( page > self._tot_pages ) page = self._tot_pages;

		self._page = page;

		self.templates [ '_CURR_PAGE' ] = self._page;

		return self.mk_str ();
	};

	self.mk_str = function ()
	{
		var s = '';
		var t, p;
		var start_page = 0;

		self.templates [ '_NUM' ] = self._page;
		self.templates [ '_PAGE' ] = self._page + 1;
		s += String.formatDict ( self.templates [ "pag-left-info" ], self.templates );

		if ( self._page > 0 )
		{
			s += String.formatDict ( '<a href="%(pag-first-lnk)s">%(pag-first)s</a>', self.templates ); 
			s += self.templates [ 'pag-link-space' ];

			self.templates [ '_PREV' ] = self._page - 1;
			self.templates [ '_PREV-LNK' ] = String.formatDict ( self.templates [ 'pag-prev-lnk' ], self.templates );
			s += String.formatDict ( '<a href="%(_PREV-LNK)s">%(pag-prev)s</a>', self.templates );
		} else {
			s += String.formatDict ( '%(pag-first)s', self.templates ); 
			s += self.templates [ 'pag-link-space' ];
			s += String.formatDict ( '%(pag-prev)s', self.templates );
		}

		//s += self.templates [ 'pag-sep' ];

		if ( self._page > ( self._tot_links / 2 ) )
		{
			start_page = self._page - ( Math.floor ( self._tot_links / 2 ) );
			if ( ( self._tot_pages - start_page ) < self._tot_links )
				start_page = self._tot_pages - self._tot_links;
		}

		for ( t = 0; t < self._tot_links; t ++ )
		{
			p = start_page + t;

			if ( ( p + 1 ) > self._tot_pages ) break;

			s += self.templates [ 'pag-link-space' ];

			if ( t > 0 )
			{
				s += self.templates [ 'pag-sep' ];
				s += self.templates [ 'pag-link-space' ];
			}

			self.templates [ '_NUM' ] = p;
			self.templates [ '_PAGE' ] = p + 1;
			self.templates [ '_POS' ] = String.formatDict ( self.templates [ 'pag-pos' ], self.templates );

			if ( p == self._page )
				s += String.formatDict ( '%(_POS)s', self.templates );
			else {
				self.templates [ '_POS-LNK' ] = String.formatDict ( self.templates [ 'pag-pos-lnk' ], self.templates );
				s += String.formatDict ( '<a href="%(_POS-LNK)s">%(_POS)s</a>', self.templates );
			}
		}

		if ( ( self._page +1 ) >= self._tot_pages ) 
		{
			s += self.templates [ 'pag-link-space' ];
			s += String.formatDict ( '%(pag-next)s', self.templates );
			s += self.templates [ 'pag-link-space' ];
			s += String.formatDict ( '%(pag-last)s', self.templates );
		} else {
			s += self.templates [ 'pag-link-space' ];

			self.templates [ '_NEXT-LNK' ] = String.formatDict ( self.templates [ 'pag-next-lnk' ], self.templates );
			s += String.formatDict ( '<a href="%(_NEXT-LNK)s">%(pag-next)s</a>', self.templates );

			s += self.templates [ 'pag-link-space' ];
			self.templates [ '_LAST-LNK' ] = String.formatDict ( self.templates [ 'pag-last-lnk' ], self.templates );
			s += String.formatDict ( '<a href="%(_LAST-LNK)s">%(pag-last)s</a>', self.templates );
		}

		self.templates [ '_NUM' ] = self._page;
		self.templates [ '_PAGE' ] = self._page + 1;
		s += String.formatDict ( self.templates [ "pag-right-info" ], self.templates );

		return s;
	};

	self._go = function ( page_no )
	{
		self.set_page ( page_no );
		self.render ();
	};

	self.render = function ( dest_id )
	{
		var s;

		if ( ! dest_id ) dest_id = self._dest_id;
		self._dest_id = dest_id;

		s = self.mk_str ();

		$( dest_id ).innerHTML = s;
	};
};



// DataSet 2.0
//
// 2009-01-10: 	- Dataset row now contain also:
//
// 			- ``_ds_row_num`` : the current row num
// 			- ``_ds_bg``:	a 0 / 1 value to distinguish odd / even rows
function DataSet ( name, ajax_cgi )
{
	DataSet._instances [ name ] = this;

	this.name = name;

	this.ajax = ajax_cgi;
	this.ajax_req = DataSet.ajax;
	this.num_rows = 0;	// Rows in totale dalla query
	this.rows = {};	// Rows in memoria
	this.len  = 0;		// Numero di rows in memoria
	this.page = 0;		// Pagina corrente
	this.lines_per_page = 10; // Linee per pagina
	this.from_row = 0;
	this.to_row   = 0;
	this.curr_doc = 0;	// Valore ordinale del documento corrente in FulShow
	this.paginator_links = 10;

	this.templates = {
				'table_start'  : '<table border="1" width="100%">',
				'table_end'    : '</table>',
				'table_header' : '',
				'table_footer' : '',
				'table_row'    : '',
				'prev_page'    : '',
				'next_page'    : '',
				'dash'         : ' - ',
				'next_doc'  : '',
				'prev_doc'  : ''
			 };

	
	this.cbacks = { 
		// Funzione ridefinibile da parte dell'utente per manipolare i dati
		// nel momento che vengono inseriti nell'array del DataSet
		'fill_manip' : null, 
		'prefetch_start' : null,
		'prefetch_end'   : null,
		'fill_start'   : null,
		'fill_end'   : null,
		'show_results' : null,
		'row_manip': null
	};

	// PRIVATE ATTRS
	this._attrs = {};
	this._form_fields = null;	// Campi della ricerca
	this._dest_div = null;
	this._fill_cback = null;

	// ========================================================================================
	// METHODS
	// ========================================================================================

	this._init_paginator = function ()
	{
		if ( ! window [ "Paginator" ] ) return null;

		var p = new Paginator ();

		p.templates [ 'pag-first' ] = "&lt;&lt;&lt;";
		p.templates [ 'pag-first-lnk' ] = "javascript:DataSet.page('" + this.name + "',0)";
		p.templates [ 'pag-last' ] = "&gt;&gt;&gt;";
		p.templates [ 'pag-last-lnk' ] = "javascript:DataSet.page('" + this.name + "',%(_TOT_PAGES)s)";
		p.templates [ 'pag-prev' ] = "&lt;";
		p.templates [ 'pag-prev-lnk' ] = "javascript:DataSet.page('" + this.name + "',%(_PREV)s)";
		p.templates [ 'pag-next' ] = '&gt;';
		p.templates [ 'pag-next-lnk' ] = "javascript:DataSet.page('" + this.name + "',%(_CURR_PAGE)s+1)";
		p.templates [ 'pag-pos' ] = '%(_PAGE)s';
		p.templates [ 'pag-pos-lnk' ] = "javascript:DataSet.page('" + this.name + "',%(_NUM)s)";
		p.templates [ 'pag-sep' ] = '|';
		p.templates [ 'pag-link-space' ] = '';

		return p;
	};

	this.paginator = this._init_paginator ();

	// This function sets the fields for the DataSet search
	this.set_fields = function ( fields )
	{
		this._form_fields = fields.clone ();
		this.clear ();
	};

	this.get_fields = function () { return this._form_fields; }

	this.del_field = function ( name ) { delete this._form_fields [ name ]; };

	this.rename_field = function ( old_field_name, new_field_name )
	{
		this._form_fields [ new_field_name ] = this._form_fields [ old_field_name ];
		delete this._form_fields [ old_field_name ];
	};

	this.clear = function ()
	{
		this.page = 0;
		this.num_rows = 0;
		this.from_row = 0;
		this.to_row   = this.lines_per_page;
		this.rows = {};
		this.len = 0;

		if ( this._form_fields )
		{
			this._form_fields [ "_X_START_POINT" ] = 0;
			this._form_fields [ "_X_PAGE" ] = 0;
		}

		this._attrs = {};
	};

	this.fill = function ( fill_callback, replace )
	{
		var _obj = this;

		if ( fill_callback ) this._fill_cback = fill_callback;

		if ( ! this._form_fields ) 
		{
			this._fill_cback ( this );
			return;
		}

		if ( this.cbacks [ 'fill_start' ] ) this.cbacks [ 'fill_start' ] ( this );

		this._form_fields [ '_X_LINES' ] = this.lines_per_page; 

		this.ajax_req ( this.ajax, this._form_fields, function ( vars ) { _obj._fill_done ( vars, _obj._fill_cback, replace ); } );
	};

	this._fill_done = function ( vars, cback, replace )
	{
		var t, len = parseInt ( vars [ 'lines' ] );

		if ( vars [ '_X_START_POINT' ] )		
			this.from_row = vars [ '_X_START_POINT' ];
		else 
			this.from_row = vars [ 'from_row' ];

		if ( ! this.from_row ) this.from_row = 0;

		for ( t = 0; t < len; t ++ )
		{
			if ( ! vars [ 'row' + t ] ) break;

			vars [ "row" + t ] [ 'ds_name' ] = this.name;

			var row = vars [ 'row' + t ];
			var row_index = row [ '_pos' ]; // this.from_row + t;

			if ( this.cbacks [ 'fill_manip' ] )
				this.rows [ row_index ] = this.cbacks [ 'fill_manip' ].call ( this, row );
			else
				this.rows [ row_index ] = row;
		}

		// FABIO: aggiunto 2009-07-13
		// FIXME: forse non serve
		this.to_row = this.from_row + len;

		this.num_rows = vars [ 'rows' ];

		if ( this.cbacks [ 'fill_end' ] ) this.cbacks [ 'fill_end' ] ( this, vars );

		if ( cback ) cback ( this );
	};

	this.needs_prefetch = function ( row_num )
	{
		if ( row_num >= this.num_rows ) row_num = this.num_rows -1;
		if ( this.rows [ row_num ] ) return false;

		var start = Math.floor ( row_num / this.lines_per_page ) * this.lines_per_page;
		var end   = start + this.lines_per_page -1;

		if ( end >= this.num_rows ) end = this.num_rows -1;

		if ( ! this.rows [ start ] ) return true;
		if ( ! this.rows [ end ] ) return true;

		return false;
	};

	this.prefetch = function ( num, cback )
	{
		if ( ! this.needs_prefetch ( num ) ) return cback ( this );

		var start = Math.floor ( num / this.lines_per_page ) * this.lines_per_page;

		this._form_fields [ '_X_START_POINT' ] = start;

		if ( this.cbacks [ 'prefetch_start' ] ) this.cbacks [ 'prefetch_start' ] ( this );

		this.fill ( cback );

		return true;
	};


	this.get_row = function ( num )
	{
		var row;

		if ( num >= this.num_rows ) return null;

		row = this.rows [ num ];

		return row;
	};

	this.filter_date = function ( s )
	{
		var g = parseInt ( s.replace ( /[^0-9]*([0-9][0-9]*)-([0-9][0-9]*)-([0-9][0-9][0-9][0-9]).*/, "$1" ) );
		var m = parseInt ( s.replace ( /[^0-9]*([0-9][0-9]*)-([0-9][0-9]*)-([0-9][0-9][0-9][0-9]).*/, "$2" ) );
		var a = s.replace ( /.*([0-9][0-9]*)-([0-9][0-9]*)-([0-9][0-9][0-9][0-9]).*/, "$3" );
		var pre = s.replace ( /([^0-9]*)[0-9][0-9]*-[0-9][0-9]*-[0-9][0-9][0-9][0-9].*/, "$1" );
		var post = s.replace ( /.*[0-9][0-9]*-[0-9][0-9]*-[0-9][0-9][0-9][0-9](.*)/, "$1" );

		if ( g < 10 ) g = "0" + g;
		if ( m < 10 ) m = "0" + m;

		return pre + g + "/" + m + "/" + a + post;
	};

	this.show_results_table = function ( dest_div, render_cback )
	{
		console.warn ( "DataSet WARNING: show_results_table() has been deprecated. Use render()" );
		this.render ( dest_div, render_cback );
	};

	this.render = function ( dest_div, render_cback )
	{
		var _obj = this;

		if ( ! dest_div ) dest_div = this._dest_div;
		this._dest_div = dest_div;

		this.prefetch ( this.from_row, function ( ds ) { _obj._render_done ( dest_div, render_cback ); } );
	};

	this._render_done = function ( dest_div, render_cback )
	{
		var s = '';

		this._prepare_pagination ();

		s = this.to_string ();

		$( dest_div ).innerHTML = s;

		if ( ! render_cback ) render_cback = this.cbacks [ 'show_results' ];
		if ( render_cback ) render_cback ( this );
	};

	this.refresh = function ( cback )
	{
		this._form_fields [ '_X_START_POINT' ] = this.from_row;
		this.fill ( cback, true );
	};

	this.to_string = function ()
	{
		var s = '';
		var t, row;

		s += String.formatDict ( this.templates [ 'table_start' ], this._attrs );
		s += String.formatDict ( this.templates [ 'table_header' ], this._attrs );

		// Ho messo <= in 'to_row' perche' altrimenti salta la prima riga
		// for ( t = 0; t < this.len; t ++ )
		for ( t = this.from_row; t < this.to_row ; t ++ )
		{
			row = this.get_row ( t ); 
			//console.debug ( "ROW: %s" + row );

			if ( ! row ) continue;

			if ( t > this.num_rows ) break;

			row [ 'ds_name' ] = this.name;
			row [ '_ds_row_num' ] = t;
			row [ '_ds_bg' ] = t % 2;

			if ( this.cbacks [ "row_manip" ] ) this.cbacks [ "row_manip" ] ( this, row );

			s += String.formatDict ( this.templates [ 'table_row' ], row );
		}

		s += String.formatDict ( this.templates [ 'table_footer' ], this._attrs );
		s += String.formatDict ( this.templates [ 'table_end' ], this._attrs );

		return s;
	};

	this._prepare_pagination = function ()
	{
		var delta    = this.to_row - this.from_row;
		var res, to_row, num_rows;

		res = this.from_row + 1;
		to_row = this.to_row;
		num_rows = this.num_rows;

		if ( to_row > num_rows ) to_row = num_rows;

		if ( num_rows <= this.lines_per_page )
			this._attrs [ 'docs_shown' ] = to_row;
		else
			this._attrs [ 'docs_shown' ] = res + " - " + to_row + " di " + num_rows;

		this._attrs [ 'from_row' ] = res;
		this._attrs [ 'to_row' ] = to_row;
		this._attrs [ 'num_rows' ] = num_rows;

		if ( this.page ) 
			this._attrs [ '_prev_page' ] = "javascript:DataSet.page('" + this.name + "'," + ( this.page -1 ) +")";
		else
			this._attrs [ '_prev_page' ] = null;

		if ( this.to_row < this.num_rows )
			this._attrs [ '_next_page' ] = "javascript:DataSet.page('" + this.name + "'," + ( this.page +1 ) + ")";
		else
			this._attrs [ '_next_page' ] = null;

		if ( this._attrs [ '_prev_page' ] )
			this._attrs [ 'prev_page' ] = String.formatDict ( this.templates [ 'prev_page' ], this._attrs );
		else
			this._attrs [ 'prev_page' ] = "&nbsp;";

		if ( this._attrs [ '_next_page' ] )
			this._attrs [ 'next_page' ] = String.formatDict ( this.templates [ 'next_page' ], this._attrs );
		else
			this._attrs [ 'next_page' ] = "&nbsp;";

		if ( this.page && ( this.to_row < this.num_rows ) )
			this._attrs [ 'dash' ] = this.templates [ "dash" ];
		else
			this._attrs [ 'dash' ] = "";

		if ( this.paginator )
		{
			this.paginator.init ( this.num_rows, this.lines_per_page, this.paginator_links );
			this.paginator.set_page ( this.page );
			this._attrs [ "paginator" ] = this.paginator.mk_str ();
		}
		else
			this._attrs [ "paginator" ] = "Include paginator.js";
	};

	this.show_page = function ( page )
	{
		this.page = page;

		this.from_row = this.lines_per_page * page;
		this.to_row = this.lines_per_page * ( page +1 );

		this.render ();
	};

	this.format_str = function ( template )
	{
		return String.formatDict ( template, this._attrs );
	};

	this.set_curr_doc   = function ( pos ) { 
		if ( pos === undefined ) pos = -1;
		this.curr_doc = pos; 
	};

	this.prepare_result_navi = function ( cback )
	{
		var _obj = this;

		if ( this.curr_doc == -1 ) return;

		this.prefetch ( this.curr_doc + 2, function ( ds ) { _obj.result_navi ( ds, cback ); } );
	};

	this.result_navi = function ( ds, cback )
	{
		if ( this._form_fields && this.needs_prefetch ( this.curr_doc +2 ) ) 
		{
			var _obj = this;
			this.prefetch ( this.curr_doc +2, function ( ds ) { _obj.result_navi ( ds, cback ); } );
			return;
		}

		var s = '';
		var row;
		
		if ( this.curr_doc > 0 )
		{
			// Posso tornare indiretro
			row = this.rows [ this.curr_doc -1 ];
			this._attrs [ 'prev_doc' ] = String.formatDict ( this.templates [ 'prev_doc' ], row );

			// 'javascript:DataSet.doc(\'' + this.name + '\',\'' + row.get ( 'id' ) + '\',{pos: ' + ( this.curr_doc -1 ) + '})';
		} else
			this._attrs [ 'prev_doc' ] = null;

		if ( this.curr_doc < this.num_rows -1 )
		{
			// Posso andare avanti
			row = this.rows [ this.curr_doc +1 ];
			this._attrs [ 'next_doc' ] = String.formatDict ( this.templates [ 'next_doc' ], row );
			// this._attrs [ 'next_doc' ] = 'javascript:DataSet.doc(\'' + this.name + '\',\'' + row.get ( 'id' ) + '\',{pos: ' + ( this.curr_doc +1 ) + '})';
		} else
			this._attrs [ 'next_doc' ] = null;

		if ( cback ) cback ( ds );
	}

}

DataSet._instances = {};

DataSet.get = function ( instance_name )
{
	return DataSet._instances [ instance_name ];
};

DataSet.page = function ( name, page_no )
{
	var ds = DataSet._instances [ name ];

	ds.show_page ( page_no );
};

DataSet.ajax = function ( ajax, fields, cback ) { liwe.AJAX.request ( ajax, fields, cback, true ); };


var kernel = {};
var modules = {};


kernel.StopExecutionException = {};


kernel.load = function ()
{
	kernel._ajax_reqs = 0;

	if ( $ ( "ajax_wait" ) )
	{
		if ( liwe.AJAX [ "cbacks" ] )
		{
			liwe.AJAX.cbacks [ "req-start" ] = kernel._start_ajax_req;
			liwe.AJAX.cbacks [ "req-end" ] = kernel._end_ajax_req;
		}
		else
		{
			liwe.AJAX.start_req_handler = kernel._start_ajax_req;
			liwe.AJAX.end_req_handler = kernel._end_ajax_req;
		}
	}

	if ( liwe.AJAX [ "cbacks" ] )
		liwe.AJAX.cbacks [ "req-error" ] = kernel._error_handler;
	else
		liwe.AJAX.error_handler = kernel._error_handler;

	kernel._init_login ();

	kernel._check_logged ();

	if ( window [ "DataSet" ] )
	{
		DataSet.ajax = function ( ajax, fields, cback ) {
			kernel.ajax ( "/cgi-bin/FulQuery", fields, cback );
		};
	}
};


kernel._check_logged = function ()
{
	kernel.command ( "get_opere", {},
		function ( v )
		{
			if ( v [ "login" ] )
				Login.render_logged ( v, site.login_div_name );
			else
				kernel.on_login ( v );
		}
	);
};


kernel._init_login = function ()
{
	if ( site && site.login_form_data )
	{
		Login.templates [ 'logged' ] = site.templates [ 'logged' ];

		Login.init ( 
				site.login_form_data.get ( 'div_logged', '' ),
				site.login_form_data.get ( 'form_id', '' ),
				site.login_form_data.get ( 'login_id', '' ),
				site.login_form_data.get ( 'pwd_id', '' ),
				site.login_form_data.get ( 'btn_id', '' )
			);
	}

	Login.events [ 'login' ] = kernel.on_login;
	//Login.render ();
};


kernel.on_login = function ( v )
{
	function _set_listener ( mod )
	{
		liwe.history.set_listener ( function ( dict, data ) { kernel._mod_listener ( mod, dict, data ); }, mod );
	}

	kernel.user_info = v;

	var mod;
	for ( mod in modules )
	{
		if ( typeof modules [ mod ] == "function" ) continue;
		_set_listener ( mod );
	}

	if ( site.on_login )
	{
		try
		{
			site.on_login ( v );
		}
		catch ( e )
		{
			if ( e != kernel.StopExecutionException )
				throw e;
		}
	}

	liwe.history.set_listener ( function ( dict, data ) { kernel._mod_listener ( site.default_module, dict, data ); } );
	liwe.history.init ();
};


kernel.init_module = function ( mod_name, dict, data )
{
	try
	{
		var mod = modules [ mod_name ];

		var navi_path_data = null;
		if ( data )
		{
			data = data.clone ();
			navi_path_data = data.get ( "_navi_path_data" );
			if ( navi_path_data )
				delete data [ "_navi_path_data" ];

			if ( data.count () == 0 )
				data = null;
		}

		kernel.init ( mod_name, dict, data, navi_path_data, function ()
		{
			site.init ( mod_name, dict, data );
			mod.init ( dict, data );
		} );

		/*
		if ( dict [ "__sy" ] )
			window.scrollTo ( 0, parseInt ( dict [ "__sy" ], 10 ) );
		*/
	}
	catch ( e )
	{
		if ( e != kernel.StopExecutionException )
			throw e;
	}
};


kernel._mod_listener = function ( mod_name, dict, data )
{
	var mod = modules [ mod_name ];
	if ( mod ) kernel.init_module ( mod_name, dict, data );
};


kernel._start_ajax_req = function ( req )
{
	kernel._ajax_reqs ++;
	
	var div = $ ( "ajax_wait" );
	if ( div ) div.style.display = "block";
};

kernel._end_ajax_req = function ( req )
{
	if ( ! --kernel._ajax_reqs )
	{
		var div = $ ( "ajax_wait" );
		if ( div ) div.style.display = "none";
	}
};


kernel.init = function ( module, dict, data, navi_path_data, cback )
{
	var navi_path = site.navi_path;
	var add = false;
	var replace = false;

	if ( ! dict ) dict = {};
	var mask = dict.get ( "mask", "m:main" );
	if ( mask.substr ( 0, 2 ) == "m:" )
	{
		dict [ "mask" ] = mask.substr ( 2 );
	}
	else if ( mask.substr ( 0, 2 ) == "a:" )
	{
		dict [ "mask" ] = mask.substr ( 2 );
		add = true;
	}
	else if ( mask.substr ( 0, 2 ) == "r:" )
	{
		dict [ "mask" ] = mask.substr ( 2 );
		add = true;
		replace = true;
	}
	else
	{
		var mode = site.get ( "navi_path_reset_mode", "on_request" );
		if ( mode != "always" )
			add = true;
	}

	function _post_init ()
	{
		kernel.module = module;
		kernel.history_dict = dict;
		kernel.history_data = data;

		kernel._ajax_error_handlers = {};

		cback ();
	}

	if ( navi_path )
	{
		if ( NaviPath._version == 1 )
		{
			if ( add )
			{
				if ( navi_path_data ) navi_path.set_status ( navi_path_data );
				if ( replace ) navi_path.back ();
			}
			else
			{
				navi_path.clear ();
			}

			_post_init ();
		}
		else if ( NaviPath._version == 2 )
		{
			if ( add )
			{
				navi_path.list ( function ()
				{
					if ( replace ) navi_path.back ( _post_init );
					else _post_init ();
				} );
			}
			else
			{
				navi_path.clear ( _post_init );
			}
		}
	}
	else
		_post_init ();
};


kernel.go = function ( module, params, data )
{
	liwe.AJAX.abort ( function () { kernel._go ( module, params, data ); } );
};

kernel._go = function ( module, params, data )
{
	if ( data ) data = data.clone ();

	if ( ! params ) params = { mask: 'm:main' };

	if ( site.navi_path && NaviPath._version == 1 )
	{
		if ( ! data ) data = {};
		data [ "_navi_path_data" ] = site.navi_path.get_status ();
	}
	else if ( site.navi_path && NaviPath._version == 2 )
	{
		var npid = site.navi_path.get_last_id ();
		if ( npid ) params [ "_npid" ] = npid;
	}

	/*if ( ! params [ "__sy" ] )
	{
		var sy = utils.getScrollXY () [ 1 ];
		params [ "__sy" ] = sy;
	}*/

	if ( module == "" )
	{
		liwe.history.add ( params, data );
		module = site.default_module;
	}
	else
		liwe.history.add_module ( module, params, data );

	kernel.init_module ( module, params, data );
};


kernel.show_mask = function ( mask, div_name, cback )
{
	kernel.ajax ( '/cgi-bin/FormParser', { msk: mask }, function ( v ) { 
		var scripts = v [ 'scripts' ];
		var l = scripts.length;
		for ( t = 0; t < l; t ++ )
			liwe.utils.append_js ( scripts [ t ] );

		if ( v [ 'check_for' ] )
			utils.multi_wait ( v [ 'check_for' ], function () {
				kernel._form_done ( v, div_name, mask, cback );
			} );    
		else    
			kernel._form_done ( v, div_name, mask, cback );
	} );            
};


kernel._form_done = function ( v, div_name, mask, cback )
{
	$ ( div_name ).innerHTML = v [ 'mask' ];

	if ( v [ "codes" ] )
	{
		var i, l = v.codes.length;
		for ( i = 0; i < l; i ++ )
			eval ( v.codes [ i ] );
	}

	v [ "original_mask" ] = $ ( div_name ).innerHTML;

	if ( cback ) cback ( v, mask );
};


kernel.quit = function ()
{
	throw kernel.StopExecutionException;
};


// da chiamare quando si preme su "Cerca" per aggiornare la history
kernel.add_history_data = function ( module, params, fields, cback )
{
	liwe.AJAX.abort ( function () { kernel._add_history_data ( module, params, fields, cback ); } );
};

kernel._add_history_data = function ( module, params, fields, cback )
{
	fields = fields.clone ();
	if ( site.navi_path && NaviPath._version == 1 )
		fields [ "_navi_path_data" ] = site.navi_path.get_status ();
	else if ( site.navi_path && NaviPath._version == 2 )
	{
		var npid = site.navi_path.get_last_id ();
		if ( npid ) params [ "_npid" ] = npid;
	}

	if ( ! params ) params = { mask: 'm:main' };

	/*if ( ! params [ "__sy" ] )
	{
		var sy = utils.getScrollXY () [ 1 ];
		params [ "__sy" ] = sy;
	}*/

	liwe.history.add_module ( module, params, fields );

	if ( params )
	{
		params = params.clone ();
		var mask = params.get ( "mask" );
		if ( mask && ( mask.startsWith ( "m:" ) || mask.startsWith ( "a:" ) || mask.startsWith ( "r:" ) ) )
		{
			mask = mask.substr ( 2 );
			params [ "mask" ] = mask;
		}
	}

	kernel.module = module;
	kernel.history_dict = params;
	kernel.history_data = fields;

	if ( cback ) cback ();
};


kernel.replace_history_data = function ( module, params, fields, cback )
{
	liwe.AJAX.abort ( function () { kernel._replace_history_data ( module, params, fields, cback ); } );
};

kernel._replace_history_data = function ( module, params, fields, cback )
{
	if ( fields ) fields = fields.clone ();

	if ( site.navi_path && NaviPath._version == 1 )
	{
		if ( ! fields ) fields = {};
		fields [ "_navi_path_data" ] = site.navi_path.get_status ();
	}

	if ( ! params ) params = { mask: 'm:main' };

	/*if ( ! params [ "__sy" ] )
	{
		var sy = utils.getScrollXY () [ 1 ];
		params [ "__sy" ] = sy;
	}*/

	liwe.history.replace ( module, params, fields );

	if ( params )
	{
		params = params.clone ();
		var mask = params.get ( "mask" );
		if ( mask && ( mask.startsWith ( "m:" ) || mask.startsWith ( "a:" ) || mask.startsWith ( "r:" ) ) )
		{
			mask = mask.substr ( 2 );
			params [ "mask" ] = mask;
		}
	}

	kernel.module = module;
	kernel.history_dict = params;
	kernel.history_data = fields;

	if ( cback ) cback ();
};


kernel.ajax = function ( url, vars, cback, easy )
{
	if ( typeof easy == "undefined" ) easy = true;

	liwe.AJAX.request ( url, vars, function ( v ) {
		if ( ! cback ) return;
		try
		{
			cback ( v );
		}
		catch ( e )
		{
			if ( e != kernel.StopExecutionException )
				throw e;
		}
	}, easy );
};


kernel.command = function ( command, dict, cback )
{
	if ( ! dict ) dict = {};
	dict [ "command" ] = command;
	kernel.ajax ( "/cgi-bin/AjaxCmd", dict, cback );
};


kernel.fulquery = function ( fq, cback )
{
	var fields = {};
	fq.fill ( fields );
	kernel.ajax ( "/cgi-bin/FulQuery", fields, cback );
};


kernel._ajax_error_handlers = {};

kernel.set_ajax_error_handler = function ( code, cback )
{
	kernel._ajax_error_handlers [ code ] = cback;
};


kernel._error_handler = function ( v )
{
	var code = v [ "err_code" ];
	var descr = v [ "err_descr" ];

	var h = kernel._ajax_error_handlers [ code ];
	if ( h )
	{
		h ( v );
		return;
	}

	switch ( code )
	{
		case 1:		// LIBDEA_ERR_BAD_LOGIN
			if ( kernel.user_info [ "login" ] )
			{
				liwe.AJAX.abort ();
				alert ( "Attenzione! La sessione e' scaduta, sara' necessario effettuare nuovamente l'accesso." );
				Login.logout ();
				break;
			}
			//FALLTHROUGH!!!

		default:
			console.error ( "ERRORE: [" + code + "] " + descr );
			if ( site && site.error_handler ) site.error_handler ( v );
			else alert ( descr );
			break;
	}
};

// Registro l'evento principale nell'onload della finestra
liwe.events.add ( window, "load", kernel.load );



var LinkReplacer = {};

LinkReplacer.scroll_parent = null;


LinkReplacer._anchors = {};


LinkReplacer.lnk2span = function ( txt )
{
	if ( ! txt ) return "";
	var s = txt.replace ( /<(.?)lnk/ig, "<$1span" );
	return s;
};

LinkReplacer.replace = function ( replace_link_cback )
{
	var lnks = document.getElementsByTagName ( "span" );
	var lnk, l, t;
	var txt;
	var a, href;
	var res = [];

	l = lnks.length;

	for ( t = 0; t < l; t ++ )
	{
		lnk = lnks [ t ];

		if ( ! lnk.getAttribute ( 'opera' ) && ! lnk.getAttribute ( 'tipolink' ) ) continue;

		txt = lnk.innerHTML;
		href = replace_link_cback ( lnk );

		a = document.createElement ( 'a' );
		a.setAttribute ( 'href', href );
		a.innerHTML = txt;

		res.push ( [ a, lnk ] );
	}

	l = res.length;
	for ( t = 0; t < l; t ++ )
	{
		lnk = res [ t ] [ 1 ];
		lnk.parentNode.replaceChild ( res [ t ] [ 0 ], lnk );
	}
};


LinkReplacer.replace_anchors = function ( el, skip_class_check )
{
	if ( ! el ) el = document;

	var as = el.getElementsByTagName ( "a" );
	var a, l, t;
	var name, href = false;

	l = as.length;

	for ( t = 0; t < l; t ++ )
	{
		a = as [ t ];

		name = a.getAttribute ( 'name' );
		if ( name )
			LinkReplacer._anchors [ name ] = a;

		try {
			href = a.getAttribute ( 'href' );
		} catch ( e ) {
			href = false;
		}

		if ( ! href ) continue;

		if ( ! skip_class_check && a.className != "cds_rif_nota" && a.className != "cds_rimando_nota" ) continue;

		href = href.split ( "#" );
		if ( href.length > 1 && ( ( ! href [ 0 ] ) || href [ 0 ] == ( location.protocol + "//" + location.hostname + location.pathname + location.search ) ) )
		{
			href = href [ 1 ];
			a.setAttribute ( 'href', "javascript:LinkReplacer.scroll('" + href + "')" );
		}
	}
};


LinkReplacer.scroll = function ( name )
{
	var a = LinkReplacer._anchors [ name ];
	if ( ! a )
	{
		var i, l = document.anchors.length;
		for ( i = 0; i < l; i ++ )
		{
			if ( document.anchors [ i ].name == name )
			{
				a = document.anchors [ i ];
				break;
			}
		}
	}
	if ( ! a )
	{
		console.warn ( "Manca l'anchor con NAME '" + name + "'" );
		return;
	}

	var pos = liwe.dom.get_offset_top ( a );

	if ( LinkReplacer.scroll_parent )
	{
		var p2 = liwe.dom.get_offset_top ( LinkReplacer.scroll_parent );
		LinkReplacer.scroll_parent.scrollTop = pos - p2;
	}
	else
		window.scrollTo ( 0, pos );
};


LinkReplacer.set_hl_navi = function ( el, first_el )
{
	if ( ! el ) el = document;

	var spans = el.getElementsByTagName ( "span" );
	var i, l = spans.length;
	var count = 0;
	var h, dest;
	var s_spans = [];
	var l_spans = [];

	for ( i = 0; i < l; i ++ )
	{
		var span = spans [ i ];
		if ( span.className != "highlight" ) continue;

		var p = span.parentNode;
		while ( p )
		{
			if ( p.tagName == "A" )
			{
				span._in_link = p;
				l_spans.push ( span );
				break;
			}

			p = p.parentNode;
		}

		LinkReplacer._anchors [ "_hl_span" + count ] = span;

		s_spans.push ( span );
		count ++;
	}

	l = l_spans.length;
	for ( i = 0; i < l; i ++ )
		LinkReplacer._fix_span_in_link ( l_spans [ i ] );

	for ( i = 0; i < count; i ++ )
	{
		span = s_spans [ i ];

		if ( span._in_link )
			span = span._in_link;

		if ( i > 0 )
		{
			// aggiungo la freccia PRIMA
			h = document.createElement ( "a" );
			h.href = "javascript:LinkReplacer.scroll('_hl_span" + ( i - 1 ) + "')";
			h.innerHTML = '<img border="0" alt="" src="/gfx/ft_prev.gif" style="margin-right: 2px" />';

			span.parentNode.insertBefore(h, span);
		}

		if ( i < count - 1 )
		{
			// aggiungo la freccia DOPO
			h = document.createElement ( "a" );
			h.href = "javascript:LinkReplacer.scroll('_hl_span" + ( i + 1 ) + "')";
			h.innerHTML = '<img border="0" alt="" src="/gfx/ft_next.gif" style="margin-left: 2px" />';

			dest = span.nextSibling;
			if (dest)
				span.parentNode.insertBefore(h, dest);
			else
				span.parentNode.appendChild(h);
		}
	}

	if ( first_el )
	{
		if ( count )
		{
			first_el.innerHTML = '<a href="javascript:LinkReplacer.scroll(\'_hl_span0\')">' +
				'<img alt="Prima occurrenza" border="0" src="/gfx/ft_first.gif" /></a>';
			first_el.style.display = "block";
		}
		else
			first_el.style.display = "none";
	}
};


LinkReplacer._fix_span_in_link = function ( s )
{
	var before = [];

	var lnk = s._in_link;
	while (lnk.childNodes.length > 0)
	{
		var el = lnk.childNodes [ 0 ];

		lnk.removeChild ( el );

		if ( el == s )
			break;
		else
			before.push ( el );
	}

	var a = lnk.cloneNode(false);

	var i, l = before.length;
	for ( i = 0; i < l; i ++ )
		a.appendChild ( before [ i ] );

	lnk.parentNode.insertBefore ( a, lnk );

	a = lnk.cloneNode(false);
	a.appendChild ( s );
	lnk.parentNode.insertBefore ( a, lnk );

	s._in_link = a;
};



var Login = {};

Login.templates = {};
Login._dest_div = '';
Login._dest_logged = '';
Login.login_command = "login";

//FORM FIELDS
Login._form_id = '';
Login._login_id = '';
Login._pwd_id = '';
Login._btn_id = '';

Login.events = {
		"login" : null,
		"logout" : null
		};

Login.init = function ( div_logged, form_id, login_id, pwd_id, btn_id )
{
	Login.set_ids ( div_logged, form_id, login_id, pwd_id, btn_id );

	Login._set_events ();
};

Login.set_ids = function ( div_logged, form_id, login_id, pwd_id, btn_id )
{
	Login._dest_logged = div_logged,
	Login._form_id  = form_id;
	Login._login_id = login_id;
	Login._pwd_id   = pwd_id;
	Login._btn_id   = btn_id;
};

Login._set_events = function ()
{
	if ( Login._form_id && $ ( Login._form_id ) ) $ ( Login._form_id ).setAttribute ( "action", "javascript:Login.login()" );
	else
	{
		if ( $ ( Login._btn_id ) ) liwe.events.add_by_id ( Login._btn_id, 'click', Login.do_login );
		if ( $ ( Login._pwd_id ) ) liwe.events.add_by_id ( Login._pwd_id , 'keydown', Login._keydown );
	}
};

Login._keydown = function ( e )
{
	var keycode;
	
	if ( window.event ) keycode = window.event.keyCode;
	else if ( e ) keycode = e.which;
	else return false;
	
	if ( keycode != 13 ) return false;
	return Login.do_login ();
};

Login.do_login = function ()
{
	if ( $ ( Login._form_id ) ) $ ( Login._form_id ).submit ();
};

Login.login = function ()
{
	var login = ( $ ( Login._login_id ) ? $ ( Login._login_id ).value : '' );
	var pwd = ( $ ( Login._pwd_id ) ? $ ( Login._pwd_id ).value : '' );

	if ( ! login.length || ! pwd.length )
		alert ( "Inserire login e password" );
	else {
		var err_handler = liwe.AJAX.cbacks [ "req-error" ] || liwe.AJAX.error_handler;
		liwe.AJAX.cbacks [ "req-error" ] = function ( v ) { alert ( v.err_descr ); };

		kernel.ajax ( '/cgi-bin/AjaxCmd', { command: Login.login_command, login: login, passwd: pwd }, 
			function ( v )
			{
				liwe.AJAX.cbacks [ "req-error" ] = err_handler;
				Login.render_logged ( v );
			}
		);
	}
};

Login.render_logged = function ( data, dest )
{
	var s = '';
	var ctr_panel = '';

	if ( ! dest ) dest = Login._dest_logged;

	if ( Login._dest_logged && document.getElementById ( Login._dest_logged ) )
	{
		if ( data [ 'usr_kind' ] > 405 ) ctr_panel = '<div class="cp_link"><a href="/control_panel">Pannello di controllo<\/a><\/div>';

		data [ 'ctr_panel' ] = ctr_panel;

		s = String.formatDict ( Login.templates [ 'logged' ], data );


		document.getElementById ( Login._dest_logged ).innerHTML = s;
	}

	if ( Login.events [ 'login' ] ) Login.events [ 'login' ] ( data );
};

Login.logout = function ()
{
	//elimina cookie e ricarica la pagina
	kernel.ajax ( "/cgi-bin/AjaxCmd", { command: "logout" }, 
		function ( v )
		{
			if ( site && site.on_logout )
				site.on_logout ();
			else
				window.location.reload();
		}
	);
};

var logout = Login.logout;



var utils = {};

utils.MESI = [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ];
utils.GIORNI = [ "Domenica", "Luned&igrave;", "Marted&igrave;", "Mercoled&igrave;", "Gioved&igrave;", "Venerd&igrave;", "Sabato" ];

utils.strip_html_body = function ( s )
{
	var p, p2;

	p = s.indexOf ( "<body" );
	if ( p < 0 ) p = s.indexOf ( "<BODY" );
	if ( p >= 0 )
	{
		p2 = s.indexOf ( ">", p + 5 );
		if ( p2 >= 0 )
			s = s.substr ( p2 + 1 );
	}

	p = s.indexOf ( "</body>" );
	if ( p < 0 ) p = s.indexOf ( "</BODY>" );
	if ( p >= 0 )
		s = s.substr ( 0, p );

	return s;
};


utils.get_browser = function ()
{	
	var s = navigator.userAgent;
	var res = '';

	if ( document.all && s.toLowerCase().indexOf ( 'msie' ) != -1 )
	{
		s = navigator.userAgent.substr ( s.toLowerCase().indexOf ( 'msie' ), 8 );
		res = 'IE';

		if ( s.indexOf ( '6.0' ) != -1 ) res += '6';
		else if ( s.indexOf ( '7.0' ) != -1 ) res += '7';
	}
	else if ( s.toLowerCase().indexOf ( 'mozilla' ) != -1 )
	{
		s = navigator.userAgent.substr ( navigator.userAgent.toLowerCase().indexOf ( 'firefox' ), 15);

		if ( s.toLowerCase().indexOf ( 'firefox' ) != -1 )
		{
			s = s.split ( "/" );

			res = 'FF';

			if ( s.length >= 1 )
				res += s [ 1 ]; 
		}
	}
	else
		res = navigator.appName + navigator.appVersion;

	return res;
};


utils.order_date = function ( date, sep, order, new_sep )
{
	var s = '';

	if ( date )
	{
		if ( order == "IT" && sep )
		{
			s = date.split ( sep );

			if ( s.length < 2 ) return s;

			if ( new_sep ) sep = new_sep;

			s = s [ 2 ] + sep + s [ 1 ] + sep + s [ 0 ];
		}
	}

	return s;
};


utils.get_file = function ( url, cback )
{
	kernel.ajax ( url, {}, function ( v )
	{
		if ( v.readyState != 4 ) return;
		if ( cback ) cback ( v.responseText, v.status );
	}, false );
};

utils.multi_wait = function ( lst, cback, vars, elem, n )
{
	var t, l = lst.length;
	if ( ! n ) n = 0;

	if ( n > 30 )
	{
		console.error ( "Non sono riuscito a caricare: " + elem );
		return;
	}

	for ( t = 0; t < l; t ++ )
	{
		if ( ! liwe.utils.is_def ( lst [ t ] ) )
		{
			console.debug ( "Attendo " + lst [ t ] );
			setTimeout ( function () { utils.multi_wait ( lst, cback, vars, lst [ t ], ++n );  }, 500 );
			return;
		}
	}

	if ( cback ) cback ( vars );
};

utils.fill_mask = function ( mask, div_name, cback, ds )
{
	kernel.show_mask ( mask, div_name, function ( v )
	{
		var requery = false;
		var data = kernel.history_data;

		if ( data )
		{
			var fields = v [ "fields" ];
			var ds_fields = ds ? ds.get_fields () : {};
			if ( ! ds_fields ) ds_fields = {};

			var t, l = fields.length;
			for ( t = 0; t < l; t ++ )
			{
				var f = fields [ t ] [ 0 ];
				var ftype = fields [ t ] [ 1 ];
				var val = data.get ( f, "" );  // dalla history

				if ( ftype == "radio" )
				{
					var el = $ ( f + "_" + val );
					if ( el ) el.checked = true;
				}
				else
				{
					var el = document.getElementById ( f );
					if ( ! el ) continue;

					if ( ftype == "checkbox" )
						el.checked = ( val.length > 0 );
					else if ( ftype == "select" && el.multiple )
					{
						var sval = val.split ( "|" );
						var opts = el.getElementsByTagName ( "option" );
						var oi, ol = opts.length;
						for ( oi = 0; oi < ol; oi ++ )
						{
							var opt = opts [ oi ];
							opt.selected = sval.indexOf ( opt.value ) >= 0;
						}
					}
					else
						el.value = val;
				}

				if ( val != ds_fields.get ( f, "" ) )
					requery = true;
			}
		}

		if ( cback ) cback ( v, requery );
	} );
};


utils.auto_focus = function ( field1, length, field2 )
{
	if ( field1.value.length < length ) return;
	if ( ! field2 )
	{
		field2 = field1.nextSibling;
		while ( field2 && ! field2 [ "focus" ] )
			field2 = field2.nextSibling;
	}
	else if ( typeof field2 == "string" )
		field2 = document.getElementById ( field2 );
	
	if ( field2 ) setTimeout ( function () { field2.focus(); }, 100 );
};


utils.get_sommarietto = function ( key, cback )
{
	var km = new KeyMan ();
	km.set ( key );
	var order_list = [ 18, 9, 15, 16, 19, 17 ];

	var dtm = DocTypeManager.get ( km.kind );
	if ( ! dtm [ "sommarietto" ] )
	{
		cback ( [] );
		return;
	}

	var fq = new FulQuery ();
	fq.opera = km.opera;
	fq.db_name = km.get_dbname ();
	fq.mode = "QUERY";
	fq.add ( "ID", "LIKE", km.main_key );
	fq.set_fields ( "ID", "FULTIPO" );
	fq.lines = 1000;

	var res = [];

	kernel.fulquery ( fq, function ( v )
	{
		var i, rows = v [ "rows" ];
		for ( i = 0; i < rows; i ++ )
		{
			var r = v [ "row" + i ];
			var fultipo = r [ "FULTIPO" ];
			var id = r [ "ID" ];

			var item = dtm.get_somm_item ( fultipo );
			if ( ! item ) continue;

			if ( item.ext == km.ext ) continue;
			if ( ! km.ext && item.ext == "OGG" ) continue;

			res.push ( [ id, item.descr, parseInt ( fultipo, 10 ) ] );
		}

		res.sort ( function ( a, b ) { 
			var at = a [ 2 ];
			var bt = b [ 2 ];

			var ai = order_list.indexOf ( at );
			var bi = order_list.indexOf ( bt );

			return ai - bi;
		} );

		cback ( res );
	} );
};


utils.getScrollXY = function ()
{
	var x = 0, y = 0;

	if ( typeof ( window.pageYOffset ) == 'number' )
	{
		// Netscape
		x = window.pageXOffset;
		y = window.pageYOffset;
	} else if ( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		// DOM
		x = document.body.scrollLeft;
		y = document.body.scrollTop;
	} else if ( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		// IE6 standards compliant mode
		x = document.documentElement.scrollLeft;
		y = document.documentElement.scrollTop;
	}

	return [ x, y ];
};


utils.tree = {};

utils.tree.show_tree = function ( tree_id, expand_limit, show_checkbox, w, h, lst_file )
{
	var tree = new OS3Tree.instance ( tree_id );

	//tree.check_explorer = true;
	tree.expand_limit = expand_limit;
	tree.show_checkbox = show_checkbox;
	tree.width = w;
	//tree.height = h;
	tree.expand_request = utils.tree.expand_request;
	tree.lst_file = lst_file;

	kernel.command ( "tree_get", { FILE_NAME: tree.lst_file },
		function ( v ) 
		{
			var t, l = v [ "nodes" ].length;

			for ( t = 0; t < l; t ++ )
			{
				var node = v [ "nodes" ] [ t ];
				if ( node.folder )
					tree.add_folder ( null, node.text, node.val, node.val );
				else
					tree.add_node ( null, node.text, node.val, node.val );
			}
			
			tree.render ( tree_id + "_DIV" );
		}
	);

	return tree;
};


utils.tree.expand_request = function ( node )
{
	kernel.command ( "tree_get", { FILE_NAME: node.tree.lst_file, NODE_ID: node.val, LEVEL: node.level },
		function ( vars ) { node.expand_done ( vars [ 'nodes' ] ); } );
};


utils.hide_windowed = function ( cnt )
{
	if ( ! cnt ) cnt = document;

	utils._windowed_status = [];

	var windowed = [ "select", "object", "iframe", "applet", "plugin", "embed" ];
	var k, len = windowed.length;
	for ( k = 0; k < len; k++ )
	{
		var els = cnt.getElementsByTagName ( windowed [ k ] );

		var t, l = els.length;
		for ( t = 0; t < l; t++ )
		{
			var el = els [ t ];
			var vis = el.style.visibility;
			utils._windowed_status.push ( [ el, vis ] );
			el.style.visibility = "hidden";
		}
	}
};


utils.restore_windowed = function ()
{
	var t, l = utils._windowed_status.length;
	for ( t = 0; t < l; t ++ )
	{
		var item = utils._windowed_status [ t ];
		var el = item [ 0 ];
		var vis = item [ 1 ];
		el.style.visibility = vis;
	}
};


utils.scrollTo = function ( el )
{
        if ( typeof el == "string" ) el = $ ( el );
        if ( ! el ) return;

        var ypos = liwe.dom.get_offset_top ( el );
        window.scrollTo ( 0, ypos );
};


utils.magic_button = function ( key )
{
	var OMEN_URL = "omen.leggiditalia.it";

	if ( kernel.user_info && kernel.user_info.attive.indexOf ( "PQ" ) >= 0 )
	{
		var km = new KeyMan ();
		km.set ( key );

		return String.format ( "http://%s/deaplugins/pm/pm_info.php?DOC_KEY=%s&ART=%s&SSCKEY=%s&LOGINDB=%s", 
			OMEN_URL, key, km.art_num, kernel.user_info.ssckey, kernel.user_info.db_name );
	}
	else
		return null;
};

utils.replace_anchors = function ( src )
{
	var as = src.getElementsByTagName ( "a" );
	var a, l, t;
	var name, href;
	var _anchors = {};

	l = as.length;

	for ( t = 0; t < l; t ++ )
	{
		a = as [ t ];

		name = a.getAttribute ( 'name' );
		if ( name )
		{
			a.setAttribute ( "id", name );
		}
		else
		{
			href = a.getAttribute ( 'href' );

			if ( ! href || ( href.indexOf ( "#" ) == -1 ) ) continue;

			var spl = href.split ( "#" );
			href = spl [ 1 ];

			a.setAttribute ( "name", href ); 

			_anchors [ href ] = a;

			a.setAttribute ( 'href', "javascript:utils.scrollTo('" + href + "')" );
		}
	}
};



// oggetto che gestisce la barra laterale

var SideBar = function ()
{
	this.sections = {};

	this.items = {};

	this._count = 1;


	this.render = function ( div_name, sections )
	{
		if ( typeof sections == "undefined" )
		{
			sections = [];
			this.sections.iterate ( function ( v, k )
			{
				sections.push ( k );
			} );
		}
	
		var s = '';
		var i, l = sections.length;
		var dict;

		for ( i = 0; i < l; i++ )
		{
			var sec = this.sections [ sections [ i ] ];
			if ( ! sec ) continue;

			if ( i > 0 ) s += "<hr />";

			if ( ! sec.get ( "id" ) )
				sec.id = "sidebar_sec_" + (++ this._count);

			sec.id += ":" + sections [ i ];

			if ( sec.get ( "title" ) )
			{
				var title = sec.title;

				var disabled = "";
				if ( sec.get ( "disabled" ) ) disabled = "_disabled";
				
				// titolo
				var expanded = true;
				if ( sec.get ( "expandable" ) )
				{
					expanded = sec.get ( "expanded" );
					title = '<div id="' + sec.id + ':toggle_btn" class="exp_' + (expanded ? "opened" : "closed") +
						'" onclick="SideBar._expand(\'' + sec.id + '\')"></div>' + title;
				}
				s += String.formatDict ( SideBar.templates [ "section_head" ], { "section": title, _disabled: disabled, id: sec.id } );

				// cose che stanno sotto
				s += '<div id="' + sec.id + ':items" style="display: ' + (expanded ? "block" : "none") + '">';

				var items = sec.get ( "items" );
				if ( ! items ) continue;

				var j, l2 = items.length;
				for ( j = 0; j < l2; j++ )
				{
					var dict = items [ j ];
					if ( ! dict ) continue;

					if ( disabled ) dict [ "disabled" ] = true;
					s += this._render_row ( dict );
				}

				s += '</div>';
			}
			else if ( sec.length )
			{
				var title = sections [ i ];
				if ( typeof ( sec ) == 'string' )
				{
					sec = sec.replace ( /\"/g, '&quot;' );
					sec.id = "";
					title = String.formatDict ( SideBar.templates [ "section_link" ], { title: title + "&nbsp;&raquo;", link: sec } );
				}

				s += String.formatDict ( SideBar.templates [ "section_head" ], { "section": title, _disabled: "", id: sec.id } );

				if ( typeof ( sec ) == 'string' ) continue;

				var j, l2 = sec.length;
				for ( j = 0; j < l2; j++ )
				{
					dict = sec [ j ];
					if ( ! dict ) continue;
					s += this._render_row ( dict );
				}
			}
		}
		
		var el = $ ( div_name );
		el.innerHTML = s;
		el.className = "side_bar";
		el.style.display = 'block';
		el._sidebar = this;
	};


	this._render_row = function ( dict )
	{
		if ( ! dict.get ( "id" ) )
			dict.id = "sidebar_item_" + (++ this._count);

		var item = new SideBar.SectionItem ( dict );

		this.items [ item.id ] = item;

		return item.render ();
	};
}


SideBar.templates = {
	"section_head": '<div id="%(id)s" class="tit%(_disabled)s">%(section)s</div>',
	"row": '<div id="%(id)s" class="row%(_disabled)s"><span class="link%(_disabled)s" onclick="%(link)s"><div class="img%(_disabled)s" %(_img)s></div>' +
		'<div class="text%(_disabled)s">%(text)s</div></span></div>',
	"section_link": '<span class="section" onclick="%(link)s">%(title)s</span>'
};


SideBar._expand = function ( id )
{
	var sec_name = id.split ( ":" ) [ 1 ];
	var section = $ ( id ).parentNode._sidebar.sections [ sec_name ];

	section.expanded = ! section.expanded;

	var el = $ ( id + ":items" );
	el.style.display = section.expanded ? "block" : "none";

	$ ( id + ":toggle_btn" ).className = section.expanded ? "exp_opened" : "exp_closed";
};


SideBar.SectionItem = function ( attrs )
{
	var self = this;

	attrs.iterate ( function ( v, k )
	{
		self [ k ] = v;
	} );


	self.render = function ()
	{
		if ( self.get ( "img" ) )
			self [ "_img" ] = 'style="background-image: url(/gfx/' + self.img + '.gif)"';
		else
			self [ "_img" ] = "";

		if ( self.get ( "disabled" ) )
		{
			self [ "_disabled" ] = "_disabled";
			self [ "link" ] = "";
		}
		else
			self [ "_disabled" ] = "";

		self [ "link" ] = self [ "link" ].replace ( /\"/g, '&quot;' );

		return String.formatDict ( SideBar.templates [ "row" ], self );
	};
};



var topbar = {};

topbar._rows = [];
topbar._row_instance = {};

topbar.Row = function ( name, args )
{
	var t, l = args.length;

	this.name = name;
	this.dest_div = name;

	this.items = [];

	for ( t = 1; t < l; t ++ )
		this.items.push ( args [ t ] );

	this.render = function ()
	{
		var t, l = this.items.length;
		var e;

		this.html = '';
		this.widgets = [];

		for ( t = 0; t < l; t ++ )
		{
			e = this.items [ t ];
			this [ '_render_' + e [ 'type' ] ] ( t, e );
		}

		$( this.dest_div ).innerHTML = this.html;

		l = this.widgets.length;
		for ( t = 0; t < l; t ++ )
			this.widgets [ t ].render ();
	};

	this [ '_render_button' ] = function ( pos, e )
	{
		var div_name = this._create_div ( pos, e );

		var b = new WWL.button ( div_name + "_class" );
		b.label = e [ 'label' ];
		b._dest_id = div_name;
		b.class_name = e.get ( 'class_name' );
		b.selected = e.get ( 'selected' );

		var onclick = e.get ( "onclick" );
		if ( onclick ) b.set_event ( "click", onclick );

		this.widgets.push ( b );
	};

	this [ '_render_togglebutton' ] = function ( pos, e )
	{
		var div_name = this._create_div ( pos, e );

		var b = new WWL.togglebutton ( div_name + "_class" );
		b.label = e [ 'label' ];
		b._dest_id = div_name;
		b.class_name = e.get ( 'class_name' );
		b.selected = e.get ( 'selected' );

		var onclick = e.get ( "onclick" );
		if ( onclick ) b.set_event ( "click", onclick );

		this.widgets.push ( b );
	};

	this [ '_render_radiobutton' ] = function ( pos, e )
	{
		var div_name = this._create_div ( pos, e );
		var items = e.items;

		var b = new WWL.radiobutton ( div_name + "_class" );
		b._dest_id = div_name;
		b.class_name = e.get ( 'class_name' );
		b.items = e.items;

		var onclick = e.get ( "onclick" );
		if ( onclick ) b.set_event ( "click", onclick );

		this.widgets.push ( b );
	};

	this._create_div = function ( pos, e )
	{
		var name = ( e [ 'name' ]  ? e [ 'name' ] : this.name + "_" + pos + "_" + e [ 'type' ] );

		this.html += '<div id="' + name + '"></div>';

		return name;
	};
};


topbar.add_row = function ()
{
	var name = arguments [ 0 ];
	var row = new topbar.Row ( name, arguments );

	topbar._rows.push ( row );
	topbar._row_instance [ row.name ] = row;
};

topbar.render = function ()
{
	var t, l = topbar._rows.length;
	var r;

	for ( t = 0; t < l; t ++ )
	{
		r = topbar._rows [ t ];
		r.render ();
	}
};



var LinkReplacer = {};

LinkReplacer.scroll_parent = null;


LinkReplacer._anchors = {};


LinkReplacer.lnk2span = function ( txt )
{
	if ( ! txt ) return "";
	var s = txt.replace ( /<(.?)lnk/ig, "<$1span" );
	return s;
};

LinkReplacer.replace = function ( replace_link_cback )
{
	var lnks = document.getElementsByTagName ( "span" );
	var lnk, l, t;
	var txt;
	var a, href;
	var res = [];

	l = lnks.length;

	for ( t = 0; t < l; t ++ )
	{
		lnk = lnks [ t ];

		if ( ! lnk.getAttribute ( 'opera' ) && ! lnk.getAttribute ( 'tipolink' ) ) continue;

		txt = lnk.innerHTML;
		href = replace_link_cback ( lnk );

		a = document.createElement ( 'a' );
		a.setAttribute ( 'href', href );
		a.innerHTML = txt;

		res.push ( [ a, lnk ] );
	}

	l = res.length;
	for ( t = 0; t < l; t ++ )
	{
		lnk = res [ t ] [ 1 ];
		lnk.parentNode.replaceChild ( res [ t ] [ 0 ], lnk );
	}
};


LinkReplacer.replace_anchors = function ( el, skip_class_check )
{
	if ( ! el ) el = document;

	var as = el.getElementsByTagName ( "a" );
	var a, l, t;
	var name, href = false;

	l = as.length;

	for ( t = 0; t < l; t ++ )
	{
		a = as [ t ];

		name = a.getAttribute ( 'name' );
		if ( name )
			LinkReplacer._anchors [ name ] = a;

		try {
			href = a.getAttribute ( 'href' );
		} catch ( e ) {
			href = false;
		}

		if ( ! href ) continue;

		if ( ! skip_class_check && a.className != "cds_rif_nota" && a.className != "cds_rimando_nota" ) continue;

		href = href.split ( "#" );
		if ( href.length > 1 && ( ( ! href [ 0 ] ) || href [ 0 ] == ( location.protocol + "//" + location.hostname + location.pathname + location.search ) ) )
		{
			href = href [ 1 ];
			a.setAttribute ( 'href', "javascript:LinkReplacer.scroll('" + href + "')" );
		}
	}
};


LinkReplacer.scroll = function ( name )
{
	var a = LinkReplacer._anchors [ name ];
	if ( ! a )
	{
		var i, l = document.anchors.length;
		for ( i = 0; i < l; i ++ )
		{
			if ( document.anchors [ i ].name == name )
			{
				a = document.anchors [ i ];
				break;
			}
		}
	}
	if ( ! a )
	{
		console.warn ( "Manca l'anchor con NAME '" + name + "'" );
		return;
	}

	var pos = liwe.dom.get_offset_top ( a );

	if ( LinkReplacer.scroll_parent )
	{
		var p2 = liwe.dom.get_offset_top ( LinkReplacer.scroll_parent );
		LinkReplacer.scroll_parent.scrollTop = pos - p2;
	}
	else
		window.scrollTo ( 0, pos );
};


LinkReplacer.set_hl_navi = function ( el, first_el )
{
	if ( ! el ) el = document;

	var spans = el.getElementsByTagName ( "span" );
	var i, l = spans.length;
	var count = 0;
	var h, dest;
	var s_spans = [];
	var l_spans = [];

	for ( i = 0; i < l; i ++ )
	{
		var span = spans [ i ];
		if ( span.className != "highlight" ) continue;

		var p = span.parentNode;
		while ( p )
		{
			if ( p.tagName == "A" )
			{
				span._in_link = p;
				l_spans.push ( span );
				break;
			}

			p = p.parentNode;
		}

		LinkReplacer._anchors [ "_hl_span" + count ] = span;

		s_spans.push ( span );
		count ++;
	}

	l = l_spans.length;
	for ( i = 0; i < l; i ++ )
		LinkReplacer._fix_span_in_link ( l_spans [ i ] );

	for ( i = 0; i < count; i ++ )
	{
		span = s_spans [ i ];

		if ( span._in_link )
			span = span._in_link;

		if ( i > 0 )
		{
			// aggiungo la freccia PRIMA
			h = document.createElement ( "a" );
			h.href = "javascript:LinkReplacer.scroll('_hl_span" + ( i - 1 ) + "')";
			h.innerHTML = '<img border="0" alt="" src="/gfx/ft_prev.gif" style="margin-right: 2px" />';

			span.parentNode.insertBefore(h, span);
		}

		if ( i < count - 1 )
		{
			// aggiungo la freccia DOPO
			h = document.createElement ( "a" );
			h.href = "javascript:LinkReplacer.scroll('_hl_span" + ( i + 1 ) + "')";
			h.innerHTML = '<img border="0" alt="" src="/gfx/ft_next.gif" style="margin-left: 2px" />';

			dest = span.nextSibling;
			if (dest)
				span.parentNode.insertBefore(h, dest);
			else
				span.parentNode.appendChild(h);
		}
	}

	if ( first_el )
	{
		if ( count )
		{
			first_el.innerHTML = '<a href="javascript:LinkReplacer.scroll(\'_hl_span0\')">' +
				'<img alt="Prima occurrenza" border="0" src="/gfx/ft_first.gif" /></a>';
			first_el.style.display = "block";
		}
		else
			first_el.style.display = "none";
	}
};


LinkReplacer._fix_span_in_link = function ( s )
{
	var before = [];

	var lnk = s._in_link;
	while (lnk.childNodes.length > 0)
	{
		var el = lnk.childNodes [ 0 ];

		lnk.removeChild ( el );

		if ( el == s )
			break;
		else
			before.push ( el );
	}

	var a = lnk.cloneNode(false);

	var i, l = before.length;
	for ( i = 0; i < l; i ++ )
		a.appendChild ( before [ i ] );

	lnk.parentNode.insertBefore ( a, lnk );

	a = lnk.cloneNode(false);
	a.appendChild ( s );
	lnk.parentNode.insertBefore ( a, lnk );

	s._in_link = a;
};



var resolve = {};

// Da codice regione a nome opera
resolve.regio_cod2name = function ( cod_reg )
{
	var dct = {
		'01':"Abruzzo",
		'02':"Basilicata",
		'03':"Calabria",
		'04':"Campania",
		'05':"Emilia-Romagna",
		'06':"Friuli-Venezia Giulia",
		'07':"Lazio",
		'08':"Liguria",
		'09':"Lombardia",
		'10':"Marche",
		'11':"Molise",
		'12':"Piemonte",
		'15':"Puglia",
		'16':"Sardegna",
		'17':"Sicilia",
		'18':"Toscana",
		'13':"Trentino-A.A./Bolzano: Provincia autonoma",
		'23':"Trentino-S&uuml;dtirol/Bozen: Autonome Provinz",
		'19':"Trentino-A.A./Trento: Provincia autonoma",
		'20':"Umbria",
		'21':"Valle d'Aosta",
		'22':"Veneto"
	};

	return dct.get ( cod_reg );
};

resolve.regio_opera2name = function ( regio_op )
{
	var dct = {
		'11':"Abruzzo",
		'22':"Basilicata",
		'23':"Trentino-A.A./Bolzano: Provincia autonoma",
		'16':"Calabria",
		'17':"Campania",
		'24':"Emilia-Romagna",
		'25':"Friuli-Venezia Giulia",
		'18':"Lazio",
		'26':"Liguria",
		'03':"Lombardia",
		'21':"Marche",
		'12':"Molise",
		'13':"Piemonte",
		'27':"Puglia",
		'28':"Sardegna",
		'04':"Sicilia",
		'19':"Toscana",
		'02':"Trentino-A.A./Trento: Provincia autonoma",
		'29':"Umbria",
		'30':"Valle d'Aosta",
		'31':"Veneto",
		'32':"Trentino-S&uuml;dtirol/Bozen: Autonome Provinz"
	};

	return dct.get ( regio_op );
};

resolve.regio_opera2cod = function ( regio_op )
{
	var dct = {
		'11' : '01',
		'22' : '02',
		'16' : '03',
		'17' : '04',
		'24' : '05',
		'25' : '06',
		'18' : '07',
		'26' : '08',
		'03' : '09',
		'21' : '10',
		'12' : '11',
		'13' : '12',
		'27' : '15',
		'28' : '16',
		'04' : '17',
		'19' : '18',
		'23' : '13',
		'32' : '23',
		'02' : '19',
		'29' : '20',
		'30' : '21',
		'31' : '22'
	};

	return dct.get ( regio_op );
};


var NaviPath = {};

NaviPath._version = 1;
NaviPath._instances = {};

NaviPath.instance = function ( name )
{
	if ( ! name ) name = "navi_path";

	this.name = name;
	this.templates = {
			'title': '<div id="title_history">%(title)s<\/div>',
			'body':  '<div id="lbl_history">%(body)s<\/div>',

			'f_lnk': '<a href="javascript:NaviPath.onclick(\'%(name)s\',%(pos)s)">%(lbl)s<\/a>'
	};

	this._mem = [];
	this._title = '';
	this._s = '';
	this._dest_div = '';
	this._lock = false;


	this.set_dest_div = function ( dest_div )
	{
		this._dest_div = dest_div;
	};

	this.set_title = function ( title )
	{
		if ( ! title ) return;

		this._title = title;

		this.render ();
	};

	this.add = function ( lbl, params, is_link )
	{
		if ( ! lbl || this._lock ) return;

		this._enabled_prev_link ( true );

		this._add ( lbl, params, is_link );

		this.render ();
	};

	this._add = function ( lbl, params, is_link )
	{
		this._mem.push ( { 'lbl': lbl, 'params': params ? params.clone () : null, 'is_link': is_link } ); 
	};

	this.set = function ( pos, lbl, params, is_link )
	{
		if ( ! lbl || this._lock ) return;

		this._enabled_prev_link ( true );

		this._mem [ pos ] = { 'lbl': lbl, 'params': params ? params.clone (): null , 'is_link': is_link };

		this.render ();
	};

	this.clear = function ()
	{
		this._mem = [];
		this._title = '';
		this._s = '';
	};

	this.truncate = function ( pos )
	{
		this._mem.length = pos;

		this.render ();
	};

	this._truncate = function ( pos )
	{
		this._mem.length = pos;
	};

	this.back = function ()
	{
		var l = this._mem.length;

		if ( ! l || l <= 1 ) return;

		this._mem.length = this._mem.length - 1;

		this.render ();
	};

	this.render = function ( dest_div )
	{
		if ( ! dest_div ) dest_div = this._dest_div;

		if ( ! dest_div || ! $ ( dest_div ) ) return;

		$ ( dest_div ).innerHTML = this._render ();
	};

	this._render = function ()
	{
		this._s = '';

		this._s = this._render_title ();

		this._s += this._render_body ();

		return this._s;
	};

	this._render_body = function ()
	{
		var t, l = this._mem.length;
		var s = '';
		var row = {};

		for ( t = 0; t < l; t ++ )
		{
			row = this._mem [ t ];

			if ( ! row || ! row [ 'lbl' ] ) continue;

			if ( t > 0 ) s += '&nbsp;&raquo;&nbsp;';

			if ( row [ 'is_link' ] )
				s += String.formatDict ( this.templates [ 'f_lnk' ], { name: this.name, pos: t, lbl: row [ 'lbl' ] } );
			else
				s += row [ 'lbl' ];

		}

		if ( s.length > 5 ) s = String.formatDict ( this.templates [ 'body' ], { 'body': s } );

		return s;
	};

	this._render_title = function ()
	{	
		return String.formatDict ( this.templates [ 'title' ], { 'title': this._title } );
	};

	this.onclick = function ( pos )
	{
		if ( ! this._mem [ pos ] ) return;

		var params; 
		
		if ( this._mem [ pos ] [ 'params' ] ) params = this._mem [ pos ].params.clone ();
		else params = null;

		this._truncate ( pos );

		this.click_handler ( params );
	};

	this._enable_link = function ( pos, enable )
	{
		if ( this._mem [ pos ] )
			this._mem [ pos ] [ 'is_link' ] = enable;
	};

	this.enable_link = function ( pos, enable )
	{
		this._enable_link ( pos, enable );

		this.render ();
	};

	this._enabled_prev_link = function ( enable )
	{
		var l = this._mem.length;

		if ( ! l ) return;

		this._enable_link ( l - 1, enable );
	};

	this.is_empty = function ()
	{
		return this._mem.length == 0;
	};

	this.get_status = function ()
	{
		var dict = {};
		var t, l = this._mem.length;
		dict [ 'mem' ] = [];

		dict [ 'title' ] = this._title;

		for ( t = 0; t < l; t ++ )
		{
			dict [ 'mem' ].push ( this._mem [ t ].clone () );
		}

		return dict;
	};

	this.set_status = function ( dict )
	{
		if ( ! dict ) return;
		var res = dict.get ( 'mem', [] );
		var t, l = res.length;
		this._mem = [];

		for ( t = 0; t < l; t ++ )
		{
			this._mem.push ( res [ t ].clone () );
		}

		this._title = dict.get ( 'title' , '' );

		this.render ();
	};

	this.lock = function ( locked )
	{
		this._lock = locked;
	};

	this.elems_num = function ()
	{
		return this._mem.length;
	};


	this.click_handler = function ( params )
	{
		var module = '';

		if ( ! params ) params = {};

		module = params.get ( 'module', '' );
		if ( module != '' ) delete params [ 'module' ];

		if ( ! module ) module = 'home';

		var data = params.get ( "data", "" );
		if ( data != "" ) delete params [ "data" ];

		kernel.go ( module, params, data );
	};


	NaviPath._instances [ this.name ] = this;
};

NaviPath.get = function ( name )
{
	return NaviPath._instances.get ( name, null );
};

NaviPath.onclick = function ( name, pos )
{
	var navi = NaviPath.get ( name );

	if ( ! navi ) return;

	navi.onclick ( pos );
};


var RifNorm = {};

RifNorm._disable_field = function ( field, disabled ) { console.warn ( "RifNorm._disable_field non settato (%s)", field.id ); };

// {{{ fill ( array_dest, key_dest, small ) - Riempie l'array (chiave ``key_dest``) con il rifnorm
RifNorm.fill = function ( a, dest, small )
{
	var rifn;
	var ext = 0;

	if ( $( "NUMCOD_EXT" ) ) ext = $( "NUMCOD_EXT" ).value;
	
	// Se non esiste il campo NUMCOD_CODICE, non sono in modalita' RifNorm
	if ( ! $ ( "NUMCOD_CODICE" ) ) return;

	if ( $ ( "NUMCOD_CODICE" ).disabled || ( ! $( "NUMCOD_CODICE" ).value ) )
	{
		// Modalita' Provvedimento (parte di destra)
		if ( small )
			rifn = RifNorm._small ( 	
						$ ( "NUMCOD_GIORNO" ).value,
						$ ( "NUMCOD_MESE" ).value,
						$ ( "NUMCOD_ANNO" ).value,
						$ ( "NUMCOD_NUMERO" ).value,
						ext,
						$ ( "NUMCOD_ART" ).value
					 );
		else 
			rifn = RifNorm._unico ( $ ( "NUMCOD_PROVV" ).value,
						$ ( "NUMCOD_GIORNO" ).value,
						$ ( "NUMCOD_MESE" ).value,
						$ ( "NUMCOD_ANNO" ).value,
						$ ( "NUMCOD_NUMERO" ).value,
						$ ( "NUMCOD_ART" ).value,
						ext,
						0, // TIPO
						0  // LIVELLO
					 );
	} else {
		// Modalita' codici (parte di sinistra)
		rifn = RifNorm._numcod_codici ( $ ( "NUMCOD_CODICE" ).value,
				       $ ( "NUMCOD_ART" ).value,
				       ext );
	}

	if ( rifn.replace ( /_/g, '' ) != '' ) a [ dest ] = rifn;
};
// }}}
// {{{ fill2 ( array_dest, key_dest, small ) - Riempie l'array (chiave ``key_dest``) con il rifnorm
RifNorm.fill2 = function ( a, dest, small )
{
	var rifn;
	var ext = 0;

	if ( $( "NUMCOD_EXT" ) ) ext = $( "NUMCOD_EXT" ).value;
	
	// Se non esiste il campo NUMCOD_CODICE, non sono in modalita' RifNorm
	if ( ! $ ( "NUMCOD_CODICE" ) ) return;

	if ( $ ( "NUMCOD_CODICE" ).disabled || ( ! $( "NUMCOD_CODICE" ).value && ! $( "NUMCOD_ART" ).value ) )
	{
		if ( ( rifn = RifNorm.nomi_comuni () ) == false )
		{
			// Modalita' Provvedimento (parte di destra)
			if ( small )
				rifn = RifNorm._small ( 	
							$ ( "NUMCOD_GIORNO" ).value,
							$ ( "NUMCOD_MESE" ).value,
							$ ( "NUMCOD_ANNO" ).value,
							$ ( "NUMCOD_NUMERO" ).value,
							ext,
							$ ( "NUMCOD_PROV_ART" ).value
						 );
			else 
				rifn = RifNorm._unico ( $ ( "NUMCOD_PROVV" ).value,
							$ ( "NUMCOD_GIORNO" ).value,
							$ ( "NUMCOD_MESE" ).value,
							$ ( "NUMCOD_ANNO" ).value,
							$ ( "NUMCOD_NUMERO" ).value,
							$ ( "NUMCOD_PROV_ART" ).value,
							ext,
							0, // TIPO
							0  // LIVELLO
						 );
		}
	} else {
		// Modalita' codici (parte di sinistra)
		rifn = RifNorm._numcod_codici ( $ ( "NUMCOD_CODICE" ).value,
				       $ ( "NUMCOD_ART" ).value,
				       ext );
	}

	if ( rifn.replace ( /_/g, '' ) != '' ) a [ dest ] = rifn;
};
// }}}
// {{{ nomi_comuni () - 
RifNorm.nomi_comuni = function ()
{
	var ext, art, ncom;

	// Se non esiste il campo NUMCOD_CODICE, non sono in modalita' RifNorm
	if ( ! $ ( "NUMCOD_NOME_COMUNE" ) ) return false;
	ncom = $( "NUMCOD_NOME_COMUNE" ).value;

	if ( ! ncom ) return false;

	ext = $( "NUMCOD_PROV_EXT" ).value;
	if ( ext )
		ext = String.format ( "%2.2d", ext );
	else
		ext = "__";
	
	art = $ ( "NUMCOD_PROV_ART" ).value
	if ( art )
		art = String.format ( "%4.4d", art );
	else
		art = "____";

	return String.format ( "%s%s%s___", ncom, art, ext );
};
// }}}
// {{{ set_events ( disable_func ) - Setta gli eventi per la abilitare / disabilitare gli input
RifNorm.set_events = function ( disable_func )
{
	if ( disable_func ) RifNorm._disable_field = disable_func;
	// Eventi per ingrigire RifNorm
	$ ( "NUMCOD_CODICE" ).onchange = RifNorm._disable_input;
	$ ( "NUMCOD_PROVV" ).onchange = RifNorm._disable_input;
	if ( $ ( "NUMCOD_EXT" ) ) $ ( "NUMCOD_EXT" ).onchange = RifNorm._disable_input;
	$ ( "NUMCOD_GIORNO" ).onblur = RifNorm._disable_input;
	$ ( "NUMCOD_MESE" ).onblur = RifNorm._disable_input;
	$ ( "NUMCOD_ANNO" ).onblur = RifNorm._disable_input;
	$ ( "NUMCOD_NUMERO" ).onblur = RifNorm._disable_input;
	$ ( "NUMCOD_ART" ).onblur = RifNorm._disable_input;
};
// }}}

// {{{ _small ( gg, mm, aa, num, ext, art )
RifNorm._small = function ( gg, mm, aa, num, ext, art )
{
	var res;

	res = RifNorm._mkdate_long ( gg, mm, aa );
	res += ( num ? String.format ( "%16.16d", parseInt ( num, 10 ) ) : '________________' );
	res += ( art ? String.format ( "%4.4d", parseInt ( art, 10 ) ) : '____' );
	res += ( ext ? String.format ( "%2.2d", parseInt ( ext, 10 ) ) : '__' );

	return res;
};
// }}}
// {{{ _disable_input ()
RifNorm._disable_input = function ()
{
	var cod = $ ( "NUMCOD_CODICE" ).value;
	var provv = $ ( "NUMCOD_PROVV" ).value;
	var gg = $ ( "NUMCOD_GIORNO" ).value;
	var mm = $ ( "NUMCOD_MESE" ).value;
	var aaaa = $ ( "NUMCOD_ANNO" ).value;
	var num  = $ ( "NUMCOD_NUMERO" ).value;

	var dis_provv = $( "NUMCOD_PROVV" ).disabled;
	var dis_cod = $( "NUMCOD_CODICE" ).disabled;

	if ( ! cod && ! provv )
	{
		RifNorm._disable_rifnorm_provv ( false );
		RifNorm._disable_rifnorm_cod ( false );
	}

	if ( cod && ! dis_cod )
	{
		RifNorm._disable_rifnorm_provv ( true );
		RifNorm._disable_rifnorm_cod ( false );
	}
	
	if ( provv && ! dis_provv )
	{
		RifNorm._disable_rifnorm_provv ( false );
		RifNorm._disable_rifnorm_cod ( true );
	}

	if ( gg || mm || aaaa || num )
	{
		RifNorm._disable_rifnorm_cod ( true );
	}
};
// }}}
// {{{ _disable_rifnorm_cod ( mode )
// Disabilita i campi legati al codice
RifNorm._disable_rifnorm_cod  = function ( mode )
{
	RifNorm._disable_field ( $("NUMCOD_CODICE"), mode );
};
// }}}
// {{{ _disable_rifnorm_provv ( mode )
RifNorm._disable_rifnorm_provv = function ( mode )
{
	RifNorm._disable_field ( $("NUMCOD_PROVV"), mode );
	RifNorm._disable_field ( $("NUMCOD_GIORNO"), mode );
	RifNorm._disable_field ( $("NUMCOD_MESE"), mode );
	RifNorm._disable_field ( $("NUMCOD_ANNO"), mode );
	RifNorm._disable_field ( $("NUMCOD_NUMERO"), mode );
};
// }}}
// {{{ _unico ( natura, gg, mm, aaaa, num, art, ext, tipo, liv )
RifNorm._unico = function ( natura, gg, mm, aaaa, num, art, ext, tipo, liv )
{
	var res = '';

	res += ( natura ? String.format ( "%3.3d", natura ) : '___' );

	if ( gg || mm || aaaa )
		res += RifNorm._mkdate_long ( gg, mm, aaaa );
	else
		res += '________';

	res += ( num ?  String.format ( "%16.16d", num ) : '________________' );
	res += ( art ? String.format ( "%4.4d", art ) : '____' );
	res += ( ext ? String.format ( "%2.2d", ext ) : '__' );
	res += ( tipo ? tipo : '_' );
	res += ( liv  ? String.format ( "%2.2d", liv ) : '__' );

	return res;
};
// }}}
// {{{ _numcod_codici ( codice, art, ext )
RifNorm._numcod_codici = function ( codice, art, ext )
{
	var res = '';

	res += ( codice ? String.format ( "%4.4d", codice ) : '____' );
	res += ( art    ? String.format ( "%4.4d", art )    : '____' );
	res += ( ext    ? String.format ( "%2.2d", ext )    : '__' );

	return res;
};
// }}}
// {{{ _mkdate_long ( g, m, a )
RifNorm._mkdate_long = function ( g, m, a )
{
	var res = '';

	g = parseInt ( g, 10 );
	m = parseInt ( m, 10 );
	a = parseInt ( a, 10 );

	if ( a > 0 )
	{
		res += ( a < 1000 ? String.format ( "__%2.2d", a ) : String.format ( "%4.4d", a ) );
	} else
		res += '____';

	res += ( m > 0 ? String.format ( "%2.2d", m ) : '__' );
	res += ( g > 0 ? String.format ( "%2.2d", g ) : '__' );

	return res;
};
// }}}


function Scadenzario ( name, attrs )
{
	var self = this;

	this.name = name;	// Nome dello scadenzario

	this._dest_div = null;

	this.cal = new OS3Calendar ();

	// ==============================================
	// INIT
	// ==============================================

	this.attrs = {
		"show_today" : 	true,
		"width":	"200px",
		"show_days_labels" : true,
		"first_day_of_week" : 1,
		"fire_same_event" : true
	};

	this._cback = {
		"date-selected" : null
	};

	if ( attrs ) attrs.iterate ( function ( v, k ) { self.attrs [ k ] = v } );

	this.cal.cbacks [ 'style_day' ] = function ( day_of_month, month_num, year, original_style, day_of_week )
	{
		return self._cback_style_day ( day_of_month, month_num, year, original_style, day_of_week );
	};

	this.cal.cbacks [ 'date_changed' ] = function ( year, month, day, cal )
	{
		if ( ! self._cback [ 'date-selected' ] ) return;
	
		var dkey = self._mk_key ( year, month, day );
		var v = self._dates.get ( dkey );

		if ( ! v ) return;

		if ( v && v.length == 1 ) v = v [ 0 ];

		self._cback [ 'date-selected' ] ( year, month + 1, day, v );	
	};

	this._apply_attrs ();

	this._dates = {};
}

Scadenzario.prototype.set_event = function ( event_name, func )
{
	event_name = event_name.toLowerCase ();

	switch ( event_name )
	{
		case "date-selected":
			this._cback [ "date-selected" ] = func;
			break;

		default:
			this.cal.cbacks [ event_name ] = func;
	}
};

Scadenzario.prototype._apply_attrs = function ()
{
	this.cal.show_today = this.attrs [ 'show_today' ] ? true : false;
	this.cal.show_days_labels = this.attrs [ 'show_days_labels' ] ? true : false;
	this.cal.first_day_of_week = this.attrs [ 'first_day_of_week' ];
	this.cal.fire_same_event = this.attrs [ 'fire_same_event' ];
};


Scadenzario.prototype._cback_style_day  = function ( day_of_month, month_num, year, original_style, day_of_week )
{
	var dkey = this._mk_key ( year, month_num, day_of_month );
	var v = this._dates.get ( dkey );

	if ( ! v ) return original_style;

	return "selected";
};

Scadenzario.prototype.render = function ( dest_div )
{
	if ( ! dest_div ) dest_div = this._dest_div;
	this._dest_div = dest_div;

	var s = '<div class="scadenzario" style="width: ' + this.attrs.width + '" id="cal:' + this.name + '">';
	$( this._dest_div, s );

	this.cal.render ( "cal:" + this.name );
};

Scadenzario.prototype.add = function ( year, month, day, value )
{
	month = parseInt ( month, 10 ) -1;

	// Calcolo la chiave (data)
	var dkey = this._mk_key ( year, month, day );
	var lst = this._dates.get ( dkey, [] );	// Prendo la lista degli eventi per dkey (o lista vuota)

	// Inserisco il nuovo valore nella lista di dkey
	lst.push ( value );

	// sovrascrivo il valore dkey
	this._dates [ dkey ] = lst;
};

Scadenzario.prototype._mk_key = function ( year, month, day )
{
	return String.format ( "%04.4d-%02.2d-%02.2d", parseInt ( year, 10 ), parseInt ( month, 10 ), parseInt ( day, 10 ) );
};


var newsletter = {};

newsletter.cfg = {};

newsletter._ready = false;

newsletter.cfg [ 'url-registration' ] = "http://reg.leggiditalia.it/Iscrizione.aspx?WKITICKET=&CODCLI=%(codcli)s&CKEY=%(ckey)s&NLNAME=%(_cod_newsletter)s&RETURNURL=%(_url_return)s"
newsletter.cfg [ 'url-newsletter' ] = "http://reg.leggiditalia.it/Iscrizione.aspx?WKITICKET=%(wkiticket)s&CODCLI=%(codcli)s&CKEY=%(ckey)s&NLNAME=%(_cod_newsletter)s&RETURNURL=%(_url_return)s"
newsletter.cfg [ 'url-registration-return' ] = "http://sistemailfisco.leggiditalia.it/cgi-bin/SmartLogin?MODE=REGNL&CODCLI=%(codcli)s&URL=http://sistemailfisco.leggiditalia.it/static/html/newsletter/confermaiscrizione.html";
newsletter.cfg [ 'url-newsletter-return' ] = "http://sistemailfisco.leggiditalia.it/static/html/newsletter/cambioindirizzo.html";
newsletter.cfg [ 'cod-newsletter' ] = 'NLQOLFIS';

newsletter.init = function ( new_registration_url, newsletter_url, return_url )
{
	if ( new_registration_url ) newsletter.cfg [ 'url-registration' ] = new_registration_url;
	if ( newsletter_url) 	    newsletter.cfg [ 'url-newsletter' ]   = newsletter_url;
	if ( return_url ) 	    newsletter.cfg [ 'url-return' ] = return_url;
};

/*
   Questa funzione prepara un link da mandare
   a reg.leggiditalia.it oppure alla pagina
   reale della newsletter, nel caso che l'utente
   risulti gia' registrato.

   Se la richiesta e' stata completata, la variabile
   ``_ready`` viene settata a true.

   Nel caso che ci sia da preparare il link piu' volte (ad es. l'utente
   si logga al sito) specificare il parametro ``force`` == true.

   NB: questa funzione deve essere invocata DOPO la login 
       ed eventualmente rieseguita DOPO che l'utente si e' loggato.
*/
newsletter.prepare_link = function ( force, cback )
{
	if ( ! force && newsletter._ready ) return;

	newsletter._ready = false;
	liwe.AJAX.request ( "/cgi-bin/AjaxCmd", { "command" : "newsletter", "action" : "register" }, 
		function ( v )
		{
			newsletter.ckey   	= v [ 'ckey' ];
			newsletter.codcli 	= v [ 'codcli' ];
			newsletter.login  	= v [ 'login' ];
			newsletter.wkiticket    = v [ 'wkiticket' ];
			newsletter._cod_newsletter = newsletter.cfg [ 'cod-newsletter' ];

			if ( newsletter.wkiticket ) {
				newsletter._url_return = escape ( newsletter.cfg [ 'url-newsletter-return' ] );
				newsletter.url = String.formatDict ( newsletter.cfg [ 'url-newsletter' ], newsletter );
			}
			else {
				if ( newsletter.ckey )
				{
					newsletter._url_return = escape ( String.formatDict ( newsletter.cfg [ 'url-registration-return' ], newsletter ) );
					newsletter.url = String.formatDict ( newsletter.cfg [ 'url-registration' ], newsletter );
				} else { 
					console.error ( "Utente non autenticato" );
					newsletter.url = "";
				}
			}

			newsletter._ready = true;

			if ( cback ) cback ( newsletter );
		}, true );
};


function WWL ( type, instance_name )
{
	this.class_name = "";

	/* REFINE WHEN NEEDED */
	this.to_string = function ()
	{
		var s = '', id;

		s = '<div class="wwl_' + this.type + '"><div id="' + this.id + '" ';

		s += this.mk_events ();

                s += ' class="' + WWL.mk_class_str ( this, ( this._is_disabled ? "disabled" : null ) ) + '">';
		s += this.name;
                s += '</div></div>';

		return s;
	};

	/* DO NOT TOUCH !! */
	this.type = type;
	this.name = instance_name;
	this.id	  = type + ":" + instance_name;

	this._events = {};
	this._is_disabled = false;
	this._dest_id = null;
	this._blocked_events = {};

	this._event_names = [ 'over', 'out', 'btn_up', 'btn_down', 'click', 'dblclick', 'blur' ];

	this.set_event 	  = function ( name, cback ) { this._events [ name ] = cback; };
	this.block_event  = function ( name, mode )  { this._blocked_events [ name ] = mode; };

	this.send_event = function ( evt_name )
	{
		WWL.evt ( null, document.getElementById ( this.id ), evt_name, this );
	};

	this.mk_events = function ()
	{
		var s = '';
		var t, l = this._event_names.length;
		var evt_name, map_name;

		for ( t = 0; t < l; t ++ )
		{
			evt_name = this._event_names [ t ];
			map_name = WWL._event_remap [ evt_name ];
			if ( ! map_name ) map_name = evt_name;

			s += ' on' + map_name + '="return WWL.evt(event,this,\'' + evt_name + '\')" ';
		}

		return s;
	};

	this.disable = function ( is_disabled )
	{
		this._is_disabled = is_disabled;
		this.render ();
	};

	this.render = function ( html_id )
	{
		var s = '', id;
		var el;

		// debugger

		if ( ! html_id ) html_id = this._dest_id;

		if ( html_id )
		{
			// Ho l'id giusto
			this._dest_id = html_id;
			el = document.getElementById ( this._dest_id );

			if ( ! el )
			{
				console.error ( "ERROR: element with id: '" + this._dest_id + "' does not exists" );
				return;
			}
		} else {
			// No HTML ID e no dest_id
			if ( ! this.id )
			{
				console.error ( "ERROR: element %s does not have dest_id or this.id", this.name );
				return;
			}
			el = document.getElementById ( this.id );

			if ( ! el ) return;

			el = el.parentNode;
		}

		el.innerHTML = this.to_string ();
	};

	this.value = function ( new_val )
	{
		var el = document.getElementById ( this.id );
		var old_val = el.value;

		if ( new_val !== undefined )
		{
			if ( new_val != old_val )
			{
				el.value = new_val;
				// WWL.evt ( null, el, 'change', this );
				this.send_event ( 'change' );
			}
		}

		return old_val;
	};

	WWL._instances [ type + ":" + instance_name ] = this;
}

WWL._instances = {};
WWL._int_events = {};
WWL._event_remap = {
			"over"  : "mouseover",
			"out"   : "mouseout",
			"btn_up" : "mouseup",
			"btn_down" : "mousedown"
		   };

WWL.get_instance = function ( type, instance_name )
{
	return WWL._instances [ type + ":" + instance_name ];
};

WWL.evt = function ( evt, div, event_name, widget )
{
	var event_result = null;

	if ( ! widget ) widget = WWL._resolve_widget ( div.id ); // WWL._instances [ div.id ];

	if ( widget._is_disabled ) return false;
	if ( widget._blocked_events [ event_name ] ) return false;

	// widget.className = widget.className ( /evt_[a-zA-Z0-9]*/, "" );
	// div.className = "wwl " + widget.type + " " + widget.class_name;

	// if ( WWL [ widget.type ]._int_events && WWL [ widget.type ]._int_events [ event_name ] ) WWL [ widget.type ]._int_events [ event_name ] ( widget, div, evt );
	if ( widget._events [ "before-" + event_name ] ) event_result = widget._events [ "before-" + event_name ] ( widget, event_name, div, evt );
	if ( widget._int_events && widget._int_events [ event_name ] ) widget._int_events [ event_name ] ( widget, div, evt );
	if ( widget._events [ event_name ] ) event_result = widget._events [ event_name ] ( widget, event_name, div, evt );

	if ( event_result === null ) event_result = true;

	return event_result === null ? true : event_result;
};

WWL._resolve_widget = function ( id_name )
{
	var w = WWL._instances [ id_name ];
	if ( w ) return w;

	var lst = id_name.split ( ":" );
	var name;
	lst.pop ();

	while ( lst.length )
	{
		name = lst.join ( ":" );
		w = WWL._instances [ name ];
		if ( w ) return w;
	}

	return null;
};

WWL.get_char_code = function ( evt )
{
        evt = ( evt ) ? evt : event;

        // if ( evt.charCode < 32 ) return true;
                
        return ( evt.charCode ) ? evt.charCode : ( ( evt.which ) ? evt.which : evt.keyCode );
};

WWL.get_char = function ( evt )
{
	var ccode = WWL.get_char_code ( evt );

	if ( ccode < 32 ) return null;

        return String.fromCharCode ( ccode );
};

// Automagically includes dependencies
// example: WWL.include ( 'button' );
//
// This function requires liwe.js module
WWL.include = function ( module_name )
{
	var wait_str = "WWL." + module_name;

	if ( liwe.utils.is_def ( wait_str ) ) return;

	liwe.utils.append_js ( module_name + ".js" );
};

WWL.mk_class_str = function ( widget, class_name )
{
	var s = ( widget.class_name ? 
			( widget.class_name  + ( class_name ? "_" + class_name : "" ) ) :
			( class_name ? class_name : "" ) );

	return s;
};

WWL._libbase = "";

WWL.set_libbase = function ( libbase_url )
{
	if ( libbase_url )
	{
		WWL._libbase = libbase_url;
		return;
	}

	var scripts = document.getElementsByTagName ( "script" );
	var l = scripts.length;
	var t, s, pos, path = "";

	for ( t = 0; t < l; t ++ )
	{
		s = scripts [ t ].src;

		if ( ! s ) continue;

		if ( s.match ( /wwl.js/ ) )
		{
			pos = s.lastIndexOf ( "/" );
			if ( pos != -1 ) path = s.slice ( 0, pos + 1 );
		}
	}

	if ( path ) WWL._libbase = path;
	else WWL._libbase = "/os3wwl";
};

WWL.set_libbase ();


var OS3Tabs = {};
// OS3Tabs._events = {};
OS3Tabs._int_events = {};
OS3Tabs._instances = {};

OS3Tabs._int_events [ 'hover' ] = function ( tabs, div )
{
	if ( tabs._curr_tab ) tabs._curr_tab.className = ( tabs._curr_tab == tabs._curr_tab_sel ? "sel" : "tab" );
	div.className = "tab_hover";
	tabs._curr_tab = div;
};

OS3Tabs._int_events [ 'out' ] = function ( tabs, div )
{
 	div.className = ( div == tabs._curr_tab_sel ? "sel" : "tab" );
};

OS3Tabs._int_events [ 'btn_down' ] = function ( tabs, div )
{
 	div.className = "btn_down";
};

OS3Tabs._int_events [ 'btn_up' ] = function ( tabs, div )
{
 	div.className = "btn_up";
};

OS3Tabs._int_events [ 'click' ] = function ( tabs, div )
{
	var d = tabs._tabs_ref [ div.id ];

	if ( ! d )
	{
		d = document.getElementById ( tabs._tabs_names_ref [ div.id ] );
		if ( d ) 
			tabs._tabs_ref [ div.id ] = d;
		else
		{
			console.warn ( "OS3Tabs: div: %s does not exist.", tabs._tabs_names_ref [ div.id ] );
			return;
		}
	}

	if ( ( tabs._curr_tab_sel ) && ( tabs._curr_tab_sel == tabs._curr_tab ) ) return;

	if ( tabs._curr_tab_sel ) tabs._curr_tab_sel.className = 'tab';

	tabs._curr_tab_sel = tabs._curr_tab;
	if ( tabs._curr_div_shown ) tabs._curr_div_shown.style.display = 'none';

	d.style.display = 'block';

	tabs._curr_div_shown = d;
	tabs._curr_tab.className = 'sel';
};

/*
This function is the event dispatcher
It takes:
	
	- event_name:	- Name of the event
	- instance	- Name of the instance
	- group_name	- Name of the group which is firing the event
	- pos		- Tab position which is firing the event
*/
OS3Tabs.evt = function ( div, event_name, instance, group_name, pos )
{
	if ( div._disabled ) return;

	var tabs = OS3Tabs._instances [ instance ];

	if ( tabs._blocked_events [ event_name ] ) return;
	if ( OS3Tabs._int_events [ event_name ] ) OS3Tabs._int_events [ event_name ] ( tabs, div );
	if ( tabs._events [ event_name ] ) tabs._events [ event_name ] ( tabs, event_name, div, tabs._curr_div_shown, pos );

	// console.debug ( "Event: %s - instance: %s - group: %s, pos: %d", event_name, instance, group_name, pos );
};

OS3Tabs.instance = function ( prefix )
{
	this._prefix  = prefix;
	this._events  = {}; 
	this._blocked_events = {};		// Events that should not be called
	this._tabs    = { 'default' : [] };
	this._tabs_ref = {};
	this._tabs_names_ref = {};
	this._divs_ref = {};
	this._group_names = [ 'default' ];	// Group names (in order)

	this._curr_group = this._tabs [ 'default' ];
	this._curr_group_name = 'default';

	this.tab_width = 0;
	this.tab_height = 0;

	this.render = function ()
	{
		var t, l = this._group_names.length;
		var grp;
		var s = '', ss;
		var header;
		var style = '';
		var rows = 0;

		for ( t = 0; t < l; t ++ )
		{
			grp = this._tabs [ this._group_names [ t ] ];
			if ( ! grp.length ) continue;
			rows ++;
			s += this._render_grp ( grp, this._group_names [ t ] );
		}

		header = document.getElementById ( this._prefix + '_header' );

		if ( ! header )
		{		
			console.warn ( "OS3Tabs: ERROR: Could not find: %s div for headers", this._prefix + "_header" );
			return;
		}
		if ( this.tab_height ) header.style.height = this._calc_header_height ( rows );

		header.innerHTML = s;
	};

	this._calc_header_height = function ( rows )
	{
		var split = this.tab_height.split ( /(mm|px|pt|ex|em|%)/i );
		if ( split.length < 2 ) return "";

		var v = parseInt ( split [ 0 ] );
		var mis = split [ 1 ];
		var res = ( v * rows ) + mis;

		return res;
	};

	this.set_tab_title = function ( title, group_name, pos )
	{
		var id = this._mk_tab_id ( this._prefix, group_name, pos );
		var d = document.getElementById ( id );

		d.innerHTML = title;
	};

	this.block_event = function ( event_name, mode )
	{
		if ( mode === undefined ) mode = true;
		this._blocked_events [ event_name ] = mode;
	};

	this._render_grp = function ( grp, grp_name )
	{
		var t, l, s = '', events, events_meta, id, style = '';
		var gname;

		l = grp.length;

		s += '<div id="' + this._mk_tab_row_id ( this._prefix, grp_name ) + '" class="row" >';

		if ( this.tab_width ) style += 'width: ' + this.tab_width;

		if ( style ) style = ' style="' + style + '" ';

		events_meta = "'" + this._prefix + "','" + grp_name + "'";
		for ( t = 0; t < l; t ++ )
		{
			events  = "onmouseover=\"OS3Tabs.evt(this,'hover'," + events_meta + "," + t + ")\" ";
			events += "onmouseout=\"OS3Tabs.evt(this,'out'," + events_meta + "," + t + ")\" ";
			events += "onmousedown=\"OS3Tabs.evt(this,'btn_down'," + events_meta + "," + t + ")\" ";
			events += "onmouseup=\"OS3Tabs.evt(this,'btn_up'," + events_meta + "," + t + ")\" ";
			events += "onclick=\"OS3Tabs.evt(this,'click'," + events_meta + "," + t + ")\" ";
			events += "ondblclick=\"OS3Tabs.evt(this,'dblclick'," + events_meta + "," + t + ")\" ";
			id=' id="' + this._mk_tab_id ( this._prefix, grp_name, t ) + '" ';
			s += '<div class="tab" ' + id + events + style + '>' + grp [ t ] + '<\/div>';
		}
		s += '<\/div>';

		return s;
	}

	this._mk_tab_row_id = function ( prefix, grp_name )
	{
		return prefix + ":" + grp_name + ":tab_row";
	};

	this._mk_tab_id = function ( prefix, grp_name, pos )
	{
		return prefix + ":" + grp_name + ":" + pos;
	};

	this.set_event = function ( evt_name, cback )
	{
		this._events [ evt_name ] = cback;
	};

	this.clear = function ()
	{
		this._tabs    = { 'default' : [] };
		this._tabs_ref = {};
		this._tabs_names_ref = {};
		this._divs_ref = {};
		this._group_names = [ 'default' ];	// Group names (in order)
		this._curr_group = this._tabs [ 'default' ];
		this._curr_group_name = 'default';
	};

	// {{{ set_group ( group_name )
	this.set_group = function ( group_name )
	{
		if ( ! this._tabs [ group_name ] )
		{
			this._group_names.push ( group_name );
			this._tabs [ group_name ] = [];
		}

		this._curr_group = this._tabs [ group_name ];
		this._curr_group_name = group_name;
	};
	// }}}
	// {{{ add ( title, div_name )
	this.add = function ( title, div_name )
	{
		var pos = this._curr_group.length;
		var id = this._mk_tab_id ( this._prefix, this._curr_group_name, pos );

		this._curr_group.push ( title );
		this._tabs_ref [ id ] = null; // document.getElementById ( div_name );
		this._tabs_names_ref [ id ] = div_name;

		this._divs_ref [ div_name ] = id;
	};
	// }}}

	this.send_event = function ( div_name, evt )
	{
		var id = this._divs_ref [ div_name ];
		var div = document.getElementById ( id );

		this._curr_tab = div;
		OS3Tabs.evt ( div, evt, this._prefix );
	};

	this.enable_tab = function ( div_name, enable )
	{
		var id = this._divs_ref [ div_name ];
		var div = document.getElementById ( id );

		if ( ! div [ "_disabled" ] && enable ) return;
		if ( div [ "_disabled" ] && ! enable ) return;

		if ( enable )
		{
			div._disabled = false;
			div.className = "tab";
		}
		else
		{
			div._disabled = true;
			div.className = "disabled";
		}
	};


	OS3Tabs._instances [ this._prefix ] = this;
};




WWL.calendar = function ( name, attrs )
{
	var cal = new WWL ( 'calendar', name );

	if ( ! attrs ) attrs = {};

	cal._calendar = new OS3Calendar ();
	cal._calendar.is_popup = true;
	cal._hour = "0";
	cal._min  = "0";

	cal.set_event = function ( evt_name, cback )
	{
		cal._calendar.cbacks [ evt_name ] = cback;
	};

	cal.set_date = function ( year, month, day, hour, minutes ) 
	{
		var undef;

		cal._calendar.set_date ( year, month, day ); 

		if ( hour === undef ) return;

		cal._hour = hour;
		cal._min  = minutes;
	};

	cal.get_date = function () { return cal._calendar.curr_date; };

	cal.form = new liwe.form.instance ( cal.id );
	cal.form.number ( { name: "gg", size: 2, nonl: true, onblur: "WWL.calendar._update_date('" + name + "')" } );
	cal.form.number ( { name: "mm", size: 2, nonl: true, onblur: "WWL.calendar._update_date('" + name + "')" } );
	cal.form.number ( { name: "aaaa", size: 4, nonl: true, onblur: "WWL.calendar._update_date('" + name + "')" } );
	cal.form.button ( { value: "&nbsp;", "class": "os3calendar_button", onclick: "WWL.calendar.popup(this,'" + name + "')" } );

	if ( attrs.get ( "time", 0 ) )
	{
		var d = new Date ();
		cal._hour = d.getHours ();
		cal._min  = d.getMinutes ();

		cal.form.number ( { label: "Ora", name: "hour", size: 2, nonl: true, value: cal._hour } );
		cal.form.number ( { name: "min", size: 2, value: cal._min } );
		
		cal._support_time = true;
	}

	cal.form.workspace ( { name: "cal:" + cal.id } );

	cal.to_string = function ()
	{
		return cal.form.get ();
	};

	cal.set_day = function ( dd )
	{
		cal.form.set_value ( "gg", dd );
	};

	cal.set_month = function( mm )
	{
		cal.form.set_value ( "mm", mm );
	};

	cal.set_year = function ( yyyy )
	{
		cal.form.set_value ( "aaaa", yyyy );
	};

	cal.set_time = function ( hh, mm )
	{
		if ( ! cal._support_time ) return;

		if ( hh !== undefined )
		{
			cal._hour = hh;
			cal._min  = mm;
		}

		cal.form.set_value ( "hour", cal._hour );
		cal.form.set_value ( "min", cal._min );
	};

	return cal;
};

WWL.calendar.popup = function ( elem, cal_id )
{
	var cal = WWL.get_instance ( "calendar", cal_id );

	cal._calendar.render ( "cal:" + cal.id );

	if ( cal._calendar.currently_shown )
		cal._calendar.hide ();
	else
		cal._calendar.show ( elem );

};

WWL.calendar._update_date = function ( cal_id )
{
	var cal = WWL.get_instance ( "calendar", cal_id );
	var vals = cal.form.get_values ();

	cal._calendar.set_date ( vals [ 'aaaa' ], vals [ 'mm' ], vals [ 'gg' ] );
	cal.set_value ( "hour", cal._hour ); //.set_date ( vals [ 'aaaa' ], vals [ 'mm' ], vals [ 'gg' ] );
	cal.set_value ( "min", cal._min ); //.set_date ( vals [ 'aaaa' ], vals [ 'mm' ], vals [ 'gg' ] );
};


/*
 * os3calendar.js
 *
 * Copyright (C) 2006 - 2010 - OS3 srl - http://www.os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
// Since Internet Exploder has some bugs, we have to work
// around them (by simply removing some features from the
// calendar for Exploders users: switch to Firefox!)
var os3cal_is_exploder = ( document.all ? true : false );

var OS3CAL_LOCALE = 
			{
				months: Array ( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ),
				days: Array ( 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ),
				today: 'Today'
			};

/*
	CALLBACKS
*/
function os3cal_cback_set_day ( id, day, month, year )
{
	var cal = _os3_cals [ id ];

	cal.set_date ( year, month +1, day );

	if ( cal.is_popup ) cal.hide ();
}

/*
	PUBLIC FUNCTIONS
*/
var _os3_cals = new Array ();

function os3cal_register ( id, cal )
{
	_os3_cals [ id ] = cal;
}

function os3cal_add_month ( id, delta )
{
	var cal = _os3_cals [ id ];

	cal.cur_date.setMonth ( cal.cur_date.getMonth () + delta );
	cal._set_vals ( false );
	cal.render ();
}

function os3cal_today ( id )
{
	var cal = _os3_cals [ id ];
	var d = new Date ();
	var y = d.getYear ();

	if ( y < 1900 ) y += 1900;

	if ( cal.set_date ( y, d.getMonth() + 1,  d.getDate (),  false ) == false ) cal.render ();
}

function os3cal_year_select ( id )
{
	os3cal_int_hide ( id, "year", "cur_year" );
}

function os3cal_year_changed ( input, id )
{
	var cal = _os3_cals [ id ];

	if ( cal.set_date ( input.value, cal.cur_month, cal.cur_day, true ) == false ) cal.render ();
}

function os3cal_month_select ( id )
{
	var cal = _os3_cals [ id ];

	if ( ! cal.cbacks [ 'month-clicked' ] )
		os3cal_int_hide ( id, "month", "cur_month" );
	else
		cal.cbacks [ 'month-clicked' ] ( cal );
}

function os3cal_int_hide ( id, inp, val )
{
	var cal = _os3_cals [ id ];
	var div1 = document.getElementById ( id + "_" + inp + "_label" );
	var div2 = document.getElementById ( id + "_" + inp + "_select" );
	var input = document.getElementById ( id + "_" + inp + "_sel" );
	var s, t;

	div1.className += " hidden";
	div2.className = "month";

	input.value = cal [ val ];
	input.focus ();
}

function os3cal_month_changed ( input, id )
{
	var cal = _os3_cals [ id ];

	if ( cal.set_date ( cal.cur_year, input.value, cal.cur_day, true ) == false ) cal.render ();
}


/*  
	METHODS
*/

function os3cal_set_date ( year, month, day, quiet )
{
	var selected = true;

	year  = parseInt ( year, 10 );
	month = parseInt ( month, 10 ) -1;
	day   = parseInt ( day, 10 );

	if ( ( year <= 0 ) || ( month <= -1 ) || ( day <= 0 ) ) return false;
	if ( ( year == this.cur_year ) && ( month == this.cur_month ) && ( day == this.cur_day ) && ( ! this.fire_same_event ) ) 
	{
		if ( this.cbacks [ 'onclick' ] ) this.cbacks [ 'onclick' ] ( year, month, day, this );
		return false;
	}

	if ( quiet ) selected = false;

	this.cur_date = new Date ( year, month, day );
	this._set_vals ( selected );


	if ( this.currently_shown && this.cbacks [ 'date_changed' ] && selected ) 
		this.cbacks [ 'date_changed' ] ( year, month, day, this );

	return true;
}

function os3cal_get_header () 
{
	var s = '';
	var t;

	s += '<table border="0" cellpadding="0" cellspacing="0">';
	s += '<tr><td style="padding-right: 3px;">';
	s += '<div id="' + this.id + '_month_label" class="month" onclick="os3cal_month_select(\'' + this.id + '\')">';
	s += OS3CAL_LOCALE [ 'months' ] [ this.cur_month ];
	s += '<\/div>';
	s += '<div id="' + this.id + '_month_select" class="month hidden">';

	s += '<select id="' + this.id + '_month_sel" class="month_select" ';
	s += 'onblur="os3cal_month_changed(this, \'' + this.id + '\')" ';
	if ( ! os3cal_is_exploder ) s += 'onchange="os3cal_month_changed( this, \'' + this.id + '\')" ';
	s += '>';

	for ( t = 0; t < 12; t ++ )
	{
		s += '<option value="' + t + '">' + this.month_label [ t ] + '<\/option>';
	}

	s += '<\/select><\/div>';
	s += '<\/td><td>';

	s += '<div id="' + this.id + '_year_label" class="month" onclick="os3cal_year_select(\'' + this.id + '\')">';
	s += this.cur_year + '<\/div>';
	s += '<div id="' + this.id + '_year_select" class="month hidden">';
	s += '<input id="' + this.id + '_year_sel" type="text" size="4" maxlength="4" class="year_select" ';
	s += 'onchange="os3cal_year_changed(this,\'' + this.id + '\')" ';
	s += '/><\/div>';
	s += '<\/td><\/tr>';
	s += '<\/table>';
	return s; 
}

function os3cal_to_string ()
{
	var first_date = new Date ( this.cur_year, this.cur_month, 1 );
	var first_day  = first_date.getDay() +1;
	var rows = 5;
	var s = new String.buffer ();

	first_day -= this.first_day_of_week;
	if ( first_day <= 0 ) first_day = 7 - first_day;

	os3cal_register ( this.id, this );

   	if ( ( ( this.days_in_month [ this.cur_month ] == 31 ) && ( first_day >= 6 ) ) ||
       	     ( ( this.days_in_month [ this.cur_month ] == 30 ) && ( first_day == 7 ) ) ) rows = 6;
   	else if ( ( this.days_in_month [ this.cur_month ] == 28) && ( first_day == 1)) rows = 4;

	s.add ( '<div id="os3cal_' + this.id + '" class="os3calendar">' );
	s.add ( this._render_header () );
	s.add ( this._render_days ( first_day, rows ) );
	s.add ( '<\/div>' );

	return s.toString ();
}

function os3cal_render ( objId )
{
	if ( ! objId ) objId = this.id;
	this.id = objId;

	if ( ! this.id ) return;

	var obj = document.getElementById ( this.id );

	if ( this.is_popup && this.currently_shown == false ) 
		obj.style.display = 'none';
	else
		this.currently_shown = true;

	obj.innerHTML = this.toString ();
}

function os3cal_meth_show ( base_element )
{
	if ( this.is_popup && ( this.currently_shown == false ) ) 
	{
		var e = document.getElementById ( this.id );

		if ( base_element )
		{
			var top, left, width, nleft;

			left  = liwe.dom.get_offset_left ( base_element );
			top   = liwe.dom.get_offset_top ( base_element );

			e.style.position = 'absolute';

			e.style.display = 'block';
			width = e.offsetWidth;
			e.style.display = 'none';

			nleft = left - ( width / 2 );
			if ( nleft < 5 ) nleft = 5;

			e.style.left = nleft + "px";

			// if ( base_element.offsetHeight )
				// e.style.top = top + base_element.offsetHeight + "px";
			// else
				e.style.top = top + "px";

			e.style.display = 'block';
		} else
			e.style.display = 'block';
	}

	this.currently_shown = true;
}

function os3cal_meth_hide ()
{
	if ( this.is_popup && this.currently_shown ) 
		document.getElementById ( this.id ).style.display = 'none';

	this.currently_shown = false;
}


function os3cal_int_render_days ( first_day, rows )
{
	var sunday_col = 8 - this.first_day_of_week;
	if ( sunday_col == 0 ) sunday_col = 1;

   	var day_counter = 1;
   	var loop_counter = 1;
	var j, i;
	var s = '';
	var style, cback;

	s = '<div align="center" class="days"><table border="0" cellpadding="0" cellspacing="0">';
	
	// Add days labels
	if ( this.show_days_labels )
	{
		s += '<tr>';
		for ( j = this.first_day_of_week; j < this.first_day_of_week + 7; j ++ )
		{
			var x = j % 7;
			s += '<td class="days_label">' + this.days_label [ x ] + '<\/td>';
		}
		s += '<\/tr>';
	}

	// alert ( 'day: ' + this.selected_day + ' - month: ' + this.selected_month + ' - year: ' + this.selected_year );

   	for ( j = 1; j <= rows; j++) 
	{
      		s += '<tr>';
      		for ( i = 1; i < 8; i++ ) 
		{
         		if ( ( loop_counter >= first_day ) && ( day_counter <= this.days_in_month [ this.cur_month ] ) ) 
			{
            			if ( ( day_counter == this.selected_day ) && ( this.selected_year == this.cur_year) && ( this.selected_month == this.cur_month)  ) style = 'today';
				else if ( i != sunday_col )
					style = 'day' + ( i % 2 );
				else
					style = 'sunday';

				if ( this.cbacks [ 'style_day' ] ) style = this.cbacks [ 'style_day' ] ( day_counter, this.cur_month, this.cur_year, style, i );
				cback = 'javascript:os3cal_cback_set_day ( \'' + this.id + '\', ' + day_counter + ',' + this.cur_month + ',' + this.cur_year + ')"';
               			s += '<td class="' + style + '"><a href="' + cback + '">' + day_counter + '<\/a><\/td>';
            			day_counter ++;    
         		} else s += '<td>&nbsp;<\/td>';
			loop_counter ++;
         	}
		s += '<\/tr>';

         	loop_counter ++;
      	}
	
	return s + '<\/table><\/div>';
}

function os3cal_int_render_header ()
{
	var s = '';

	s  = '<div class="header">';
	s += '<table border="0" width="100%%"><tr><td align="left" valign="top">';
	s += '<a href="javascript:os3cal_add_month(\'' + this.id + '\', -1 );">&lt;&lt;<\/a><\/td>';
	s += '<td width="100%%">';
	s += this.get_header();
	s += '<\/td><td align="right" valign="top">';
	if ( this.show_today ) s += '<a href="javascript:os3cal_today(\'' + this.id + '\');">' + OS3CAL_LOCALE [ 'today' ] + '<\/a>&nbsp;';
	s += '<a href="javascript:os3cal_add_month(\'' + this.id + '\',  1 );">&gt;&gt;<\/a>&nbsp;';
	s += '<\/td><\/tr><\/table>';
	s += '<\/div>';
	return s;
}

function int_calc_offset_left ( base_elem, v )
{
	if ( ! base_elem.offsetParent ) return  ( v );
	if ( ( ! base_elem.offsetParent.offsetParent ) && ( base_elem.parentNode.nodeName != 'BODY' ) ) return ( v );
	return int_calc_offset_left ( base_elem.offsetParent, v + base_elem.offsetLeft );
}

function int_calc_offset_top ( base_elem, v )
{
	if ( ! base_elem.offsetParent ) return  ( v );
	if ( ( ! base_elem.offsetParent.offsetParent ) && ( base_elem.parentNode.nodeName != 'BODY' ) ) return ( v );
	return int_calc_offset_top ( base_elem.offsetParent, v + base_elem.offsetTop );
}

function os3cal_int_set_vals ( set_selected )
{
	var d, m, y;
	m = this.cur_date.getMonth ();
	y = this.cur_date.getYear ();
	d = this.cur_date.getDate ();

	if ( ( d == this.cur_day ) && ( m == this.cur_month ) && ( y == this.cur_year ) ) return;

	this.cur_month = m;
	this.cur_year = y;
	this.cur_day = d;

	if ( this.cur_year < 1000 ) this.cur_year += 1900;

   	if ( this.cur_month == 1) this.days_in_month [ 1 ] = ( ( this.cur_year % 400 == 0) || (( this.cur_year % 4 == 0 ) && ( this.cur_year % 100 !=0))) ? 29 : 28;

	if ( set_selected == true )
	{
		// Selected date splitted.
		this.selected_day = this.cur_day;
		this.selected_month = this.cur_month;
		this.selected_year  = this.cur_year;
	}

	if ( this.cbacks [ 'date_shown' ] ) this.cbacks [ 'date_shown' ] ( this.cur_year, this.cur_month + 1, this.cur_day, this );
	if ( this.currently_shown ) this.render ();
}

function OS3Calendar ()
{
	this.id = null;

	this.days_in_month = new Array ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
	this.month_label = OS3CAL_LOCALE [ 'months' ];
	this.days_label  = OS3CAL_LOCALE [ 'days' ];

	this.show_today = true;
	this.fire_same_event = false;

	this.cbacks = {
		// This cb is called each time the user "clicks" on a date
		"date_changed" : null,

		// This cb is called for each day that is rendered and it is used to define the
		// style the day must have
		// the callback prototype must be as the following:
		// 	function cback ( day_of_month, month_num, year, original_style, day_of_week )
		//
		// 	if  day_of_week == 1 it is sunday
		// the function must return a valid style string name (eg. "selected")
		"style_day" : null,

		// This cb is called each time the user changes the month viewed on the calendar
		"date_shown" : null,

		// This cb is called every time a day is clicked
		"onclick" : null,

		// This cb is called every time the user clicks on the calendar's month label
		"month-clicked" : null
	};

	// =====================================================================================
	// PRIVATE STUFF
	// =====================================================================================
	this.currently_shown = false;	// Flag T/F. If T, the calendar is currently being shown


	// =====================================================================================
	// PUBLIC ATTRS
	// =====================================================================================
	this.is_popup = false;		// Flag T/F. If T, this calendar is a popup
	this.show_days_labels = true;	// Flag T/F. If T, days names are shown
	this.first_day_of_week = 0;	// 0 -> Sunday

	// Date shown inside the calendar
	this.cur_date = new Date();

	// =====================================================================================
	// PUBLIC METHODS
	// =====================================================================================
	this.get_header = os3cal_get_header;
	this.set_date   = os3cal_set_date;
	this.render     = os3cal_render;
	this.show	= os3cal_meth_show;
	this.hide	= os3cal_meth_hide;
	this.toString   = os3cal_to_string;

	
	// =====================================================================================
	// PRIVATE METHODS - DO NOT USE IN PRODUCTION CODE!!
	// =====================================================================================
	this._render_days = os3cal_int_render_days;
	this._render_header = os3cal_int_render_header;
	this._set_vals  = os3cal_int_set_vals;

	// =====================================================================================
	// INIT PROCEDURE
	// =====================================================================================

	this._set_vals ( true );
}


//{{{ FulQuery ()
function FulQuery ()
{
	this.mode = '';
	this.db_name = '';
	this.resource = '';
	this.order_by = '';
	this.group_by = '';
	this.highlight = false;
	this.opera = '';

	// <VerQuery specific>
	this.bucket = '';
	this.buckets = '';
	// </VerQuery specific>

	this.lines = 10;
	this.page  = 0;

	this.clear 	= fulquery_clear;
	this.add	= fulquery_add;
	this.query	= fulquery_query;
	this.add_date	= fulquery_add_date;
	this.del	= fulquery_del;
	this.fill 	= fulquery_fill;
	this.set_fields = fulquery_set_fields;
	this.set_fields_by_list = fulquery_set_fields_by_list;

	this.set_id 	= fulquery_set_id;

	this._conds = [];
	this._fields = null;
	this._doc_text = '';
	this._id1 = '';
	this._id2 = '';
	this._query_full = '';

	// Variabili di supporto per il Multi Query
	this._multi = [];
}
//}}}
//{{{ fulquery_clear ()
function fulquery_clear ()
{
	this.mode = '';
	this.db_name = '';
	this.order_by = '';
	this.group_by = '';
	this.resource = '';
	this.highlight = false;
	this.page = 0;
	this.lines = 10;

	this._conds  = [];
	this._fields = [];
	this._doc_text = '';
	this._id1 = '';
	this._id2 = '';
}
//}}}
//{{{ fulquery_add ( field, mode, value, db_field, prepend, append, base )
/*
	field		-> nome del campo (es. "NATURA")
	mode		-> modalita' di ricerca (es. "IN_STR")
	value		-> valore da ricercare ( es. 'L.|D.Lgs.|DM.' )
	db_field	-> campo del db associato al field (di default == field, es. "DATAGU")
	prepend		-> stringa da prependere al valore 
	append		-> stringa da appendere al valore
	base		-> base dei campi data [NOTA: solo per campi data] (es. "GU" per "GUGIORNO1" ... )
*/
function fulquery_add ( field, mode, value, db_field, prepend, append, base )
{
	mode = mode.toUpperCase ();
	this._conds.push ( [ field, mode, value, db_field, prepend, append, base ] );

	if ( field.toUpperCase () == 'DOCUMENT_TEXT' )
		this._doc_text = value;
}
//}}}

function fulquery_query ( sql )
{
	this._query_full = sql;
}

//{{{ fulquery_add_date ( anno1, mese1, giorno1, anno2, mese2, giorno2, db_field, prepend, append, base )
function fulquery_add_date ( anno1, mese1, giorno1, anno2, mese2, giorno2, db_field, prepend, append, base )
{
	if ( ! base ) base = "";
	this._conds.push ( [ base + "ANNO1", "DATA", anno1, db_field, prepend, append, base ] );
	this._conds.push ( [ base + "MESE1", "DATA", mese1, db_field, prepend, append, base ] );
	this._conds.push ( [ base + "GIORNO1", "DATA", giorno1, db_field, prepend, append, base ] );
	this._conds.push ( [ base + "ANNO2", "DATA", anno2, db_field, prepend, append, base ] );
	this._conds.push ( [ base + "MESE2", "DATA", mese2, db_field, prepend, append, base ] );
	this._conds.push ( [ base + "GIORNO2", "DATA", giorno2, db_field, prepend, append, base ] );
}
//}}}
//{{{ fulquery_del
function fulquery_del ( field )
{
	var i, l = this._conds.length;
	for ( i = 0; i < l; i ++ )
	{
		if ( this._conds [ i ] [ 0 ] == field )
		{
			this._conds.splice ( i, 1 );
			break;
		}
	}
}
//}}}
//{{{ fulquery_fill ( dst )
function fulquery_fill ( dst, prefix )
{
	var t, l;
	var cond;
	var s = '';

	if ( ! prefix ) 
		prefix = "";
	else
		this._multi.push ( prefix );


	if ( ! this.opera )
	{
		console.error ( "[FulQuery]: manca l'opera !!!" );
		alert ( "[FulQuery]: manca l'opera !!!" );
		return;
	}

	// FIX: add prefix in already added fields
	if ( prefix )
	{
		var dst2 = dst.clone ();
		dst2.iterate ( function ( v, k ) { dst [ prefix + k ] = v; delete dst [ k ]; } );
	}
	// END FIX

	l = this._conds.length;

	for ( t = 0; t < l; t ++ )
	{
		cond = this._conds [ t ];
		
		dst [ prefix + cond [ 0 ] ] = cond [ 2 ];
		dst [ prefix + "_M_" + cond [ 0 ] ] = cond [ 1 ];

		if ( cond [ 3 ] ) dst [ prefix + "_F_" + cond [ 0 ] ] = cond [ 3 ];
		if ( cond [ 4 ] ) dst [ prefix + "_P_" + cond [ 0 ] ] = cond [ 4 ];
		if ( cond [ 5 ] ) dst [ prefix + "_A_" + cond [ 0 ] ] = cond [ 5 ];
		if ( cond [ 6 ] ) dst [ prefix + "_B_" + cond [ 0 ] ] = cond [ 6 ];
	}

	if ( ! this._fields ) this._fields = [];
	l = this._fields.length;
	for ( t = 0; t < l; t ++ )
	{
		if ( ! this._fields [ t ] ) continue;
		s += this._fields [ t ] + ":";
	}

	s = s.substr ( 0, s.length -1 );

	dst [ prefix + '_X_SEARCH_FIELDS' ] = s;
	dst [ prefix + '_X_MODE' ] = this.mode;
	dst [ prefix + '_X_LINES' ] = this.lines;
	dst [ prefix + '_X_PAGE' ] = this.page;
	dst [ prefix + '_X_DBNAME' ] = this.db_name;
	dst [ prefix + '_X_RESOURCE' ] = this.resource;
	dst [ prefix + '_X_FULL' ] = this._query_full;
	dst [ prefix + '_X_OPERA' ] = this.opera;

	if ( this.bucket ) dst [ prefix + '_X_BUCKET' ] = this.bucket;
	if ( this.buckets ) dst [ prefix + '_X_BUCKETS' ] = this.buckets;

	if ( this._id1 )
	{
		dst [ prefix + '_X_ID1' ] = this._id1;
		dst [ prefix + '_X_ID2' ] = this._id2;
	}

	if ( this.order_by ) dst [ prefix + '_X_ORDER_BY' ] = this.order_by;
	if ( this.group_by ) dst [ prefix + '_X_GROUP_BY' ] = this.group_by;
	if ( this.highlight && this._doc_text ) dst [ prefix + '_X_HIGHLIGHT' ] = this._doc_text;

	// Se multi e' settato, aggiungo _X_MULTI
	if ( this._multi.length ) dst [ '_X_MULTI' ] = ':'.join ( this._multi );

	// Cancello i dati in memoria
	if ( prefix ) this.clear ();
}
//}}}
//{{{ fulquery_set_fields ()
function fulquery_set_fields ()
{
	this._fields = arguments;
}
//}}}
// {{{ fulquery_set_fields_by_list ( lst )
function fulquery_set_fields_by_list ( lst )
{
	this._fields = lst; //.clone ();
}
// }}}

function fulquery_set_id ()
{
	var d = new Date ();
	
	this._id1 = d.getTime ().toString ();
	this._id2 = MD5.hex_md5 ( this._id1 );
}


modules.home = {};

modules.home._coupon_lnk =  'http://el.leggiditalia.it/studiolegale/coupon/';	

//{{{ desk_leg_array
modules.home.desk_leg_array = [
        {
                title: 'G.U. del giorno',
                img: 'gfx/gu_icon.png',
                abbr: 'gu',
                onclick: "",
                link: "javascript:kernel.go({mask:'frame',page:'http://el.leggiditalia.it/gu/'})",
                link_coupon: "javascript:kernel.go({mask:'frame',page:'http://el.leggiditalia.it/gu/'})"
        },
        {
                title: 'Calcolo interessi',
                img: 'gfx/calc_icon.png',
                abbr: 'calc',
                onclick: "",
                link: "javascript:kernel.go({mask:'frame',page:'http://tools.wki.it/CalcInteressiMain.aspx[SSCKEY=%(ssckey)s&CKEY=%(ckey)s&SITO=studiolegale.leggiditalia.it&TITOLO=Studio-Legale'})",
                //link: "javascript:alert('Funzionalit&agrave; di prossima pubblicazione')",
                link_coupon: "javascript:kernel.go({mask:'frame',page:'" + modules.home._coupon_lnk + "'})"
        },
        {
                title: 'Parcellazione forfettaria',
                img: 'gfx/parcel_icon.png',
                abbr: 'parc',
                onclick: "",
                link: "javascript:kernel.go({mask:'frame',page:'http://tools.wki.it/CalcParcMain.aspx[SSCKEY=%(ssckey)s&CKEY=%(ckey)s&SITO=studiolegale.leggiditalia.it&TITOLO=Studio-Legale'})",
                //link: "javascript:alert('Funzionalit&agrave; di prossima pubblicazione')",
                link_coupon: "javascript:kernel.go({mask:'frame',page:'" + modules.home._coupon_lnk + "'})"
        },
        {
                title: 'Polis Web',
                img: 'gfx/polis_icon.png',
                abbr: 'polis',
                onclick: "window.open('http://tools.wki.it/PolisWeb.aspx?SSCKEY=%(ssckey)s&CKEY=%(ckey)s&SITO=studiolegale.leggiditalia.it&TITOLO=Studio-Legale','_blank','top=100,left=100,scrollbars=0,width=365,height=160,resizable=0,toolbar=0,menubar=0',true);",
                //onclick: "javascript:alert('Funzionalit&agrave; di prossima pubblicazione')",
                link: "javascript:void(0)",
                link_coupon: "javascript:kernel.go({mask:'frame',page:'" + modules.home._coupon_lnk + "'})"
        },
        {
                title: 'G.U. del giorno',
                img: 'gfx/gu_icon.png',
                abbr: 'gu',
                onclick: "",
                link: "javascript:kernel.go({mask:'frame',page:'http://el.leggiditalia.it/gu/'})",
                link_coupon: "javascript:kernel.go({mask:'frame',page:'http://el.leggiditalia.it/gu/'})"
        },
	{
                title: 'Altri servizi',
                img: 'gfx/serv_icon.png',
                abbr: 'serv',
                onclick: "",
                link: "javascript:kernel.go({mask:'static',page:'desklegale/APutil.htm'})",
                link_coupon: "javascript:kernel.go({mask:'static',page:'desklegale/APutil.htm'})"
        }
        /*,
        {
                title: 'ITER',
                img: 'gfx/polis_icon.png',
                abbr: 'polis',
                onclick: "",
                link: "/iter.html?URL=http://iter.leggiditalia.it/default.aspx?BRAND=leggiditalia&SSCKEY=%(ssckey)s&CKEY=%(ckey)s&SITO=studiolegale.leggiditalia.it&TITOLO=Studio-Legale",
                link_coupon: "javascript:void(0)"
        }*/
];
//}}}


modules.home.init = function ( dict, data )
{
	var mask = dict.get ( "mask" );

	var mname = dict.get ( "menu_name" );

	switch ( mask )
	{
		case "static":
			if ( mname ) site.select_menu ( mname );	
			modules.home.load_static ( dict [ "file" ] );
			break;

		case "frame":
			modules.home.show_frame ( dict [ "url" ] );
			break;

		case "scad":
			modules.home.show_scad ( dict [ "gg" ], dict [ "mm" ], dict [ "aa" ] );
			break;

		default:
			site.select_menu ( 'home' );
			site.set_mask ( "cont" );

			modules.home.show_tabs ();
			modules.home.show_rivista ();
			site.show_warn ();
			break;
	}
};




modules.home.load_static = function ( page )
{
	utils.get_file ( '/static/' + page + ".html", function ( v )
	{
		v = utils.strip_html_body ( v );
		v = LinkReplacer.lnk2span ( v );
		$( "cont3" ).innerHTML = v;

		LinkReplacer.replace ( site.link_replace );
	
		var lnks = $ ( "cont3" ).getElementsByTagName ( "a" );
		var lnk, t, l = lnks.length;

		for ( t = 0; t < l; t ++ )
		{
			lnk = lnks [ t ];

			if ( lnk.href.indexOf ( "static/pdf/" ) < 0 ) continue;

			lnk.setAttribute ( "target", "_blank" );
		}

		site.set_mask ( "cont3" );
	});
};


modules.home.show_frame = function ( url )
{
	$ ( "main_frame" ).src = url;
	site.set_mask ( "cont2" );
};


modules.home._tabs = null;
modules.home.show_tabs = function ()
{
	if ( modules.home._tabs ) return;

	var t = modules.home._tabs = new OS3Tabs.instance ( "qol_tab" );
	t.set_event ( "hover", modules.home._tab_hover );
	t.set_event ( "btn_down", modules.home._tab_hover );
	t.set_event ( "btn_up", modules.home._tab_hover );

	t.add ( "NOTIZIE FLASH", "qol_tab1" );
	t.add ( "ATTUALIT&Agrave;", "qol_tab2" );
	t.add ( "GIURISPRUDENZA", "qol_tab3" );
	t.add ( "RASSEGNA STAMPA", "qol_tab4" );

	t.render ( "qol_tab" );
	t.send_event ( "qol_tab1", "click" );

	// facciamo le queries....
	modules.home._do_query_tabs ();
};


modules.home._tab_hover = function ( tabs, event_name, div, curr_div, pos )
{
	if ( div == tabs._curr_tab_sel )
		div.className = "sel";
	else
		div.className = "tab";
};


modules.home.show_scad = function ( g, m, a )
{
	var mesi = [ "GENNAIO", "FEBBRAIO", "MARZO", "APRILE", "MAGGIO", "GIUGNO", "LUGLIO", "AGOSTO", "SETTEMBRE", "OTTOBRE", "NOVEMBRE", "DICEMBRE" ];
	var giorni = [ "Domenica", "Luned&igrave;",  "Marted&igrave;", "Mercoled&igrave;", "Gioved&igrave;", "Venerd&igrave;", "Sabato" ];

	var fq = new FulQuery ();
	fq.opera = "92";
	fq.db_name = "SCADENZA92";
	fq.lines = 1000;
	fq.mode = "QUERY";
	fq.set_fields ( "ID", "TITOLO", "ABSTRACT" );

	fq.add_date ( a, m, g, null, null, null, "DATA" );

	fq.set_id ();

	a = parseInt ( a, 10 );
	m = parseInt ( m, 10 ) - 1;
	g = parseInt ( g, 10 );

	var d = new Date ( a, m, g );
	var date = g + " " + mesi [ m ] + " " + a + " - " + giorni [ d.getDay () ];

	kernel.fulquery ( fq, function ( v )
	{
		var s = '';

		var i, l = v [ "rows" ];
		for ( i = 0; i < l; i ++ )
		{
			var r = v [ "row" + i ];
			if ( ! r ) break;

			r [ '_date_scad_prefix' ] = '';
			r [ "_data" ] = '';
			if ( i == 0 )
			{
				r [ '_date_scad_prefix' ] = modules.home.templates [ 'scad_row_date' ];
				r [ "_data" ] = date;
			}

			s += String.formatDict ( modules.home.templates [ "scad_row" ], r );
		}

		$ ( "cont3" ).innerHTML = s;
		site.set_mask ( "cont3" );
	} );
};


modules.home._do_query_tabs = function ()
{
	function _query ( tab, fq )
	{
		kernel.fulquery ( fq, function ( v )
		{
			modules.home._format_tab_res ( tab, v );
		} );
	}

	var arr = [ "92", "87", "88", "34" ];

	var i, l = arr.length;
	for ( i = 0; i < l; i ++ )
	{
		var tab = "qol_tab" + ( i + 1 );

		var fq = new FulQuery ();
		fq.opera = "92";
		fq.db_name = "QUOTY92";
		fq.set_fields ( "ID", "DATA", "TITOLO", "CLASSDESCR" );
		fq.lines = 3;
		fq.order_by = "DATA DESC";
		fq.add ( "TIPO", "EQUAL", arr [ i ] );
		//fq.add ( "FLAG_ANTEPRIMA", "EQUAL", "S" );

		fq.set_id ();

		_query ( tab, fq );
	}
};


modules.home._format_tab_res = function ( tab, v )
{
	var s = "";

	var i, l = v [ "rows" ];
	for ( i = 0; i < l; i ++ )
	{
		var r = v [ "row" + i ];
		if ( ! r ) break;

		r [ "_lnk" ] = "http://www.clientiwkip.it/coupon92";
		r [ "_target" ] = "";

		r [ '_data' ] = utils.order_date ( r [ 'DATA' ], "-", "IT", "/" );

		if ( kernel.user_info [ "login" ] && kernel.user_info.attive.indexOf ( "92" ) >= 0 )
			r [ "_lnk" ] = "/quotidiano.html#__m=quot_doc,id=" + r [ "ID" ];
		else
			r [ "_target" ] = 'target="_blank"';

		s += String.formatDict ( modules.home.templates [ "tab_row" ], r );
	}

	$ ( tab ).innerHTML = s;
};


modules.home.show_rivista = function ()
{
	utils.get_file ( "/static/html/portale/prima_pagina_ilfisco.html", function ( v )
	{
		v = utils.strip_html_body ( v );
		v = LinkReplacer.lnk2span ( v );
		$( "rivistailfisco_cnt" ).innerHTML = v;

		LinkReplacer.replace ( site.link_replace );
		//LinkReplacer.replace_anchors ( $ ( "rivistailfisco_cnt" ), true );
	});
};



modules.home.templates = {};


modules.home.templates [ 'logged' ] =  '<div id="login_box" class="lbar_box" style="background-color: #82B7D9;">' +
				'  <div class="lbar_title">' +
				'    <div class="lbar_title_fr"><\/div>' +
				'    <div class="lbar_title_txt">LOGIN<\/div>' +
				'  <\/div>' +
				'  <div id="login_body" class="lbar_body">' +
				'    <div id="login1">' +
				'      <b>&nbsp;&nbsp;Ora sei loggato come: %(login)s<\/b>' +
				'      <br \/><br \/><br \/>' +
				'      %(ctr_panel)s' +
				'    <\/div>' +
				'  <\/div>' +
				'<\/div>';


modules.home.templates [ 'quot_home_first' ] = '	<div id="ar_gen_first" class="first">' +
					'		<div class="tit">' +
					'			<div class="fr"><\/div>' +
					'			<div class="tit_txt">IN PRIMO PIANO<\/div>' +
					'		<\/div>' +
					'		<div id="primo_p_box" class="cnt_box"><\/div>' +
					'	<\/div>';


modules.home.templates [ 'quot_home_left' ] = 	'	<div id="ar_gen_left" class="left">' +
					'		<div class="tit">' +
					'			<div class="fr"><\/div>' +
					'			<div class="tit_txt">NEWS<\/div>' +
					'		<\/div>' +
					'		<div id="news_box" class="cnt_box"><\/div>' +
					'	<\/div>';

modules.home.templates [ 'quot_home_right' ] = '	<div id="ar_gen_right" class="right">' +
					'		<div class="tit">' +
					'			<div class="fr"><\/div>' +
					'			<div class="tit_txt">APPROFONDIMENTI<\/div>' +
					'		<\/div>' +
					'		<div id="appr_box" class="cnt_box"><\/div>' +
					'	<\/div>';

modules.home.templates [ 'quot_home' ] = 	'<div id="ar_gen_top" class="top"> ' +
					'	<div id="top_data">%(top_data)s<\/div>' +
					'	<div id="title1">%(title)s<\/div>' +
					'	<div id="title2"><\/div>' +
					'<\/div>' +
					'<div id="ar_gen_center" class="center_box">' +
					'<\/div>';


modules.home.templates [ 'quot_search' ] = 	'<div class="tit">' +
					'	<div class="fr"><\/div>' +
					'	<div id="tit_search" class="tit_txt"><\/div>' +
					'<\/div>' +
					'<div id="search_div"><\/div>' +
					'<div id="container_res" class="container_res"><\/div>' +
					'<div id="pagination" class="pagination"><\/div>';

modules.home.templates [ "search_prev_page" ] = '<a href="%(_prev_page)s"><img alt="Pagina precedente" border="0" src="/gfx/gfx_quotidiano/navi_prev.gif" \/><\/a>';
modules.home.templates [ "search_next_page" ] = '<a href="%(_next_page)s"><img alt="Pagina successiva" border="0" src="/gfx/gfx_quotidiano/navi_next.gif" \/><\/a>';

modules.home.templates [ "search_row" ] = '<tr>' +
					'	<td valign="top"><div class="res_tipo">%(descr_tipo)s<\/div><\/td>' +
					'	<td valign="top">' +
                                        '       	<div class="res_occh">&raquo;&nbsp;%(occhiello)s<\/div>' +
					'		<div class="res_titolo"><a href="%(link)s">%(titolo)s<\/a><\/div>' +
					'		<div class="autore">%(AUTORE)s<\/div>' +
					'		<div id="%(id)s_abs" style="display: none;">' +
					'			%(ABSTRACT)s' +
					'			<div class="link"><a href="%(int_link)s">Vai al documento<\/a><\/div>' +
					'		<\/div>'  +
					' 	<\/td>' +
                                        '       <td valign="top" class="res_data">%(date)s<\/td>' +
                                        '<\/tr>' +
					'<tr><td colspan="3"><div class="hr"><\/div><\/td><\/tr>';

modules.home.templates [ "search_pagination" ] = '<div class="res_navi">%(prev_page)s %(dash)s %(next_page)s<\/div>';

modules.home.templates [ "doc_92" ] =	'<div class="tit">' +
					'	<div class="fr"><\/div>' +
					'	<div class="tit_txt">%(descr_tipo)s<\/div>' +
					'<\/div>' +
					'<div id="cnt_doc">' +
					'<div class="doc_occ">&raquo; %(occhiello)s<\/div>' +
					'<div class="doc_data">%(data)s<\/div>' +
					//'<div class="doc_title">%(titolo)s<\/div>' +
					//'<div class="autore">di %(autore)s<\/div>' +
					'<div class="doc_txt">%(document_text)s<\/div>' +
					'		%(_printer)s' +
					'<div class="doc_footer"><a href="javascript:history.go(-1)">Torna indietro<\/a><\/div>' +
				'<\/div>';

modules.home.templates [ "doc_87" ] =	'<div class="tit">' +
						'	<div class="fr"><\/div>' +
						'	<div class="tit_txt">%(descr_tipo)s<\/div>' +
						'<\/div>' +
						'<div id="cnt_doc">' +
						'	<div class="doc_occ">&raquo; %(occhiello)s<\/div>' +
						'	<div class="doc_data">%(data)s<\/div>' +
						//'	<div class="doc_title">%(titolo)s<\/div>' +
						//'	<div class="autore">di %(autore)s<\/div>' +
						'	<div class="doc_txt">%(document_text)s<\/div>' +
						'		%(_printer)s' +
						'	<div class="doc_footer"><a href="javascript:history.go(-1)">Torna indietro<\/a><\/div>' +
						'<\/div>';

modules.home.templates [ "doc_90" ] =      '<div class="tit">' +
                                                '       <div class="fr"><\/div>' +
                                                '       <div class="tit_txt">%(descr_tipo)s<\/div>' +
                                                '<\/div>' +
                                                '<div id="cnt_doc">' +
                                                '       <div class="doc_occ">&raquo; %(occhiello)s<\/div>' +
                                                '       <div class="doc_data">%(data)s<\/div>' +
                                                '       <div class="doc_txt">%(document_text)s<\/div>' +
						'		%(_printer)s' +
                                                '       <div class="doc_footer"><a href="javascript:history.go(-1)">Torna indietro<\/a><\/div>' +
                                                '<\/div>';

modules.home.templates [ 'lnk_save_print' ] = 	'<div align="left" class="lnk_print"' +
					' onclick="local.print_save_doc(\'%(mode)s\',\'%(templ)s\',\'%(id)s\')">Stampa<\/div>';

modules.home.templates [ "search_no_res" ] = 	'<div class="nores">' +
					' <div class="body_nores">' +
					'  <div class="noresult">%(str)s<\/div>' +
					' <\/div>' +
					'<\/div>';


modules.home.templates [ 'primo_piano' ] = 	'<table border="0" class="quot" width="100%">' + 
					'<tr><td class="occhiello">&raquo; %(OCCHIELLO)s<\/td><td class="data">%(data)s<\/td><\/tr>' +
					'<tr><td colspan="2" class="titolo"><a href="javascript:site.utils.show_hide(\'%(ID)s_abs\')">%(TITOLO)s<\/a><\/td><\/tr>' +
					'<td colspan="2"><div class="autore">%(AUTORE)s<\/div><\/td>' +
					'<tr><td class="abstract" colspan="2">' +
					'		<div id="%(ID)s_abs" style="display: none;">' +
					//'			<div class="autore">di %(AUTORE)s<\/div>' +
					'			%(ABSTRACT)s' +
					'			<div class="link"><a href="%(link)s">Vai al documento<\/a><\/div>' +
					'		<\/div><\/td><\/tr>'  +
					//'<tr><td colspan="2" class="link"><a href="%(link)s">Vai al documento<\/a><\/td><\/tr>'  +
					'<\/table>';

modules.home.templates [ 'appr' ] = 	'<table border="0" class="quot">' + 
				'<tr><td class="data">%(data)s<\/td><td class="occhiello">%(OCCHIELLO)s<\/td><\/tr>' +
				'<tr><td><\/td><td class="titolo"><a href="javascript:site.utils.show_hide(\'%(ID)s_abs\')">%(TITOLO)s<\/a><\/td><\/tr>' +
				'<tr><td><\/td><td class="abstract">' +
				'			<div id="%(ID)s_abs" style="display: none;">' +
				'				<div class="autore">%(AUTORE)s<\/div>' +
				'					%(ABSTRACT)s' +
				'			<\/div>'+ 
				'		<\/td><\/tr>'  +
				'<tr><td colspan="2" class="link"><a href="%(link)s">Vai al documento<\/a><\/td><\/tr>'  +
				'<\/table>';

modules.home.templates [ 'op_70_lnk' ] = 	'<div class="lnk_bold%(_reg)s">' +
					'       <a href="%(link1)s">Ricerca per Riviste<\/a>' +
					'<\/div>' +
					'<div class="lnk_bold%(_reg)s">' +
					'       <a href="%(link2)s">Ricerca per riferimento<\/a>' +
					'<\/div>' +
					'<div class="lnk_bold%(_reg)s">' +
					'       <a href="%(link3)s">Ricerca integrata su Riviste e Giurisprudenza<\/a>' +
					'<\/div>';

modules.home.templates [ 'scad_row_date' ] =
	//'<span style="text-transform: uppercase;">SCADENZARIO TRIBUTARIO </span>&nbsp;&nbsp;';
	'<div class="data" style="text-transform: uppercase; padding-bottom: 0">SCADENZARIO TRIBUTARIO </div>';

modules.home.templates [ 'scad_row' ] =
	'<div class="scad_row">' +
	//'	<div class="data">%(_date_scad_prefix)s%(_data)s</div>' +
	'	%(_date_scad_prefix)s' +
	'	<div class="data">%(_data)s</div>' +
	'	<div class="titolo">%(TITOLO)s</div>' +
	'	<div class="abstract">%(ABSTRACT)s</div>' +
	'</div>';


modules.home.templates [ "tab_row" ] =
	'<div class="tab_row_cnt">' +
	'	<div class="data">%(_data)s</div>' +
	'	<div class="classdescr">%(CLASSDESCR)s</div>' +
	'	<ul>' +
	'		<li>' +
	'			<div class="titolo"><a %(_target)s href="%(_lnk)s">%(TITOLO)s</a></div>' +
	'		</li>' +
	'	</ul>' +
	'</div>';




var site = {};


site.login_form_data = {
        div_logged: 'loginform_cnt',
        form_id: 'loginform',
        login_id: 'username',
        pwd_id: 'passwd',
        btn_id: 'buttonlogin'
};

site.default_module = "home";


site._inited = false;

// remap calendar langs
OS3CAL_LOCALE [ 'months' ] =
	[ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ];
OS3CAL_LOCALE [ 'days' ]   = [ "D", "L", "M", "M", "G", "V", "S" ];
OS3CAL_LOCALE [ 'today' ]   = 'Oggi';

site.init = function ( module, dict, data )
{
	if ( ! site._inited )
	{
		site._inited = true;
		/*site.check_opere (function () {
			kernel.init_module ( module, dict, data ); 
		});

		kernel.quit ();*/
	}

	//site.menu_selectstyle ();

	if ( ! site._scadenzario )
		site.scadenzario ();

	window.scrollTo ( 0, 0 );
};

site.set_mask = function ( mask )
{
	switch ( mask )
	{
		case 'cont':
			$ ( "cont" ).style.display = "block";
			$ ( "cont2" ).style.display = "none";
			$ ( "cont3" ).style.display = "none";
			break;

		case 'cont2':
			$ ( "cont" ).style.display = "none";
			$ ( "cont2" ).style.display = "block";
			$ ( "cont3" ).style.display = "none";
			break;

		case 'cont3':
			$ ( "cont" ).style.display = "none";
			$ ( "cont2" ).style.display = "none";
			$ ( "cont3" ).style.display = "block";
			break;
	}
};

site.opere_info = null;

site.on_login = function ( v )
{
	site.check_opere ();
	modules.home._tabs = null;
};

site.show_warn = function ()
{
        kernel.command ( "dump_html", { fname: "warning.html" }, function ( vars ) {
                if ( ! vars [ 'content' ] ) return;

                var d = $( "warn_msg" );
                d.innerHTML = vars [ 'content' ];
                d.style.display = 'block';
        }, true );
};

site.check_opere = function ( cback )
{
	if ( kernel.user_info.get ( 'login' ) )
	{
		$ ( 'teleskill_lnk' ).setAttribute ( "href", "http://reg.leggiditalia.it/el/elearning.aspx?CKEY=" + kernel.user_info.get ( 'ckey' ) );
		$ ( 'teleskill_lnk' ).setAttribute ( "target", "_blank" );

		if ( kernel.user_info.attive.indexOf ( "H3" ) >= 0 )
		{
			$ ( "risponde_fisco" ).setAttribute ( "onclick", "location='/esperto.html'" );
			$ ( "risponde_accedi" ).style.display = "block";
		}
		else
		{
			$ ( "risponde_fisco" ).setAttribute ( "onclick", "kernel.go('home',{mask:'static',file:'html/portale/fisco_risponde'})" );
			$ ( "risponde_accedi" ).style.display = "none";
		}
	}
	else
	{
		$ ( 'teleskill_lnk' ).setAttribute ( "href", "javascript:kernel.go('home',{mask:'static',file:'html/portale/Presentazione_elearnig'})" );
		$ ( 'teleskill_lnk' ).setAttribute ( "target", "" );

		$ ( "risponde_fisco" ).setAttribute ( "onclick", "kernel.go('home',{mask:'static',file:'html/portale/fisco_risponde'})" );
		$ ( "risponde_accedi" ).style.display = "none";
	}

	//if ( location.host.indexOf ( "lan." ) >= 0 )
	//{
	newsletter.prepare_link ( true, function () {
		if ( ! newsletter.url )
		{
			$ ( 'newsl_qol' ).setAttribute ( "href", "javascript:void(0)" );
			$ ( 'newsl_qol' ).setAttribute ( "target", "" );
		}
		else
		{
			$ ( 'newsl_qol' ).setAttribute ( "href", newsletter.url );
			$ ( 'newsl_qol' ).setAttribute ( "target", "_blank" );
			//$ ( 'newsl_qol' ).setAttribute ( "href", 'javascript:kernel.go(\'home\',{url:\'' + newsletter.url + '\',mask:\'frame\'})' );	
		}

		if ( kernel.user_info.get ( 'login' ) ) $ ( 'li_newsl_qol' ).style.display = "";
		else $ ( 'li_newsl_qol' ).style.display = "none";
	});
	//}
	//else $ ( 'li_newsl_qol' ).style.display = "none";

	function set_link ( cback )
	{
		var opinfo = site.opere_info;

		var attive = [];
		if ( kernel.user_info [ "login" ] ) attive = kernel.user_info.attive;

		var links = document.getElementsByTagName ( "A" );
		var i, l = links.length;
		
		for ( i = 0; i < l; i ++)
		{
			var lnk = links [ i ];
			if ( ! lnk [ "id" ] || ! lnk.id.startsWith ( "lnk_" ) ) continue;

			var op = lnk.id.substr ( 4 );
			if ( ! opinfo.opere [ op ] ) continue;

			var auth = MD5.hex_md5 ( kernel.user_info.ssckey + op + "errepici" );

			var href;


			if ( attive.indexOf ( op ) >= 0 )
			{
				href = opinfo.homes [ op ].replace ( /__SSCKEY__/g, kernel.user_info.ssckey );
				href = href.replace ( /__AUTH__/g, auth );
				lnk.setAttribute ( "target", "" );

				site.set_link_check ( lnk, true );
			}
			else
			{
				if ( ! opinfo.coupons [ op ] ) href = "javascript:void(0)";
				else
				{
					href = opinfo.coupons [ op ];
					lnk.setAttribute ( "target", "_blank");
				}
				//else href = "javascript:kernel.go('home',{mask:'frame',url:'" + opinfo.coupons [ op ] + "'})";

				site.set_link_check ( lnk, false );
			}

			lnk.setAttribute ( "href", href );
		}

		// Gestisco l'opera Fisco Guida Operativa - Modulo Lavoro (AX, AY, AZ)
		lnk = $ ( "lnk_fisconline_guida_operativa" );

		var fgol_opere = [ "AX", "AY", "AZ" ];
		var chk_op = false;
		l = fgol_opere.length;
		for ( i = 0; i < l; i ++ )
		{
			var op = fgol_opere [ i ];
			if ( attive.indexOf ( op ) >= 0 )
				chk_op = op;

			auth = MD5.hex_md5 ( kernel.user_info.ssckey + op + "errepici" );
			href = opinfo.homes [ op ].replace ( /__SSCKEY__/g, kernel.user_info.ssckey );
			href = href.replace ( /__AUTH__/g, auth );
			lnk.setAttribute ( "target", "" );

			site.set_link_check ( lnk, true );
		}

		if ( chk_op )
		{
			auth = MD5.hex_md5 ( kernel.user_info.ssckey + chk_op + "errepici" );
			href = opinfo.homes [ chk_op ].replace ( /__SSCKEY__/g, kernel.user_info.ssckey );
			href = href.replace ( /__AUTH__/g, auth );
			lnk.setAttribute ( "target", "" );

			site.set_link_check ( lnk, true );
		}
		else
		{
			href = opinfo.coupons [ "AX" ];
			lnk.setAttribute ( "target", "_blank");
			//href = "javascript:kernel.go('home',{mask:'frame',url:'" + opinfo.coupons [ "AX" ] + "'})";
			site.set_link_check ( lnk, false );
		}

		lnk.setAttribute ( "href", href );


		// Gestisco l'opera Digesto DX - DA DB DC DD
		lnk = $ ( "_DX_" );
		var dx_opere = opinfo.get ( 'keys', {} ).get ( 'DX_OPERASEZ', "" ).split ( " " );
		chk_op = false;
		l = dx_opere.length;
		for ( i = 0; i < l; i ++ )
		{
			var op = dx_opere [ i ];
			if ( attive.indexOf ( op ) >= 0 )
			{
				chk_op = op;
				break;
			}
		}

		if ( chk_op )
		{
			href = opinfo.homes [ "DX" ].replace ( /__SSCKEY__/g, kernel.user_info.ssckey );
			href = href.replace ( /__AUTH__/g, auth );
			lnk.setAttribute ( "target", "" );

			site.set_link_check ( lnk, true );
		}
		else
		{
			href = opinfo.coupons [ "DX" ];
			lnk.setAttribute ( "target", "_blank");
			site.set_link_check ( lnk, false );
		}

		lnk.setAttribute ( "href", href );

		cback && cback ();
	}

	if ( ! site.opere_info )
	{
		kernel.command ( "list_opere", {}, function ( v )
		{
			site.opere_info = v;
			set_link ();
		});
	}
	else
	{
		set_link ();
	}

};

site.set_link_check = function ( lnk, check )
{
	var p = lnk.parentNode;
	while ( p )
	{
		if ( p [ "className" ] && p.className.endsWith ( "reg" ) )
		{
			p.className = check ? "reg" : "noreg";
			break;
		}

		p = p.parentNode;
	}
};


site.resetfield = function ( fieldname, type )
{
	$( fieldname ).setAttribute ( "type", type )
	$( fieldname ).value = "";
};

site.menu_selectstyle = function ( currdiv )
{
	var child = $( "optionmenu" ).childNodes;
	var ln = child.length;

	for ( var i = 0; i < ln - 1; i++)
	{
		if ( child [ i ].className == "select" )
			child [ i ].className = "unselect";
	}

	if ( currdiv && currdiv.id && currdiv.id != "optionmenu_home" ) currdiv.className = "select";
};

site.select_menu = function ( m )
{
	site.menu_selectstyle ( $ ( "optionmenu_" + m ) );
};

site.section_expand = function ( curr )
{
	var parent = curr.parentNode;

	if ( parent.className == "section_unclick" )
		parent.className = "section_click";
	else
		parent.className = "section_unclick";
};


site._get_cal_scadenze = function ( cback )
{
	var fq = new FulQuery ();
	fq.opera = "92";
	fq.db_name = "SCADENZA92";
	fq.lines = 1000;
	fq.mode = "QUERY";
	fq.set_fields ( "ID", "DATA" );

	fq.set_id ();

	kernel.fulquery ( fq, cback );
};

site.link_replace = function ( lnk )
{
	var href;
	var tipo = lnk.getAttribute ( "tipo" );

	switch ( tipo )
	{
		case "page":
			var opera = lnk.getAttribute ( "opera" );
			var page = lnk.getAttribute ( "chiavi" );
			page = page.replace ( ".html", "" );
			page = page.replace ( ".htm", "" );
			page = page.replace ( "/static/", "" );
			href = "javascript:kernel.go('home',{mask:'static',file:'" + page + "'})";
			break;

		case "file":
			var file = lnk.getAttribute ( "chiavi" );
			href = file;
			break;
	}

	return href;
};


site._scadenzario = null;
site.scadenzario = function ()
{
	site._get_cal_scadenze ( function ( v )
	{
		var s = site._scadenzario = new Scadenzario ( "scad", { "show_today" : false, "first_day_of_week": 1 } );

		s.set_event ( 'date-selected', function ( year, month, day, data )
		{
			kernel.go ( 'home', { mask: 'scad', gg: day, mm: month, aa: year } );
		});

		var i, l = v [ "rows" ];
		for ( i = 0; i < l; i ++ )
		{
			var row = v [ "row" + i ];
			if ( ! row ) break;

			var d = row [ "DATA" ];
			d = d.split ( "-" );

			s.add ( d [ 0 ], d [ 1 ], d [ 2 ], row [ "ID" ] );
		}

		s.render ( "scadenzario" );
	} );
};



site.templates = {};

site.templates [ "logged" ] =
        '<div id="logged_template"><b><font color="#316796">&nbsp;&nbsp;Ora sei loggato come: %(login)s</font></b>' +
        '<br /><br /><br />' +
        '<div id="cp_link" class="cp_link" style=""><a href="/control_panel">Pannello di controllo</a></div></div>';



