最近做的一个类似Google自动完成的服务器控件
项目背景:
最近项目中需要根据公司选择该公司的部门,根据公司查找该公司的员工。其实类似于以前做过的级联菜单,
选择一级城市后过滤二级城市。为了方便输入,做成了一个控件。
实现:
因为该控件服务器端主要是继承至CompositeControl控件,里面注册了一个TextBox,HiddenField,和
Image三个服务器端控件,然后注册js调用该控件客户端的初始化函数。没有特别的东西,故不贴出来了。
客户端js还是比较多的,有些比较重要的东西。先看代码
Code
if(typeof("sg_AutoFilterState")!='object')
sg_AutoFilterState = [];
if(typeof("sg_AutoFilterIndex")!='object')
sg_AutoFilterIndex = [];
function sg_AutoFilter(id,targetcontrolid,popupcontrolid,hiddenControlId,initvalue,selecttype)
{
sg_AutoFilterState[id]=this;
sg_AutoFilterIndex[sg_AutoFilterIndex.length]=this;
this.TargetControl=$get(targetcontrolid);
this.PopupControl=$get(popupcontrolid);
this.HiddenControl=$get(hiddenControlId);
this.DropdownPanelSelectedItem=[];//eg:[{text:张三,value:800382}]
this.TargetPanelSelectedItem=[];//eg:[{fieldname:branchid,fieldvalue:469}]
this.DropdownPanel=null;
this.PopupPanel=null;
this.TextChanged=null;
this.DisplayRrecordsCount=10;
this.MultiSelect=false;
this.FilterInitValue=initvalue;
this.SelectType=selecttype;
this._bgcolr=null;
this._currentSelect=-1;
this._oldSelectItem=null;
}
sg_AutoFilter.prototype = {
initialize:function(){
this.TargetControl.onfocus=Function.createDelegate(this,this.add_TextChanged);
this.TargetControl.onblur=Function.createDelegate(this,this._textBlur);
this.add_PopupClick();
},
get_DropdownPanelSelectedItem:function(){
return this.DropdownPanelSelectedItem;
},
set_DropdownPanelSelectedItem:function(item){
this.DropdownPanelSelectedItem[this.DropdownPanelSelectedItem.length]=item;
},
get_TargetPanelSelectedItem:function(){
return this.TargetPanelSelectedItem;
},
set_TargetPanelSelectedItem:function(item){
this.TargetPanelSelectedItem[this.TargetPanelSelectedItem.length]=item;
},
add_TextChanged:function(){
var targetDiv=document.createElement('DIV');
var region=Sys.UI.DomElement.getBounds(this.TargetControl);
targetDiv.style.left=region.x;
targetDiv.style.width= (region.width <= 0)?150:region.width;
targetDiv.style.top=region.y+region.height;
targetDiv.style.height=this.DisplayRrecordsCount*25;
targetDiv.style.display='none';
targetDiv.style.zIndex=1000;
targetDiv.style.position="absolute";
targetDiv.style.backgroundColor="#C9DAE9";
targetDiv.style.border="1px solid #000000";
this.TargetControl.parentElement.appendChild(targetDiv);
this.DropdownPanel=targetDiv;
this.TargetControl.onpropertychange=Function.createDelegate(this,this._textChanged);
},
remove_TextChanged:function(handler){
$removeHandler(this.TargetControl,'propertychange',handler);
},
add_PopupClick:function(){
var popupDiv=document.createElement('DIV');
var region=Sys.UI.DomElement.getBounds(this.PopupControl);
popupDiv.style.left=region.x;
popupDiv.style.width=160;
popupDiv.style.height=120;
popupDiv.style.overflow="auto";
popupDiv.style.top=region.y+region.height;
popupDiv.style.display='none';
popupDiv.style.zIndex=1000;
popupDiv.style.position="absolute";
popupDiv.style.backgroundColor="#C9DAE9";
popupDiv.style.border="1px solid #000000";
popupDiv.style.scrollbar3dLightColor="#A6CAEE";
popupDiv.style.scrollbarBaseColor="#c9dae9";
popupDiv.style.scrollbarArrowColor="#000000";
popupDiv.style.scrollbarShadowColor="#c9dae9";
popupDiv.style.scrollbarFaceColor="#c9dae9";
popupDiv.style.scrollbarTrackColor="#c9dae9";
this.PopupControl.parentElement.appendChild(popupDiv);
this.PopupPanel=popupDiv;
this.PopupControl.onclick=Function.createDelegate(this,this._popupClickHandler);
},
remove_PopupClick:function(handler){
$removeHandler(this.PopupControl,'click',handler);
},
set_DisplayRrecordsCount:function(value){
if(value)
this.DisplayRrecordsCount=value;
},
set_DisplayRrecordsCount:function(){
return this.DisplayRrecordsCount;
},
show_DropdownPanel:function(){
if(self.frameElement)
{
var p = this._getPosition(this.TargetControl);
this.DropdownPanel.style.left = p.x;
this.DropdownPanel.style.top = p.y;
}
this.DropdownPanel.style.display='';
},
hide_DropdownPanel:function(){
if(this.DropdownPanel)
this.DropdownPanel.style.display='none';
},
get_Text:function(){
return this.TargetControl.value;
},
set_Text:function(text){
this.TargetControl.value=text;
},
get_Value:function(){
return this.HiddenControl.value;
},
set_Value:function(value){
this.HiddenControl.value=value;
},
_textChanged:function(){
//if(this.TargetControl.value.trim()=='') return;
this.show_DropdownPanel();
var xmldom=sg.xmlDocument();
var root=xmldom.createElement("Root");
if(this.SelectType=="SelectOrganization")
root.setAttribute("type","SelectOrganization");
if(this.SelectType=="SelectPosition")
root.setAttribute("type","SelectPosition");
if(this.SelectType=="SelectPerson")
root.setAttribute("type","SelectPerson");
xmldom.appendChild(root);
var keyword=xmldom.createElement("keyword");
keyword.text=this.TargetControl.value;
root.appendChild(keyword);
var branchid=xmldom.createElement("branchid");
if(this.TargetPanelSelectedItem.length==0)
branchid.text=this.FilterInitValue;
else
branchid.text=this.TargetPanelSelectedItem[this.TargetPanelSelectedItem.length-1].Value;
root.appendChild(branchid);
var maxrecord=xmldom.createElement("maxrecord");
maxrecord.text=this.DisplayRrecordsCount;
root.appendChild(maxrecord);
if(sg.Location)
var result = sg.SendXmlDataSync(sg.Location+"ajax/share/sgAutoFilter.ashx",xmldom).responseText;
else
var result = sg.SendXmlDataSync("ajax/share/sgAutoFilter.ashx",xmldom).responseText;
this.DropdownPanel.innerHTML=result;
this._currentSelect=-1;
//为下拉面板添加事件
var liList = this.DropdownPanel.getElementsByTagName("LI");
for(var i=0;i<liList.length;i++)
{
var li=liList[i];
li.onmousedown = Function.createDelegate(this,this._onClickRowHandler);
li.onmouseover = Function.createDelegate(this,this._onMouseOverRowHandler);
li.onmouseout = Function.createDelegate(this,this._onMouseOutRowHandler);
}
document.onkeydown=Function.createDelegate(this,this._keydown);
},
_textBlur:function(){
this.DropdownPanel.style.display='none';
},
_keydown:function(){
if(this.DropdownPanel.style.display=='')
{
var liList = this.DropdownPanel.getElementsByTagName("LI");
if(event.keyCode==40)//向下
{
if(this._currentSelect==liList.length-1)
{
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
return;
}
this._currentSelect++;
var li=liList[this._currentSelect];
this._bgcolr=li.style.backgroundColor;
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
}
if(event.keyCode==38)//向上
{
if(this._currentSelect==-1)
return;
if(this._currentSelect==0)
{
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
return;
}
this._currentSelect--;
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
}
if(event.keyCode==13)
{
if(this._currentSelect==-1)
return;
var li=liList[this._currentSelect];
this.TargetControl.value=li.innerText;
this.HiddenControl.value=li.id.split('_')[1];
this.DropdownPanel.style.display='none';
this.set_Text(this.TargetControl.value);
this.set_Value(li.id.split('_')[1]);
var item = {"text":this.TargetControl.value,"value":li.id.split('_')[1]}
this.DropdownPanelSelectedItem.push(item);
}
if(event.keyCode==27)
{
this.DropdownPanel.style.display='none';
}
}
},
_popupClickHandler:function(){
//debugger
if(this.PopupPanel.style.display=='none')
{
if(self.frameElement)
{
var p = this._getPosition(this.TargetControl);
this.PopupPanel.style.left = p.x;
this.PopupPanel.style.top = p.y;
}
this.PopupPanel.style.display='';
}
else
{
this.PopupPanel.style.display='none';
var chekboxList = this.PopupPanel.getElementsByTagName('INPUT');
for(var i=0;i<chekboxList.length;i++)
{
if(chekboxList[i].checked==true)
{
var fieldName=chekboxList[i].id.split('_')[1];
var fieldValue=chekboxList[i].id.split('_')[2];
var item={"Name":fieldName,"Value":fieldValue};
this.TargetPanelSelectedItem.push(item);
}
}
}
},
_onClickRowHandler:function(){
this.TargetControl.value=event.srcElement.innerText;
this.HiddenControl.value=event.srcElement.id.split('_')[1];
this.set_Text(this.TargetControl.value);
this.set_Value(event.srcElement.id.split('_')[1]);
},
_onMouseOverRowHandler:function(){
var liList = this.DropdownPanel.getElementsByTagName("LI");
this._bgcolr=event.srcElement.style.backgroundColor;
event.srcElement.style.backgroundColor="#FFCCCC";
if(this._currentSelect<liList.length)
this._currentSelect++;
},
_onMouseOutRowHandler:function(){
event.srcElement.style.backgroundColor=this._bgcolr;
if(this._currentSelect>0)
this._currentSelect--;
},
_getPosition:function(control){
var elementParent = control;
var scrollHeight = 0;
var topHeight=0;
var leftWidth = 0;
while(elementParent.tagName!="BODY")
{
if(elementParent.style.position=="absolute")
{
elementParent = elementParent.offsetParent;
continue;
}
topHeight+=elementParent.offsetTop;
if(elementParent.tagName=="DIV")
{
topHeight = topHeight - elementParent.scrollTop;
leftWidth = leftWidth - elementParent.scrollLeft;
scrollHeight += elementParent.scrollTop;
}
leftWidth+=elementParent.offsetLeft//+(elementParent.scrollWidth-elementParent.offsetWidth);
elementParent = elementParent.offsetParent;
};
var x = control.offsetLeft+leftWidth+document.body.scrollLeft;
var y = control.offsetHeight+topHeight+document.body.scrollTop;
if(y+control.offsetHeight+scrollHeight>self.frameElement.offsetHeight)
y = y-control.offsetHeight-control.style.posHeight;
var p = {};
p.x = x;
p.y = y;
return p;
}
}
sg.get_sgAutoFilterById = function(id)
{
return sg_AutoFilterState[id];
}
if(typeof("sg_AutoFilterState")!='object')
sg_AutoFilterState = [];
if(typeof("sg_AutoFilterIndex")!='object')
sg_AutoFilterIndex = [];
function sg_AutoFilter(id,targetcontrolid,popupcontrolid,hiddenControlId,initvalue,selecttype)
{
sg_AutoFilterState[id]=this;
sg_AutoFilterIndex[sg_AutoFilterIndex.length]=this;
this.TargetControl=$get(targetcontrolid);
this.PopupControl=$get(popupcontrolid);
this.HiddenControl=$get(hiddenControlId);
this.DropdownPanelSelectedItem=[];//eg:[{text:张三,value:800382}]
this.TargetPanelSelectedItem=[];//eg:[{fieldname:branchid,fieldvalue:469}]
this.DropdownPanel=null;
this.PopupPanel=null;
this.TextChanged=null;
this.DisplayRrecordsCount=10;
this.MultiSelect=false;
this.FilterInitValue=initvalue;
this.SelectType=selecttype;
this._bgcolr=null;
this._currentSelect=-1;
this._oldSelectItem=null;
}
sg_AutoFilter.prototype = {
initialize:function(){
this.TargetControl.onfocus=Function.createDelegate(this,this.add_TextChanged);
this.TargetControl.onblur=Function.createDelegate(this,this._textBlur);
this.add_PopupClick();
},
get_DropdownPanelSelectedItem:function(){
return this.DropdownPanelSelectedItem;
},
set_DropdownPanelSelectedItem:function(item){
this.DropdownPanelSelectedItem[this.DropdownPanelSelectedItem.length]=item;
},
get_TargetPanelSelectedItem:function(){
return this.TargetPanelSelectedItem;
},
set_TargetPanelSelectedItem:function(item){
this.TargetPanelSelectedItem[this.TargetPanelSelectedItem.length]=item;
},
add_TextChanged:function(){
var targetDiv=document.createElement('DIV');
var region=Sys.UI.DomElement.getBounds(this.TargetControl);
targetDiv.style.left=region.x;
targetDiv.style.width= (region.width <= 0)?150:region.width;
targetDiv.style.top=region.y+region.height;
targetDiv.style.height=this.DisplayRrecordsCount*25;
targetDiv.style.display='none';
targetDiv.style.zIndex=1000;
targetDiv.style.position="absolute";
targetDiv.style.backgroundColor="#C9DAE9";
targetDiv.style.border="1px solid #000000";
this.TargetControl.parentElement.appendChild(targetDiv);
this.DropdownPanel=targetDiv;
this.TargetControl.onpropertychange=Function.createDelegate(this,this._textChanged);
},
remove_TextChanged:function(handler){
$removeHandler(this.TargetControl,'propertychange',handler);
},
add_PopupClick:function(){
var popupDiv=document.createElement('DIV');
var region=Sys.UI.DomElement.getBounds(this.PopupControl);
popupDiv.style.left=region.x;
popupDiv.style.width=160;
popupDiv.style.height=120;
popupDiv.style.overflow="auto";
popupDiv.style.top=region.y+region.height;
popupDiv.style.display='none';
popupDiv.style.zIndex=1000;
popupDiv.style.position="absolute";
popupDiv.style.backgroundColor="#C9DAE9";
popupDiv.style.border="1px solid #000000";
popupDiv.style.scrollbar3dLightColor="#A6CAEE";
popupDiv.style.scrollbarBaseColor="#c9dae9";
popupDiv.style.scrollbarArrowColor="#000000";
popupDiv.style.scrollbarShadowColor="#c9dae9";
popupDiv.style.scrollbarFaceColor="#c9dae9";
popupDiv.style.scrollbarTrackColor="#c9dae9";
this.PopupControl.parentElement.appendChild(popupDiv);
this.PopupPanel=popupDiv;
this.PopupControl.onclick=Function.createDelegate(this,this._popupClickHandler);
},
remove_PopupClick:function(handler){
$removeHandler(this.PopupControl,'click',handler);
},
set_DisplayRrecordsCount:function(value){
if(value)
this.DisplayRrecordsCount=value;
},
set_DisplayRrecordsCount:function(){
return this.DisplayRrecordsCount;
},
show_DropdownPanel:function(){
if(self.frameElement)
{
var p = this._getPosition(this.TargetControl);
this.DropdownPanel.style.left = p.x;
this.DropdownPanel.style.top = p.y;
}
this.DropdownPanel.style.display='';
},
hide_DropdownPanel:function(){
if(this.DropdownPanel)
this.DropdownPanel.style.display='none';
},
get_Text:function(){
return this.TargetControl.value;
},
set_Text:function(text){
this.TargetControl.value=text;
},
get_Value:function(){
return this.HiddenControl.value;
},
set_Value:function(value){
this.HiddenControl.value=value;
},
_textChanged:function(){
//if(this.TargetControl.value.trim()=='') return;
this.show_DropdownPanel();
var xmldom=sg.xmlDocument();
var root=xmldom.createElement("Root");
if(this.SelectType=="SelectOrganization")
root.setAttribute("type","SelectOrganization");
if(this.SelectType=="SelectPosition")
root.setAttribute("type","SelectPosition");
if(this.SelectType=="SelectPerson")
root.setAttribute("type","SelectPerson");
xmldom.appendChild(root);
var keyword=xmldom.createElement("keyword");
keyword.text=this.TargetControl.value;
root.appendChild(keyword);
var branchid=xmldom.createElement("branchid");
if(this.TargetPanelSelectedItem.length==0)
branchid.text=this.FilterInitValue;
else
branchid.text=this.TargetPanelSelectedItem[this.TargetPanelSelectedItem.length-1].Value;
root.appendChild(branchid);
var maxrecord=xmldom.createElement("maxrecord");
maxrecord.text=this.DisplayRrecordsCount;
root.appendChild(maxrecord);
if(sg.Location)
var result = sg.SendXmlDataSync(sg.Location+"ajax/share/sgAutoFilter.ashx",xmldom).responseText;
else
var result = sg.SendXmlDataSync("ajax/share/sgAutoFilter.ashx",xmldom).responseText;
this.DropdownPanel.innerHTML=result;
this._currentSelect=-1;
//为下拉面板添加事件
var liList = this.DropdownPanel.getElementsByTagName("LI");
for(var i=0;i<liList.length;i++)
{
var li=liList[i];
li.onmousedown = Function.createDelegate(this,this._onClickRowHandler);
li.onmouseover = Function.createDelegate(this,this._onMouseOverRowHandler);
li.onmouseout = Function.createDelegate(this,this._onMouseOutRowHandler);
}
document.onkeydown=Function.createDelegate(this,this._keydown);
},
_textBlur:function(){
this.DropdownPanel.style.display='none';
},
_keydown:function(){
if(this.DropdownPanel.style.display=='')
{
var liList = this.DropdownPanel.getElementsByTagName("LI");
if(event.keyCode==40)//向下
{
if(this._currentSelect==liList.length-1)
{
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
return;
}
this._currentSelect++;
var li=liList[this._currentSelect];
this._bgcolr=li.style.backgroundColor;
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
}
if(event.keyCode==38)//向上
{
if(this._currentSelect==-1)
return;
if(this._currentSelect==0)
{
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
return;
}
this._currentSelect--;
var li=liList[this._currentSelect];
li.style.backgroundColor="#FFCCCC";
if(this._oldSelectItem)
this._oldSelectItem.style.backgroundColor=this._bgcolr;
this._oldSelectItem=li;
}
if(event.keyCode==13)
{
if(this._currentSelect==-1)
return;
var li=liList[this._currentSelect];
this.TargetControl.value=li.innerText;
this.HiddenControl.value=li.id.split('_')[1];
this.DropdownPanel.style.display='none';
this.set_Text(this.TargetControl.value);
this.set_Value(li.id.split('_')[1]);
var item = {"text":this.TargetControl.value,"value":li.id.split('_')[1]}
this.DropdownPanelSelectedItem.push(item);
}
if(event.keyCode==27)
{
this.DropdownPanel.style.display='none';
}
}
},
_popupClickHandler:function(){
//debugger
if(this.PopupPanel.style.display=='none')
{
if(self.frameElement)
{
var p = this._getPosition(this.TargetControl);
this.PopupPanel.style.left = p.x;
this.PopupPanel.style.top = p.y;
}
this.PopupPanel.style.display='';
}
else
{
this.PopupPanel.style.display='none';
var chekboxList = this.PopupPanel.getElementsByTagName('INPUT');
for(var i=0;i<chekboxList.length;i++)
{
if(chekboxList[i].checked==true)
{
var fieldName=chekboxList[i].id.split('_')[1];
var fieldValue=chekboxList[i].id.split('_')[2];
var item={"Name":fieldName,"Value":fieldValue};
this.TargetPanelSelectedItem.push(item);
}
}
}
},
_onClickRowHandler:function(){
this.TargetControl.value=event.srcElement.innerText;
this.HiddenControl.value=event.srcElement.id.split('_')[1];
this.set_Text(this.TargetControl.value);
this.set_Value(event.srcElement.id.split('_')[1]);
},
_onMouseOverRowHandler:function(){
var liList = this.DropdownPanel.getElementsByTagName("LI");
this._bgcolr=event.srcElement.style.backgroundColor;
event.srcElement.style.backgroundColor="#FFCCCC";
if(this._currentSelect<liList.length)
this._currentSelect++;
},
_onMouseOutRowHandler:function(){
event.srcElement.style.backgroundColor=this._bgcolr;
if(this._currentSelect>0)
this._currentSelect--;
},
_getPosition:function(control){
var elementParent = control;
var scrollHeight = 0;
var topHeight=0;
var leftWidth = 0;
while(elementParent.tagName!="BODY")
{
if(elementParent.style.position=="absolute")
{
elementParent = elementParent.offsetParent;
continue;
}
topHeight+=elementParent.offsetTop;
if(elementParent.tagName=="DIV")
{
topHeight = topHeight - elementParent.scrollTop;
leftWidth = leftWidth - elementParent.scrollLeft;
scrollHeight += elementParent.scrollTop;
}
leftWidth+=elementParent.offsetLeft//+(elementParent.scrollWidth-elementParent.offsetWidth);
elementParent = elementParent.offsetParent;
};
var x = control.offsetLeft+leftWidth+document.body.scrollLeft;
var y = control.offsetHeight+topHeight+document.body.scrollTop;
if(y+control.offsetHeight+scrollHeight>self.frameElement.offsetHeight)
y = y-control.offsetHeight-control.style.posHeight;
var p = {};
p.x = x;
p.y = y;
return p;
}
}
sg.get_sgAutoFilterById = function(id)
{
return sg_AutoFilterState[id];
}
实现效果,先看看以下以下两个图
根据拼音检索
根据汉字检索
里面有几个重要的知识点,
1)dom的操作。
2)Function.createDelegate(this,this._handler) 或者用函数的闭包来实现。
3)该控件如果放在浮动的层中时设定弹出层的相对位置。
内容太多,页面不动了:),下篇分析!
作者:Jackhuclan
出处:http://jackhuclan.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://jackhuclan.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。