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
=
0
;
while
(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的客户可以联系我们对这个控件进行升级,或者在提供的全部源码基础上自己完善也可以,呵呵。
希望对大家有所帮助