/*
  QuinScape Xtreme Foundation Classes   (QXFC)
  JavaScript Framework
  
  Copyright (c) 2009-2010 QuinScape GmbH
  All Rights Reserved.
 
  http://www.quinscape.de
 
  No part of this source code may be distributed in any form, be it altered
  or unaltered, without the explicit written permission of QuinScape.
 
  Author: Nils Berger
*/ 

if(!qxfc)
{
  throw('Requires QXFC JavaScript Framework'); 
}
else if(!qxfc.wait)
{
  /**
   * <p>Erzeugt ein halb-transparentes Overlay mit Warte-Grafik und Sanduhr-Mauszeiger für einen
   * angegebenen Container.</p>
   * 
   * <p>Kann global in das Laden von Seiten per Ajax und in das Tabellen-Sortieren/-Paging sowie
   * dynmaische Filter eingehängt werden.</p>
   * 
   * <p>Ausserdem kann qxfc.wait auch explizit für eine(n) Container/Gruppierung über
   * {@link qxfc.wait.show} oder für eine Tabelle über {@link qxfc.wait.showForTable}
   * ausgelöst werden.</p>
   * 
   * @namespace
   * 
   * @author Nils Berger
   */
  qxfc.wait =
  {
    registerForFilterReload : false, 
    registerForTableReload : false,
    registerForOnLoad : false,

    waitDiv : null,
    ie6HackIFrame : null,
    

    /** @constant */
    ZINDEX_DEFAULT : 2,

    /**
     * Vor Kalenderinhalt aber hinter Tooltips 
     * @constant
     */
    // 1000 -> vor Inhalt, aber hinter Tooltips(1001)
    // hoher Index da alle Kalender-Einträge einen z-index >= 2 haben!
    ZINDEX_CALENDAR : 1000,

    /**
     * vor Inhalt, Menü und Tooltips
     * @constant
     */
    //Menü (3) und Tooltips(1001)
    ZINDEX_FULLSCREEN : 1111,
    
    fixedPosDefault : false,
    newWaitDiv : null,
    newWaitDivFullscreen : null,
    trickIFrame : null,

    showFullscreen : function(container)
    {
      this.hide();
      newWaitDiv = this.newWaitDivFullscreen;
      return this.showDiv(container, newWaitDiv);
    },

    /**
     * Zeigt das Warte-Overlay für einen angegebenen Container.
     * 
     * @param {object} container
     * @param {number} [zindex]
     * 		 Wenn nicht übergeben wird {@link qxfc.wait.ZINDEX_DEFAULT} verwendet.
     * @param {boolean} [fixedPos]
     *       Bestimmt, ob die Position des containers mit berücksichtigt werden soll, oder nicht.
     *       Relevant z.B. bei der Positionierung für Tabellen vs. Tooltips.
     *       Default: false
     */
    show : function(container, zindex, fixedPos)
    {     
      this.hide();
      
      if (!zindex) zindex = this.ZINDEX_DEFAULT;
      if (fixedPos == null) fixedPos = this.fixedPosDefault;
      
      newWaitDiv = this.newWaitDiv;

      newWaitDiv.style.zIndex = zindex;
    
      /*
       * Browser-Workarounds:
       * IE liefert für den Tabellen-DIV scrollHeight und scrollWidth = 0
       * Firefox liefert für Body scrollHeight = 3
       * Safari liefert für Body.parentNode.scrollHeight = 0
       */
      if (fixedPos)
      {
        newWaitDiv.style.width = container.scrollWidth + "px";
        newWaitDiv.style.height = container.scrollHeight + "px";

        newWaitDiv.style.top="0px";
        newWaitDiv.style.left="0px";
      }
      else
      {  
        newWaitDiv.style.width = Math.max(container.scrollWidth, container.parentNode.scrollWidth) + "px";
        newWaitDiv.style.height = Math.max(container.scrollHeight, container.parentNode.scrollHeight) + "px";

        var posXY=this.getOffsetToContainer(container);

        newWaitDiv.style.top=posXY.posY + "px";
        newWaitDiv.style.left=posXY.posX + "px";
      }

      return this.showDiv(container, newWaitDiv);
    },
    
    showDiv : function(container, newWaitDiv)
    {
      this.waitDiv = newWaitDiv;
      container.appendChild(newWaitDiv);
      // redraw fix
      newWaitDiv.style.display="none";
      var redrawFix = newWaitDiv.offsetHeight;
      newWaitDiv.style.display="block";


      if(Browser.ie6)
      {
        trickIFrame = this.trickIFrame;
        
        trickIFrame.className = "qxfc_wait";
        trickIFrame.setAttribute("frameborder","0");
        trickIFrame.setAttribute("src","images/1px.gif");

        trickIFrame.style.width = newWaitDiv.style.width;
        trickIFrame.style.height = newWaitDiv.style.height;
        trickIFrame.style.left = newWaitDiv.style.left;
        trickIFrame.style.top = newWaitDiv.style.top;

        trickIFrame.style.zIndex = newWaitDiv.style.zIndex-1;
        this.ie6HackIFrame = trickIFrame;
        container.appendChild(trickIFrame);
      }
      
      return true;
    },
    
    getOffsetToContainer : function(container)
    {
      var posXY=Browser.getPosition2Container(container);
      return posXY
    },
    
    /**
     * Zeigt das Warte-Overlay für eine Tabelle an. Beispielsweise beim Sortieren, Blättern oder Filtern einer Tabelle.
     * 
     * @param {string} tableName
     *      Name der Tabelle, über die das Warte-Overlay gelegt werden soll.
     */
    showForTable : function(tableName)
    {
      // Versuchen qxfc.wait an den richtigen Stellen anzuzeigen.
      // Bei Fehlern abfangen und mit normale Intrexx-Verarbeitung fortsetzen.
      try
      {
        var table = document.getElementById('ID_' + tableName);
        // Verhindern, dass bei noch nicht dargestellten Tabellen (dynamischer Filter)
        // der gesammte Nachlade-Prozess durch einen Null-Pointer aussteigt.
        if (table)
        {
          var parentDiv = this.findParentDiv(table);
          this.show(parentDiv, ZINDEX_DEFAULT);
        }
      }
      catch(err)
      {
        // Im Fehlerfall qxfc.wait ausblenden, damit nicht versehentlich eine Daueranzeige entsteht.
        qxfc.wait.hide();     
      }
    },
    
    findParentDiv : function(element)
    {
      parentDiv = element.parentNode;
      while(parentDiv != null && parentDiv.nodeName != "DIV")
        parentDiv = parentDiv.parentNode;
      return parentDiv;
    },

    /**
     * Blendet Warte-Overlay aus, falls angezeigt.
     */
    hide : function()
    {
      if(this.waitDiv && this.waitDiv.parentNode) this.waitDiv.parentNode.removeChild(this.waitDiv);
      if(this.ie6HackIFrame && this.ie6HackIFrame.parentNode) this.ie6HackIFrame.parentNode.removeChild(this.ie6HackIFrame);
      this.ie6HackIFrame=null;
      this.waitDiv=null;
    },

    /**
     * Einhängen in Tabellen-Sortierung/-Paging
     * Erzeugt eine Wrapper um die original Verarbeitungsfunktion und hängt {@link qxfc.wait.show} davor.
     * Ein Aufruf von {@link qxfc.wait.hide} ist nicht nötig, da die Tabelle beim Laden komplett ersetzt wird.
     * @private
     */
    wrapActionProcessRequest : function(e)
    {

      // Versuchen qxfc.wait an den richtigen Stellen anzuzeigen.
      // Bei Fehlern abfangen und mit normale Intrexx-Verarbeitung fortsetzen.
      try
      {
        // Tabellen-Kopf
        if (this.requestType==3 && this.linkType==0 && !this.oTarget.bToolTipPopup)
        {
          if (qxfc.wait.registerForTableReload)
          {
            // Kalender-Control
            if (this.oHtml.oUp && this.oHtml.oUp.upType == "upCalGroovyControl")
            {
              var parentDiv = this.oHtml.oUp.oDivContent.oHtml;

              var start =  new Date();
              this.oXmlHttp.processResponseUP = this.oXmlHttp.processResponse;
              this.oXmlHttp.start = start;
              this.oXmlHttp.processResponse = function()
              {
                result = this.processResponseUP();
                qxfc.wait.hide();
                return result;
              }

              qxfc.wait.show(parentDiv, qxfc.wait.ZINDEX_CALENDAR);
              
            }
            // Normale Tabelle
            else if (this.oHtml.parentNode)
            {
              var parentDiv = qxfc.wait.findParentDiv(this.oHtml.parentNode);
              qxfc.wait.show(parentDiv, qxfc.wait.ZINDEX_DEFAULT);
            }
          }
        }
        else
        {
          var showWait = false;
          // Aktion wurde durch klick ausgelöst und öffnet ein Tooltip-Popup
          // Tooltip ist noch nicht geöffnet (z.B. durch Mouseover)
          if (this.oTarget.bToolTipPopup && !(this.oToolTipPopup && this.oToolTipPopup.loaded))
            {
              // Unterscheiung von Mouseover und normalen Tooltips
              if (this.linkType != 0 || 
                   (typeof e == 'undefined' && this.oHtml.oUp && (this.oHtml.oUp.upType == "upCalGroovyControl" || this.oHtml.oUp.upType == "")))
              {
                if (qxfc.wait.registerForOnLoad = true)
                {
                  showWait = true;
                }
              }
          }
          // Seitenwechsel im Tooltip oder Popup
          // linkType
          // 0 = Sprung auf bestehenden Datensatz
          // 2 = Sprung auf Mutterdatensatz oder neuen Datensatz Speichern und auf selben springen
          // 9 = Sprung auf neuen Datensatz
          // 16 = Sprung in Hauptfenster
          // 23 = Webservice-Datapicker
          else if (this.close == 1 ||
            (this.linkType == 0 || this.linkType == 2 || this.linkType == 9 || this.linkType == 16 || this.linkType == 23)
            && (!this.oTarget.bTooltipPopup && this.oTarget.newWindow == 0)
            && !(this.changeParent==1 && this.close == 0) // nicht bei Änderung des Hauptfenster aus Popup ohne Popup zu schließen
            )
          {
            showWait = true;
          }
          if (showWait)
          {
            // Vor Anzeige erst Laden anstoßen lassen -> Prüfungen, ob laden möglich
              if (this.oFup.runIn == "ToolTipPopup")
              qxfc.wait.show(this.oFup.oToolTipPopup.oFuncPart.oHtml.parentNode, qxfc.wait.ZINDEX_FULLSCREEN, true);
              else if (this.oFup.runIn == "Popup")
                qxfc.wait.showFullscreen(document.body);
              else
                qxfc.wait.showFullscreen(document.body);

            var result = this.processRequestUP(e);
            qxfc.wait.hide();
            return result;
          }
        }
      }
      catch(err)
      {
        // Im Fehlerfall qxfc.wait ausblenden, damit nicht versehentlich eine Daueranzeige entsteht.
        qxfc.wait.hide();
      }
      
      return this.processRequestUP(e);
    },


    /**
     * Einhängen in Filter-Reload.
     * Erzeugt eine Wrapper um die original Verarbeitungsfunktion und hängt qxfc.wait.show() davor.
     * Ein Aufruf von qxfc.wait.hide() ist nicht nötig, da die Tabelle beim laden komplett ersetzt wird.
     * @private
     */
    wrapFilterProcess : function()
    {
      // Versuchen qxfc.wait an den richtigen Stellen anzuzeigen.
      // Bei Fehlern abfangen und mit normale Intrexx-Verarbeitung fortsetzen.
      try
      {
        for(table in this.tableList)
        {
          // Verhindern, dass andere Elemente der Liste (z.B. Funktionen) als Table interpretiert werden.
          if(this.tableList[table].name)
            qxfc.wait.showForTable(this.tableList[table].name);
        }
      }
      catch(err)
      {
        // Im Fehlerfall qxfc.wait ausblenden, damit nicht versehentlich eine Daueranzeige entsteht.
        qxfc.wait.hide();
      }

      return this.processUP();
    },

    /**
     * Interne Funktion, die nach dem Laden der Seite in alle Filter-Gruppen qxfc.wait einhängt.
     * @private
     */
    doRegisterFilterReload : function()
    {
      if(typeof upDependency != 'undefined' && !upDependency.prototype.triggerTargetFilterUP)
      {
        upDependency.prototype.triggerTargetFilterUP = upDependency.prototype.triggerTargetFilter
        upDependency.prototype.triggerTargetFilter = function(p_oTgt)
        {
          try {
            var container = p_oTgt.ref.oHtml;
            if(typeof p_oTgt.ref.oHtml == 'undefined')
            {
              qxfc.wait.showForTable(p_oTgt.ref.controlName);
            }
            else
            {
              qxfc.wait.show(p_oTgt.ref.oHtml);
            }
          }
          catch (err) {
            qxfc.wait.hide();
          }

          return this.triggerTargetFilterUP(p_oTgt);
        }
      }
    },

    addEvent : function(obj, eventType, func, useCaption)
    {
      if (obj.addEventListener) {
        obj.addEventListener(eventType, func, useCaption);
        return true;
      } else if (obj.attachEvent) {
        var retVal = obj.attachEvent("on"+eventType, func);
        return retVal;
      } else {
        return false;
      }
    },

    /**
     * Aktiviert die globale Verwendung von {@link qxfc.wait} für das dynamische
     * Nachladen von Seiten in einem framelosen Layout.
     * 
     * @param {boolean} onTop
     *         vor Tooltips & Menü?
     */
    registerOnLoad : function(onTop)
    {
      this.registerForOnLoad = true;
      
      upFupLoader.prototype.onBeforeLoad = function()
      {
        // Versuchen qxfc.wait an den richtigen Stellen anzuzeigen.
        // Bei Fehlern abfangen und mit normale Intrexx-Verarbeitung fortsetzen.
        try
        {
          if (onTop)
            qxfc.wait.showFullscreen(document.body);
          else
          {
            var container = this.oHtmlContainer;
            if (Browser.ie) container = document.getElementById("Container_Stage");
            qxfc.wait.show(container, qxfc.wait.ZINDEX_DEFAULT);
          }
        }
        catch(err)
        {
          // Im Fehlerfall qxfc.wait ausblenden, damit nicht versehentlich eine Daueranzeige entsteht.
          qxfc.wait.hide();
        }

        return true;
      }
      upFupLoader.prototype.onAfterLoad = function()
      {
        qxfc.wait.hide();

        // nach dem Laden der Seite für neu geladene Filter registrieren
        if (qxfc.wait.registerForFilterReload) qxfc.wait.doRegisterFilterReload();

        return true;
      }
      
      // wait 
      upResponseHandler.prototype.loadToolTipPopupUP = upResponseHandler.prototype.loadToolTipPopup
      upResponseHandler.prototype.loadToolTipPopup = function()
      {
        var result = upResponseHandler.prototype.loadToolTipPopupUP();
        if(oRequest.readyState==State.done && oRequest.status==Status.ok) 
          qxfc.wait.hide();
        return result;
      }
    },

    /**
     * Aktiviert die globale Verwendung von {@link qxfc.wait} für das dynamische
     * Nachladen von Tabellen beim Sortieren und Paging.
     */
    registerTableReload : function()
    {
      this.registerForTableReload = true;
      
      upActionControl.prototype.processRequestUP = ActionProcessRequest;
      upActionControl.prototype.processRequest = this.wrapActionProcessRequest;
    },

    /**
     * Aktiviert die globale Verwendung von {@link qxfc.wait} für das dynamische
     * Nachladen von Tabellen durch dynamische Filter.
     */
    registerFilterReload : function()
    {
      this.registerForFilterReload = true;

      this.addEvent(window, "load", qxfc.wait.doRegisterFilterReload, false);
    },
    
    init : function()
    {
      this.newWaitDiv = document.createElement("div");
      this.newWaitDiv.className = "qxfc_wait";
      this.newWaitDivFullscreen = document.createElement("div");
      this.newWaitDivFullscreen.className = "qxfc_wait_full";
    
      if(Browser.ie6)
      {
        this.trickIFrame = document.createElement("iframe");
        this.trickIFrame.id = "qsWaitTrickIFrame";
      }
    }
  };
  qxfc.wait.init();
}

