
/******************* FMD WEB FRAMEWORK - USER INTERFACE ELEMENTS *******************/
/* Version: 3.0                                                                    */
/* Copyright (c) 2005 Flying Machine Development, Inc All Rights Reserved          */
/* Contact: info@flyingmachine.com                                                 */
/***********************************************************************************/

/************************************ globals **************************************/

  WEBUI_READYSTATE_UNINITIALIZED = 0;
  WEBUI_READYSTATE_LOADING = 1;
  WEBUI_READYSTATE_COMPLETE = 4;

  WEBUI_OBJECTTYPE_UNDEFINED = "undefined";
  WEBUI_OBJECTTYPE_APPLICATION="application"
  WEBUI_OBJECTTYPE_DIALOG = "dialog";
  WEBUI_OBJECTTYPE_FORM = "form";
  WEBUI_OBJECTTYPE_MENU = "menu";
  WEBUI_OBJECTTYPE_MENUBAR = "menubar";
  WEBUI_OBJECTTYPE_TAB = "tab";
  WEBUI_OBJECTTYPE_TABBAR = "tabbar";
  WEBUI_OBJECTTYPE_TABLE = "table";
  WEBUI_OBJECTTYPE_TOOLBAR = "toolbar";
  WEBUI_OBJECTTYPE_PANEL = "panel";

  WEBUI_PARAMETER_DATATYPE = "datatype";
  WEBUI_PARAMETER_TAGNAME = "tag-name";
  WEBUI_PARAMETER_FORMSECTION = "form-section";
  WEBUI_PARAMETER_REQUIRED = "required";

/********************************* WebUI_Element object ***************************/

  function WebUI_Element(p)
  {
    var self=new Object();

    // private vars
    var showOnLoadComplete=false;

    // properties
    self.parent=p;
    self.id=undefined;
    self.frame=undefined;
    self.type=WEBUI_OBJECTTYPE_UNDEFINED;
    self.href=undefined;
    self.height=0;
    self.width=0;
    self.top=0;
    self.left=0;
    self.align="left";
    self.valign="top";
    self.readyState=WEBUI_READYSTATE_UNINITIALIZED;
    self.elements=new Collection()
    self.variables=new Collection();
    self.xmlDocument=undefined;

    // arguments
    self.getVariable=function(key)
    {
      return this.variables[key];
    }
    self.setVariable=function(key, value)
    {
      this.variables.add(key, value)
    }

    // event handlers (NOT IMPLEMENTED FOR ALL EVENTS YET)
    handleKeyUp=function(webUIElement){webUIElement.onkeyup()};
    handleFocus=function(webUIElement){webUIElement.onfocus()};
    handleChange=function(webUIElement){webUIElement.onchange()};
    handleBlur=function(webUIElement){webUIElement.onblur()};
    
    handleShow=function(webUIElement)
    {
      if(webUIElement.href)
      {
        d=webUIElement.getDocument();
        if(!d.body) // page is not loaded - wait until it is (could be a problem - need a timeout!!!!!!)
        {
          return setTimeout(function(){handleShow(webUIElement)},10)
        }
        else
        {
          webUIElement.onshow()
        }
      } 
      else
      {
        webUIElement.onshow()
      }
    }
    handleHide=function(webUIElement){webUIElement.onhide()};
    
    handleLoad=function(webUIElement, showOnLoadComplete)
    {
      webUIElement.readyState=WEBUI_READYSTATE_COMPLETE;
      webUIElement.onload();
      if(showOnLoadComplete)
      {
        webUIElement.show();
      }
    }

    self.onkeyup=function(){};
    self.onfocus=function(){};
    self.onchange=function(){};
    self.onblur=function(){};
    self.onshow=function(){};
    self.onhide=function(){};
    self.onload=function(){};

    self.createElement=function(type)
    {
      switch(String(type).toLowerCase())
      {
      case WEBUI_OBJECTTYPE_DIALOG:
        return new WebUI_Dialog(this);
        break;
      case WEBUI_OBJECTTYPE_FORM:
        return new WebUI_Form(this);
        break;
      case WEBUI_OBJECTTYPE_MENU:
        return new WebUI_Menu(this);
        break;
      case WEBUI_OBJECTTYPE_MENUBAR:
        return new WebUI_Menubar(this);
        break;
      case WEBUI_OBJECTTYPE_TAB:
        return new WebUI_Tab(this);
        break;
      case WEBUI_OBJECTTYPE_TABBAR:
        return new WebUI_Tabbar(this);
        break;
      case WEBUI_OBJECTTYPE_TABLE:
        return new WebUI_Table(this);
        break;
      case WEBUI_OBJECTTYPE_TOOLBAR:
        return new WebUI_Toolbar(this);
        break;
      case WEBUI_OBJECTTYPE_PANEL:
        return new WebUI_Panel(this);
        break;
      default:
        return new WebUI_Element(this);
        break;
      }
    }

    self.appendChild=function(e)
    {
      if(e.id)
      {
        this.elements.add(e.id,e);
      }
    }

    self.show=function()
    {
      if(this.readyState==WEBUI_READYSTATE_LOADING && !this.frame.style)
      {
        var o=this;
        return setTimeout(function(){o.show()}, 10)
      }

      if(this.readyState!=WEBUI_READYSTATE_COMPLETE)
      {
        showOnLoadComplete=true;
        return this.refresh();
      }
      showOnLoadComplete=false;
      this.frame.style.zIndex=999;
      this.frame.style.visibility="visible"
      handleShow(this);
    }

    self.hide=function()
    {
      if(this.frame)
      {
        this.frame.style.zIndex=0;
        this.frame.style.visibility="hidden";
      }
      handleHide(this)
    }

    self.refresh=function()
    {
      this.readyState=WEBUI_READYSTATE_LOADING

      if(this.parent.frame)
      {
        var d=this.parent.getDocument();
      }
      else
      {
        var d=document;
      }

      if(this.parent.href && !d.body)
      {
        // parent has not finished loading
        var o=this;
        return setTimeout(function(){o.refresh()},10);
      }

      if(!this.frame) // might cause a problem if the parent window is refreshed...
      {
        //var f=d.createElement('iframe');
        var f=d.createElement('<iframe allowtransparency="true" background-color="transparent" application="yes">');
        f.setAttribute('scrolling',"no");
        f.setAttribute('noresize','true');
        f.frameBorder='0';
        f.style.zIndex=0;
        f.style.border='0px';
        f.style.position="absolute";
        f.style.visibility="hidden"
        d.body.appendChild(f);
        this.frame=f;
      }

      if(this.top) this.frame.style.top=this.top + "px";
      if(this.left) this.frame.style.left=this.left + "px";
      if(this.width) this.frame.style.width=this.width + "px";
      if(this.height) this.frame.style.height=this.height + "px"
      //if(this.align) this.frame.parentNode.setAttribute("align",this.align);
      //if(this.valign) this.frame.parentNode.style.verticalAlign=this.valign;

      // force children to refresh the frame
      //for(var n=0;n<this.elements.length;n++)
      //{
      //  this.elements[n].frame=undefined;
      //}

      var d=this.getDocument()
      d.onload=handleLoad(this, showOnLoadComplete)
      d.location.replace(this.href);
    }

    self.getDocument=function()
    {
      if(this.frame.contentDocument) 
      {
        return this.frame.contentDocument; 
      } 
      else if(this.frame.contentWindow) 
      {
        return this.frame.contentWindow.document;
      } 
      else if(this.frame.document) 
      {
        return this.frame.document;
      } 
    }

    self.getWindow=function()
    {
      if(this.frame.contentWindow) 
      {
        return this.frame.contentWindow;
      } 
      else
      {
        return this.frame;
      } 
    }

    self.setCursor=function(c)
    {
      if(this.getDocument()) 
      {
        if(this.getDocument().body) 
        {
          this.getDocument().body.style.cursor=c
        } 
      } 
      for(var n=0;n<this.elements.length;n++)
      {
        this.elements[n].setCursor(c);
      }
    }

    return self;

  }

/*********************************** WebUI_Dialog object **************************/

  function WebUI_Dialog(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_DIALOG;

    // event handlers
    self.submit=function(){return this.onsubmit()};
    self.cancel=function(){return this.oncancel()};
    self.onsubmit=function(){this.hide();return true};
    self.oncancel=function(){this.hide();return true;};

    return self;
  }

/************************************ WebUI_Form object ***************************/

  function WebUI_Form(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_FORM;

    self.getForm=function()
    {
      var d=this.getDocument()
      if(d)
      {
        return d.forms[0];
      } 
    }

    self.validate=function()
    {
      var f=this.getForm();
      for(var n=0;n<f.elements.length;n++)
      {
        var required=String(this.getWebUIParameter(f.elements[n],WEBUI_PARAMETER_REQUIRED)).toLowerCase();
        if(required=='yes')
        {
          if(f.elements[n].value=="")
          {
            return false;
          }
        }
      }
      return true;
    }
    self.getQueryString=function()
    {
      var f=this.getForm();
      var qs="";
      for(var e=0;e<f.elements.length;e++) 
      {
        if(f.elements[e].name!="") 
        {
          qs+=(qs!='')?'&':''
          qs+=f.elements[e].name+'=' + escape(this.getWebUIPostValue(f.elements[e]))
        }
      }
      return qs
    }

    self.getXML=function(section)
    {
      var f=this.getForm();
      var xml="";
      for(var e=0;e<f.elements.length;e++) 
      {
        if(f.elements[e].name!="") 
        {
          if(this.getWebUIParameter(f.elements[e],WEBUI_PARAMETER_TAGNAME))
          {
            var tagName=this.getWebUIParameter(f.elements[e],WEBUI_PARAMETER_TAGNAME)
          }
          else
          {
            var tagName=f.elements[e].name
          }
          if(section)
          {
            if(this.getWebUIParameter(f.elements[e],WEBUI_PARAMETER_FORMSECTION)==section)
            {
              xml+='<' + tagName + ' datatype="' + this.getWebUIParameter(f.elements[e],WEBUI_PARAMETER_DATATYPE) + '">' + this.getWebUIPostValue(f.elements[e]) + '</' + tagName + '>'
            }
          }
          else
          {
            xml+='<' + tagName + ' datatype="' + this.getWebUIParameter(f.elements[e],WEBUI_PARAMETER_DATATYPE) + '">' + this.getWebUIPostValue(f.elements[e]) + '</' + tagName + '>'
          }
        }
      }
      return xml
    }

    self.getWebUIParameter=function(e,p)
    {
      if(e.WebUIParameters)
      {
        var v=e.WebUIParameters
        if(v.indexOf(p)>=0)
        {
          v=v.substr(v.indexOf(p))
          v=v.substr(0,v.indexOf(";"))
          return v.split(":")[1]
        }
      }        
      return;        
    }

    self.getFormattedValue=function(e)
    {
      return e.value;
    }

    self.getWebUIPostValue=function(e)
    {
      if(e.WebUIPostValue)
      {
        return e.WebUIPostValue;
      }
      else if(e.type=='checkbox')
	    {
  		  return e.checked;
	    }
      return e.value;
    }

    // event handlers
    self.submit=function(){return this.onsubmit()};
    self.onvalidate=function(){return true};
    self.onsubmit=function(){return true};

    return self;
  }

/************************************ WebUI_Menu object ***************************/

  function WebUI_Menu(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_MENU;
    return self;

    return self;
  }

/********************************** WebUI_Menubar object **************************/

  function WebUI_Menubar(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_MENUBAR;
    return self;
  }

/********************************* WebUI_Tabbar object ****************************/

  function WebUI_Tabbar(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_TABBAR;
    self.currentTabIndex=0;

    // event handlers
    self.ontabchange=function(){;};
    handleTabChange=function(webUIElement){webUIElement.ontabchange()};

    self.showTab=function(tab)
    {
      for(var n=0;n<this.elements.length;n++)
      {
        if(this.elements[n].id !=tab)
        {
          this.elements[n].hide()
        }
      }
      this.elements[tab].show()
      handleTabChange(this);
    }

    return self;
  }

/************************************ WebUI_Tab object ****************************/

  function WebUI_Tab(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_TAB;
    
    return self;
  }

/*********************************** WebUI_Table object ***************************/

  function WebUI_Table(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_TABLE;
    return self;
  }

/********************************** WebUI_Toolbar object **************************/

  function WebUI_Toolbar(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_TOOLBAR;
    return self;
  }

/********************************** WebUI_Panel object ****************************/

  function WebUI_Panel(p)
  {
    var self=new WebUI_Element(p);
    self.type=WEBUI_OBJECTTYPE_PANEL;
    return self;
  }

/********************************** WebUI_Application object **************************/

  function WebUI_Application()
  {
    var self=new WebUI_Element();
    self.type=WEBUI_OBJECTTYPE_APPLICATION;
    delete self.parent;
    delete self.frame;
    delete self.show;
    delete self.hide;
    delete self.refresh;
    delete self.getDocument;
    delete self.getWindow;
    return self;
  }

/********************************** WebUI_AutoComplete object **************************/

  function WebUI_AutoComplete(i)
  {
    var self=new Object();
    i.WebUIAutoComplete=self;
    if(!i.WebUIPostValue)  i.WebUIPostValue='';
    i.onblur=function()
    {
      var o=this.WebUIAutoComplete;
      if(!o.inPulldown) 
      {
        o.hidePulldown();
        if(this.value!='' && !this.WebUIPostValue)
        {
          o.filterValues(this.value)

          if(o.values.length==0)
          {
            this.value='';
            this.WebUIPostValue='';
          }
          else
          {
            //o.setValue(o.values[0].selectSingleNode('Value').text);
          }
        }
      }
    }

    i.onkeyup=function()
    {
      this.WebUIAutoComplete.lastKey=window.event.keyCode;
      var lastValue=this.value
      if(this.WebUIAutoComplete.lastKey==9) return
      if(this.WebUIAutoComplete.lastKey==40){ this.WebUIAutoComplete.refreshPulldown();this.WebUIAutoComplete.showPulldown();this.WebUIAutoComplete.pulldown.focus();this.WebUIAutoComplete.setCurrentItem(0);return;}

      var o=this.WebUIAutoComplete;
      return setTimeout(function(){if(lastValue==o.textInput.value || lastValue==''){o.refreshPulldown();o.showPulldown();return;}}, 100);
    }
    self.textInput=i;
    self.inPulldown=false;
    self.inHidePause=false;
    self.inRefreshPause=false;
    self.lastKey=0;
    self.displayValue="";
    self.xmlDocument=undefined;
    self.getXMLCallback=function(){return this.xmlDocument;}
    self.getXMLValueCallback=function(){return this.xmlDocument;}
    self.values=undefined;
    self.height=150;
    self.width=0;
    self.top=0;
    self.left=0;
    self.currentItemIndex=0;

    // build the pulldown 
    var d=window.top.document
    var dv=d.createElement("div")
    dv.WebUIAutoComplete=self;
    dv.style.border="1px solid #666666";
    dv.style.position="absolute";
    dv.style.backgroundColor="#FFFFFF";
    dv.style.visibility="hidden";
    dv.style.overflow="auto";
    dv.style.zIndex=999;
    dv.onfocus=function(){this.WebUIAutoComplete.inPulldown=true};
    dv.onblur=function(){this.WebUIAutoComplete.inPulldown=false;this.WebUIAutoComplete.hidePulldown()};
    dv.onkeyup=function()
    {
      if(window.top.event.keyCode==40)
      {
        this.WebUIAutoComplete.setCurrentItem(this.WebUIAutoComplete.currentItemIndex+1)
      }
      else if(window.top.event.keyCode==38)
      {
        this.WebUIAutoComplete.setCurrentItem(this.WebUIAutoComplete.currentItemIndex-1)
      }
      else if(window.top.event.keyCode==13 || window.top.event.keyCode==9)
      {
        this.WebUIAutoComplete.setValue(this.children[this.WebUIAutoComplete.currentItemIndex].selectValue);
        this.WebUIAutoComplete.inPulldown=false;
        this.WebUIAutoComplete.hidePulldown();
        this.WebUIAutoComplete.textInput.focus()
      }
    }

    d.body.appendChild(dv)
    self.pulldown=dv;

    self.handleBlur=function(){this.hidePulldown()};


    self.setCurrentItem=function(idx)
    {
      if(idx<this.values.length && idx>=0) 
      {
        this.pulldown.children[this.currentItemIndex].style.backgroundColor='#FFFFFF'
        this.currentItemIndex=idx;
        this.pulldown.children[this.currentItemIndex].style.backgroundColor='#CCCCCC'
        this.pulldown.children[this.currentItemIndex].focus()
      }
    }

    self.filterValues = function(v) 
    {
      var v1=String(v)
      if(v1.length>1)
      {
        var v2=v1.substring(v1.length-1)
        v2=String.fromCharCode(v2.charCodeAt(0)+1)
        v2=v1.substring(0,v1.length-1) + v2
        this.xmlDocument=this.getXMLCallback(v1, v2)
        this.values=this.xmlDocument.selectNodes('//Option[Description >="' + v1 + '" and Description < "' + v2 + '"]')  
      }
      else if(v1.length==1)
      {
        this.xmlDocument=this.getXMLCallback(v1)
        this.values=this.xmlDocument.selectNodes('//Option[Description >="' + v1 + '"]')  
      }
      else
      {
        this.xmlDocument=this.getXMLCallback()
        this.values=this.xmlDocument.selectNodes('//Option')  
      }
    }

    self.findValue = function(v) 
    {
      this.xmlDocument=this.getXMLValueCallback(v)
      this.values=this.xmlDocument.selectNodes('//Option')  
    }

    self.setValue = function(v)
    {
      if(v!="")
      {
        this.value=v;
        this.findValue(v);
        if(this.xmlDocument.selectSingleNode('//Option[Value ="' + v + '"]/Description'))
        {
          this.displayValue=this.xmlDocument.selectSingleNode('//Option[Value ="' + v + '"]/Description').text;
          if(this.textInput)
          {
            this.textInput.value=this.displayValue;
            this.textInput.WebUIPostValue=v;
          }
        }
      }
    }

    self.refreshPulldown = function(endPause)
    {
      this.filterValues(this.textInput.value)
      if(this.values.length==0 && this.lastKey!=8)
      {
        while(this.values.length==0)
        {
          this.textInput.value=String(this.textInput.value).substring(0,this.textInput.value.length-1);
          this.filterValues(this.textInput.value)
        }
      }

      if(this.values.length==1 && this.lastKey!=8)
      {
        this.setValue(this.values[0].selectSingleNode('Value').text);
        this.textInput.focus();
        this.inPulldown=false;
      }

      var dv=this.pulldown;
      while(dv.children.length>0)
      {
        dv.removeChild(dv.children[0]);
      }

      for(var n=0;n<this.values.length;n++)
      {
        var d=window.top.document;
        var dvItm=d.createElement('div')
        var tx=d.createTextNode(this.values[n].selectSingleNode('Description').text)
        dvItm.WebUIAutoComplete=this;
        dvItm.itemIndex=n;
        dvItm.selectValue=this.values[n].selectSingleNode('Value').text;
        dvItm.style.paddingLeft="2px"
        dvItm.style.lineHeight="13px"
        dvItm.style.fontFamily="Trebuchet MS"
        dvItm.style.fontSize="11px"
        dvItm.style.cursor="hand";
        dvItm.style.backgroundColor='#FFFFFF'
        dvItm.onmouseover=function(){this.WebUIAutoComplete.setCurrentItem(this.itemIndex)}
        dvItm.onclick=function()
        {
          this.WebUIAutoComplete.setValue(this.selectValue);
          this.WebUIAutoComplete.hidePulldown();
          this.WebUIAutoComplete.textInput.focus();
        }
        dvItm.appendChild(tx)
        dv.appendChild(dvItm)

        dv.onmouseout="this.backgroundColor='#FFFFFF'"
      }
      
      this.currentItemIndex=0;
    }

    self.hidePulldown = function() {
     
      if(!this.inHidePause)
      {
        this.inHidePause=true;
        var o=this;
        function hidePause(){o.hidePulldown()}         
        return setTimeout(hidePause, 150);
      }     

      this.inHidePause=false;
      if(!this.inPulldown)
      {
        this.pulldown.style.visibility="hidden"
        this.inPulldown=false;
      }
    }

    self.showPulldown = function() {
      var dv=this.pulldown;
      dv.style.zIndex=999;
      if(this.width==0)
      {
        dv.style.width=this.textInput.style.width;
      }
      else
      {
        dv.style.width=this.width + "px";
      }
      dv.style.top=this.top + "px"; // need to replace with detect of textInput position!
      dv.style.left=this.left + "px";  // need to replace with detect of textInput position!
      dv.style.height=this.height +"px";
      dv.style.visibility="visible"
    }

    return self;
  }

