
	//
	// definizione del NS FlexJS
	//

FlexJS = window.FlexJS || {};

	// browser test

FlexJS.isIE = jQuery.browser.msie;
FlexJS.isGecko = jQuery.browser.mozilla;

	//
	// accesso alle variabili di configurazione di flex
	//

FlexJS.AppConfigure = window.FlexJS.AppConfigure || {};

FlexJS.AppConfigure.Get = function (pName) {

	return gAppConfigure[pName];
	
		// TBD: se non è presente nelle variabili, una chiamata ajax
		//  perpopolae l'array
};

	//
	// loader dinamico
	//

/*

	FlexJS.Loader.LoadJS('path/to/file.js', function () { use JS });

*/

FlexJS.Loader = window.FlexJS.Loader || {};

FlexJS.Loader.sCache = [];
FlexJS.Loader.sImageCache = [];

	// carica un JS esterno

FlexJS.Loader.LoadJS = function(path, cb, useUniqueID) {

	path = path instanceof Array ? path : [path];
	useUniqueID = useUniqueID || false;

		// se ho già caricato l'include mi limito ad eseguire la CB

	for (var i = 0, m = path.length; i < m; i++) {

		var fName = path[i];

		if (FlexJS.Loader.sCache[ fName ]) {

				// se siamo all'ultimo elemento

			if (i == m - 1) {

				if (cb) cb();

				return;
			}
		}

		var script = document.createElement('script');

			// aggiunge al nome del file un identificativo numerico univoco
			// per forzare il caricamento (no cache) per il debug

		script.type = 'text/javascript';
		script.src = FlexJS.AppConfigure.Get('kBaseURL') + fName + (useUniqueID ? ('?v=' + FlexJS.Utils.Random(1, 9999)) : '');

			// metto la callback solamente sull'ultimo elemento

		if (i == m - 1) {

			var f = function() {
				
				FlexJS.Loader.sCache[ fName ] = true;
				if (cb) cb();
			};

		} else {

			var f = function() {
				
				FlexJS.Loader.sCache[ fName ] = true;
			};
		}

		if (FlexJS.isIE)
			script.onreadystatechange = function () {
				if (! script.p && (script.readyState == 'loaded' || script.readyState == 'complete')) {
					f();
					script.p = true;
				}
			};
		else
			$(script).load(f /* cb */ );

		document.getElementsByTagName('head')[0].appendChild(script);  
	}
};

FlexJS.Loader.LoadCSS = function (path) {

	if (FlexJS.Loader.sCache[path])
		return;

	var css = document.createElement('link');

	css.type = 'text/css';
	css.rel = 'stylesheet';
	css.href = FlexJS.AppConfigure.Get('kBaseURL') + path; //'js/jq/jDialog/jDialog.css';
	css.media = 'screen';

	document.getElementsByTagName('head')[0].appendChild(css);

	FlexJS.Loader.sCache[ path ] = true;
};

	//
	// Funzionalità ajax
	// 

FlexJS.Ajax = window.FlexJS.Ajax || {};

	// effettua una chiamata all'ajax server con il path specificato
	// 
	// la callback, se presente, deve accettare un parametro: il risultato

FlexJS.Ajax.get = function(path, cb) {

	var url = FlexJS.AppConfigure.Get('kBaseURL') + 'modules/ajax/ajax.php/' + path;
	$.get(url, {
		u: new Date().valueOf()
	}, function(data) {

		if (cb)
			cb(data);

	}, 'json');
};

	//
	// utility generiche
	//

FlexJS.Utils = window.FlexJS.Utils || {};

FlexJS.Utils.InArray = function (needle, haystack) {

	for (var i = 0, m = haystack.length; i < m; i++)
		if (haystack[i] === needle)
			return true;

	return false;
};

FlexJS.Utils.Random = function (min, max) {

	if (! min) min = 0;
	if (! max) max = 10e10;

	return Math.round(max * Math.random() + min);
};

	// conversione da e verso JSON
	
FlexJS.Utils.toJSON = function(o) {

	if (typeof(JSON) == 'object' && JSON.stringify)
		return JSON.stringify(o);

	var type = typeof(o);

	if (o === null)
		return "null";

	if (type == "undefined")
		return undefined;

	if (type == "number" || type == "boolean")
		return o + "";

	if (type == "string")
		return FlexJS.Utils.q(o);

	if (type == 'object') {

			// caso speciale per la codifica delle date

		if (o.constructor === Date) {
			
			var month = o.getUTCMonth() + 1;
			if (month < 10) month = '0' + month;

			var day = o.getUTCDate();
			if (day < 10) day = '0' + day;

			var year = o.getUTCFullYear();

			var hours = o.getUTCHours();
			if (hours < 10) hours = '0' + hours;

			var minutes = o.getUTCMinutes();
			if (minutes < 10) minutes = '0' + minutes;

			var seconds = o.getUTCSeconds();
			if (seconds < 10) seconds = '0' + seconds;

			var milli = o.getUTCMilliseconds();
			if (milli < 100) milli = '0' + milli;
			if (milli < 10) milli = '0' + milli;

			return '"' + year + '-' + month + '-' + day + 'T' +
				hours + ':' + minutes + ':' + seconds + 
				'.' + milli + 'Z"'
			;
		}

		if (o.constructor === Array) {

			var ret = [];
			for (var i = 0, m = o.length; i < m; i++)
				ret.push( FlexJS.Utils.toJSON(o[i]) || 'null' );

			return '[' + ret.join(',') + ']';
		}

		var pairs = [];
		for (var k in o) {

			var name,
				type = typeof k
			;

			if (type == 'number')
				name = '"' + k + '"';
			else if (type == 'string')
				name = FlexJS.Utils.q(k);
			else
				continue;  // salta chiavi che non siano stringhe o numeri

			if (typeof o[k] == 'function')
				continue;  // salta elementi funzione

			var val = FlexJS.Utils.toJSON(o[k]);

			pairs.push(name + ':' + val);
		}

		return '{' + pairs.join(', ') + '}';
	}
};

FlexJS.Utils.fromJSON = function(src) {

	if (typeof(JSON) == 'object' && JSON.parse)
		return JSON.parse(src);

	var filtered = src;
	filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
	filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
	filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');

	if (/^[\],:{}\s]*$/.test(filtered))
		return eval('(' + src + ')');
	else
		throw new SyntaxError("Error parsing JSON, source is not valid.");
};

FlexJS.Utils._escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;

FlexJS.Utils._meta = {
	'\b': '\\b',
	'\t': '\\t',
	'\n': '\\n',
	'\f': '\\f',
	'\r': '\\r',
	'"' : '\\"',
	'\\': '\\\\'
};

FlexJS.Utils.q = function(s) {

	if (s.match(FlexJS.Utils._escapeable)) {
		
		return '"' + s.replace(FlexJS.Utils._escapeable, function (a) {

				var c = FlexJS.Utils._meta[a];
				if (typeof c === 'string') return c;

				c = a.charCodeAt();
				return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
			}) + '"'
		;
	}

	return '"' + s + '"';
};

	//
	// apertura in una nuova finestra dei link
	//

FlexJS.TBHack = window.FlexJS.TBHack || {};

FlexJS.TBHack.sKeyCode = [13, 32];

FlexJS.TBHack.Init = function() {

	$('a.target_blank').each(function() {

		this.title += FlexJS.AppConfigure.Get('kBlankLinkMessage');

		$(this).click(function(e) {

			FlexJS.TBHack.Open(this.href);

			return e.preventDefault();
		});

		$(this).keypress(function(e) {

			if (FlexJS.Utils.InArray(e.keyCode, FlexJS.TBHack.sKeyCode)) {

				FlexJS.TBHack.Open(this.href);

				return e.preventDefault();
			}
		});
	});
};

FlexJS.TBHack.Open = function(url) {

		// apre in una finestra nuova

	window.open(url, 'TBH' + FlexJS.Utils.Random());
};

	// funzione usata per replicare il comportamento del click nel keypress

FlexJS.TBHack.InitKeypress = function() {

	$('.InputIMG').each(function() {

		$(this).keypress(function(e) {

			if (FlexJS.Utils.InArray(e.keyCode, FlexJS.TBHack.sKeyCode)) {

				this.click();

				return e.preventDefault();
			}
		});
	});
};

	// estrae gli attributi meta dalla classe dell'oggetto
	// se è specificato un nome, restituisce solo quel valore
	// 
	// la struttura del nome della classe è:
	// 		snMeta-<name>-<value>
	// 
	// TBD: duplicata in sn.js

FlexJS.Utils.MetaFromEl = function(el, n) {
	
	var
		c = $(el).attr('class').split(' '),
		mt = {}
	;

	for (var i = 0, m = c.length; i < m; i++)
		if ((e = c[i].match(/^snMeta\-(.*)\-(.*)$/)))
			mt[ e[1] ] = e[2].replace(/_/g, '/');

	return n ? mt[n] : mt;
};

	//
	// AJAX query
	//

FlexJS.Ajax = window.FlexJS.Ajax || (function () {

		// inizializza le funzionalità ajax di jq
/*
	$.ajaxSetup( {
		url: FlexJS.AppConfigure.Get('kBaseURL') + 'pages/Lite/AS.php',
		global: false,
		type: 'POST'
	} );
*/
	return {};

})();

FlexJS.Ajax.Query = function(what, cb) {

	$.get(FlexJS.AppConfigure.Get('kBaseURL') + 'pages/Lite/AS.php', {H: what}, cb);
};

	//
	// inizializzazioni
	// 

$().ready(function() {

	FlexJS.TBHack.Init();
	FlexJS.TBHack.InitKeypress();
});

	//
	// JS inheritance
	// 
	// cfr: http://ejohn.org/blog/simple-javascript-inheritance/
	//

(function(){

	var
		initializing = false,
		fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/
	;

		// The base Class implementation (does nothing)

	this.Class = function(){};

		// Create a new Class that inherits from this class

	Class.extend = function(prop) {
		
		var _super = this.prototype;

			// Instantiate a base class (but only create the instance,
			// don't run the init constructor)

		initializing = true;
		var prototype = new this();
		initializing = false;

			// Copy the properties over onto the new prototype
			
		for (var name in prop) {
	
			// Check if we're overwriting an existing function

			prototype[name] = typeof prop[name] == "function" && 
				typeof _super[name] == "function" && fnTest.test(prop[name]) ?
					(function(name, fn){
						return function() {
							var tmp = this._super;

								// Add a new ._super() method that is the same method
								// but on the super-class
								
							this._super = _super[name];

								// The method only need to be bound temporarily, so we
								// remove it when we're done executing

							var ret = fn.apply(this, arguments);        
							this._super = tmp;

							return ret;
					  };
					})(name, prop[name]) :
					prop[name];
		}

			// The dummy class constructor

		function Class() {

			// All construction is actually done in the init method

			if ( !initializing && this.init )
				this.init.apply(this, arguments);
		}

			// Populate our constructed prototype object
		
		Class.prototype = prototype;

			// Enforce the constructor to be what we expect
		
		Class.constructor = Class;

			// And make this class extendable
		
		Class.extend = arguments.callee;

		return Class;
	};
	
})();

