/* EFFETTO SLIDE PER MENU VERTICALI

  Questo effetto si applica a menu verticali annidati.
  
  Per utilizzarlo è necessario includere nello head del documento html l'istruzione
  
  <script type="text/javascript" src="sliding-menus.js"></script>
  
  Inoltre il codice HTML deve essere strutturato come segue perchè questo effetto funzioni:
  - tutte le voci del menu sono DIV
  - ogni menu è costituito da un DIV con class menu-group che contiene un DIV con class menu-header e un div con class menu-body: il DIV con class menu-header è quello che contiene le voci di menu che corrispondono a sottomenu (e che saranno sensibili al click del mouse), il Div con class menu_body è quello che contiene le voci del sottomenu corrispondete allo header
  - le voci che corrispondono a titoli di sottomenu possono essere accompagnate da una immagine che deve essere inserita nel DIV dello header dopo il testo; lo script cambia l'immagine da 'images/rolled-up.gif' a 'images/rolled-down.gif': la prima è l'immagine che caratterizza i sottomenu chiudi, la seconda quelli aperti
  - lo voci che corrispondono a foglie del menu, cioè che non corrispondono ad alcun sottomenu sono DIV con class menu-leaf
  
  esempio:
  
  il codice 
  
   <div class="menu-group"><div class="menu-header">sottomenu 1 <img src="images/rolled-up.gif"></div>
    <div class="menu-body">
      <div class="menu-group"><div class="menu-header">sottomenu 1.1 <img src="images/rolled-up.gif"></div>
        <div class="menu-body">
          <div class="menu-leaf">voce 1.1.1</div>
          <div class="menu-leaf">voce 1.1.2</div>
          <div class="menu-leaf">voce 1.1.3</div>
        </div>
      </div>
      <div class="menu-leaf">voce 1.2</div>
    </div>
   </div>
   <div class="menu-group"><div class="menu-header">sottomenu 2 <img src="images/rolled-up.gif"></div>
    <div class="menu-body">
      <div class="menu-leaf">voce 2.1</div>
      <div class="menu-leaf">voce 2.2</div>
      <div class="menu-leaf">voce 2.3</div>
    </div>
   </div>

  produce la struttura
  
  sottomenu 1
    sottomenu 1.1
      voce 1.1.1
      voce 1.1.2
      voce 1.1.3
    voce 1.2
  sottomenu 2            
    voce 2.1
    voce 2.2
    voce 2.3
*/

window.addEvent('domready', function(){
  var slideOnComplete = function(body){
    // l'effetto slide inserisce l'elemento a cui si applica all'interno di un div che nel caso di menu annidati è necessario ridimensionare in modo tale che i menu interni trovino lo spazio per aprirsi
    wrapper = body.getParent();
    if (wrapper) {
      // rolledDown indica lo stato dell'elemento e serve per dimensionare l'altessa del wrapper in modo che il menu generale di allarghi e restringa per accomodare la comparsa e scomparsa dei sottomenu
      rolledDown = body.hasClass('_rolledDown');
      // ATTENZIONE: il caso wrapper.setStyle('height', '0') serve per garantire compatibilità con IE6, altrimenti basterebbde wrapper.setStyle('height', 'auto') indipendentemente dal valore di rolledDown
      if (!rolledDown) {
        wrapper.setStyle('height', '0')
      }
      else {
        wrapper.setStyle('height', 'auto')
      }
    }
  }
  
  var toggleRolledDown = function(options){
    // i valori di rolledDown sono 1 o 0; se non viene specificato come parametro si cambia il valore di rolledDown da quello corrente all'altro, altrimenti si cambia il valore di rolledDown a quello specificato
    header = options.header;
    pippo = options.body;
    if (!$defined(header)) {alert('toggleRolledDown: header non specificato'); return 0};
    if (!$defined(pippo)) {alert('toggleRolledDown: body non specificato'); return 0};
    if (!$defined(options.rolledDown)) {
      rolledDown = pippo.hasClass('_rolledDown');
    }
    else {
      rolledDown = options.rolledDown == true ? false : true;
    }
    // si realizza il toggle del valore di rolledDown da 1 a 0 e viceversa
    if (rolledDown) {
      // memorizza lo stato del menu
      pippo.removeClass('_rolledDown');
      header.removeClass('_rolledDownHeader');
    }
    else {
      // memorizza lo stato del menu
      pippo.addClass('_rolledDown');
      header.addClass('_rolledDownHeader');
    }
  }; 
   // costruisce la lista dei gruppi di menu
  var list = $$('.menu-group');
  var header2slide = [];
  // crea la transizione
  var transition = new Fx.Transition(Fx.Transitions.Expo);
 
  i = 0;
  list.each(function(element) {
    // per ogni gruppo di menu, aggiunge un listener per l'evento click del mouse sullo header: l'evento applicherà una transizione di tipo slide al DIV del corpo del menu e cambierà l'immagine associata allo header, se ce ne è una
    var header = element.getElement('.menu-header');
    var body = element.getElement('.menu-body');
      
    if (body) {
      // crea la funzione che applica la transizione al body
      slide = new Fx.Slide(body, {duration: 500, transition: transition.easeOut, onComplete: slideOnComplete.pass(body)});
      // costruisce le corrispondenze fra header, body e relative funzioni per lo slide
      header2slide[i] = {header: header, body:body, slide: slide};
      // si segna se il menu è aperto o chiuso
      rolledDown = body.hasClass('_rolledDown');
      // se il menu è chiuso o la pagina è appena stata caricata (property _rolledDown non definita) nasconde il body
      if (!rolledDown) {
        header.removeClass('_rolledDownHeader');
        header2slide[i].slide.hide();
      }
      else {
        header.addClass('_rolledDownHeader');
      }
      // serve per rendere visibili i body di menu che sono stati dichiarati con display:none nello stile per evitare che si vedano in fase di carimaneto della pagina
      body.setStyle('display', 'block');
      i++;
    }
  });
  
  var numBodies = header2slide.length;
  
  // aggiunge il listener al click sullo header
  header2slide.each(function(element) {
    var header = element.header;
    var body = element.body;
    
    header.addEvent('click', function(){
      // chiude tutti gli altri menu
      header2slide.each(function(otherElement) {
        otherHeader = otherElement.header;
        otherBody = otherElement.body;
        if (header != otherHeader) {
          toggleRolledDown({header: otherHeader, body: otherBody, rolledDown: false});
          otherElement.slide.slideOut('vertical');
        }
      });
      // aggiorna la proprietà _rolledDown che indica lo stato dell'elemento
      // ATTENZIONE: va fatto PRIMA di chiamare l'evento se di vuole usare questa proprietà nella onComplete dell'evento
      toggleRolledDown({header: header, body: body});
      // applica la transizione al body
      element.slide.toggle('vertical');
    });
  });
});
