/**
 * <h2>subForm</h2>
 *
 * <p>Teile eines Formulars/Webseite nur auf Bedarf einblenden/ausblenden per Button. Auch zum Realisieren von Menus geeignet</p>
 * Ein Subform enthält
 * <ul>
 *  <li> die CSS-Klasse "subForm"</li>
 *  <li> ein "for"-Attribut mit der Id / den Ids der Button-Element, die das subform offnen/schlissen (toggle-Mechanismus).
 *    Mehere Ids werden mit Leerzeichen getrennen.</li> 
 *  <li> ODER/UND ein "hover" Attribut mit der Id des Button-Elements (wie for; statt Klickevent mit mouseover) 
 *    Wichtig: hier kein close, load, option, moeglich. Radio/Checkbox oder Selectlisten werden nicht untestuetzt.
 *    Das subForm wird geschlossen wenn der button ODER die subForm verlassen wird. (wird die subForm in 100ms betrehten, 
 *    wird wegen Verlassens des button nicht geschlossen -> nuetzlich fuem Realisieren von Menus)
 *    Mehere Ids werden mit Leerzeichen getrennen.</li>
 * </ul>   
 * 
 * Optional:
 * <ul> 
 *  <li> die CSS-Klasse "open":    lasst subForm am Anfang offen</li>
 *  <li> die CSS-Klasse "norest":  lasst die Formulardaten stehen beim Schliessen</li>
 *  <li> die CSS-Klasse "notrans": oeffnet/schliesst subForm sofort, sonst mit Verzoegerungseffekt</li>
 *  <li> die CSS-Klasse "noBlock": sorgt dafuer, dass beim Anzeigen, die normale css Vorgabe benuzt wird, nicht explizit Block</li>
 *  <li> die CSS-Klasse "menu-bottom" oder 'menu-right': positioniert das subForm unter/rechts vom Button</li>
 *  
 *  <li> ein "load" Attribut, das die zu ladende Inhalt angibt, wenn die Subform geoeffnet wird (per Ajax, Url angeben)</li>
 *  <li> ein "close" Attribut mit der Id des A-Elements, dessen subForms geschlossen werden sollen (* wildcard verwendbar)
 *    zusaetzlich: zusammen mit load ist es auch die Button-ID IN der subForm, die die subForm schliesst.
 *  <li> ein "option" Attribut gibt die Selectoptionfelder-Ids an, die als Button dienen sollen</li>
 *  
 *  <li>als button werden a, input.checkbox, input.radio, und select.option unterstuetzt</li>
 *  <li> a,input mit einer CSS-Klasse "noclose" verbietet das Schliessen seiner Subforms (nur oeffnen)</li>
 * </ul>
 * <br/>
 * @version      0.99<br/>
 * @author       Dragan Espenschied <drx@a-blast.org>, Michael Kaiser<mk@plusw.de><br/>
 * @requires     jQeury v1.3.1<br/>
 *
 */
var subForm = {

    /**
     * Liste aller form-umschaltenden Buttons mit ihren forms
     */
    buttonList: {},
    buttonListHover: {},
    /**
     * Liste aller forms mit ihren buttons
     */   
    nodeList: [],
     /**
     * Liste aller form-close Buttons
     */   
    closerList: {},

    /**
     * Timer fur das schliesen de subnenus beim verlassen (onmouseout)
     */
    timer: null,
    /**
     * Initialisiert Behandlung der subForms.
     * Muss in $(document).ready ausgeführt werden.
     * Gesucht werden alle Elemente mit der Klasse subForm.
     * Diese werden erstmal unsichtbar geschaltet.
     * Zu jedem Subform wird über das "for"-Attribut der
     * entsprechende Trigger-Button gesucht und dieser mit
     * der Einblende-Funktion ausgestattet.
     *
     * Parameter: 
     *  tag (Object) : Ein Tag, ab dessen Stelle subForms gesucht werden sollen. Optional. Default Suche ab body.
     *  
     * @see     subForm#handler
     */
    init: function(tag){
      
        //bei ajaxreload und am anfang neu init
        subForm.buttonList = {};
        subForm.nodeList = []; 
      
        var subforms;
        if (tag) {
          subforms = $(tag).find(".subForm");
        }
        else {
          subforms = $(".subForm");
        }
        
        subforms.each(function(){
        
            var node = this;            
        
            if ($(node).hasClass('open')){
               $(node).removeClass('open');
            }
            else {
               subForm.hide(node,null, '1'); //schliessen ohne inhalt zu loschen
            }
            
            if (node.attributes['for']) {
                // sofern für das subform einer oder mehrere
                // trigger im "for" des Tags definiert sind ...
                var forAttribute = node.attributes['for'].value;
                
                if (forAttribute.length > 0) {
                
                    var triggerIds = forAttribute.split(/\s+/);
                  
                    var triggers = [];
                    $.each(triggerIds, function(){
                      var t = Util.idDom(this);
                      if (t && (t.tagName == 'A' || t.tagName == 'SELECT' || (t.tagName == 'INPUT' && (t.type == "radio" || t.type == "checkbox")))) {
                        triggers.push(t);
                      }
                    });
                    
                    //buttons wo subForm schliessenden soll, mit *-wildcart werden alle gefunden die passen
                    if (node.attributes.close && node.attributes.close.value) {
                      var closeIds = node.attributes.close.value.split(/\s+/);
                      $.each(closeIds, function(){

                        //wenn wildcard, alle gewuenschten suchen und hinzufuegen
                        if (this.indexOf('*') !=-1) {
                          $('a[id*='+this.replace('*','')+']').each(function(){
                              //ungueltige buttons ignorieren
                              if (!Util.idDom(this)) {
                                return;
                              }
                              if (subForm.closerList[this.id]) {
                                subForm.closerList[this.id].forform.push(node);
                              } 
                              else {
                                subForm.closerList[this.id] = {forform: [node]};
                              }

                          });
                        } else {
                            //ungueltige buttons ignorieren
                            if (!Util.idDom(this)) {
                              return;
                            }                         
                            //einfache id hizufuegen   
                            if (subForm.closerList[this]) {
                              subForm.closerList[this].forform.push(node);
                            } 
                            else {
                              subForm.closerList[this] = {forform: [node]};
                            }
                        }
                      });
                    }

                    subForm.nodeList.push({node:node, elements:triggers});
                    //var trigger = Util.idDom(this.attributes["for"].value);    // zugehöriger Button
                  
                    // gefundene Trigger-Buttons untersuchen und speichern
                    $.each(triggers, function(){
                      var button = this;
                      var listb = subForm.buttonList[$(button).attr('id')];
                      if (listb) {
                        listb.forform.push(node);
                        //if (closetriggers[button.id]) listb.closeform.push(closetriggers[button.id]);
                      }
                      else {
                        subForm.buttonList[$(button).attr('id')] = {
                                  element: button,
                                  forform: [node]
                                  //closeform: closetriggers[button.id] ? [closetriggers[button.id]] : []
                        };
                      } // Erstmal den Button an sich speichern
                      if (button.tagName == "INPUT") {
                        if (button.type == "radio") {
                        
                          // Alle Radio-Buttons mit dem gleichen Namen finden
                          $("input[name=" + button.name + "]").each(function(){
                            var radio = this;
                            //aktuellen und alle die schon drin sind ignorieren
                            var listr = subForm.buttonList[$(radio).attr('id')];
                            if (!listr) {
                               subForm.buttonList[$(radio).attr('id')] = {
                                  element: radio,
                                  forform: []
                               };
                            }
                          });
                        }
                      }
                      if (button.tagName == "SELECT") {
                         if (node.attributes && node.attributes.option) {
                           var optionsValues = node.attributes.option.value.split(/\s+/);
                           //alle options speichern, die ein trigger haben sollen

                           $.each(optionsValues, function(){
                             var el = $(button).find('option[value=' + this + ']');
                             if(el.val()){
                               var lists = subForm.buttonList[$(button).attr('name')+$(el).val()];
                               if (lists) {
                                 lists.forform.push(node);
                               }
                               else {
                                 subForm.buttonList[$(button).attr('name') + $(el).val()] = {
                                   element: el[0],
                                   forform: [node]
                                 };
                               }
                             }
                           });
                         }
                      }
                    });  
               }   
            }
            
            if (this.attributes.hover) {
                // sofern für das subform einer oder mehrere
                // trigger im "hover" des Tags definiert sind ...
                var hoverAttribute = this.attributes.hover.value;
                
                if (hoverAttribute.length > 0) {
                
                    var triggerHoverIds = hoverAttribute.split(/\s+/);
                    
                    var triggersHover = [];
                    $.each(triggerHoverIds, function(){
                      var hid = Util.idDom(this);
                      if (hid) {
                        triggersHover.push(hid);
                      }
                    });
                    
                    // gefundenes Subform mit Triggern speichern
                    $.each(triggersHover, function(){
                      var button = this;
                      var listb = subForm.buttonListHover[$(button).attr('id')];
                      if (listb) {
                        listb.forform.push(node);
                        //if (closetriggers[button.id]) listb.closeform.push(closetriggers[button.id]);
                      }
                      else {
                        subForm.buttonListHover[$(button).attr('id')] = {
                                  element: button,
                                  forform: [node]
                                  //closeform: closetriggers[button.id] ? [closetriggers[button.id]] : []
                      
                        }; 
                      }
                    });             
                }
                
               //subForm schliessen, wenn diese verlassen wird
               $(node).mouseleave(function() {
                 var t=  window.setTimeout(function(n){
                   subForm.hide(n);
                 },100,this);
                 $(this).data('timer', t);;
               });
               $(node).mouseenter(function() {
                 var t = $(this).data('timer');
                 if(t){
                   window.clearTimeout(t);
                   $(this).data('timer','');
                 };
               });                         
            }
        });
        
        // Alle gefundenen Buttons mit der Funktion belegen
        $.each(subForm.buttonList, function(){
            var node = this;
           //nur einamal machen (kann per ajax wiederholt werden)
           if ($(node).data('click')){
             return;
           }
           $(node).data('click',true);
           
           if (node.element.tagName != "SELECT" && node.element.tagName != "OPTION") {
              $(node.element).bind("click", function(event){
                subForm.handler(node);
                //link abschalten
                if (node.element.tagName == "A"){
                  event.preventDefault();
                  return false;
                }
              });
            }
           else if (node.element.tagName == "SELECT"){
             $(node.element).bind("change", function(){
               subForm.handler(node);
             });             
           }
  
        });
        
        // Alle gefundenen Buttons mit der hover Funktion hover belegen
        $.each(subForm.buttonListHover, function(){
          var button = this;
          //nur einamal machen (kann per ajax wiederholt werden)
          if ($(button).data('hover')){
            return;
          }
          $(button).data('hover',true);
          $(button.element).hover(
            function(){
              subForm.handlerHover(button);
          },function(){
            
               $.each(button.forform, function(){
                 
                 var t = window.setTimeout(function(n){
                   subForm.hide(n)
                 },200, this);
                 $(this).data('timer', t);
               });     
 
            
          });
        });
        
        // funktion einmal ohne user-beteiligung aufrufen,
        // damit die richtigen teile des dokuments sichtbar gemacht werden
        $.each(subForm.buttonList, function(){
          if (this.element.tagName == "INPUT") {
           if (this.element.type == "checkbox" || this.element.type == "radio") {
             if (this.element.checked) {
                subForm.handler(this);
             }
            }
		      }  
          if (this.element.tagName == "SELECT") {
              subForm.handler(this); 
          }
        });
        
    },
     
    /**
     * Kann aufgerufen werden, wenn ein Button geklickt wurde,
     * der irgendwie mit einem Subform in Verbindung steht.
     *
     */
    handler: function(button){

        var element = button.element;
                 
        //radioliste durchpruefen, alle schliessen ausser aktuelles
        if (element.tagName == "INPUT" && element.type == "radio") {

          var name = $(element).attr('name');

          //ganze radiogruppe durchlaufen und alle anderen subForms abschalten
          $.each(subForm.buttonList, function(){
          
            var opt_name = $(this.element).attr('name');
            var b = this;
            if (b.element == element) {
              return;
            } //sich selbst ignorieren
            if (opt_name != name) {
              return;
            }  //nur selbe radiogruppe}
            if (b.forform.length === 0) {
              return;
            } //keine subform vorhanden
            
            //alle subforms durchgehen
            $.each(b.forform, function(){
              if (this) //gueltige subform?
               {
                var bform = this;
                //button hat keine subForms? dann die andere einfach schliessen
                if (button.forform.length === 0) {
                  subForm.hide(bform,b.element);
                }
                else {
                  //andere subForm schliessen, ausser wenns eigene subForm ist
                  $.each(button.forform, function(){
                    if (this && this != bform) {
                      subForm.hide(bform, b.element);
                    }
                  });
                }
              }
            });                 
          });
        } 

        // subForm wird aus- oder eingeblendet.
        // Sofern nicht die Stylesheet-Klasse "notrans" gesetzt ist
        // über eine Animation
        $.each(button.forform, function(){
          var node = this;
          if (node === null || node === undefined) {
            return;
          }
          var show = false;
  
          //zu schliessende subforms aus close liste
          if (subForm.closerList[element.id]) {
            $.each(subForm.closerList[element.id].forform, function(){
              var form = this;
              if (form === null || form === undefined || form == node) {
                return;
              }
              subForm.hide(form);
                              
            });
          }
 
          if (element.tagName == "INPUT") {
              if (element.type == "checkbox") {
                   //toggle open/closed
                  if ($(node).hasClass("closed")) {                  
                        show = true;                  
                  }
                  //offene nicht schliessen , wenn verboten
                  if ($(element).hasClass('noclose') && !$(node).hasClass("closed")) {                  
                        show = true;                  
                  }
              }
              
              if (element.type == "radio") {
                show = true;
              }
          
          }
          
          if (element.tagName == "SELECT") {
            var val = element.value;
            var l_button = subForm.buttonList[$(element).attr('name')+val]; //aktuelles option zu select suchen
            if (l_button && l_button == button) {
              show = true;
            }   
          } 
         
          //wenn closed class gesetzt
          if (element.tagName == "A" && $(node).hasClass("closed")) {
              show = true;
          }
          
          //oeffnen/schliessen 
          if (show) {         
            //wenn geschlossen, oeffnen
            $(node).removeClass("closed");
            //nicht als block anzeigen, sondern  wie im css definiert
            if ($(node).hasClass("noBlock")) {
              $(node).css('display', '');
            }
            else {
              //sofort anzeigen
              if ($(node).hasClass("notrans")) {
                $(node).show();
              }
              else {
                //mit effekt anzeigen
                $(node).slideDown();
              }
            }  
            //neuen inhalt laden
            if($(node).attr('load')) {
              $.ajax({
                url: $(node).attr('load'),
                dataType: 'html',
                success: function(data){
                
                  $(node).html(data);
                  subForm.init(node);
                  //buttons wo subForm schliessenden soll (neu in subForm)
                  if (node.attributes.close && node.attributes.close.value) {
                    var closeIds = node.attributes.close.value.split(/\s+/);
                    $.each(closeIds, function(){
                      var trigger = $(node).find('#'+this);
                      if (trigger.length == 0) {
                        return;
                      } 
                      $(trigger).unbind("click");
                      $(trigger).bind("click", function(event){
                        subForm.hide(node);
                        //link abschalten
                        event.preventDefault();
                        return false;
                      });
                    });
                  }                    
                }
              });
            }
           
            //erstes node bei input.radio auswahlen
            var name;
            //$(this.node).find('input:radio').attr('checked','checked');
            $(node).find('input:radio').each(function(){
              //if (name != $(this).attr('name')){
              name = $(this).attr('name');
              
              if (!$('input:radio[name=' + name + ']:checked').val()) {            
                $(this).attr('checked', 'checked');
                //funktionen ausloesen
                $(this).trigger('click');               
              }
            });
          }
          else {
            //schliessen
            subForm.hide(node, element);
          }

          //andere buttons derselben form gleichschalten --bisher nur input zu input unterstuezt--
          /*jQuery.each(subForm.nodeList, function(){
            var inode = this;
            
            if (inode.node != node) {
              return;
            } //nur selbst
            if (inode.elements.length === 0) {
              return;
            }  // keine buttons, ende
            $.each(inode.elements, function(){
               //mit subform des zu oeffnenten subforms vergleichen -- was es offen ist, net schliessen
              if (this) {

                if (this.tagName == "INPUT" && element.tagName == "INPUT" && this.name != element.name) {
                  if (element.checked) {
                    this.checked = true;
                  }
                  else {
                    this.checked = false;
                  }
                }
                if (element.tagName == "OPTION" && this.tagName == "INPUT") {
                   this.checked = true;                  
                }
              }
            });             
         });*/
       });
     },   
     
     hide: function(node, element, noreset){
       
          //kein schliessen, wenns button es so will
          if (element && ($(element).hasClass('noclose'))) {
            return;
          }
          
          if (node === null || node === undefined || node === this) {
           return;
          }
          
          //ist schon zu
          if ($(node).hasClass("closed")) {
            return;
          }          
          $(node).addClass("closed");

          if ($(node).hasClass("noBlock")){
               $(node).css('display','none');
          }          
          else if ($(node).hasClass("notrans")) {
                $(node).hide();
            }
            else {
                $(node).slideUp();
            }
          //formulardaten leeren  
          if ($(node).hasClass('noreset') || noreset) {
            return;
          } 
          
          $(node).find('input:radio').removeAttr('checked');
          $(node).find('input:checkbox').removeAttr('checked');
          $(node).find('option:selected').removeAttr('selected');
          $(node).find('input:text').val('');
          $(node).find('textarea').html('');       
    },
    
    handlerHover: function(button){
      
      $.each(button.forform, function(){
         var node = this;
         if (node === null || node === undefined) {
           return;
         } 
         
         //SubForm an die Position des buttons schieben (unten oder rechts)
         if($(node).hasClass('menu-bottom')){
           $(node).offset({
             'top':($(button.element).position().top + $(button.element).outerHeight()),
             'left':($(button.element).position().left)
           });
           $(node).css({'minWidth':$(button.element).outerWidth()});
         }
         if($(node).hasClass('menu-right')){
           $(node).offset({
             'top':($(button.element).position().top), 
             'left':($(button.element).position().left + $(button.element).outerWidth())
           });
         }
         
         
         $(node).removeClass("closed");
        //nicht als block anzeigen, sondern  wie im css definiert
        if ($(node).hasClass("noBlock")) {
          $(node).css('display', '');
        }
        else {
          //sofort anzeigen
          if ($(node).hasClass("notrans")) {
            $(node).show();
          }
          else {
            //mit effekt anzeigen
            $(node).slideDown();
          }
        }
                
        //erstes node bei input.radio auswahlen
        var name;
        //$(this.node).find('input:radio').attr('checked','checked');
        $(node).find('input:radio').each(function(){
          //if (name != $(this).attr('name')){
          name = $(this).attr('name');
          
          if (!$('input:radio[name=' + name + ']:checked').val()) {            
            $(this).attr('checked', 'checked');
            //funktionen ausloesen
            $(this).trigger('click');               
          }
        });  
      });      
    }   
};
