javascrip 中 onkeyup 事件在输入法情况下不稳定的山寨解决方案【有代码】

 

    E8前一次版本升级提供了拼音智能快速输入的控件,但客户发现了一个不太好用的地方,中文输入法进行中文输入的时候 onkeyup事件不稳定,很多时候取不到,网上一查,这个问题还是一个普遍存在的问题。

   在IE中触发keydown和keyup, 不触发keypress
输入值能够获得,但不稳定。有时候会延后
   在Firefox:触发keydown和keypress, 不触发keyup
输入值未能获得 [Enter]后会触发keyup, 可获得输入值
   在Opera中keydown, keypress和keyup都不触发,输入值也未能获得
[Enter]后,在opera 9.24中会触发keydown和keypress
输入过程中,Space和enter会触发三者

   对于一个控件需要适合在各种环境上运行的,既然存在这样的一些区别,因此实现方式应该更加巧妙一些,这个问题一直困扰了好几天,后来在网上有人推荐了google的脚本文件http://www.google.cn/ac.js 虽然脚本做了干扰处理,但还是能看出它的一些思路,由于控件还有其它功能需求,不能直接照搬这个脚本文件,于是想到了一个山寨的解决方案。(感觉还是没有google流畅,但比以前的版本好很多了)

    主要思路是:

        不用onkeyup事件,改为 在 onfocus 时设置 setInterval 自动处理的机制判断是否有新的输入值, onblur时通过 clearInterval(oTimer) 方法取消自动处理。

     用到的技术点有几个

       1、用匿名函数的方法为 setInterval  传递参数,注意对象的直接传入会有问题,先传入控件的ID,找到后再传递给匿名方法

       2、如果发现有不同的输入值的时候,利用XMLHTTP获取列表

       3、缓存已经获得过的列表,减少后台操作

       4、用动态的div 和 select 动态展示列表

       5、利用键盘事件选择对应的值

       6、处理特定场景下的特定键值,防止浏览器发生不意愿的动作

      

      主要的技术点是以上几点,写脚本是个细致活,再有什么问题再继续完善了。

       脚本文件如下: 希望能给到大家参考

      

//应用开发的基础脚本函数:获取下拉列表快速输入,2008-04-16 苏  2009-02-09 孔修改
    var xmlDroplst = new ActiveXObject("Msxml2.DOMDocument.3.0");  //客户端XML对象
    var arrDroplstID;
    arrDroplstID 
= new Array();     //缓存已经XMLHTTP获取过的ID
    var arrDroplstValue;
    arrDroplstValue 
= new Array();
    
var iDroplstSavedCont = 0;
    
var objOldValue = "";    //保存控件原来的值
    var xmlhttpDroplst = null
    
var currTextBoxID = "-1";
    
var currDivID = "-1";
    
var currOpendDivName = "";
    
var oTimer;
    
// 设置自动检查输入并获取列表
    function SetInputCheckValid(id,idSelect,idText,idFields,obj)
    {
        
var args=[];
        
var object = document.getElementById(id);
        
var objSelect = document.getElementById(idSelect);
        
var objText = document.getElementById(idText);
        args.push(id);
        args.push(object);
        args.push(objSelect);
        args.push(objText);
        args.push(idFields);
        args.push(objText);
        oTimer 
=  setInterval(function(){
                                AutoGetItems.apply(
this,args);
                               },
400);
        }
        
    
function SetInputCheckDisable(){clearInterval(oTimer);}
    
function AutoGetItems(id,object,objSelect,objText,idFields,obj)
    {
         
var i = 0;
         
var j=0;
         
var sCurr = '';
         
var soptText='';
         
var blnAdd = false;
         
var xmlDroplst = new ActiveXObject("Msxml2.DOMDocument.3.0");  //客户端XML对象
         if(objText != null){sCurr = objText.value;}
        
//为空,清除 退出
        if(sCurr == "")
        {
              
//清除现有内容
            if(objSelect != null)
               objSelect.options.length 
= 0;  //清除内容
            return;
        }
        
//值相同则退出
        if(sCurr == objOldValue)
            
return;
        objOldValue 
= sCurr;
        
var sXml  = getXmlHttpFields(idFields + "_" + escape(sCurr));
        
if(sXml != "-1")
        {
            
//从缓存中获取到
            if(object != null)
            {
                
if(sXml=="")  //没有
                {
                    xmlDroplst.loadXML(
"<Root></Root>");
                }
                
else
                {
                    xmlDroplst.loadXML(sXml);
                 }
                
var nodes = xmlDroplst.documentElement.childNodes;
                
if(objSelect != null)
                {
                   objSelect.options.length 
= 0;  //清除内容
                   for (i=0;i<nodes.length;i++)
                   {
                        soptText 
= nodes(i).getAttribute("Text");
                        
//动态获取的情况,所以的内容是从后台筛选过的
                        objSelect.add(document.createElement("OPTION"));
                        objSelect.options[j].text
= soptText;
                        objSelect.options[j].value
=j; 
                        j
++;
                    }
                }
                
if(j >0)
                  {
                     
//存在时显示
                     object.style.left = absoluteLocation(obj, 'offsetLeft'- 2 + "px";       
                     object.style.top 
= absoluteLocation(obj, 'offsetTop'+ obj.offsetHeight + 2 + "px"
                     object.style.width 
= obj.offsetWidth + 2 + 'px';
                     hideMe(id,
'');
                     currOpendDivName 
= id;
                  }
            }
        }
        
else
        {
           
if( sCurr != "")
           {
                
//异步获取
                if(xmlhttpDroplst == null)
                     xmlhttpDroplst 
= CreateDroplstXmlHttpObject();       
                
if(xmlhttpDroplst != null)
                {
                    
try
                    {    
                        xmlhttpDroplst.open(
"GET""../Common/frmXmlHttpDroplst.aspx?id=" + idFields + "&curr=" + escape(sCurr), true); 
                        
//window.open("../Common/frmXmlHttpDroplst.aspx?id=" + idFields);
                        xmlhttpDroplst.setRequestHeader( "CONTENT-TYPE ""application/x-www-form-urlencoded "); 
                        xmlhttpDroplst.onreadystatechange 
= function() 
                                                    { 
                                                        
if ( xmlhttpDroplst.readyState==4 ) 
                                                        {   
                                                            sXml 
= xmlhttpDroplst.responseText;
                                                            
                                                            
if(sXml=="")  //没有
                                                            {
                                                                xmlDroplst.loadXML(
"<Root></Root>");
                                                            }
                                                            
else
                                                            {
                                                                xmlDroplst.loadXML(sXml);
                                                            }
                                                            
//缓存这次结果
                                                            arrDroplstID[iDroplstSavedCont] = idFields + "_" + escape(sCurr);
                                                            arrDroplstValue[iDroplstSavedCont] 
= sXml;
                                                            iDroplstSavedCont
++;
                                                            
if(object != null)
                                                            {
                                                                
var nodes = xmlDroplst.documentElement.childNodes;
                                                                
if(objSelect != null)
                                                                {
                                                                   objSelect.options.length 
= 0;  //清除内容
                                                                   for (i=0;i<nodes.length;i++)
                                                                   {
                                                                        soptText 
= nodes(i).getAttribute("Text");
                                                                        
//动态获取的情况,所以的内容是从后台筛选过的
                                                                        objSelect.add(document.createElement("OPTION"));
                                                                        objSelect.options[j].text
= soptText;
                                                                        objSelect.options[j].value
=j; 
                                                                        j
++;
                                                                        
                                                                    }
                                                                }
                                                                
if(j >0)
                                                                  {
                                                                     
//存在时显示
                                                                     object.style.left = absoluteLocation(obj, 'offsetLeft'- 2 + "px";       
                                                                     object.style.top 
= absoluteLocation(obj, 'offsetTop'+ obj.offsetHeight + 2 + "px"
                                                                     object.style.width 
= obj.offsetWidth + 2 + 'px';
                                                                     hideMe(id,
'');
                                                                  }
                                                            }
                                                            
                                                         }
                                                    }   
                          xmlhttpDroplst.send(
null);   
                     }
                     
catch(e3)
                     {
                     }
               }
           }
       }
    }
    
    setInterval(
"AutoCloseDiv()",3000);
    
function setInputID(idText){currTextBoxID = idText; }
    
function setInputIDNone(){currTextBoxID = "-1"; }
    
function AutoCloseDiv()
    {
        
if(currTextBoxID == "-1" && currDivID == "-1")
        {
            
try{hideMe(currOpendDivName,"none");}catch(e3){}
        }
    }
    
function CreateDroplstXmlHttpObject()
    {
        
try  
        {  
            xmlhttpDroplst 
= new ActiveXObject("MSXML2.XMLHTTP");  
        }  
        
catch(e)  
        {  
            
try  
            {  
                xmlhttpDroplst 
= new ActiveXObject("Microsoft.XMLHTTP");  
            }  
            
catch(e2){}  
        }
        
return xmlhttpDroplst;
    }
    
function focusToDropDown(idSelect)
    {
         
if(event.keyCode == 40)
         {
            
var objSelect = document.getElementById(idSelect);
            
if(objSelect != null)
            {   
try
                {
                   
//有控件不可见的情况
                    objSelect.focus();
                    
if(objSelect.lenght > 0)
                        objSelect.options[
0].selected = true;
                 }
                 
catch(e1)
                 {
                 }
            }
         }
    }
    
function MoverToDropDownLayer(idSelect)
    {
            
var objSelect = document.getElementById(idSelect);
            
if(objSelect != null)
            {   
                 
try
                {
                   
//有控件不可见的情况
                    objSelect.focus();
                    
if(objSelect.selectedIndex == -1)
                        objSelect.selectedIndex 
= 0;
                        
                    currDivID 
= idSelect;
                }
                 
catch(e1)
                 {
                 }
            }
    }
    
function absoluteLocation(element, offset) 
    { 
var c = 0while (element) {  c += element[offset];  element = element.offsetParent; } return c; 
    } 
    
function getSelectedLabel(id,idText,obj) 
    {  
         
var opt = obj.options[obj.selectedIndex]; 
         hideMe(id,
'none'); 
         
var objText = document.getElementById(idText);
        
if(objText != null)
        {
            objText.value 
= getIdiomDeal(opt.text);
        }
    } 
    
function getIdiomDeal(s)
    {
        
var sRet = s;
        
if(typeof(getUserIdiomDeal) !="undefined")
        {
            sRet 
= getUserIdiomDeal(s);
        }
        
return sRet;
    }
    
function selectOnReturn(id,idText,obj)
    {
       
if(event.keyCode == 8)
          event.keyCode 
= null;
       
if(event.keyCode==13)
       {
            event.returnValue 
= false;
            getSelectedLabel(id,idText,obj);
        }
    }
    
function hideMe(id,status)
    {
        
var object = document.getElementById(id);
        
if(object != null)
        {
            object.style.display 
= status;
            
if(status == "none")
            {
                currDivID 
= "-1";
                currTextBoxID 
= "-1";
            }
        }
    }
    
function getItemsForDropdown(id,idSelect,idText,idFields,obj)
    {
         
var object = document.getElementById(id);
         
var objSelect = document.getElementById(idSelect);
          
var objText = document.getElementById(idText);
          
var objFields = document.getElementById(idFields);
         
var i = 0;
         
var j=0;
         
var sCurr = '';
         
var soptText='';
         
var blnAdd = false;
         
         
if(objFields != null)
         {  
var sXml = objFields.value;
            xmlDroplst.loadXML(sXml);
         }
         
if(objText != null){ sCurr = objText.value; }
        
if(object != null)
        {
            
var nodes = xmlDroplst.documentElement.childNodes;
            
if(objSelect != null)
            {
               objSelect.options.length 
= 0;  //清除内容
               for (i=0;i<nodes.length;i++)
               {
                    soptText 
= nodes(i).getAttribute("Text");
                    blnAdd 
= false;
                    
if(sCurr == '')
                    {
                       blnAdd 
= true;
                    }
                    
else
                    {
                       
if(soptText.toUpperCase().indexOf(sCurr.toUpperCase()) == 0)
                         {
                            blnAdd
=true;
                         }
                    }
                    
if(blnAdd == true)
                    {
                        objSelect.add(document.createElement(
"OPTION"));
                        objSelect.options[j].text
= soptText;
                        objSelect.options[j].value
=j; 
                        j
++;
                        
                    }
                }
            }
            object.style.left 
= absoluteLocation(obj, 'offsetLeft'- 2 + "px";       
            object.style.top 
= absoluteLocation(obj, 'offsetTop'+ obj.offsetHeight + 2 + "px"
            object.style.width 
= obj.offsetWidth + 2 + 'px';
            hideMe(id,
'');
            currOpendDivName 
= id;
        }
    }
    
//来源于XMLHTTP异步获取,***未改***
    function getItemsForDropdownXmlHttp(id,idSelect,idText,idFields,obj)
    {
         
var object = document.getElementById(id);
         
var objSelect = document.getElementById(idSelect);
          
var objText = document.getElementById(idText);
         
var i = 0;
         
var j=0;
         
var sCurr = '';
         
var soptText='';
         
var blnAdd = false;
         
var xmlDroplst = new ActiveXObject("Msxml2.DOMDocument.3.0");  //客户端XML对象
         
         
if(objText != null){sCurr = objText.value;}
        
var sXml  = getXmlHttpFields(idFields);
        
if(sXml != "-1")
        {
            
//从缓存中获取到
            if(object != null)
            {
                
if(sXml=="")  //没有
                {
                    xmlDroplst.loadXML(
"<Root></Root>");
                }
                
else
                {
                    xmlDroplst.loadXML(sXml);
                 }
                
var nodes = xmlDroplst.documentElement.childNodes;
                
if(objSelect != null)
                {
                   objSelect.options.length 
= 0;  //清除内容
                   for (i=0;i<nodes.length;i++)
                   {
                        soptText 
= nodes(i).getAttribute("Text");
                        blnAdd 
= false;
                        
if(sCurr == '')
                        {
                           blnAdd 
= true;
                        }
                        
else
                        {
                           
if(soptText.toUpperCase().indexOf(sCurr.toUpperCase()) == 0)
                             {
                                blnAdd
=true;
                             }
                        }
                        
if(blnAdd == true)
                        {
                            objSelect.add(document.createElement(
"OPTION"));
                            objSelect.options[j].text
= soptText;
                            objSelect.options[j].value
=j;  
                            
//objSelect.options[j].className = "combo-item";
                            j++;
                        }
                    }
                }
                
if(j >0)
                  {
                     
//存在时显示
                     object.style.left = absoluteLocation(obj, 'offsetLeft'- 2 + "px";       
                     object.style.top 
= absoluteLocation(obj, 'offsetTop'+ obj.offsetHeight + 2 + "px"
                     object.style.width 
= obj.offsetWidth + 2 + 'px';
                     hideMe(id,
'');
                     currOpendDivName 
= id;
                  }
            }
        }
        
else
        {
            
//异步获取
            if(xmlhttpDroplst == null)
                 xmlhttpDroplst 
= CreateDroplstXmlHttpObject();       
            
if(xmlhttpDroplst != null)
            {
                
try
                {    
                    xmlhttpDroplst.open(
"GET""../Common/frmXmlHttpDroplst.aspx?id=" + idFields, true); 
                    
//window.open("../Common/frmXmlHttpDroplst.aspx?id=" + idFields);
                    xmlhttpDroplst.setRequestHeader( "CONTENT-TYPE ""application/x-www-form-urlencoded "); 
                    xmlhttpDroplst.onreadystatechange 
= function() 
                                                { 
                                                    
if ( xmlhttpDroplst.readyState==4 ) 
                                                    {   
                                                        sXml 
= xmlhttpDroplst.responseText;
                                                        
                                                        
if(sXml=="")  //没有
                                                        {
                                                            xmlDroplst.loadXML(
"<Root></Root>");
                                                        }
                                                        
else
                                                        {
                                                            xmlDroplst.loadXML(sXml);
                                                            
                                                        }
                                                        
//缓存这次结果
                                                        arrDroplstID[iDroplstSavedCont] = idFields;
                                                        arrDroplstValue[iDroplstSavedCont] 
= sXml;
                                                        iDroplstSavedCont
++;
                                                        
if(object != null)
                                                        {
                                                            
var nodes = xmlDroplst.documentElement.childNodes;
                                                            
if(objSelect != null)
                                                            {
                                                               objSelect.options.length 
= 0;  //清除内容
                                                               for (i=0;i<nodes.length;i++)
                                                               {
                                                                    soptText 
= nodes(i).getAttribute("Text");
                                                                    blnAdd 
= false;
                                                                    
if(sCurr == '')
                                                                    {
                                                                       blnAdd 
= true;
                                                                    }
                                                                    
else
                                                                    {
                                                                       
if(soptText.toUpperCase().indexOf(sCurr.toUpperCase()) == 0)
                                                                         {
                                                                            blnAdd
=true;
                                                                         }
                                                                    }
                                                                    
if(blnAdd == true)
                                                                    {
                                                                        objSelect.add(document.createElement(
"OPTION"));
                                                                        objSelect.options[j].text
= soptText;
                                                                        objSelect.options[j].value
=j; 
                                                                        j
++;
                                                                    }
                                                                }

                                                            }
                                                            
if(j >0)
                                                              {
                                                                 
//存在时显示
                                                                 object.style.left = absoluteLocation(obj, 'offsetLeft'- 2 + "px";       
                                                                 object.style.top 
= absoluteLocation(obj, 'offsetTop'+ obj.offsetHeight + 2 + "px"
                                                                 object.style.width 
= obj.offsetWidth + 2 + 'px';
                                                                 hideMe(id,
'');
                                                              }
                                                        }
                                                     }
                                                }   
                      xmlhttpDroplst.send(
null);   
                 }
                 
catch(e3)
                 {
                 }
           }
       }
    }
    
//通过缓存数组获取可以选择的值
    function getXmlHttpFields(idFields)
    {
        
var respText = "-1";
        
var i = 0;
        
for(i=0;i<iDroplstSavedCont;i++)
        {
            
if(idFields == arrDroplstID[i])
            {
               respText 
= arrDroplstValue[i];
            }
        }
        
return respText;
  }

 

 

    整个控件脚本只是一部分,还有相应的aspx 后台代码 ascx代码等,这个就不一一介绍了,E8的客户可以联系我们对这个控件进行升级,或者在提供的全部源码基础上自己完善也可以,呵呵。

 

    希望对大家有所帮助

posted @ 2009-02-11 10:34  赵思伟  阅读(2301)  评论(6编辑  收藏  举报