var GloGfx=function(){
  
  var undefined; //test undefined  variable === undefined instead of using typeof variable=='undefined' idea from jquery > // Will speed up references to undefined, and allows munging its name.
  
  var _GloGfx_buttonList=[];
  var _glogfxbutton_active=null;

  window.document.onmousedown=function(e){
    if (_glogfxbutton_active) {
      var event={target:_glogfxbutton_active};
      _glogfxbutton_active._onclick(event);
    }
  }  
  window.document.onmousemove=function(e){
    if (e===undefined)
      e=window.event; //IE
    var t=choose(e.srcElement,e.target);
    if (t.id!='' && t.id.indexOf('_glogfxb')>-1) {
      var prevActiveButton=_glogfxbutton_active; //save old button
      var glogfxbuttonid=t.id.split('_')[3]; //obtain current button
      _glogfxbutton_active=_GloGfx_buttonList[glogfxbuttonid];
      if (_glogfxbutton_active==prevActiveButton) //if already activated exit
        return;

      if (prevActiveButton && prevActiveButton!=_glogfxbutton_active && prevActiveButton.mouseIsOver) {
        //mouse over button but mouseout for old button not fired yet (e.g. mouse moving really fast or very close buttons)
        var event={target:prevActiveButton};
        prevActiveButton.mouseIsOver=0;  
        prevActiveButton._onmouseout(event);
      }

      if (!_glogfxbutton_active.mouseIsOver) {
        var event={target:_glogfxbutton_active};
        _glogfxbutton_active._onmouseover(event);        
        _glogfxbutton_active.mouseIsOver=1;
      }
      
    } else {
      if (_glogfxbutton_active) {
        var event={target:_glogfxbutton_active};
        _glogfxbutton_active.mouseIsOver=0;  
        _glogfxbutton_active._onmouseout(event);
      }
      _glogfxbutton_active=null;
    }
  };

  var buildStyleList=function(object) {
    var s=[];
    for (var z in object) {
      s[s.length]=z+':'+object[z];
    }
    return s.join(';');
  }

/*
  var findPos=function(obj) { //find absolute pos of element... unused
  //http://www.quirksmode.org/js/findpos.html  
	  var curleft = curtop = 0;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while (obj = obj.offsetParent);
	  }
    return [curleft,curtop];
  }
*/
  
  var choose=function() { //choose the first defined object
    for (var z=0;z<arguments.length;z++)
      if (arguments[z]!==undefined)
        return arguments[z];
    return arguments[z-1]; //always return last value   
  }
  
  function gcb_doClick(obj) {
    try { 
      var evt = document.createEvent("MouseEvents");
      evt.initMouseEvent("click", true, true, window,0, 0, 0, 0, 0, false, false, false, false, 0, null);
      var canceled = !obj.dispatchEvent(evt);
      if(canceled) {
        // A handler called preventDefault  
      } else {
        // None of the handlers called preventDefault
      }
    } catch(er) {
      obj.click();  
    } 
  }  
  
  var object_set=function(x,y) {
    if (y===undefined)
      y={};
    if (x===undefined && typeof y=='object') x={};
    if (typeof x=='object' && typeof y=='object') {
      for (var z in y) {
        switch(typeof y[z]) {
          case 'undefined':
          break; //do nothing
          case 'number':
            if (!isNaN(y[z]))
              try {
                x[z]=y[z];
            } catch(er) {
              //console.log(z);
            }  
          break;
          default:
            try {
              x[z]=y[z];
            } catch(er) {
              //console.log(z);
            }  
        }  
      }  
      return x;    
    }
  }
  var array_max=function(array) {
    var max=array[0];
    for (var z=0,zEnd=array.length;z<zEnd;z++) {
      if (max<array[z])
        max=array[z];
    }
    return max;
  }
  
  return {
  
    Utils:function() {

      var _Browser=function(cfg){
        this.ver=navigator.appVersion;
        this.dom=document.getElementById?1:0
        this.ie  =(this.ver.indexOf("MSIE")>-1)?1:0;
        this.ie5 =(this.ver.indexOf("MSIE 5")>-1 && this.dom)?1:0;
        this.ie55=(this.ver.indexOf("MSIE 5.5")>-1 && this.dom)?1:0;
        this.ie6 =(this.ver.indexOf("MSIE 6")>-1 && this.dom)?1:0;
        this.ie4=(document.all && !this.dom)?1:0;
        this.ns5=(this.dom && parseInt(this.ver) >= 5) ?1:0; //hi, MoZ!
        this.ns4=(document.layers && !this.dom)?1:0;
        var re=/MSIE\s([\d\.]+)/;
        if (re.exec(this.ver))
          this.ieVer=RegExp.$1;
        else
          this.ieVer=-1;
        this.ieVer=parseFloat(this.ieVer);
      }

      var tableRuler=function(cfg) {
        cfg=object_set({
          tables:document.getElementsByTagName('table'),
          overBackgroundStyle:'red',
          outBackgroundStyle:'',
          skipTrWithThisClass:'-.-', //do not apply auto rule if tr has this class applied
          overFunction:'', //run this function on row over
          outFunction:''
        },cfg);        
        
        if (document.getElementById && document.createTextNode) {
          var tables=cfg.tables;
          if (!tables.length) {
            tables=[tables];
          } else {
            if (typeof tables=='string')
              tables=document.getElementById(tables);
            tables=[tables];
          }
          
          function make_onmouseover(_this) {
            return function () {
              _this.style.background=cfg.overBackgroundStyle;
              if (cfg.overFunction)
                cfg.overFunction(_this)
              return false;  
            }
          }
          function make_onmouseout(_this) {
            return function () {
              _this.style.background=cfg.outBackgroundStyle;
              if (cfg.outFunction)
                cfg.outFunction(_this)
              return false;
            }
          }

          //var tables=document.getElementsByTagName('table');
          for (var i=0,iEnd=tables.length;i<iEnd;i++) {
            if (typeof tables[i]=='string')
              tables[i]=document.getElementById(tables[i]);
            //if (tables[i].className=='ruler') {
              var trs=tables[i].getElementsByTagName('tr');
              for (var j=0,jEnd=trs.length;j<jEnd;j++) {
                if (trs[j].parentNode.nodeName=='TBODY' && trs[j].parentNode.nodeName!='TFOOT') {
                  //console.log(trs[j].className,' - ',cfg.skipTrWithThisClass,trs[j]);
                  if (trs[j].className!=cfg.skipTrWithThisClass) {
                    trs[j].onmouseover=make_onmouseover(trs[j]);
                    trs[j].onmouseout=make_onmouseout(trs[j]);
                  }  
                }
              }
            //}
          }
        }
      }

      return {
        browser:new(_Browser),
        tableRuler:tableRuler,
        $:function(s) {
          return document.getElementById(s);
        }
      }
    }(),    
    
    Ui:function() {
      return {
        buildButton:function(cfg) {
          cfg=object_set({
            cssTextClass:'ENTER',
            overCssClass:'', //or red
            source:null, //or button dom object
            width:70,
            float:'none',
            position:null, //or 'absolute',
            buttonClass:'', //or className to assign to the button
            IEBUTTONHEIGHT:9 //max height of the image used for the button's text
          },cfg);
          var id=_GloGfx_buttonList.length;
          var s='';
          s+='<div id="_glogfxb_div_'+id+'" class="gfxbutton" style="-moz-user-select: none;-khtml-user-select: none;user-select: none;width:'+cfg.width+'px;height:18px;">'
          s+='<table id="_glogfxb_table_'+id+'" cellpadding=0 cellspacing=0 width="100%">';
          s+='<col id="_glogfxb_col1_'+id+'" width="6"><col id="_glogfxb_col2_'+id+'" width="100%"><col id="_glogfxb_col3_'+id+'"width="8">';
          s+='<tr id="_glogfxb_tr_'+id+'">';
          s+='<td id="_glogfxb_td1_'+id+'"><div id="_glogfxb_div2_'+id+'" class="boffleft"></div></td>';
          s+='<td id="_glogfxb_td2_'+id+'"><div id="_glogfxb_div3_'+id+'" class="bofffill" style="text-align:center;">';
          
          if (GloGfx.Utils.browser.ie)
            s+='<div id="_glogfxb_div4_'+id+'" style="z-index:-1;margin-top:5px;height:'+cfg.IEBUTTONHEIGHT+'px;overflow:hidden;" class="btntext_'+cfg.cssTextClass+'"></div>';
          else  
            s+='<img id="_glogfxb_img_'+id+'" style="border:none;margin-top:5px;" src="/images/spacer.gif" class="btntext_'+cfg.cssTextClass+'"/>';
          s+='</div></td>';
          s+='<td id="_glogfxb_td3_'+id+'"><div id="_glogfxb_div5_'+id+'" class="boffright"></div></td>';
          s+='</tr></table>';
          s+='</div>'
          var d=document.createElement('div');
          d.style.width=cfg.width+'px';
          d.style.height='18px';
          //d.style.background='red';
          d.className='buttonFloat'+cfg.float;
          d._glofx_buttonContainer=true;
          d.style.zIndex=0;
          d.overCssClass=cfg.overCssClass;
          
          d.innerHTML=s;
          
          var changeButtonStyle=function(oButton,srcClassREGEXP,newClassString) {
            if (oButton.length) {
              for (var z=0,zEnd=oButton.length;z<zEnd;z++) {
                if (oButton[z]!==undefined) {
                  var c=oButton[z].className;
                  oButton[z].className=c.replace(srcClassREGEXP,newClassString);
                }  
              }  
            } else {
              var c=oButton.className;
              oButton.className=c.replace(srcClassREGEXP,newClassString);
            }  
          }

          var changeButtonState=function(e,srcClassREGEXP,newClassString) {
            var t=e.target;
            var divs=t.getElementsByTagName('div');            
            for (var z=0,zEnd=divs.length;z<zEnd;z++) {
              changeButtonStyle(divs[z],srcClassREGEXP,newClassString);
            }
          }
          
          //since mouseover and mouseout are launched even for childs
          //we need to build a global user-defined mouse event handler
          //to obtain mouseenter and mouseleave property
          
          d._onmouseover=function(e){
            changeButtonState(e,/^boff(.*)/,'bon'+e.target.overCssClass+'$1');
          }

          d._onmouseout=function(e){
            var re=new RegExp('^bon('+e.target.overCssClass+')(.*)');
            changeButtonState(e,re,'boff$2');
            changeButtonState(e,/^bhit(.*)/,'boff$1');
          }

          d._onclick=function(e) {
            var t=e.target; 
            
            for (var z=0,zEnd=_GloGfx_buttonList.length;z<zEnd;z++) {
              var divs=_GloGfx_buttonList[z].getElementsByTagName('div');
              var re=new RegExp('^bon('+e.target.overCssClass+')(.*)');
              //disable all buttons
              for (var z1=0,z1End=divs.length;z1<z1End;z1++) {
                changeButtonStyle(divs[z1],re,'boff$2');
                changeButtonStyle(divs[z1],/^bhit(.*)/,'boff$1');
              }
            }
            
            var divs=t.getElementsByTagName('div');
            changeButtonStyle([divs[0],divs[1],divs[2],divs[3],divs[4]],/^boff(.*)/,'bhit$1'); //lite current button
            //setTimeout(function(z1){changeButtonStyle([divs[0],divs[1],divs[2],divs[3],divs[4]],/^bhit(.*)/,'boff$1')},150);
            //setTimeout(function(z1){changeButtonStyle([divs[0],divs[1],divs[2],divs[3],divs[4]],/^boff(.*)/,'bhit$1')},300);
            gcb_doClick(cfg.source); 
          }
          
          _GloGfx_buttonList[_GloGfx_buttonList.length]=d;
          
          if (cfg.position=='absolute') {
            d.style.position='absolute';
            d.style.left=cfg.source.offsetLeft+'px';
            d.style.top=cfg.source.offsetTop+'px';
          }  
          if (cfg.buttonClass!='') {
            d.className=d.className+' '+cfg.buttonClass;
          }
          
          cfg.source.style.display='none';
          cfg.source.parentNode.appendChild(d);

        }
      }
    }(),    
   
    Chart:function() {
      var _Chart_object=function(cfg){        
        this.xAxis=cfg.xAxis;
        this.yAxis=cfg.yAxis;
        this.yAxisAlign=cfg.yAxisAlign;
        this.values=cfg.values;
        this.canvas=document.createElement('div');
        //this.canvas.style.position='absolute';
        //this.canvas.style.border='1px solid black'
        var parent=cfg.parent;
        if (parent===undefined)
          parent=document.body;
        if (typeof parent=='string')
          parent=document.getElementById(parent);  
          
        parent.appendChild(this.canvas);
      }      
      _Chart_object.prototype.draw=function(cfg) {
        cfg=object_set({
          width:150,
          height:100,
          padding:10,
          color:'#FF0000',
          chartBackground:'#FFFFFF',
          chartBarWidth:'auto',
          chartBarHorizontalSpacing:1,
          
          //yaxis
          drawYAxis:true,
          yAxisFontFamily:'verdana',
          yAxisFontSize:7,
          yAxisColor:'#C2C2C2',
          yAxisBackground:'#FFFFFF',
          yAxisSkip:1,
          yAxisWidth:18,
          yAxisPadding:0,
          yAxisPaddingRight:3,
          yAxisMarginTop:-4,
          yAxisPosition:'relative',
          
          //xaxis
          drawXAxis:false,
          xAxisFontFamily:'verdana',
          xAxisFontSize:7,
          xAxisColor:'#C2C2C2',
          xAxisBackground:'#E0F0FC',
          xAxisSkip:1,
          xAxisHeight:15,
          xAxisTopBorderHeight:1,
          xAxisTopBorderColor:'#FFFFFF',
          //xaxis title
          drawXAxisBottomTitle:true,
          xAxisBottomTitle:'Title',
          xAxisBottomTitleColor:'#BBBBBB',
          xAxisBottomTitleFontFamily:'verdana',
          xAxisBottomTitleFontSize:9,
          xAxisBottomTitleHeight:20,
          xAxisBottomTitleTopBorderHeight:1,
          xAxisBottomTitleTopBorderColor:'#FFFFFF',
          
          setConfig:[
            {
              x:-1,
              background:'gray',
              color:'cyan'
            }
          ]
          
        },cfg);
        if (!cfg.drawXAxis) {
          cfg.xAxisHeight=0;
          cfg.xAxisTopBorderHeight=0;
        }
        if (!cfg.drawXAxisBottomTitle) {
          cfg.xAxisBottomTitleHeight=0;
          cfg.xAxisBottomTitleTopBorderHeight=0;
        }
        this.width=cfg.width;
        this.height=cfg.height-cfg.xAxisHeight-cfg.xAxisTopBorderHeight-cfg.xAxisBottomTitleHeight-cfg.xAxisBottomTitleTopBorderHeight;
        this.canvas.style.padding=cfg.padding+'px';
        this.canvas.style.width=this.width+'px';
        this.canvas.style.height=(this.height+cfg.xAxisHeight+cfg.xAxisTopBorderHeight+cfg.xAxisBottomTitleHeight+cfg.xAxisBottomTitleTopBorderHeight)+'px';
        var w;
        w=cfg.chartBarWidth;//parseInt(this.width/this.xAxis.length);
        if (w=='auto') {
          w=parseInt(this.width/(this.xAxis.length+((this.xAxis.length-1)*cfg.chartBarHorizontalSpacing)));
        }
        if (w<1) w=1;
        //alert(w);
        var s='';
        
        //container table
        s+='<table cellspacing=0 width="100%" cellpadding=0 border=0 height=100% style="table-layout:fixed">';
        if (cfg.drawYAxis)
          s+='<col width='+cfg.yAxisWidth+'>';
        s+='<col width=100%>';
        s+='<tr>';
        
        if (cfg.drawYAxis) {
          //y axis
          var yAxisStyle=buildStyleList({
            'font-family':cfg.yAxisFontFamily,
            'font-size':cfg.yAxisFontSize,
            'color':cfg.yAxisColor,
            'padding':cfg.yAxisPadding+'px',
            'padding-right':cfg.yAxisPaddingRight+'px',
            'margin-top':cfg.yAxisMarginTop+'px',
            'position':cfg.yAxisPosition
          });          
          s+='<td>';
            s+='<table cellspacing=0 cellpadding=0 border=0 width="100%" height=100% style="table-layout:fixed">';
            s+='<tr>';
            s+='<td style="background:'+cfg.yAxisBackground+'">';
            //y axis values
            s+='<table cellspacing=0 cellpadding=0 border=0 width="100%" height=100%>'
            for (var z=0,zEnd=this.yAxis.length;z<zEnd;z++) {
              s+='<tr><td align="right" valign="'+this.yAxisAlign[this.yAxis.length-z-1]+'"><div style="'+yAxisStyle+'">'+this.yAxis[this.yAxis.length-z-1]+'</div></td></tr>';
            }
            s+='</table>'
            s+='</td>';
            s+='</tr>';
            if (cfg.drawXAxis)
              s+='<tr style="height:'+cfg.xAxisHeight+'px;"><td></td></tr>';
            if (cfg.xAxisBottomTitle!=='' && cfg.xAxisBottomTitle!=null)
              s+='<tr style="height:'+cfg.xAxisBottomTitleHeight+'px;">';
            s+='</table>';
          s+='</td>';
        }  
        
        s+='<td>';

          s+='<table cellspacing=0 cellpadding=0 border=0 width=100% height=100% style="table-layout:fixed">';
          for (var z=0,zEnd=this.xAxis.length;z<zEnd;z++) {
            s+='<col width='+w+'>';
            if (z<this.xAxis.length-1)
              s+='<col width='+cfg.chartBarHorizontalSpacing+'>';
          }
          var maxValue=array_max(this.values);
          var zxEnd=cfg.setConfig.length;
          
          for (var z=0,zEnd=this.xAxis.length;z<zEnd;z++) {
            var value=parseInt(this.values[z]*this.height/maxValue);
            //console.log(value);
            var d='';
            var dColor=cfg.color;
            var tdBackground=cfg.chartBackground;

            for (var zx=0;zx<zxEnd;zx++) {
              if (cfg.setConfig[zx].x==z) {
                if (cfg.setConfig[zx].color!==undefined)
                  dColor=cfg.setConfig[zx].color;
                if (cfg.setConfig[zx].background!==undefined) {
                  tdBackground=cfg.setConfig[zx].background;
                  //console.log(cfg.setConfig[zx].background);
                }
              }
            }
            if (!isNaN(value)) {
              d='<div style="overflow:hidden;width:100%;background:'+dColor+';height:'+value+'px"></div>'
            }
            s+='<td style="background:'+tdBackground+'" valign=bottom>'+d+'</td>';
            if (z<this.xAxis.length-1)
              s+='<td></td>';
          }        
          s+='</tr>'
          
          var columns=this.xAxis.length+this.xAxis.length-1;
          
          if (cfg.drawXAxis) {
            if (cfg.xAxisTopBorderHeight>0)
              s+='<tr style="height:'+cfg.xAxisTopBorderHeight+'px;background:'+cfg.xAxisTopBorderColor+'"><td colspan='+columns+'></td></tr>';
            s+='<tr style="height:'+cfg.xAxisHeight+'px;background:'+cfg.xAxisBackground+'">';
            var xAxisStyle=buildStyleList({
              'font-family':cfg.xAxisFontFamily,
              'font-size':cfg.xAxisFontSize,
              'color':cfg.xAxisColor
            });          
            for (var z=0,zEnd=this.xAxis.length;z<zEnd;z++) {
              var xValue=this.xAxis[z];
              if (z>0 && cfg.xAxisSkip>1 && z%cfg.xAxisSkip!=0)
                xValue='';
              s+='<td align="center" style="'+xAxisStyle+'">'+xValue+'</td>'
              if (z<this.xAxis.length-1)
                s+='<td></td>';
            }        
            s+='</tr>';
          }
          if (cfg.drawXAxisBottomTitle) { 
            if (cfg.xAxisBottomTitleTopBorderHeight>0)
              s+='<tr style="height:'+cfg.xAxisBottomTitleTopBorderHeight+'px;background:'+cfg.xAxisBottomTitleTopBorderColor+'"><td colspan='+columns+'></td></tr>';
            var xAxisBottomTitleStyle=buildStyleList({
              'font-family':cfg.xAxisBottomTitleFontFamily,
              'font-size':cfg.xAxisBottomTitleFontSize+'px',
              'color':cfg.xAxisBottomTitleColor
            });            
            if (cfg.xAxisBottomTitle!=='' && cfg.xAxisBottomTitle!=null) {
              s+='<tr style="height:'+cfg.xAxisBottomTitleHeight+'px;background:'+cfg.xAxisBackground+'">';
              s+='<td colspan="'+columns+'" align="center" style="'+xAxisBottomTitleStyle+'">'+cfg.xAxisBottomTitle+'</td>'
              s+='</tr>';
            }
          }  
          s+='</table';
        
        s+='</td>';
        s+='</tr>';
        s+='</table>';

        this.canvas.innerHTML=s;
      }      
      return {
        define:function(cfg) {
          cfg=object_set({
            xAxis: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
            yAxis: [0,50,100],
            yAxisAlign:['bottom','middle','top'],
            values:[5,6,8,19,30,50,200,100,20,30,4,11,0,1,2,3,4,5,23,44,12,12,33,35],
            parent:document.body
          },cfg);
          return new _Chart_object(cfg);
        }
      }
    }()
  } 
}();

