自动适应输入内容宽度的TextBox控件

    在ASP.NET的上面,TextBox是表单设计时最常用的控件之一。很多时候为了页面的紧凑和美观,我们需要适当的限制TextBox的显示宽度,但是如果TextBox过于窄了之后,又会给用户的填写带了不便,而且更麻烦的是很多时候我们并不知道用户到底会往那个TextBox里填多少内容。为了解决这些问题,下面给大家推荐一个可自动适应输入内容的宽度的TextBox控件。

    本控件是从TextBox控件继承,设计原理是使用一个agent input(type=text)来做为实际的用户录入的TextBox,在焦点切换的过程中完成background input和agent input的属性同步。 

    下面的代码完成两个input之间的样式和属性同步:

ContractedBlock.gif ExpandedBlockStart.gif function ATB_SwitchToInputAgent(input) #region function ATB_SwitchToInputAgent(input)
None.giffunction ATB_SwitchToInputAgent(input)
None.gif{
None.gif    
var spanWrapper = input.parentElement;
None.gif    
var agentInput = spanWrapper.lastChild;
None.gif    
var userOffsetTop, userOffsetLeft;
None.gif    
with(input.style)
None.gif    {
None.gif        
var userMarginTop = parseInt(marginTop);
None.gif        
var userMarginLeft = parseInt(marginLeft);
None.gif        
var userBorderTop = parseInt(borderTopWidth);
None.gif        
var userBorderLeft = parseInt(borderLeftWidth);
None.gif        userMarginTop 
= isNaN(userMarginTop) ? 0 : userMarginTop;
None.gif        userMarginLeft 
= isNaN(userMarginLeft) ? 0 : userMarginLeft;
None.gif        userBorderTop 
= isNaN(userBorderTop) ? 0 : userBorderTop;
None.gif        userBorderLeft 
= isNaN(userBorderLeft) ? 0 : userBorderLeft;
None.gif        userOffsetTop 
= userBorderTop + userMarginTop;
None.gif        userOffsetLeft 
= userBorderLeft + userMarginLeft;
None.gif    }
None.gif    
var retouch = 0;
None.gif    agentInput.style.top 
= userOffsetTop;
None.gif    agentInput.style.left 
= userOffsetLeft-1;
None.gif    spanWrapper.style.zIndex 
= 2;
None.gif    agentInput.style.display 
= 'inline';
None.gif    agentInput.value 
= input.value;
None.gif    agentInput.style.borderWdith 
= input.style.borderWdith;
None.gif    agentInput.style.borderColor 
= input.style.borderColor;
None.gif    agentInput.style.backgroundColor 
= input.style.backgroundColor;
None.gif    agentInput.style.color 
= input.style.color;
None.gif    agentInput.style.fontFamily 
= input.style.fontFamily;
None.gif    agentInput.style.fontWegith 
= input.style.fontWeight;
None.gif    agentInput.style.fontSize 
= input.style.fontSize;
None.gif    agentInput.style.height 
= input.style.height;
None.gif    agentInput.style.fontStyle 
= input.style.fontStyle;
None.gif    
try { agentInput.style.font = input.style.font } catch(exp){};
None.gif    agentInput.style.fontVariant 
= input.style.fontVariant;
None.gif    agentInput.style.zoom 
= input.style.zoom;
None.gif    agentInput.focus();
None.gif    agentInput.select();
None.gif}
  #endregion
 
    注意:不能使用style=style或for( attribute in style)的方式来赋值,否这引起onpropertychange的死循环递归 emcrook.gif

    第二个问题是使用onpropertychange属性来同步agent input的宽度和其内容宽度相等,代码如下: 
None.gif function  ATB_AutoIncreaseWidth(input) 
None.gif
None.gif    
if  ( input.style.display  ==  'none' )  return
None.gif    
var  spanWrapper  =  input.parentElement; 
None.gif    
var  userInput  =  spanWrapper.firstChild; 
None.gif    userInput.value 
=  input.value; 
None.gif    
var  absOffsetWidth  =  GetAbsoluteOffsetLeft(input); 
None.gif    
var  docClientWidth  =  window.document.body.clientWidth; 
None.gif    
if  ( input.scrollWidth  <  userInput.clientWidth ) 
None.gif    { 
None.gif        
if  ( absOffsetWidth  +  styleWidth  >=  docClientWidth )  
None.gif        { 
None.gif            input.style.width 
=  docClientWidth  -  absOffsetWidth; 
None.gif        } 
None.gif        
else  
None.gif        { 
None.gif            input.style.width 
=  userInput.clientWidth + 2
None.gif        } 
None.gif        
return
None.gif    } 
None.gif    
var  styleWidth  =  parseInt(input.style.width); 
None.gif    
if  ( styleWidth  !=  input.scrollWidth + 2  ) 
None.gif    { 
None.gif        
if  ( absOffsetWidth  +  styleWidth  >=  docClientWidth )  
None.gif        { 
None.gif            input.style.width 
=  docClientWidth  -  absOffsetWidth; 
None.gif        } 
None.gif        
else  
None.gif        { 
None.gif            input.style.width 
=  input.scrollWidth + 2
None.gif        } 
None.gif    } 
None.gif
    这里需要注意的是当增长的agent input的最右端超出了IE的body区域时,需要停止其增长,否则用户看不见输入的东西了。 

    演示效果如下:
    
*

ContractedBlock.gif ExpandedBlockStart.gif 附 AdjustableTextBox 控件源码 #region 附 AdjustableTextBox 控件源码
InBlock.gif
using System;
InBlock.gif
using System.IO;
InBlock.gif
using System.Drawing;
InBlock.gif
using System.Text;
InBlock.gif
using System.Web.UI;
InBlock.gif
using System.Web.UI.WebControls;
InBlock.gif
using System.ComponentModel;
InBlock.gif
InBlock.gif
namespace WebExcel.UI.WebControls
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Summary description for AdjustableTextBox.
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    [DefaultProperty("Text")]
InBlock.gif    [ToolboxData(
"<{0}:AdjustableTextBox runat=server></{0}:AdjustableTextBox>")]
InBlock.gif    
public class AdjustableTextBox : TextBox
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public Color AgentBorderColor
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
object obj = ViewState["AgentBorderColor"];
InBlock.gif                
return obj == null ? Color.Gray : (Color)obj;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ViewState[
"AgentBorderColor"= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool AutoIncrease
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
object obj = ViewState["AutoIncrease"];
InBlock.gif                
return obj == null ? true : (bool)obj;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                ViewState[
"AutoIncrease"= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// the property is always TextBoxMode.SingleLine.
InBlock.gif
        public override TextBoxMode TextMode
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return base.TextMode;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
base.TextMode = value;
InBlock.gif                
if ( value != TextBoxMode.SingleLine )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
this.AutoIncrease = false;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
this.AutoIncrease = true;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public new Unit BorderWidth
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if ( base.BorderWidth == Unit.Empty )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
base.BorderWidth = 1;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return base.BorderWidth;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if ( value != Unit.Empty )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
base.BorderWidth = value;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> 
InBlock.gif        
/// Render this control to the output parameter specified.
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <param name="output"> The HTML writer to write out to </param>

InBlock.gif        protected override void Render(HtmlTextWriter output)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if ( this.AutoIncrease )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.RegisterClientScript();
InBlock.gif                
base.Attributes["onfocus"= "ATB_SwitchToInputAgent(this)";
InBlock.gif                
base.Attributes.CssStyle["position"= "relative";
InBlock.gif                
if ( base.BorderWidth == Unit.Empty )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
base.BorderWidth = 1;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
string spanWrapper = @"<span style='z-index: 1; position: relative; border: solid 0px black;'>{0}<input type='text' οnblur='ATB_GetAgentValue(this)' onpropertychange='ATB_AutoIncreaseWidth(this)' style='border: solid 1px gray; position: absolute; display:none;' /></span>";
InBlock.gif                StringBuilder sb 
= new StringBuilder();
InBlock.gif                StringWriter sw 
= new StringWriter(sb);
InBlock.gif                HtmlTextWriter htw 
= new HtmlTextWriter(sw);
InBlock.gif                
base.Render(htw);
InBlock.gif                output.Write(
string.Format(spanWrapper, sb.ToString(), ColorTranslator.ToHtml(this.AgentBorderColor)));
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// base.Attributes["onfocus"] = "this.height='100%'";
InBlock.gif
                base.Render(output);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void RegisterClientScript()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
const string COMMON_SCRIPT_KEY = "__CommonJavaScript__";
InBlock.gif            
string strCommon = @"<script language='javascript'>
InBlock.gif
            function GetAbsoluteOffsetLeft(element)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if ( element == null || arguments.length != 1 )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
return;
ExpandedSubBlockEnd.gif                }

InBlock.gif                var offsetLeft 
= element.offsetLeft;
InBlock.gif                
while( element = element.offsetParent )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    offsetLeft 
+= element.offsetLeft;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
return offsetLeft;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
</script>";
InBlock.gif
            if ( !this.Page.IsStartupScriptRegistered(COMMON_SCRIPT_KEY) )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.Page.RegisterStartupScript(COMMON_SCRIPT_KEY, strCommon);
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
const string SCRIPT_KEY = "__AdjustableTextBoxKey__";
InBlock.gif            
string strScript = @"
InBlock.gif
                <script language='javascript'>
InBlock.gif                function ATB_SwitchToInputAgent(input)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if ( input.disabled ) return;
InBlock.gif                    var spanWrapper 
= input.parentElement;
InBlock.gif                    var agentInput 
= spanWrapper.lastChild;
InBlock.gif                    var userOffsetTop, userOffsetLeft;
InBlock.gif                    with(input.style)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        var userMarginTop 
= parseInt(marginTop);
InBlock.gif                        var userMarginLeft 
= parseInt(marginLeft);
InBlock.gif                        var userBorderTop 
= parseInt(borderTopWidth);
InBlock.gif                        var userBorderLeft 
= parseInt(borderLeftWidth);
InBlock.gif                        userMarginTop 
= isNaN(userMarginTop) ? 0 : userMarginTop;
InBlock.gif                        userMarginLeft 
= isNaN(userMarginLeft) ? 0 : userMarginLeft;
InBlock.gif                        userBorderTop 
= isNaN(userBorderTop) ? 0 : userBorderTop;
InBlock.gif                        userBorderLeft 
= isNaN(userBorderLeft) ? 0 : userBorderLeft;
InBlock.gif                        userOffsetTop 
= userBorderTop + userMarginTop;
InBlock.gif                        userOffsetLeft 
= userBorderLeft + userMarginLeft;
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    var retouch 
= 0;
InBlock.gif                    agentInput.value 
= input.value; // must be mdified at first
InBlock.gif
                    agentInput.style.top = userOffsetTop;
InBlock.gif                    agentInput.style.left 
= userOffsetLeft-1;
InBlock.gif                    spanWrapper.style.zIndex 
= 10;
InBlock.gif                    agentInput.style.display 
= 'inline';
InBlock.gif                    agentInput.style.borderWdith 
= input.style.borderWdith;
InBlock.gif                    agentInput.style.borderColor 
= input.style.borderColor;
InBlock.gif                    agentInput.style.backgroundColor 
= input.style.backgroundColor;
InBlock.gif                    agentInput.style.color 
= input.style.color;
InBlock.gif                    agentInput.style.fontFamily 
= input.style.fontFamily;
InBlock.gif                    agentInput.style.fontWegith 
= input.style.fontWeight;
InBlock.gif                    agentInput.style.fontSize 
= input.style.fontSize;
InBlock.gif                    agentInput.style.height 
= input.style.height;
InBlock.gif                    var absOffsetWidth 
= GetAbsoluteOffsetLeft(input);
InBlock.gif                    var docClientWidth 
= window.document.body.clientWidth;
InBlock.gif                    var styleWidth 
= parseInt(agentInput.style.width);
InBlock.gif                    
if ( absOffsetWidth + styleWidth >= docClientWidth ) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        agentInput.style.width 
= docClientWidth - absOffsetWidth;
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        agentInput.style.width 
= input.clientWidth+2;
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    agentInput.style.fontStyle 
= input.style.fontStyle;
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
try dot.gif{ agentInput.style.font = input.style.font } catch(exp)dot.gif{};
InBlock.gif                    agentInput.style.fontVariant 
= input.style.fontVariant;
InBlock.gif                    agentInput.style.zoom 
= input.style.zoom;
InBlock.gif                    agentInput.readOnly 
= input.readOnly;
InBlock.gif                    
//agentInput.focus(); must remove!!!
InBlock.gif
                    if ( !agentInput.readOnly )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{        
InBlock.gif                        agentInput.select();
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                function ATB_GetAgentValue(input)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    var spanWrapper 
= input.parentElement;
InBlock.gif                    var userInput 
= spanWrapper.firstChild;
InBlock.gif                    input.style.width 
= userInput.clientWidth+2;
InBlock.gif                    spanWrapper.style.zIndex 
= 1;
InBlock.gif                    userInput.value 
= input.value;
InBlock.gif                    input.style.display 
= 'none';
ExpandedSubBlockEnd.gif                }

InBlock.gif                
InBlock.gif                function ATB_AutoIncreaseWidth(input)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if ( input.style.display == 'none' ) return;
InBlock.gif                    var spanWrapper 
= input.parentElement;
InBlock.gif                    var userInput 
= spanWrapper.firstChild;
InBlock.gif                    userInput.value 
= input.value;
InBlock.gif                    var absOffsetWidth 
= GetAbsoluteOffsetLeft(input);
InBlock.gif                    var docClientWidth 
= window.document.body.clientWidth;
InBlock.gif                    
if ( input.scrollWidth < userInput.clientWidth )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
if ( absOffsetWidth + styleWidth >= docClientWidth ) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            input.style.width 
= docClientWidth - absOffsetWidth;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            input.style.width 
= userInput.clientWidth+2;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
return;
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    var styleWidth 
= parseInt(input.style.width);
InBlock.gif                    
if ( styleWidth != input.scrollWidth+2 )
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
if ( absOffsetWidth + styleWidth >= docClientWidth ) 
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            input.style.width 
= docClientWidth - absOffsetWidth;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            input.style.width 
= input.scrollWidth+2;
ExpandedSubBlockEnd.gif                        }

ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
</script>";
InBlock.gif
            if ( !this.Page.IsStartupScriptRegistered(SCRIPT_KEY) )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
this.Page.RegisterStartupScript(SCRIPT_KEY, strScript);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif
#endregion
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值