这是一个teddy最近封装的autocompletetextbox。我们知道,asp.net本身的textbox也是支持一定的autocomplete功能的,但是那是依赖浏览器实现的,并不能指定自定义的autocomplete候选项。本文列举的autocompletetextbox则弥补了这个缺憾。只需设置autocompletetextbox.autocompletedata属性,传递一个string[],就能使textbox支持自定义候选项了。
autocomplete逻辑
如果没有匹配当前输入的候选项,则同一般的textbox;如果只有一个候选项与当前输入匹配,则自动完成;如果有超过一个候选项与当前输入匹配,则在textbox中自动完成第一个候选项,并弹出包含所有候选项的弹出框。
实现源码
源码是在vs2005编译的,不过实际上几乎没有使用依赖2.0的语法,在vs2003下经极少修改就同样能编译的。
using system;
using system.collections.generic;
using system.componentmodel;
using system.text;
using system.web;
using system.web.ui;
using system.web.ui.webcontrols;
using system.web.ui.htmlcontrols;
namespace ilungasoft.framework.web.ui.webcontrols
{
[toolboxdata("<{0}:autocompletetextbox runat=server></{0}:autocompletetextbox>")]
public class autocompletetextbox : webcontrol
{
private members#region private members
private textbox textbox = new textbox();
private htmlgenericcontrol autocompleteframe = new htmlgenericcontrol();
private string tojsstringarray(params string[] strs)
{
if (strs != null && strs.length > 0)
{
stringbuilder sb = new stringbuilder();
sb.append(" new array(");
foreach (string str in strs)
{
sb.append(string.format("'{0}', ", str.replace("'", "//'")));
}
return sb.tostring().trimend(',', ' ') + ");";
}
else
{
return " new array;";
}
}
private string makeuniqueid(string id)
{
if (id != null && id.trim().length > 0)
{
return string.concat(this.uniqueid.replace("$", "_"), "_", id);
}
else
{
return this.uniqueid.replace("$", "_");
}
}
#endregion
properties#region properties
[bindable(true)]
[category("appearance")]
[defaultvalue("")]
[localizable(true)]
public string text
{
get
{
if (page.ispostback)
{
textbox.text = page.request.form[makeuniqueid("textbox")];
}
return textbox.text;
}
set
{
textbox.text = value;
}
}
[bindable(true)]
[category("behavior")]
[defaultvalue("")]
[localizable(true)]
public int maxlength
{
get
{
return textbox.maxlength;
}
set
{
textbox.maxlength = value;
}
}
[bindable(true)]
[category("behavior")]
[defaultvalue(false)]
[localizable(true)]
public bool readonly
{
get
{
return textbox.readonly;
}
set
{
textbox.readonly = value;
}
}
public string[] autocompletedata
{
get
{
string[] s = (string[])viewstate["autocompletedata"];
return ((s == null) ? null : s);
}
set
{
viewstate["autocompletedata"] = value;
}
}
#endregion
overriden members#region overriden members
protected override void createchildcontrols()
{
create textbox#region create textbox
textbox.id = makeuniqueid("textbox");
textbox.autocompletetype = autocompletetype.disabled;
textbox.attributes.add("onkeypress", string.format("return __doautocomplete(event, '{0}')", makeuniqueid(null)));
textbox.attributes.add("onblur", string.format("if (!document.show_{0}) document.getelementbyid('{1}').style.display = 'none';", makeuniqueid(null), makeuniqueid("autocompleteframe")));
textbox.width = width;
#endregion
create autocompleteframe#region create autocompleteframe
autocompleteframe.tagname = "iframe";
autocompleteframe.id = makeuniqueid("autocompleteframe");
autocompleteframe.attributes.add("style", "display:none; position: absolute; border: ridge 1px");
autocompleteframe.attributes.add("frameborder", "0");
autocompleteframe.attributes.add("marginheight", "0");
autocompleteframe.attributes.add("marginwidth", "2");
autocompleteframe.attributes.add("scrolling", "auto");
autocompleteframe.attributes.add("width", width.tostring());
autocompleteframe.attributes.add("height", "100px");
autocompleteframe.attributes.add("src", "javascript:''");
autocompleteframe.attributes.add("onmouseover", string.format("document.show_{0} = true;", makeuniqueid(null)));
autocompleteframe.attributes.add("onmouseout", string.format("document.show_{0} = false;", makeuniqueid(null)));
#endregion
}
protected override void onprerender(eventargs e)
{
register client script block#region register client script block
if (!page.clientscript.isclientscriptblockregistered("__doautocomplete"))
{
string script = string.concat(
"<script language=/"javascript/" type=/"text/javascript/">/r/n",
" var isopera = navigator.useragent.indexof('opera') > -1;/r/n",
" var isie = navigator.useragent.indexof('msie') > 1 && !isopera;/r/n",
" var ismoz = navigator.useragent.indexof('mozilla/5.') == 0 && !isopera;/r/n",
"/r/n",
" function textboxselect (otextbox, istart, iend)/r/n",
" {/r/n",
" switch(arguments.length) {/r/n",
" case 1:/r/n",
" otextbox.select();/r/n",
" break;/r/n",
"/r/n",
" case 2:/r/n",
" iend = otextbox.value.length;/r/n",
" /* falls through *//r/n",
" /r/n",
" case 3: /r/n",
" if (isie) {/r/n",
" var orange = otextbox.createtextrange();/r/n",
" orange.movestart(/"character/", istart);/r/n",
" orange.moveend(/"character/", -otextbox.value.length + iend); /r/n",
" orange.select(); /r/n",
" } else if (ismoz){/r/n",
" otextbox.setselectionrange(istart, iend);/r/n",
" } /r/n",
" }/r/n",
"/r/n",
" otextbox.focus();/r/n",
" }/r/n",
"/r/n",
" function textboxreplaceselect (otextbox, stext)/r/n",
" {/r/n",
" if (isie) {/r/n",
" var orange = document.selection.createrange();/r/n",
" orange.text = stext;/r/n",
" orange.collapse(true);/r/n",
" orange.select(); /r/n",
" } else if (ismoz) {/r/n",
" var istart = otextbox.selectionstart;/r/n",
" otextbox.value = otextbox.value.substring(0, istart) + stext + otextbox.value.substring(otextbox.selectionend, otextbox.value.length);/r/n",
" otextbox.setselectionrange(istart + stext.length, istart + stext.length);/r/n",
" }/r/n",
"/r/n",
" otextbox.focus();/r/n",
" }/r/n",
"/r/n",
" function autocompletematch (stext, arrvalues)/r/n",
" {/r/n",
" var retmatches = /"/"; /r/n",
" /r/n",
" for (var i=0; i < arrvalues.length; i++)/r/n",
" {/r/n",
" if (arrvalues[i].indexof(stext) == 0)/r/n",
" {/r/n",
" retmatches += arrvalues[i] + ',';/r/n",
" }/r/n",
" }/r/n",
" /r/n",
" if (retmatches.length > 0)/r/n",
" {/r/n",
" retmatches = retmatches.substr(0, retmatches.length - 1);/r/n",
" } /r/n",
"/r/n",
" return retmatches;/r/n",
" }/r/n",
"/r/n",
" function __doautocomplete(oevent, id)/r/n",
" {/r/n",
" var otextbox = document.getelementbyid(id + '_textbox');/r/n",
" var frame = document.getelementbyid(id + '_autocompleteframe');/r/n",
" var arrvalues = document[id + '_data'];/r/n",
" /r/n",
" switch (oevent.keycode) /r/n",
" {/r/n",
" case 38: //up arrow /r/n",
" case 40: //down arrow/r/n",
" case 37: //left arrow/r/n",
" case 39: //right arrow/r/n",
" case 33: //page up /r/n",
" case 34: //page down /r/n",
" case 36: //home /r/n",
" case 35: //end /r/n",
" case 13: //enter /r/n",
" case 9: //tab /r/n",
" case 27: //esc /r/n",
" case 16: //shift /r/n",
" case 17: //ctrl /r/n",
" case 18: //alt /r/n",
" case 20: //caps lock/r/n",
" case 8: //backspace /r/n",
" case 46: //delete/r/n",
" return true;/r/n",
" break;/r/n",
" /r/n",
" default:/r/n",
" textboxreplaceselect(otextbox, string.fromcharcode(isie ? oevent.keycode : oevent.charcode));/r/n",
" var ilen = otextbox.value.length;/r/n",
"/r/n",
" var smatches = autocompletematch(otextbox.value, arrvalues);/r/n",
"/r/n",
" if (smatches.length > 0)/r/n",
" {/r/n",
" var arrmatches = smatches.split(',');/r/n",
" otextbox.value = arrmatches[0];/r/n",
" textboxselect(otextbox, ilen, otextbox.value.length);/r/n",
" /r/n",
" if (arrmatches.length > 1)/r/n",
" {/r/n",
" frame.style.display = 'inline';/r/n",
" frame.height = '100';/r/n",
" /r/n",
" frame.contentwindow.document.body.innerhtml = '';/r/n",
" for (var i = 0; i < arrmatches.length; i++)/r/n",
" {/r/n",
" frame.contentwindow.document.body.innerhtml += '<div style=/"width: 100%; cursor: default/" onmouseover=/"this.style.backgroundcolor=//'#316ac5//'; this.style.color=//'white//';/" onmouseout=/"this.style.backgroundcolor=//'//'; this.style.color=//'black//';/" onclick=/"parent.document.getelementbyid(//'' + id + '_textbox//').value = this.innerhtml/">' + arrmatches[i] + '</div>';/r/n",
" }/r/n",
" /r/n",
" frame.contentwindow.document.body.style.backgroundcolor = 'white';/r/n",
" frame.contentwindow.document.onclick = function() { document.getelementbyid(id + '_autocompleteframe').style.display = 'none'; };/r/n",
" } /r/n",
" } /r/n",
" /r/n",
" return false;/r/n",
" } /r/n",
" }/r/n",
"</script>/r/n",
"");
page.clientscript.registerclientscriptblock(typeof(string), "__doautocomplete", script);
}
if (!page.clientscript.isclientscriptblockregistered(makeuniqueid("data")))
{
page.clientscript.registerclientscriptblock(typeof(string), makeuniqueid("data"), string.format("<script language=/"javascript/" type=/"text/javascript/">document.{0}_data = {1}</script>", makeuniqueid(null), tojsstringarray(autocompletedata)));
}
#endregion
}
protected override void rendercontents(htmltextwriter output)
{
output.writeline(string.format("<div onmouseleave=/"document.getelementbyid('{0}').style.display = 'none';/" style=/"width:{1}/" >", makeuniqueid("autocompleteframe"), width));
textbox.rendercontrol(output);
output.writeline("<br />");
autocompleteframe.rendercontrol(output);
output.writeline("</div>");
}
#endregion
}
}
http://teddyma.cnblogs.com/files/teddyma/autocompletetextbox.zip
新闻热点
疑难解答
图片精选