﻿/*
 * Copyright (c) 2006, www.never-online.net! All rights reserved.
 * web    : http://www.never-online
 * author : never-online, BlueDestiny
 * version: 0.10.0 
 * this is a autocomplete extras version, complete version in neverModules framework.
 * debug in IE6.0, Opera9.0, Mozilla Firefox1.5.0
 */ 


var neverModules = window.neverModules || {};

neverModules.browser = neverModules.browser || {
  isMozilla: (typeof document.implementation != 'undefined') && (typeof document.implementation.createDocument != 'undefined') && (typeof HTMLDocument!='undefined'),
  isIE: window.ActiveXObject?true:false,
  isOpera: (navigator.userAgent.toLowerCase().indexOf("opera")!=-1)
}

neverModules.modules = neverModules.modules || {}; 

if (!neverModules.browser.isIE) {
  HTMLElement.prototype.click = function() {
    var evt = this.ownerDocument.createEvent('MouseEvents');
    evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
    this.dispatchEvent(evt);
  }
}

String.prototype.regEncode = function () {
  var val = this; if (val=="undefined") { return ""; }
  val = val.replace(/\\/g,"\\");
  val = val.replace(/\//g,"\/");
  val = val.replace(/\^/g,"\\^");
  val = val.replace(/\*/g,"\\*");
  val = val.replace(/\?/g,"\\?");
  val = val.replace(/\+/g,"\\+");
  val = val.replace(/\./g,"\\.");
  val = val.replace(/\|/g,"\\|");
  val = val.replace(/\[/g,"\\[");
  val = val.replace(/\]/g,"\\]");
  val = val.replace(/\(/g,"\\(");
  val = val.replace(/\)/g,"\\)");
  val = val.replace(/\{/g,"\\{");
  val = val.replace(/\}/g,"\\}");
  return val;
}

function FnGetElementos(e) {

  var t = e.offsetTop;
  var l = e.offsetLeft;
  var w = e.offsetWidth;
  var h = e.offsetHeight;
  while (e=e.offsetParent) {
    t += e.offsetTop;
    l += e.offsetLeft;
  }; return {
    top: t,
    left: l,
    width: w,
    height: h
  }
}

// main module of autocomplete

neverModules.modules.autocomplete = function (oConfigs) {

  this.bIgnoreCase = (oConfigs.ignoreCase===false)?false:true;
  this.bIgnoreWhere = (oConfigs.ignoreWhere===true)?true:false;
  this.name = oConfigs.instanceName; // need
  window[this.name] = this;
  this.oTextbox = oConfigs.textbox;  // need
  this.oHiddenTextbox = oConfigs.hiddenTextbox //need for our codetable
  this.oRetTextBox = oConfigs.retTextBox||this.oTextbox; //optional
  this.autoSlice = (oConfigs.autoSlice===false)?false:true;
  this.nMaxSlice = isNaN(parseInt(oConfigs.maxSlice))?100:parseInt(oConfigs.maxSlice); // if autoSlice==true config this object
  this.queryRange = {low: 0, high: 200}; // if autoSlice==true config this object
  this.highlighted = (oConfigs.highlight===false)?false:true;
    
  this._oContainer = null;
  this._oPopupIframe = null;
  this._styleName = oConfigs.style?oConfigs.style:"neverModules-auto";
  this._nScrollHeight = isNaN(parseInt(oConfigs.height))?200:parseInt(oConfigs.height);
  this._nSelectIndex = -1;
  this._ownInstance = this;
  this._dataSource = '';
  this.setDataSource(oConfigs.dataSource);
  this._defaultInitializer.apply(this);

}

neverModules.modules.autocomplete.prototype = {

  _defaultInitializer: function() { with(this) {
      oTextbox.setAttribute("autocomplete","off");
      _oContainer    = document.createElement("DIV");
      //_oContainer.onmouseout = function(){_oContainer.style.display="none"};
      document.body.appendChild(_oContainer);

      _oContainer.className = this._styleName;
      with (_oContainer.style) {
        height   = _nScrollHeight+"px";
        overflow = "auto";
        zIndex   = "20001";
        position = "absolute";
        display  = "none";
      }

      if (neverModules.browser.isIE) {
        _oPopupIframe = document.createElement("IFRAME");
        document.body.appendChild(_oPopupIframe);
        with (_oPopupIframe.style) {
          position = "absolute";
          display  = "none";
          zIndex = 1;
          overflow = "hidden";
          frameBorder = "0";
          scrolling = "no";
          marginHeight = "0";
          marginWidth = "0";
        }
      }
      var own = this._ownInstance;
      oTextbox.onblur = function() {
        var arr = $A(this.auto._oContainer.getElementsByTagName('div'))
        if(document.activeElement==this.auto._oContainer){
            this.auto._oContainer.auto = this.auto
            this.auto._oContainer.onblur = function(){
                this.auto.handlerClose()
            }
            return
        }
        if(arr.indexOf(document.activeElement)==-1){
            own.handlerClose()
        }
      }
  }},

  _tg: function (oItem, sClassName) {
    this._ownInstance._handlerToggleEvent.apply(this, arguments);
  },
  _handlerToggleEvent: function (oItem, sClassName) {
    var e = this._oContainer.childNodes[this._nSelectIndex];
    if (e) e.className = "out";
    oItem.className = sClassName;
  },

  _handlerClickEvent: function (oElement) {
	//debugger
    this.oTextbox.value = oElement.innerHTML.replace(/<[^<>]*>/g,"");
    if(this.oTextbox.o){
        var oTextboxHidden = this.oTextbox.o.eDmCod;
        if(!oTextboxHidden)
            $(this.oTextbox.id+"_value")
        oTextboxHidden.value = oElement.hiddenValue;
        if(oTextboxHidden.onchange){
            oTextboxHidden.onchange()
        }
        //lisq add 2006-01-25
        Field.activate(this.oTextbox)
    }
    this.handlerClose();
  },
  _hc: function (oElement) {
    this._ownInstance._handlerClickEvent.apply(this, arguments);
  },

  _handlerQueryEvent: function (sQueryVal) {
    var sRegExp = ""; var sRegOpt = "";
    this.bIgnoreCase ? sRegOpt="i" : sRegOpt="";
    sRegExp = '<div[^<>]+?>' +(this.bIgnoreWhere?'[^<>]*?':'')+sQueryVal+'[^<>]*?<\/div>';
    if (this.bCustom) sRegExp=sCustomRegExp;

    var oRegExp = new RegExp().compile(sRegExp, sRegOpt+"g");
    var aMatch = this._dataSource.match(oRegExp); 
    oRegExp = null; if (aMatch==null && false) { this.handlerClose(); return; }

    if (this.highlighted===true) {
      oRegExp = new RegExp().compile("(?:>)([^<>]*?)(" +sQueryVal+ ")", sRegOpt+"g");
      this._oContainer.innerHTML=this._dataSource;
      //this._oContainer.innerHTML=(this.autoSlice && aMatch.length>this.nMaxSlice?aMatch.slice(this.queryRange.low, this.queryRange.high).join(""):aMatch.join("")).replace(oRegExp, ">$1<strong>$2</strong>");
    } else {
      this._oContainer.innerHTML=this.autoSlice && aMatch.length>this.nMaxSlice?aMatch.slice(this.queryRange.low, this.queryRange.high).join(""):aMatch.join("");
    }
    //_handlerToggleEvent(this._oContainer.firseChild, "over");
    this._nSelectIndex = 0; //lisq how to focus on the first element
    var e = this._oContainer.childNodes[this._nSelectIndex];
    e.className = "over";
    e.scrollIntoView(false);
  },

  _handlerArrowEvent: function (nKeyCode) { with(this) {
    switch (nKeyCode) {
      case 13: // enter
        if (_oContainer.childNodes[_nSelectIndex])
        _oContainer.childNodes[_nSelectIndex].click();
        break;
      case 38: // up arrow
        if (_oContainer.childNodes[_nSelectIndex]) _oContainer.childNodes[_nSelectIndex].className = "out";
        if (--_nSelectIndex<=0) _nSelectIndex=0;
        break;
      case 40: // down arrow
        if (_oContainer.childNodes[_nSelectIndex]) _oContainer.childNodes[_nSelectIndex].className = "out"; 
        if (++_nSelectIndex>=_oContainer.childNodes.length) _nSelectIndex=_oContainer.childNodes.length-1;
        break;
      case 27: // esc
        this.handlerClose();
        break;
      default: // to do
        return;
    }
    if (_oContainer.childNodes[_nSelectIndex]) {
      var e = _oContainer.childNodes[_nSelectIndex];
      e.className = "over";
      e.scrollIntoView(false);
      //e.focus(); lisq because input element will fire typecheck event when it blur
    }

  }},
  
  _fixCoordinate: function () {
	if(this._oContainer.childNodes.length==0)
		return;
    var p = FnGetElementos(this.oTextbox); 
    var x = this._oContainer.style; 

    x.left    = p.left+5+"px";
    x.top     = p.top+p.height+5+"px";
    x.width   = p.width+"px";
    x.display = "block";

    if (neverModules.browser.isIE) {
      var w = this._oPopupIframe.style;
      w.left    = p.left+"px";
      w.top     = p.top+p.height+"px";
      w.width   = p.width+"px";
      w.height  = this._oContainer.offsetHeight+"px";
      w.display =  "block";
    }

    this._oContainer.scrollTop = '0px';
  },

  handlerClose: function () {
    if (neverModules.browser.isIE) {this._oContainer.style.display = "none";this._oPopupIframe.style.display = "none"};
    this._oContainer.style.display = "none";
  },

  clearDataSource: function () {
    this._dataSource = "";
  },

  setDataSource: function(aDataSource) {
	if(aDataSource.length == 0)
		return;
    if (aDataSource.constructor==Array) {
      if (aDataSource[0].length==1) {
        this._dataSource = '<div hiddenValue="' + aDataSource[1][0] +'" class="out" onclick="' +this.name+'._hc(this)" onmouseover="' +this.name+'._tg(this,\'over\')" onmouseout="' +this.name+'._tg(this,\'out\')">' +aDataSource[0][0]+ '</div>';
        //window.setTime("this._oContainer.childNodes[0].click()", 1000);
        //this.oTextbox.value = aDataSource[0][0];
        //$(this.oTextbox.id+"_hidden").value = aDataSource[1][0];
      } else {
        /*
        this._dataSource = '<div class="out" onclick="' +this.name+'._hc(this)" onmouseover="'
        +this.name+'._tg(this,\'over\')" onmouseout="'
        +this.name+'._tg(this,\'out\')">'+aDataSource[0].join('</div><div class="out" onclick="'
        +this.name+'._hc(this)" onmouseover="' +this.name+'._tg(this,\'over\')" onmouseout="'
        +this.name+'._tg(this,\'out\')">')+"</div>";
        */
        var s = "";
        var o = this;
        aDataSource[0].each(function(dmcpt, i){s +='<div hiddenValue="' + aDataSource[1][i] +'" class="out" onclick="' +o.name+'._hc(this)" onmouseover="' +o.name+'._tg(this,\'over\')" onmouseout="' +o.name+'._tg(this,\'out\')">' +dmcpt+ '</div>';});
        this._dataSource = s;
      }
    } else { throw new Error("配置参数 dataSource 不是一个数组"); }
  },

  handlerEvent: function (nKeyCode) {
    var queryVal = this.oTextbox.value; 
    //var nKeyCode = window.event?event.keyCode:evt.which;

    if (nKeyCode==13 || nKeyCode==38 || nKeyCode==40 || nKeyCode==27) {
      this._handlerArrowEvent(nKeyCode);
      return true;
    } else {    
      this._oContainer.innerHTML = "";
    }

    if (queryVal == "") {
      this.handlerClose();
      return false;
    } else {
      this._handlerQueryEvent(queryVal.regEncode()); 
      this._fixCoordinate();
      return true;
    }

  }
}
