/*************************************************************************[info]
  FRAMEWORK:            eXtend
  DATA:                 04/02/2009
  COMPANY:              Onlime S.n.c.
 
  VERS:                 2
  LAST EDIT:            10/03/2009
*******************************************************************************/
(function() {
/*******************************************************************************
  [ESTENSIONE PROTOTIPI]  
*******************************************************************************/ 
/* 
  [Array.indexOf] - Recupero indice tramite elemento passato come argomento
  ---
  @obj        : OBJ       --oggetto da ricercare
  @start      : INT       --posizione di partenza
*/ 
if (!Array.indexOf) 
{
  Array.prototype.indexOf = function (obj, start) 
  {
    for (var i = (start || 0); i < this.length; i++) 
    {
      if (this[i] == obj){ return i; }
    }
    return -1;
  }
};

/* 
  [Array.each] - Esegue una funzione passata come argomento su ciascun elemento 
  dell'array
  ---
  @fn         : FUNCTION  --funzione da eseguire
  @scope      : OBJECT    --scope associato
*/
if (!Array.each) 
{
  Array.prototype.each = function ( fn, scope )
  {
    for(var j = 0, len = this.length; j < len; j++)
    {
	    fn.apply( scope || this[j], [ this[j], j, this ] );
	  }
  }
};

/* 
  [Function.bind] - ...
  ---
  @object         : OBJECT  --scope
*/
Function.prototype.bind = function (object) 
{
   var method = this;
   var oldArguments = toArray(arguments).slice(1);
   return function () {
       var newArguments = toArray(arguments);
       return method.apply(object, oldArguments.concat(newArguments));
   };
};

/* 
  [Function.bindEventListener] - ...
  ---
  @object         : OBJECT  --scope
*/
Function.prototype.bindEventListener = function (object) 
{
   var method = this;
   var oldArguments = toArray(arguments).slice(1);
   return function (event) {
      if ( JEvent.eventStates[ oldArguments[0] ].status == 0 )
      {
        return method.apply(object, [event || window.event].concat(oldArguments));
      }
   };
};

/* 
  [Function.cascade] - ...
  ---
  @callbackFn         : FUNCTION  --callbackFn
*/
Function.prototype.cascade = function()
{ 
  var method = this;
  var oldArguments = toArray(arguments);

  return function() {
    var newArguments = toArray(arguments);
    
    var esito = method.apply( oldArguments[0], oldArguments.slice(2).concat(newArguments) );
    
    if ( (esito===true) && (oldArguments[1]) ) 
    {
      return oldArguments[1].apply( method );  
    }
  } 
};

/* NOT USED 
Object.prototype.Inherits = function( parent )
{
	if( arguments.length > 1 )
	{
		parent.apply( this, Array.prototype.slice.call( arguments, 1 ) );
	}
	else
	{
		parent.call( this );
	}
}
Function.prototype.Inherits = function( parent )
{
	this.prototype = new parent();
	this.prototype.constructor = this;
}
*/

/* 
  [Function.inherits] - ...
  ---
  @superclass         : OBJECT  --superclass
*/
Function.prototype.inherits = function(superclass) {
  var Tmp = function() {};
  Tmp.prototype = superclass.prototype;
  this.prototype = new Tmp();
  this.prototype.constructor = this;
} 
/*******************************************************************************
  [END ESTENSIONE PROTOTIPI]  
*******************************************************************************/
/*******************************************************************************
  [OVERLOADIND DEGLI OGGETTI EXTEND, EVENT, AJAX]  
*******************************************************************************/
/* 
  [$] - ...
  ---
  @selector         : [string,object]  --selector
*/
$ = function( selector ) 
{ 
  var obj = null;
  
  if ( typeOf(selector) == 'string' )
  {  
    obj  = document.getElementById( selector );
  }
  else if ( typeOf(selector) == 'object' )
  {
    obj = selector;
  }
  else
  {
    return null;
  }
  
  if ( !obj ) return null;
  
  if( obj.fn )
  {
    return obj; // recupero
  }
  else
  {
    // Attach delle funzioni estese
    obj.fn = new eXtend( obj ); // istanzio
    return obj;
  } 
};

/* 
  [$$] - ...
  ---
  @selector         : [string,array]  --selector
*/
window.$$ = function( selector ) 
{
  var array_ret = [];
  
  if ( typeOf(selector) == 'string' )
  {  
    var splitted = selector.split(' ');
    
    for (var i=0;i<splitted.length;i++)
    {
      if ( splitted[i].charAt(0) == '#')
      {
        // element by id
        var obj  = document.getElementById( splitted[i].substring(1) );
        if ( obj ) array_ret.push( obj );
      }
      else if( splitted[i].charAt(0) == '.' )
      {
        // element by classname
        var arr_obj = getElementsByClass( splitted[i].replace('.','') );
        for (var j=0;j<arr_obj.length;j++){ array_ret.push( arr_obj[j] ); }
      }
    }
  }
  else if ( typeOf(selector) == 'array' )
  {
    array_ret = selector;
  }
  
  if ( array_ret.length == 0 ) return null;
   
  array_ret.fn = new Group ( array_ret );
  return array_ret; 
};
/*******************************************************************************
  [END OVERLOADIND DEGLI OGGETTI EXTEND, EVENT, AJAX]  
*******************************************************************************/

/*******************************************************************************
  [EXTEND OBJECT]  
*******************************************************************************/
eXtend = function( obj )
{
  if (!obj) return;
  
  this.domElm  = null;
	this.elm_id  = null;
  this.lock    = null;
  
  // all'istanziazione bindo il "package" UI e data
  this.UI   = eXtend.UI.bind(this)();
  this.data = eXtend.data.bind(this)();
  
  this.data.init( obj );
};

eXtend.prototype.isChildOf = function( parent ) 
{
  return Utility.isChildOf ( this.domElm, parent )
};

eXtend.prototype.css = function (parameters)
{
	obj = this.domElm;
	
	if ( typeOf(parameters) == "object" ){  	
  	for (var param in parameters) 
    {
      obj.style[param] = parameters[param];
    }
  }
  else if ( typeOf(parameters) == "string" )
  {
    if (obj.currentStyle) return obj.currentStyle[parameters];
	   else if (window.getComputedStyle)
		  return document.defaultView.getComputedStyle(obj,null).getPropertyValue(parameters);
  }
  else if ( typeOf(parameters) == "array" )
  {
    var arr_ret = {};
    for (var i=0;i<parameters.length;i++)
    {
      if (obj.currentStyle) arr_ret[parameters[i]] = obj.currentStyle[parameters[i]];
	     else if (window.getComputedStyle)
		    arr_ret[parameters[i]] = document.defaultView.getComputedStyle(obj,null).getPropertyValue(parameters[i]);         
    }
    return arr_ret;
  }
};

eXtend.UI = function()
{
  var eXobj = this;
  
  var pk = {
      setOpacity  : function( level ){
          return GE.setOpacity.apply( eXobj, [level] );
        },  
      fadeOut     : function ( parameters, cbFn ){
          return GE.fadeOut.apply( eXobj, [parameters,cbFn] );
        },
      fadeIn      : function ( parameters, cbFn ){
          return GE.fadeIn.apply( eXobj, [parameters,cbFn] );
        },
      open        : function ( parameters, cbFn ){
          return GE.open.apply( eXobj, [parameters,cbFn] );
        },
      close       : function ( parameters, cbFn ){
          return GE.close.apply( eXobj, [parameters,cbFn] );
        },
      fadeColor   : function ( parameters, cbFn ){
          return GE.fadeColor.apply( eXobj, [parameters,cbFn] );
        },
      slide       : function ( parameters,cbFn ){
          return GE.slide.apply( eXobj, [parameters,cbFn] );
        },
      morphing    : function ( parameters, cbFn ){
          return GE.morphing.apply( eXobj, [parameters,cbFn] );
        },
      // -- Composite --  
      slideAndMorphing  : function ( parametersSlide, parametersMorphing, cbFn ){
          return GE.slideAndMorphing.apply( eXobj, [parametersSlide,parametersMorphing,cbFn] );
        },
      reduceAndClose  :  function ( parametersMorphing, parametersClose, cbFn  ){
          return GE.reduceAndClose.apply( eXobj, [parametersMorphing,parametersClose,cbFn] );
        },
      fadeOutAndClose  :  function ( parametersFadeOut, parametersClose, cbFn  ){
          return GE.fadeOutAndClose.apply( eXobj, [parametersFadeOut,parametersClose,cbFn] );
        },
      openAndFadeIn  :  function ( parametersOpen, parametersFadeIn, cbFn ){
          return GE.openAndFadeIn.apply( eXobj, [parametersOpen,parametersFadeIn,cbFn] );
        },
      reduceFadeOutAndClose  :  function ( parameters, cbFn ){
          return GE.reduceFadeOutAndClose.apply( eXobj, [parameters,cbFn] );
        }  
    };
    
  return pk; 
};

eXtend.data = function()
{
  var eXobj = this;
  
  var pk = {
    init : function( obj )
      { 
        eXobj.domElm  = obj;
      	eXobj.elm_id  = obj.id;
        eXobj.lock    = false;
        
        // Da controllare
        if ( eXobj.css('display') == 'none' )      eXobj.data.effects.display = false;
        if ( eXobj.css('visibility') == 'hidden' ) eXobj.data.effects.visible = false;
        
        eXobj.data.effects.curBgColor = ( eXobj.css('backgroundColor') || '#FFFFFF' );  //  Da rendere funzionante (RGB esa da trasformare)
        eXobj.data.effects.curBdColor = ( eXobj.css('borderColor')     || '#FFFFFF' );  //  Da rendere funzionante (RGB esa da trasformare)
        eXobj.data.effects.oHeight    = ( parseInt(eXobj.css('height')) || eXobj.domElm.offsetHeight );
        eXobj.data.effects.oWidth     = ( parseInt(eXobj.css('width'))  || eXobj.domElm.offsetWidth  );
      },
    effects : {
        "visible"       : true,
        "display"       : true,
        "curBgColor"    : "#FFFFFF",    // Background Color
        "curBdColor"    : "#FFFFFF",    // Border Color
        "curFtColor"    : "#000000",    // Font Color
        "oHeight"       : null,         // Original Height
        "oWidth"        : null          // Original Width
      } 
    };
  
  return pk;
};

eXtend.utility = {  
  // by HTML.it
  // converte da decimale (0..255) a esadecimale (stringa a due caratteri)
  DecToHex  : function (n){
    hex=n.toString(16);
    if(hex.length==1) hex="0"+hex;
    return hex.toUpperCase();
  },
  
  // by HTML.it
  // converte da stringa esadecimale a numero decimale
  HexToDec  : function (s){
    return parseInt(s,16);
  },
  
  // by HTML.it
  // riceve un vettore rgb in decimale e lo converte in stringa esadecimale
  HEX : function (c){
    return ("#" + eXtend.utility.DecToHex(c[0])+ eXtend.utility.DecToHex(c[1]) + eXtend.utility.DecToHex(c[2]));
  },
  
  // by HTML.it
  // restituisce la conversione esadecimale sotto forma di array di interi
  RGB : function (c){
    var r=new Array(3);
    if(c.charAt(0)=="#") c=c.substr(1,6); //elimina il cancelletto
    for(i=0;i<3;i++)
    r[i]=eXtend.utility.HexToDec(c.substr(i*2,2));
    return r;
  },
  
  cross : {
    w3: function() {
      return !!(document.getElementById && document.createElement); }(),
    ie: function() {
      return !!window.ActiveX; }()
  },
  
  // typeof ottimizzata (torna direttamente anche tipo array e null) 
  typeOf : function ( value ) 
  {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (typeof value.length === 'number' &&
                    !(value.propertyIsEnumerable('length')) &&
                    typeof value.splice === 'function') {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
  }                                                                     
};
/*******************************************************************************
  [END EXTEND OBJECT]  
*******************************************************************************/

/*******************************************************************************
  [Group OBJECT]  
*******************************************************************************/
Group = function ( arr_obj )
{
  this.arr_elm = null;
  
  this.init( arr_obj );
  this.UI = this.UI.bind(this)();  
} 
 
Group.prototype.init = function( arr_obj )
{
  this.arr_elm = [];
  
  var fn = function (obj){ this.arr_elm.push( $( obj ) ) };
  arr_obj.each( fn, this );
}

Group.prototype.UI = function()
{
  var groupObj = this;
  
  var pk = { 
      fadeOut     : function ( parameters ){
          var fn = function (){ this.fn.UI.fadeOut( parameters ) };
          return groupObj.arr_elm.each( fn );
        },
      fadeIn      : function ( parameters ){
          var fn = function (){ this.fn.UI.fadeIn( parameters ) };
          return groupObj.arr_elm.each( fn );
        },  
      open        : function ( parameters ){
          var fn = function (){ this.fn.UI.open( parameters ) };
          return groupObj.arr_elm.each( fn );
        }, 
      close       : function ( parameters ){
          var fn = function (){ this.fn.UI.close( parameters ) };
          return groupObj.arr_elm.each( fn );
        },  
      fadeColor   : function ( parameters ){
          var fn = function (){ this.fn.UI.fadeColor( parameters ) };
          return groupObj.arr_elm.each( fn );
        },  
      fadeOutAndClose  :  function ( parametersFadeOut, parametersClose ){
          var fn = function (){ this.fn.UI.fadeOutAndClose( parametersFadeOut, parametersClose ) };
          return groupObj.arr_elm.each( fn );
        },
      openAndFadeIn  :  function ( parametersOpen, parametersFadeIn ){
          var fn = function (){ this.fn.UI.openAndFadeIn( parametersOpen, parametersFadeIn ) };
          return groupObj.arr_elm.each( fn );
        },
      openOnly : function ( elm ){
          var fn = function ()
          {
            if ( typeOf(elm) == 'string' )
            {
              if ( this.id != elm ) this.fn.UI.close();
              else this.fn.UI.open();
            }
            else
            {
              if ( this !== elm ) this.fn.UI.close();
              else this.fn.UI.open();
            }
          };
          return groupObj.arr_elm.each( fn );
        } 
    };
  
  return pk;
}

Group.prototype.addEventListener = function(evType, funct, useCapture, opt)
{
  var arrListener = [];
  
  var fn = function (){ arrListener.push( $E.add( this,evType, funct, useCapture, opt ) ); };
  this.arr_elm.each( fn );
  
  return arrListener;
}
/*******************************************************************************
  [END Group OBJECT]  
*******************************************************************************/


/*******************************************************************************
  [GE]  
*******************************************************************************/
GE = {};

/* [setOpacity]
    @opacity  : opacitá
    
   Note : per setOpacity su elementi contenenti font impostare il colore di 
   sfondo del background. 
*/ 
GE.setOpacity = function ( opacity )
{
  opacity=(opacity==100) ? 99.999 : opacity;
  
  this.css ({
    // IE/Win
    "filter": "alpha(opacity:"+opacity+")",
    //filter: "progid:DXImageTransform.Microsoft.Alpha(opacity="+opacity+")",
    // Safari<1.2, Konqueror
    "KHTMLOpacity" : opacity/100,
    // Older Mozilla and Firefox
    "MozOpacity" : opacity/100,
    // Safari 1.2, newer Firefox and Mozilla, CSS3
    "opacity" : opacity/100
  });
};

/* [fadeOut]
@parameters v    : velocitá
@parameters a    : accuratezza
@parameters o    : opacitá
@parameters lim_opacity : limite opacitá
@cbFn : funzione di callback
*/         
GE.fadeOut  = function ( parameters, cbFn )
{ 
  if ( this.lock ) return;
  
  if (!parameters) parameters = {};
  var v = (parameters['v']) || 50;
  var a = (parameters['a']) || 5;
  var x = (parameters['lim_opacity']) || 0;
  var y = (parameters['o'] == undefined ) ? 100 : parameters['o'];
  
  if(y >= x)
  {
    this.UI.setOpacity( y );
    y = y - a;
    parameters["o"] = y;
    
    if( cbFn )
    {
      var fn = this.UI.fadeOut.cascade( this, cbFn, parameters, cbFn );
    }
    else
    {
      var fn = this.UI.fadeOut.bind ( this, parameters, null );
    }
    
    window.setTimeout(fn, v);
    return false;
  }
  else
  {
    // Exit condition
    return true;               
  }
};

/* [fadeIn]
@parameters v    : velocitá
@parameters a    : accuratezza
@parameters o    : opacitá
@cbFn : funzione di callback
*/
GE.fadeIn = function ( parameters, cbFn ) 
{   
  if ( this.lock ) return;
  
  if (!parameters) parameters = {};
  var v = (parameters['v']) || 60;
  var a = (parameters['a']) || 5;
  var o = (parameters['o']) || 0;    
         
  if( o <= 100)
  {
    this.UI.setOpacity( o ); 
    o = o+ a;
    parameters["o"] = o;
    
    if( cbFn )
    { 
      var fn = this.UI.fadeIn.cascade( this, cbFn, parameters, cbFn );
    }
    else
    {
      var fn = this.UI.fadeIn.bind ( this, parameters, null );
    }
    
    window.setTimeout(fn, v);
    return false;
  }
  else
  {
    this.UI.setOpacity( 100 );
    
    // Exit condition
    return true;
  } 
};

/* [close]
@parameters displayMode : displayMode
@cbFn : funzione di callback
*/
GE.close = function ( parameters, cbFn )
{   
  if ( this.data.effects.display )
  {
    parameters = (parameters) ? (parameters) : ({});
    
    this.css({ "display" : "none" });
    this.data.effects.display = false;
    
    if ( cbFn ){ cbFn(); }
  }

  return true;
};

/* [open]
@parameters displayMode : displayMode
@cbFn : funzione di callback
*/
GE.open = function ( parameters, cbFn )
{ 
  if ( !this.data.effects.display )
  {
    parameters = (parameters) ? (parameters) : ({});
    var displayMode = (parameters["displayMode"]) || "block";
    
    this.css({ "display" : displayMode });
    this.data.effects.display = true;
    
    if ( cbFn ){ cbFn(); }
  }
  return true;
};


/* [fadeColor]
@parameters v    : velocitá
@parameters a    : accuratezza
@parameters t    : on css element ['background'/'border'/'font']
@parameters fromColor : da colore
@parameters toColor   : a colore
@cbFn : funzione di callback
*/ 
GE.fadeColor = function ( parameters, cbFn )
{ 
  if ( this.lock ) return;
  
  if (!parameters) parameters = {};
  var v = (parameters['v'])  || 60;
  var a = (parameters['a'])  || 20;
  var t = (parameters['on']) || 'background';
  
  if ( t=='background' )
  {
    var fromRgbColor = eXtend.utility.RGB( (parameters['fromColor']) || (this.data.effects.curBgColor) );
    var toRgbColor   = eXtend.utility.RGB( (parameters['toColor'])   || (this.data.effects.curBgColor) );
  }
  else if ( t=='border' )
  {
    var fromRgbColor = eXtend.utility.RGB( (parameters['fromColor']) || (this.data.effects.curBdColor) );
    var toRgbColor   = eXtend.utility.RGB( (parameters['toColor'])   || (this.data.effects.curBdColor) );
  }
  else if ( t=='font' )
  {
    var fromRgbColor = eXtend.utility.RGB( (parameters['fromColor']) || (this.data.effects.curFtColor) );
    var toRgbColor   = eXtend.utility.RGB( (parameters['toColor'])   || (this.data.effects.curFtColor) );
  }
  
  var cresciteRgb = [];
  for (i=0;i<3;i++)
  {
    cresciteRgb[i] = ( fromRgbColor[i] <= toRgbColor[i] ) ? true : false;
    
    if( fromRgbColor[i] < toRgbColor[i] ){ cresciteRgb[i] = 1 }
    else if( fromRgbColor[i] > toRgbColor[i] ){ cresciteRgb[i] = 2 }
    else{ cresciteRgb[i] = 3 }    
  }
  
  // da verificare
  cbFn = cbFn || null;
    
  // Call computing_fade
  GE.executeFadeColor.apply( this, [ fromRgbColor, toRgbColor, cresciteRgb, a, v, t, cbFn ] );   
};

/* [executeFadeColor]
@currentRgbColor : array valori rgb correnti
@toRgbColor      : array valori rgb finali
@cresciteRgb     : array crescite rgb
@accuracy        : accuratezza
@time            : velocitá
@on              : css element ['background'/'border'/'font']
*/
GE.executeFadeColor = function ( currentRgbColor, toRgbColor, cresciteRgb, accuracy, time, on, cbFn )
{ 
  // exit condition
  if ( 
    (currentRgbColor[0] == toRgbColor[0]) &&
    (currentRgbColor[1] == toRgbColor[1]) &&
    (currentRgbColor[2] == toRgbColor[2])
  )
  {
    return true; 
  }
  
  for (i=0;i<3;i++)
  {
    if ( (cresciteRgb[i] == 1) && ( (currentRgbColor[i]+accuracy) < toRgbColor[i]) )
    {
      currentRgbColor[i] += accuracy;
    }
    else if ( (cresciteRgb[i] == 2) && ( (currentRgbColor[i]-accuracy) > toRgbColor[i]) )
    {
      currentRgbColor[i] -= accuracy;
    }
    else
    {
      cresciteRgb[i] = 3;
      currentRgbColor[i] = toRgbColor[i];
    }
  }
  
  if ( on=='background' )
  {     
    this.css({ 'backgroundColor': eXtend.utility.HEX( currentRgbColor ) });
    this.data.effects.curBgColor = eXtend.utility.HEX( currentRgbColor );
  }
  else if ( on=='border' )
  { 
    this.css({ 'borderColor': eXtend.utility.HEX( currentRgbColor ) });
    this.data.effects.curBdColor = eXtend.utility.HEX( currentRgbColor );
  }
  else if ( on=='font' )
  {
    this.css({ 'color': eXtend.utility.HEX( currentRgbColor ) });
    this.data.effects.curFtColor = eXtend.utility.HEX( currentRgbColor );
  }
  
  if( cbFn )
  {
    var fn = GE.executeFadeColor.cascade( this, cbFn, currentRgbColor,toRgbColor,cresciteRgb,accuracy,time,on,cbFn ); 
  }
  else
  {
    var fn = GE.executeFadeColor.bind( this, currentRgbColor,toRgbColor,cresciteRgb,accuracy,time,on, null );
  }
  
  window.setTimeout(fn, time);
  
  return false;
};

/* [slide]
@parameters v : 
@parameters a : 
@parameters x : 
@parameters y : 
@parameters z : 
@parameters p : 
@cbFn : 
*/            
GE.slide  = function ( parameters, cbFn )
{ 
  if ( this.lock ) return;
  
  if (!parameters) parameters = {};
  // rapporto fluidità 1:5
  var v = (parameters["v"]) || 10;
  var a = (parameters["a"]) || 2;
  var x = (parameters["x"]) || 0;
  var y = (parameters["y"]) || 0;
  var z = (parameters["z"]) || "auto";
  var p = (parameters["p"]) || "relative";    
  
  
  this.css ({
    "position" : String(p),
    "zIndex"   : String(z) & "" // forcing casting for solve ie problem
  });
  
  var arrFromCoord = [ 
    parseInt(this.css('left')) || 0, 
    parseInt(this.css('top'))  || 0
  ];
  
  var arrToCoord = [x,y];
  
  var arrCrescita = [];
  for (i=0;i<2;i++)
  { 
    if( arrFromCoord[i] < arrToCoord[i] ){ arrCrescita[i] = 1 }
    else if( arrFromCoord[i] > arrToCoord[i] ){ arrCrescita[i] = 2 }
    else{ arrCrescita[i] = 3 }    
  }
  
  // da verificare
  cbFn = cbFn || null;
  
  // Call executeSlide
  GE.executeSlide.apply( this, [ arrFromCoord, arrToCoord, arrCrescita, a, v, cbFn ] );
};

GE.executeSlide = function ( arrCurCoord, arrToCoord, arrCrescita, accuracy, time, cbFn )
{ 
  // exit condition
  if ( 
    (arrCurCoord[0] == arrToCoord[0]) && (arrCurCoord[1] == arrToCoord[1]) 
  ){
    return true; 
  }
       
  for (i=0;i<2;i++)
  {
    if ( (arrCrescita[i] == 1) && ( (arrCurCoord[i]+accuracy) < arrToCoord[i]) )
    {
      arrCurCoord[i] += accuracy;
    }
    else if ( (arrCrescita[i] == 2) && ( (arrCurCoord[i]-accuracy) > arrToCoord[i]) )
    {
      arrCurCoord[i] -= accuracy;
    }
    else
    {
      arrCrescita[i] = 3;
      arrCurCoord[i] = arrToCoord[i];
    }
  }
  
  this.css({
    "left" : arrCurCoord[0] + "px",
    "top"  : arrCurCoord[1] + "px"
  });

  if( cbFn )
  {
    var fn = GE.executeSlide.cascade( this, cbFn, arrCurCoord,arrToCoord,arrCrescita,accuracy,time, cbFn ); 
  }
  else
  {
    var fn = GE.executeSlide.bind( this, arrCurCoord,arrToCoord,arrCrescita,accuracy,time, null );
  }

  window.setTimeout(fn, time);
  return false;
}; 

GE.morphing = function ( parameters, cbFn )
{ 
  if (!parameters) parameters = {};
  // rapporto fluidità 1:5
  var v = (parameters['v']) || 15;
  var a = (parameters['a']) || 3;
  var x = (parameters['newWidth'])  || this.data.effects.oWidth;
  var y = (parameters['newHeight']) || this.data.effects.oHeight;
  
  if( parameters['saveNewDimensions'] === true )
  {
    this.data.effects.oWidth  = x;
    this.data.effects.oHeight = y;
  }
  
  var x0 = parseInt(this.css("width"));
  var y0 = parseInt(this.css("height"));
  
  var maxX = Math.abs( (x-x0) );
  var maxY = Math.abs( (y-y0) ); 
  var rate = maxY/maxX;
  
  var aX = a;
  var aY = a*rate;
  
  var arrFromDimension = [x0,y0];
  var arrToDimension = [x,y];
  
  var arrCrescita = [];
  for (i=0;i<2;i++)
  { 
    if( arrFromDimension[i] < arrToDimension[i] ){ arrCrescita[i] = 1 }
    else if( arrFromDimension[i] > arrToDimension[i] ){ arrCrescita[i] = 2 }
    else{ arrCrescita[i] = 3 }    
  }
  
  // da verificare
  cbFn = cbFn || null;
  
  // Call executeMorphing
  GE.executeMorphing.apply( this , [ arrFromDimension, arrToDimension, arrCrescita, [aX,aY], v, cbFn ] );
}
    
GE.executeMorphing = function (arrCurDimension, arrToDimension, arrCrescita, accuracy, time, cbFn )
{ 
  //alert ( "accuracy : "+accuracy);
  //return;
  
  // exit condition
  if ( 
    (arrCurDimension[0] == arrToDimension[0]) &&
    (arrCurDimension[1] == arrToDimension[1]) 
  ){
    return true; 
  }
       
  for (i=0;i<2;i++)
  {
    if ( (arrCrescita[i] == 1) && ( (arrCurDimension[i]+accuracy[i]) < arrToDimension[i]) )
    {
      arrCurDimension[i] += accuracy[i];
    }
    else if ( (arrCrescita[i] == 2) && ( (arrCurDimension[i]-accuracy[i]) > arrToDimension[i]) )
    {
      arrCurDimension[i] -= accuracy[i];
    }
    else
    {
      arrCrescita[i] = 3;
      arrCurDimension[i] = arrToDimension[i];
    }
  }
  
  this.css ({
    width  : arrCurDimension[0],
    height : arrCurDimension[1]
  });
  
  
  if( cbFn )
  {
    var fn = GE.executeMorphing.cascade( this, cbFn, arrCurDimension,arrToDimension,arrCrescita,accuracy,time, cbFn ); 
  }
  else
  {
    var fn = GE.executeMorphing.bind( this,  arrCurDimension,arrToDimension,arrCrescita,accuracy,time, null );
  }
  
  window.setTimeout(fn, time);
  
  return false;
};


          
GE.slideAndMorphing  = function ( parametersSlide, parametersMorphing, cbFn )
{ 
  if ( this.lock ) return;
  
  
  parametersSlide     = (!parametersSlide)    ? ( {} ) : ( parametersSlide );
  parametersMorphing  = (!parametersMorphing) ? ( {} ) : ( parametersMorphing );
  
  var cbSlide    = parametersSlide["cbFn"] || null;
  var cbMorphing = parametersMorphing["cbFn"] || null;
  
  var arEsiti = {
    "0" : { "stato":false,"cbFn":cbSlide },
    "1" : { "stato":false,"cbFn":cbMorphing }
  };
  
  if ( cbFn ) arEsiti.cbFn = cbFn;
  
  parametersSlide["cbFn"] = sync.bind(arEsiti,0);
  this.UI.slide( parametersSlide, parametersSlide["cbFn"] );
  
  parametersMorphing["cbFn"] = sync.bind(arEsiti,1);
  this.UI.morphing( parametersMorphing, parametersMorphing["cbFn"] );
}


GE.reduceAndClose = function ( parametersMorphing, parametersClose, cbFn )
{
  if ( this.lock ) return;
  
  if ( this.data.effects.display )
  { 
    parametersMorphing  = (!parametersMorphing) ? ( {} ) : ( parametersMorphing );
    parametersClose     = (!parametersClose)    ? ( null ) : ( parametersClose );
  
    parametersMorphing["newWidth"]  = 1;
    parametersMorphing["newHeight"] = 1;
    
    cbFn = cbFn || null;
    
    var fnCbClose = this.UI.close.cascade( this, cbFn, parametersClose );
    this.UI.morphing( parametersMorphing, fnCbClose );
  }
};

/* [fadeOutAndClose]
@parametersFadeOut : fadeOutParameters
@parametersClose   : closeParameters
@cbFn : funzione di callback
*/ 
GE.fadeOutAndClose = function ( parametersFadeOut, parametersClose, cbFn )
{
  if ( this.lock ) return;
  
  if ( this.data.effects.display )
  {
    parametersClose   = ( !parametersClose ) ? ( {} ) : ( parametersClose );
    parametersFadeOut = ( !parametersFadeOut ) ? ( {} ) : ( parametersFadeOut );
    
    cbFn = cbFn || null;
    
    var fnCbClose = this.UI.close.cascade( this, cbFn, parametersClose );
    this.UI.fadeOut( parametersFadeOut, fnCbClose );
  }
};

/* [openAndFadeIn]
@parametersOpen   : parametersOpen
@parametersFadeIn : parametersFadeIn
@cbFn : funzione di callback
*/
GE.openAndFadeIn = function( parametersOpen, parametersFadeIn, cbFn )
{
  if ( this.lock ) return;
  
  if ( !this.data.effects.display )
  { 
    parametersOpen     = ( !parametersOpen ) ? ( {} ) : ( parametersOpen );
    parametersFadeIn   = ( !parametersFadeIn ) ? ( {} ) : ( parametersFadeIn );
    
    cbFn = cbFn || null;
    
    this.UI.setOpacity(0);
    this.UI.open( parametersOpen );
    this.UI.fadeIn( parametersFadeIn, cbFn );
  } 
};

/* [reduceFadeOutAndClose]
@parameters   : parameters
@cbFn : funzione di callback
*/
GE.reduceFadeOutAndClose = function ( parameters, cbFn )
{
  if ( this.lock ) return;
  
  if ( this.data.effects.display )
  { 
    parameters = (parameters) ? (parameters) : ( {} );
    var v = parameters["v"] || 10;
    var a = parameters["a"] || 2;
    
    var parametersMorphing = { "newWidth":1,"newHeight":1,"v":v };
    var parametersFadeOut = { "v":v };
    
    var x = parseInt( this.css ("width") );
    var y = parseInt( this.css ("height") );
    
    var max = ( x > y ) ? ( x ) : ( y );
    var rate = 100 / max; 
    
    parametersMorphing["a"] = a;
    parametersFadeOut["a"]  = a*rate;
    
    cbFn = cbFn || null;
    
    // !Occorre calcolare il rapporto giusto tra fadeOut e morphing(reduce)
    // in base a dimensioni height e width obj, velocità, accuracy.
    
    cbFn = cbFn || null;
    var fnCbClose = this.UI.close.cascade( this, cbFn, null, null );
    
    this.UI.fadeOut( parametersFadeOut, null ); 
    this.UI.morphing( parametersMorphing, fnCbClose );
  } 
};
/*******************************************************************************
  [END GE]  
*******************************************************************************/
/*******************************************************************************
  [UTILITY]  
*******************************************************************************/
Utility = {};

// Funzione Cross per recuperare gli oggetti appartenenti ad una data classe 
// dato il nodo di partenza e il tipo di nodo
Utility.getElementsByClassName = function (oElm, strTagName, strClassName)
{
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	
	var arrReturnElements = new Array();
	
  strClassName = strClassName.replace(/\-/g, "\\-");
  var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
	var oElement;
	
  for(var i=0; i<arrElements.length; i++)
  {
		oElement = arrElements[i];
		if( oRegExp.test(oElement.className) )
    {
			arrReturnElements.push(oElement);
		}
	}
	
	return (arrReturnElements)
};

// Funzione Cross per recuperare tutti gli oggetti appartenenti ad una data classe
Utility.getElementsByClass = function (strClassName)
{
  return Utility.getElementsByClassName(document, "*", strClassName);
};

// typeof ottimizzata (torna direttamente anche tipo array e null) 
Utility.typeOf = function (value) 
{
    var s = typeof value;
    if (s === 'object') 
    {
      if (value) 
      {
        if (  
          typeof value.length === 'number' &&
          !(value.propertyIsEnumerable('length')) &&
          typeof value.splice === 'function'
        ){
          s = 'array';
        }
      } 
      else 
      {
        s = 'null';
      }
    }
    return s;
};

/* 
  [toArray] - Trasforma un pseudo array in array
  ---
*/
Utility.toArray = function ( pseudoArray ) 
{
   var result = [];
   for (var i = 0; i < pseudoArray.length; i++) result.push(pseudoArray[i]);
   return result;
};

/* 
  [sync] - ...
  ---
*/
Utility.sync = function ( idx )
{
  this[idx]["stato"] = true;
  if ( this[idx]["cbFn"] ) this[idx]["cbFn"]();
  
  for ( var i in this )
  {
    if ( this[i]["stato"] === false ) return;
  }
  
  if ( this.cbFn ) this.cbFn();
};

// retriveRcFromXml  
Utility.retriveRcFromXml =  function ( rcName, responseXml )
{
  var ans_ret = [];
  var rc_ans = null;
  var ans = responseXml.getElementsByTagName("recordset");

  for(i=0;i<ans.length;i++)
  { 
    if ( ans[i].getAttribute("name") == rcName )
    {
      rc_ans = ans[i];
      break;
    }
  }
  
  if (!rc_ans) return null;
  
  ans = rc_ans.getElementsByTagName("record");
  
  for(i=0;i<ans.length;i++)
  {
    ans_ret[i] = new Array();
    var campi = ans[i].getElementsByTagName("campo");
    
    for(k=0;k<campi.length;k++)
    {
      var chiave = campi[k].getAttribute("chiave");
      var valore = campi[k].childNodes[0].nodeValue;
      ans_ret[i][chiave] = valore;
    }
  }
  
  return ans_ret;
};

Utility.parseStrToJson = function ( str )
{ 
  return eval("("+str+")");
};

Utility.parseFileToXml = function ( file )
{
  var xmlDom = Utility.createXmlDom();
  if ( xmlDom )
  {
    try
    {
      xmlDom.async = false;
      xmlDom.load( file );
      return xmlDom;
    }
    catch(e)
    {
      return null;
    }
  }
  return null;
};

Utility.createXmlDom = function()
{
  var xmlDomObj;
  //preserveWhiteSpace = preserveWhiteSpace || true;
  
  try
  {
    xmlDomObj = new ActiveXObject("Microsoft.XMLDOM");
  }
  catch(e)
  {
    try
    {
      xmlDomObj = document.implementation.createDocument("","",null);
    }
    catch(e)
    {
      return null;
    }
  }
  
  xmlDomObj.preserveWhiteSpace = true;
  return xmlDomObj;
};

Utility.parseStrToXml = function ( str )
{
  try
  {
    var xmlDom = Utility.createXmlDom();
    xmlDom.async = "false";
    xmlDom.loadXML( str );
    return xmlDom;
  }
  catch(e)
  {
    try
    {
      var parser = new DOMParser();
      xmlDom = parser.parseFromString( str,"text/xml" );
      return xmlDom ;
    }
    catch(e)
    {
      return null;
    }
  }
};

Utility.xsltTransform = function( xmlDom, xsltDom, target )
{
  if ( (xmlDom == null) || (xsltDom == null) ) return null;

  try
  {
    var transform = xmlDom.transformNode( xsltDom );
    target.innerHTML = transform;
  }
  catch(e)
  {
    try
    {
      var xsltProcessor = new XSLTProcessor();
      xsltProcessor.importStylesheet( xsltDom );
      var transform = xsltProcessor.transformToFragment( xmlDom, document );
      target.appendChild( transform );
    }
    catch(e)
    {
      return null;
    }
  }
  
  return true;
}


Utility.visitDomTree = function( currNode, fn, level )
{
  if ( level && (level<0) ) return;
  
  fn( currNode );
  // Controllo che il nodo abbia figli
  if(currNode.childNodes.length > 0)
  {
    // Per ogni figlio del nodo corrente
    for(var i=0; currNode.childNodes.item(i); i++)
    {
      // Chiamo ricorsivamente la funzione
      Utility.visitDomTree( currNode.childNodes.item(i), fn, (level-1) );
    }
  }
};

/**
* setUnselectable
* Da controllare : preserve
*
* @param elm required dom element
* @param array (string) optional preserve element type
*/
Utility.setUnselectable = function  ( elm, preserve ) 
{
  if(elm && typeof(elm.tagName) != 'undefined')
  {
    // if(elm.tagName != 'INPUT' && elm.tagName != 'TEXTAREA' && elm.tagName != 'IFRAME') // Controllo sulla tipologia ELIMINATO
    if(elm.hasChildNodes())
    {
      for(var i = 0; i < elm.childNodes.length; i++)
      {
        Utility.setUnselectable( elm.childNodes[i], preserve );
      }
    }
    
    if ( preserve )
    {
      if ( preserve.indexOf( elm.tagName.toLowerCase() ) == -1 )
      {
        elm.unselectable = true;
      }  
    }
    else
    {
      elm.unselectable = true;
    }
  }
};

/**
* getElementsByAttribute
* Da sistemare : portare in json attibuti, utilizzare visitDomTree, ie6 (with strTagName=*)!
*
* @param node required oElm - Node element
* @param string required strTagName
* @param string required strAttributeName
* @param string required strAttributeValue
* @return array arrReturnElements
*/
Utility.getElementsByAttribute = function (oElm, strTagName, strAttributeName, strAttributeValue){
    var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)") : null;
    var oCurrent;
    var oAttribute;
    for(var i=0; i<arrElements.length; i++){
        oCurrent = arrElements[i];
        oAttribute = oCurrent.getAttribute(strAttributeName);
        if(typeof oAttribute == "string" && oAttribute.length > 0){
            if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
                arrReturnElements.push(oCurrent);
            }
        }
    }
    return arrReturnElements;
};

Utility.isChildOf = function ( elm, parent )
{
  while( (elm=elm.parentNode) != null ) if ( elm === parent ) return true;
  return false;
};

/**
* Cross browser method for creating new DOM nodes with name attributes. This
* gets around an Internet Explorer bug that prevents that get the name property
* assigned to them and their values aren't sent when the form submits.
*
* @param string required Node name, like "div" or "input"
* @param string required Value of the name attribute
* @return object New DOM node
*/
Utility.createElement = function (nodeName, name, enctype) 
{
  var node;
  try 
  {
    node = Utility.createElementMsie(nodeName, name, enctype);
    createElement = Utility.createElementMsie;
  } 
  catch (e) 
  {
    node = Utility.createElementStandard(nodeName, name, enctype);
    createElement = Utility.createElementStandard;
  }
  return node;
};

/**
* Code required by Internet Explorer when creating a new DOM node with the
* name attribute set.
*/
Utility.createElementMsie = function (nodeName, name, enctype) 
{
  if (!enctype) enctype = "";
  return document.createElement("<"+nodeName+" name="+name+" enctype="+enctype+">");
};

/**
* Code required by all other browsers that support web standards.
*/
Utility.createElementStandard = function (nodeName, name, enctype) 
{
  var node = document.createElement(nodeName);
  node.name = name;
  if (enctype)
  {
    node.setAttribute("enctype", enctype);
  }
  return node;
};

// Funzione per la creazione di cookie da javascript
Utility.createCookie = function (name,value,days) 
{
	if (days) 
  {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

// Funzione per la lettura dei cookie da javascript
Utility.readCookie = function (name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

/**
* loadSyncFile
*
* @param string required url
* @param boolean option xmlReturn
*/
Utility.loadSyncFile = function ( url, xmlReturn )
{
  var xmlHttp;
  try
  {
    // Oggetto per Firefox, Opera 8.0+, Safari
    xmlHttp = new XMLHttpRequest();
  }
  catch (e)
  {
    try
    {
      // ActiveX per Internet Explorer
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
      try
      {
        // ActiveX per Internet Explorer < 6.0
        xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e)
      {
        return null;
      }
    }
  }
  
  xmlHttp.open("GET", url, false);
  xmlHttp.send(null);
  
  if (xmlHttp.status == 200) 
  {
    if ( xmlReturn === true ) return xmlHttp.responseXml;
    else return xmlHttp.responseText; 
  }
  else 
  {
    return null;
  }
};

// Funzione per la cancellazione di un cookie
Utility.eraseCookie = function (name) 
{
	createCookie(name,"",-1);
};

// Funzione per il controllo sui numeri ( float ed int )
Utility.is_numeric = function (val)
{
   if ((isNaN(val)) || (val.length == 0))
      return false;
   else
      return true;
};

// Funzione per il controllo sui numeri interi
Utility.is_int = function (val)
{
   if ((isNaN(val)) || (val.length == 0) || ( val.indexOf(".") != -1 ) )
      return false;
   else
      return true;
};

// Funzioni da controllare e ottimizzare
Utility.trim = function (stringa)
{ 
  while (stringa.substring(0,1) == ' ')
  {
      stringa = stringa.substring(1, stringa.length);
  }
  while (stringa.substring(stringa.length-1, stringa.length) == ' ')
  {
      stringa = stringa.substring(0,stringa.length-1);
  }
  return stringa;
};

/*
  Individuo la posizione del cursore in una textare o input text.             
  In generale
              -> 0 è inizio
              -> e node.value.length è la fine
*/
Utility.caret = function (node) 
{
  if(node.selectionStart) return node.selectionStart;
  else if(!document.selection) return 0;
  var c		= "\001";
  var sel	= document.selection.createRange();
  var txt	= sel.text;
  var dul	= sel.duplicate();
  var len	= 0;
  try{ dul.moveToElementText(node); }catch(e) { return 0; }
  sel.text	= txt + c;
  len		= (dul.text.indexOf(c));
  sel.moveStart('character',-1);
  sel.text	= "";
  return (len == -1)? node.value.length : len;
};

Utility.is_numeric = function ( val )
{
   if ((isNaN(val)) || (val.length == 0))
      return false;
   else
      return true;
};

Utility.removeAllChild = function ( nodo )
{
  while ( nodo.hasChildNodes() ) 
  { 
    nodo.removeChild( nodo.firstChild );
  }
};

Utility.getIframeValue = function ( obj )
{
  try
  {
    var val = obj.contentDocument.body.innerHTML;
  }
  catch(e)
  {
    var val = obj.contentWindow.document.body.innerHTML;
  }
  return val;
};

/*******************************************************************************
  [END UTILITY]  
*******************************************************************************/
/*******************************************************************************
  [OVERLOADIND OVERRING FUNZIONI DI UTILITÁ]  
*******************************************************************************/
sync                    = Utility.sync;
toArray                 = Utility.toArray;
typeOf                  = Utility.typeOf;

createXmlDom            = Utility.createXmlDom;
createElement           = Utility.createElement;
removeAllChild          = Utility.removeAllChild;

parseStrToXml           = Utility.parseStrToXml;
parseFileToXml          = Utility.parseFileToXml;
parseStrToJson          = Utility.parseStrToJson;
retriveRcFromXml        = Utility.retriveRcFromXml;
loadSyncFile            = Utility.loadSyncFile;

getElementsByClassName  = Utility.getElementsByClassName;
getElementsByClass      = Utility.getElementsByClass;
getElementsByAttribute  = Utility.getElementsByAttribute;
visitDomTree            = Utility.visitDomTree;
isChildOf               = Utility.isChildOf;
setUnselectable         = Utility.setUnselectable;

caret                   = Utility.caret;
trim                    = Utility.trim;
is_int                  = Utility.is_int;
is_numeric              = Utility.is_numeric;
eraseCookie             = Utility.eraseCookie;
readCookie              = Utility.readCookie;
createCookie            = Utility.createCookie;
getIframeValue          = Utility.getIframeValue;
is_numeric              = Utility.is_numeric;
/*******************************************************************************
  [END OVERLOADIND OVERRING FUNZIONI DI UTILITÁ]  
*******************************************************************************/
/*******************************************************************************
  [JEvent OBJECT]  
*******************************************************************************/
$E  = JEvent = {};

/*
  [JEvent.eventStates] - Struttura dati listener 
  @obj        : OBJ DOM   --oggetto
  @evType     : STRING    --evento
  @funct      : FUNCTION  --funzione con bind
  @realFunct  : FUNCTION  --funzione originale
  @useCapture : BOOLEAN   --useCapture
  @opt        : JSON      --parametri
  
  Nota: La proprietà realFunct serve per confrontare le funzioni dei listenere
  nel metodo retriveIdx. I confronti non possono essere eseguiti con la funzione
  bindata, in quanto viene associato un indice differente e ciò comporta una replica
  della funzione di input ( con riferimento diverso dall'originale). Per poter
  eseguire correttamente il confronto dobbiamo confrontare i riferimenti alle
  funzioni orginali.
*/

$ES = JEvent.eventStates = [];

/* 
  [JEvent.add] - Metodo per l'aggiunta di un listener
  ritorna false in caso di problemi o nel caso il listener sia già presente
  altrimenti torna l'indice associato al listener
  ---
  @obj        : OBJ DOM   --oggetto
  @evType     : STRING    --evento
  @funct      : FUNCTION  --funzione
  @useCapture : BOOLEAN   --useCapture
  @opt        : JSON      --parametri
  ---
  
  Possiamo recuperare i parametri in 2 modi:
  - Tramite un terzo parametro passato come argomento ( oggetto ) che passa per
    valore numeri e var stringhe    
  - Tramite $ES che mantiene dei riferimenti
*/
JEvent.add = function(obj, evType, funct, useCapture, opt)
{
  // Calcolo idxEventStates 
  var idxEventStates = JEvent.eventStates.indexOf ( null );
  idxEventStates = ( (idxEventStates != -1) ) ? ( idxEventStates ) : (JEvent.eventStates.length);
  
  // Binding idxEventStates
  var realFunct = funct;
  var funct     = funct.bindEventListener( obj, idxEventStates, opt );
  
  // se il listener risulta gia' presente ritorno false
  if ( 
    JEvent.retriveIdx({
        "obj"         : obj,
        "evType"      : evType,
        "realFunct"   : realFunct,
        "useCapture"  : useCapture
      }) 
  ){
    return false;
  }
  
  // Allacciamento Listener
  try
  { 
    obj.addEventListener( evType, funct, useCapture );   
  }
  catch(e)
  {
    try
    {
      obj.attachEvent("on" + evType, funct);
    }
    catch(e)
    {
      return false;
    }
  }
  
  // Aggiunta informazioni in eventStates
  JEvent.eventStates[idxEventStates] = 
    ({ 
      "obj"         : obj, 
      "evType"      : evType,
      "realFunct"   : realFunct,
      "funct"       : funct,
      "useCapture"  : useCapture,
      "opt"         : opt,
      "status"      : 0 
    });
  
  // Ritorno l'indice associato  
  return idxEventStates;  
};

/* 
  [JEvent.deactive] - Metodo ...
*/
JEvent.deactive = function( JSON )
{
  var arrIdxListener = JEvent.retriveIdx( JSON );
  
  if ( arrIdxListener )
  {
    var esito = true;
    
    for ( i=0;i<arrIdxListener.length;i++)
    {
      esito = ( JEvent.deactiveIdx ( arrIdxListener[i] ) ) ? ( esito ) : ( false ) ;
    }
    
    return esito;
  }
  else
  {
    return false;
  }
};

/* 
  [JEvent.deactiveIdx] - Metodo per la disattivazione di un listener (idx)
  Ritorna false se idx non esiste nell'array altrimenti true.
  ---
  @idx : INTEGER   --indice
*/
JEvent.deactiveIdx = function( idx )
{
  if ( JEvent.eventStates[idx] )
  {
    JEvent.eventStates[idx].status = 1;
    return true;
  }
  else
  {
    return false;
  }
};

/* 
  [JEvent.active] - Metodo ....
*/
JEvent.active = function( JSON )
{
  var arrIdxListener = JEvent.retriveIdx( JSON );
  
  if ( arrIdxListener )
  {
    var esito = true;
    
    for ( i=0;i<arrIdxListener.length;i++)
    {
      esito = ( JEvent.activeIdx ( arrIdxListener[i] ) ) ? ( esito ) : ( false ) ;
    }
    
    return esito;
  }
  else
  {
    return false;
  }
};

/* 
  [JEvent.activeIdx] - Metodo per l'attivazione di un listener (idx)
  Ritorna false se idx non esiste nell'array altrimenti true
  ---
  @idx : INTEGER   --indice
*/
JEvent.activeIdx = function( idx )
{
  if ( JEvent.eventStates[idx] )
  {
    JEvent.eventStates[idx].status = 0;
    return true;
  }
  else
  {
    return false;
  }
};

/* 
  [JEvent.retriveIdx] - Metodo per il retrive indice di un listener
  Ritorna false se non viene trovato nessun elemento altrimenti l'array degli 
  indici restituiti. ( ! da completare )
  ---
  @JSON  : OBJ DOM   --oggetto
*/
JEvent.retriveIdx = function( JSON )
{
  var tempArrIdx = [];   
  
  for ( idx=0; idx<JEvent.eventStates.length; idx++  )
  {
    if ( JEvent.eventStates[idx] )
    {
      var pushing = true;
      
      for ( param in  JSON )
      {
        pushing = ( JSON[param] != JEvent.eventStates[idx][param] ) ? ( false ) : ( pushing ) ; 
      }
      
      if ( pushing ) tempArrIdx.push( idx );
    }
  }

  return ( tempArrIdx.length == 0) ? ( null ) : ( tempArrIdx );
};

/* 
  [JEvent.retriveListenerInformation] - Metodo per il retrive informazioni
  Ritorna false se idx non esiste nell'array altrimenti il JSON contente le informazioni
  sul listener idx
  ! forse inutile visto eventStates e' pubblico
  ---
  @idx : INTEGER   --indice
*/
/*
JEvent.retriveListenerInformation = function( idx )
{
  if ( JEvent.eventStates[idx] )
  {
    return JEvent.eventStates[idxEventStates];
  }
  else
  {
    return false;
  }
};
*/

/* 
  [JEvent.remove] - Metodo per la rimozioni di un array di listener
  Ritorna false in caso di problemi altrimenti true se tutte le rimozioni avviengono
  con successo.
  ---
  @arrIdx     : ARRAY[INTEGER]   --array interi indici listener
*/
JEvent.remove = function( arrIdx )
{
  var esito = true;
  if ( typeOf ( arrIdx ) == 'array' ) 
  {
    for (i=0;i<arrIdx.length;i++)
    {
      esito = ( JEvent.removeIdx ( arrIdx[i] ) ) ? ( esito ) : ( false );
    }
    return esito;
  }
  return false;
};

/* 
  [JEvent.removeIdx] - Metodo per la rimozioni di un listener
  Ritorna false se idx non esiste o se si verificano problemi altrimenti true 
  se la rimozione del lister avviene con successo.
  ---
  @idx : INTEGER   --indice
*/
JEvent.removeIdx = function( idx )
{ 
  if ( JEvent.eventStates[idx] )
  { 
    try
    {
      JEvent.eventStates[idx].obj.removeEventListener(
          JEvent.eventStates[idx].evType, 
          JEvent.eventStates[idx].funct, 
          JEvent.eventStates[idx].useCapture
        );
    }
    catch(e)
    {
      try
      {
        JEvent.eventStates[idx].obj.detachEvent(
            "on" + JEvent.eventStates[idx].evType, 
            JEvent.eventStates[idx].funct
          );
      }
      catch(e)
      {
        return false;
      }
    }
    
    JEvent.eventStates[idx] = null;
    return true;  
  }
  
  return false;
};

/* 
  [JEvent.fire] - Metodo per lanciare un evento.
  Ritorna false in caso di problemi, altrimenti true.
  ---
  @obj        : OBJ DOM   --oggetto
  @evType     : STRING    --evento
*/
JEvent.fire = function (obj, evType)
{
  try{
      obj.fireEvent("on"+evType);
      return true;
  }
  catch(e)
  {
    var fireEvent = window.document.createEvent("UIEvent");   // KeyEvent  e MouseEvent sono sottoclassi
    fireEvent.initEvent(evType, false, true);                 // ci sono anche altre funzioni da capire il funzionamento: false -> bubbling true -> canceleable
    obj.dispatchEvent(fireEvent);
    return true;
  }
  return false;
};

/* 
  [JEvent.fireIdx] - Metodo per lanciare un evento
  Ritorna false in caso di problemi, altrimenti true.
  ---
  @obj        : OBJ DOM   --oggetto
  @evType     : STRING    --evento
*/ 
JEvent.fireIdx = function ( idx )
{
  if ( JEvent.eventStates[idx] )
  {
    return JEvent.fire( 
        JEvent.eventStates[idx].obj, 
        JEvent.eventStates[idx].evType 
      );
  }
  else
  {
    return false;
  }
};

/* 
  [JEvent.preventDefault] - Metodo per annullare l'azione HTML di default
  Ritorna false in caso di problemi, altrimenti true.
  ---
  @evt  : EVENT OBJ   --oggetto evento scatenato dalla funzione 
*/
JEvent.preventDefault = function ( evt )
{
  try
  {
    evt.preventDefault();   // FF
  }
  catch(err)
  {
    try
    {
      evt.returnValue = false;  // IExplorer ( non sempre c'è un azione di default con il try se non c'è non sollevo l'errore)
    }
    catch(e)
    { 
      return false; 
    }
  }
  return true;
} 
/*******************************************************************************
  [END JEvent OBJECT]  
*******************************************************************************/
/*******************************************************************************
  [JAjax OBJECT]  
*******************************************************************************/
$A = function( parameters )
{
  return new JAjax ( parameters );
};

JAjax = function( parameters )
{
  this.XHR          = null;
  this.ttl          = null;
  this.queryString  = null;
  this.method       = null;
  this.responseType = null;
  this.action       = null;
  this.cache        = null;
  this.operation    = null; 
  this.errOperation = null;
  this.localState   = null;
  this.lock         = null;
   
  this.init( parameters );
};

JAjax.prototype.init = function( parameters )
{
  var xmlHttp;
  try
  {
    // Oggetto per Firefox, Opera 8.0+, Safari
    xmlHttp = new XMLHttpRequest();
  }
  catch (e)
  {
    try
    {
      // ActiveX per Internet Explorer
      xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
      try
      {
        // ActiveX per Internet Explorer < 6.0
        xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e)
      {
        return false;
      }
    }
  }
  
  parameters = ( parameters ) ? ( parameters ) : ( {} );
  
  this.XHR          = xmlHttp;
  this.ttl          = parameters["ttl"] || 600000;
  this.method       = parameters["method"] || "GET";
  this.responseType = parameters["responseType"] || "TEXT";
  this.action       = parameters["action"] || "";
  this.cache        = parameters["cache"] || true;
  this.operation    = parameters["operation"] || null;
  this.errOperation = parameters["errOperation"] || displayError; 
  this.localState   = parameters["localState"] || true;
  this.lock         = parameters["lock"] || false;
  this.queryString  = "";
  
  return true;
};


JAjax.prototype.addQueryString = function ( key,value )
{
  if (this.queryString != "") this.queryString += "&";
  // EncodeUri oltre che a proteggere l'invio dei dati in get/post da caratteri
  // particolare, converte il tutto in utf8 per l'invio corretto.
  this.queryString += key + "=" + encodeURIComponent(value);
};


JAjax.prototype.sendData = function()
{
  if ( ( !JAjax.globalState ) || ( !this.localState )  || ( this.lock ) )
  {
    return false;
  }
  
  // Closure
  var istanceJA = this;
  
  istanceJA.localState = false;
  
  var checkTime;          // Oggetto per il controllo del tempo
  var firstCheck = true;  // Semaforo per il controllo del tempo
  
  // Devo costruire il corretto passaggio di dati per GET/POST
  var link    = ( istanceJA.method.toUpperCase() == "POST" ) ? istanceJA.action : istanceJA.action+"?"+istanceJA.queryString ;
  var qstring = ( istanceJA.method.toUpperCase() == "POST" ) ? istanceJA.queryString : "" ;
  
  // Sistema di protezione da cache
  if ( (istanceJA.method.toUpperCase() == "GET") && (istanceJA.cache) )
  {
    var data = new Date();
    link += "&tstamp=" + encodeURIComponent(data.getHours() + data.getMinutes() + data.getSeconds() );
  }
  
  // Memorizzo l'istante della chiamata ajax
  var dateCall = new Date();
  var startCall = dateCall.getTime();
  
  // Imposto gli header per la chiamata
  istanceJA.XHR.open( istanceJA.method, link, true );
  
  // Per le chiamte POST devo aggiungere l'intestazione corretta
  if (istanceJA.method.toUpperCase() == "POST")
  {
    istanceJA.XHR.setRequestHeader("content-type", "application/x-www-form-urlencoded");
  }
  
  // Questa intestazione va aggiunta per ciascuna connessione
  istanceJA.XHR.setRequestHeader("connection", "close");
  
  // Imposto la funzione di controllo dello stato della chiamata ajax
  istanceJA.XHR.onreadystatechange = function()
  {
    if ( istanceJA.XHR.readyState === readyState.COMPLETATO )
    {
      checkTime = function(){};
      
      if( statusText[istanceJA.XHR.status] === "OK" )
      {
        if ( istanceJA.responseType.toUpperCase() === "XML" )
        {
          istanceJA.localState = true;
          istanceJA.operation ( istanceJA.XHR.responseXML );
        }
        else
        {
          istanceJA.localState = true;
          istanceJA.operation ( istanceJA.XHR.responseText );
        }
      }
      else
      {
        istanceJA.localState = true;
        istanceJA.errOperation ( statusText[istanceJA.XHR.status] );
      }
    }
    else if( firstCheck )
    {
      firstCheck = false;
      
      checkTime = function()
        {
          dateCurrent = new Date();
          currentCall = dateCurrent.getTime();
      
          if ( (currentCall - startCall) > istanceJA.ttl )
          {
            istanceJA.XHR.onreadystatechange = function(){ return false; };
            istanceJA.XHR.abort();
            istanceJA.localState = true;
          }
          else
          {
            setTimeout(checkTime, 100);
          }
        };
      checkTime();  
    }
  };
  
  // Effettuo la chiamata ajax
  istanceJA.XHR.send(qstring);
};

JAjax.globalState = true;

function displayError(){};

// Oggetto per la verifica dello stato
var readyState = {
  INATTIVO: 0,
  INIZIALIZZATO: 1,
  RICHIESTA: 2,
  RISPOSTA: 3,
  COMPLETATO: 4
};

// Array descrittivo dei codici restituiti dal server
var statusText = new Array();
statusText[0] = "Richiesta Fallita. Riprovare più tardi"; // Aggiunta per Abort
statusText[100] = "Continue";
statusText[101] = "Switching Protocols";
statusText[200] = "OK";
statusText[201] = "Created";
statusText[202] = "Accepted";
statusText[203] = "Non-Authoritative Information";
statusText[204] = "No Content";
statusText[205] = "Reset Content";
statusText[206] = "Partial Content";
statusText[300] = "Multiple Choices";
statusText[301] = "Moved Permanently";
statusText[302] = "Found";
statusText[303] = "See Other";
statusText[304] = "Not Modified";
statusText[305] = "Use Proxy";
statusText[306] = "(unused, but reserved)";
statusText[307] = "Temporary Redirect";
statusText[400] = "Bad Request";
statusText[401] = "Unauthorized";
statusText[402] = "Payment Required";
statusText[403] = "Forbidden";
statusText[404] = "Not Found";
statusText[405] = "Method Not Allowed";
statusText[406] = "Not Acceptable";
statusText[407] = "Proxy Authentication Required";
statusText[408] = "Request Timeout";
statusText[409] = "Conflict";
statusText[410] = "Gone";
statusText[411] = "Length Required";
statusText[412] = "Precondition Failed";
statusText[413] = "Request Entity Too Large";
statusText[414] = "Request-URI Too Long";
statusText[415] = "Unsupported Media Type";
statusText[416] = "Requested Range Not Satisfiable";
statusText[417] = "Expectation Failed";
statusText[500] = "Internal Server Error";
statusText[501] = "Not Implemented";
statusText[502] = "Bad Gateway";
statusText[503] = "Service Unavailable";
statusText[504] = "Gateway Timeout";
statusText[505] = "HTTP Version Not Supported";
statusText[509] = "Bandwidth Limit Exceeded";
/*******************************************************************************
  [END JAjax OBJECT]  
*******************************************************************************/
})();   
