自动适应输入内容宽度的TextBox控件
在ASP.NET的上面,TextBox是表单设计时最常用的控件之一。很多时候为了页面的紧凑和美观,我们需要适当的限制TextBox的显示宽度,但是如果TextBox过于窄了之后,又会给用户的填写带了不便,而且更麻烦的是很多时候我们并不知道用户到底会往那个TextBox里填多少内容。
在ASP.NET的上面,TextBox是表单设计时最常用的控件之一。很多时候为了页面的紧凑和美观,我们需要适当的限制TextBox的显示宽度,但是如果TextBox过于窄了之后,又会给用户的填写带了不便,而且更麻烦的是很多时候我们并不知道用户到底会往那个TextBox里填多少内容。为了解决这些问题,下面给大家推荐一个可自动适应输入内容的宽度的TextBox控件。
本控件是从TextBox控件继承,设计原理是使用一个agent input(type=text)来做为实际的用户录入的TextBox,在焦点切换的过程中完成background input和agent input的属性同步。
下面的代码完成两个input之间的样式和属性同步:
function ATB_SwitchToInputAgent(input)#region function ATB_SwitchToInputAgent(input)
function ATB_SwitchToInputAgent(input)
{
var spanWrapper = input.parentElement;
var agentInput = spanWrapper.lastChild;
var userOffsetTop, userOffsetLeft;
with(input.style)
{
var userMarginTop = parseInt(marginTop);
var userMarginLeft = parseInt(marginLeft);
var userBorderTop = parseInt(borderTopWidth);
var userBorderLeft = parseInt(borderLeftWidth);
userMarginTop = isNaN(userMarginTop) ? 0 : userMarginTop;
userMarginLeft = isNaN(userMarginLeft) ? 0 : userMarginLeft;
userBorderTop = isNaN(userBorderTop) ? 0 : userBorderTop;
userBorderLeft = isNaN(userBorderLeft) ? 0 : userBorderLeft;
userOffsetTop = userBorderTop + userMarginTop;
userOffsetLeft = userBorderLeft + userMarginLeft;
}
var retouch = 0;
agentInput.style.top = userOffsetTop;
agentInput.style.left = userOffsetLeft-1;
spanWrapper.style.zIndex = 2;
agentInput.style.display = 'inline';
agentInput.value = input.value;
agentInput.style.borderWdith = input.style.borderWdith;
agentInput.style.borderColor = input.style.borderColor;
agentInput.style.backgroundColor = input.style.backgroundColor;
agentInput.style.color = input.style.color;
agentInput.style.fontFamily = input.style.fontFamily;
agentInput.style.fontWegith = input.style.fontWeight;
agentInput.style.fontSize = input.style.fontSize;
agentInput.style.height = input.style.height;
agentInput.style.fontStyle = input.style.fontStyle;
try { agentInput.style.font = input.style.font } catch(exp){};
agentInput.style.fontVariant = input.style.fontVariant;
agentInput.style.zoom = input.style.zoom;
agentInput.focus();
agentInput.select();
}
#endregion
function ATB_SwitchToInputAgent(input)
{
var spanWrapper = input.parentElement;
var agentInput = spanWrapper.lastChild;
var userOffsetTop, userOffsetLeft;
with(input.style)
{
var userMarginTop = parseInt(marginTop);
var userMarginLeft = parseInt(marginLeft);
var userBorderTop = parseInt(borderTopWidth);
var userBorderLeft = parseInt(borderLeftWidth);
userMarginTop = isNaN(userMarginTop) ? 0 : userMarginTop;
userMarginLeft = isNaN(userMarginLeft) ? 0 : userMarginLeft;
userBorderTop = isNaN(userBorderTop) ? 0 : userBorderTop;
userBorderLeft = isNaN(userBorderLeft) ? 0 : userBorderLeft;
userOffsetTop = userBorderTop + userMarginTop;
userOffsetLeft = userBorderLeft + userMarginLeft;
}
var retouch = 0;
agentInput.style.top = userOffsetTop;
agentInput.style.left = userOffsetLeft-1;
spanWrapper.style.zIndex = 2;
agentInput.style.display = 'inline';
agentInput.value = input.value;
agentInput.style.borderWdith = input.style.borderWdith;
agentInput.style.borderColor = input.style.borderColor;
agentInput.style.backgroundColor = input.style.backgroundColor;
agentInput.style.color = input.style.color;
agentInput.style.fontFamily = input.style.fontFamily;
agentInput.style.fontWegith = input.style.fontWeight;
agentInput.style.fontSize = input.style.fontSize;
agentInput.style.height = input.style.height;
agentInput.style.fontStyle = input.style.fontStyle;
try { agentInput.style.font = input.style.font } catch(exp){};
agentInput.style.fontVariant = input.style.fontVariant;
agentInput.style.zoom = input.style.zoom;
agentInput.focus();
agentInput.select();
}
#endregion
第二个问题是使用onpropertychange属性来同步agent input的宽度和其内容宽度相等,代码如下:
function ATB_AutoIncreaseWidth(input)
{
if ( input.style.display == 'none' ) return;
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
userInput.value = input.value;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
if ( input.scrollWidth < userInput.clientWidth )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = userInput.clientWidth+2;
}
return;
}
var styleWidth = parseInt(input.style.width);
if ( styleWidth != input.scrollWidth+2 )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = input.scrollWidth+2;
}
}
}
{
if ( input.style.display == 'none' ) return;
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
userInput.value = input.value;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
if ( input.scrollWidth < userInput.clientWidth )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = userInput.clientWidth+2;
}
return;
}
var styleWidth = parseInt(input.style.width);
if ( styleWidth != input.scrollWidth+2 )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = input.scrollWidth+2;
}
}
}
演示效果如下:
* |
附 AdjustableTextBox 控件源码#region 附 AdjustableTextBox 控件源码
using System;
using System.IO;
using System.Drawing;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace WebExcel.UI.WebControls
{
/**//// <summary>
/// Summary description for AdjustableTextBox.
/// </summary>
[DefaultProperty("Text")]
[ToolboxData("<{0}:AdjustableTextBox runat=server></{0}:AdjustableTextBox>")]
public class AdjustableTextBox : TextBox
{
public Color AgentBorderColor
{
get
{
object obj = ViewState["AgentBorderColor"];
return obj == null ? Color.Gray : (Color)obj;
}
set
{
ViewState["AgentBorderColor"] = value;
}
}
public bool AutoIncrease
{
get
{
object obj = ViewState["AutoIncrease"];
return obj == null ? true : (bool)obj;
}
set
{
ViewState["AutoIncrease"] = value;
}
}
// the property is always TextBoxMode.SingleLine.
public override TextBoxMode TextMode
{
get
{
return base.TextMode;
}
set
{
base.TextMode = value;
if ( value != TextBoxMode.SingleLine )
{
this.AutoIncrease = false;
}
else
{
this.AutoIncrease = true;
}
}
}
public new Unit BorderWidth
{
get
{
if ( base.BorderWidth == Unit.Empty )
{
base.BorderWidth = 1;
}
return base.BorderWidth;
}
set
{
if ( value != Unit.Empty )
{
base.BorderWidth = value;
}
}
}
/**//// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{
if ( this.AutoIncrease )
{
this.RegisterClientScript();
base.Attributes["onfocus"] = "ATB_SwitchToInputAgent(this)";
base.Attributes.CssStyle["position"] = "relative";
if ( base.BorderWidth == Unit.Empty )
{
base.BorderWidth = 1;
}
string spanWrapper = @"<span style='z-index: 1; position: relative; border: solid 0px black;'>{0}<input type='text' onblur='ATB_GetAgentValue(this)' onpropertychange='ATB_AutoIncreaseWidth(this)' style='border: solid 1px gray; position: absolute; display:none;' /></span>";
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htw = new HtmlTextWriter(sw);
base.Render(htw);
output.Write(string.Format(spanWrapper, sb.ToString(), ColorTranslator.ToHtml(this.AgentBorderColor)));
}
else
{
// base.Attributes["onfocus"] = "this.height='100%'";
base.Render(output);
}
}
private void RegisterClientScript()
{
const string COMMON_SCRIPT_KEY = "__CommonJavaScript__";
string strCommon = @"<script language='javascript'>
function GetAbsoluteOffsetLeft(element)
{
if ( element == null || arguments.length != 1 )
{
return;
}
var offsetLeft = element.offsetLeft;
while( element = element.offsetParent )
{
offsetLeft += element.offsetLeft;
}
return offsetLeft;
}
</script>";
if ( !this.Page.IsStartupScriptRegistered(COMMON_SCRIPT_KEY) )
{
this.Page.RegisterStartupScript(COMMON_SCRIPT_KEY, strCommon);
}
const string SCRIPT_KEY = "__AdjustableTextBoxKey__";
string strScript = @"
<script language='javascript'>
function ATB_SwitchToInputAgent(input)
{
if ( input.disabled ) return;
var spanWrapper = input.parentElement;
var agentInput = spanWrapper.lastChild;
var userOffsetTop, userOffsetLeft;
with(input.style)
{
var userMarginTop = parseInt(marginTop);
var userMarginLeft = parseInt(marginLeft);
var userBorderTop = parseInt(borderTopWidth);
var userBorderLeft = parseInt(borderLeftWidth);
userMarginTop = isNaN(userMarginTop) ? 0 : userMarginTop;
userMarginLeft = isNaN(userMarginLeft) ? 0 : userMarginLeft;
userBorderTop = isNaN(userBorderTop) ? 0 : userBorderTop;
userBorderLeft = isNaN(userBorderLeft) ? 0 : userBorderLeft;
userOffsetTop = userBorderTop + userMarginTop;
userOffsetLeft = userBorderLeft + userMarginLeft;
}
var retouch = 0;
agentInput.value = input.value; // must be mdified at first
agentInput.style.top = userOffsetTop;
agentInput.style.left = userOffsetLeft-1;
spanWrapper.style.zIndex = 10;
agentInput.style.display = 'inline';
agentInput.style.borderWdith = input.style.borderWdith;
agentInput.style.borderColor = input.style.borderColor;
agentInput.style.backgroundColor = input.style.backgroundColor;
agentInput.style.color = input.style.color;
agentInput.style.fontFamily = input.style.fontFamily;
agentInput.style.fontWegith = input.style.fontWeight;
agentInput.style.fontSize = input.style.fontSize;
agentInput.style.height = input.style.height;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
var styleWidth = parseInt(agentInput.style.width);
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
agentInput.style.width = docClientWidth - absOffsetWidth;
}
else
{
agentInput.style.width = input.clientWidth+2;
}
agentInput.style.fontStyle = input.style.fontStyle;
try { agentInput.style.font = input.style.font } catch(exp){};
agentInput.style.fontVariant = input.style.fontVariant;
agentInput.style.zoom = input.style.zoom;
agentInput.readOnly = input.readOnly;
//agentInput.focus(); must remove!!!
if ( !agentInput.readOnly )
{
agentInput.select();
}
}
function ATB_GetAgentValue(input)
{
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
input.style.width = userInput.clientWidth+2;
spanWrapper.style.zIndex = 1;
userInput.value = input.value;
input.style.display = 'none';
}
function ATB_AutoIncreaseWidth(input)
{
if ( input.style.display == 'none' ) return;
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
userInput.value = input.value;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
if ( input.scrollWidth < userInput.clientWidth )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = userInput.clientWidth+2;
}
return;
}
var styleWidth = parseInt(input.style.width);
if ( styleWidth != input.scrollWidth+2 )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = input.scrollWidth+2;
}
}
}
</script>";
if ( !this.Page.IsStartupScriptRegistered(SCRIPT_KEY) )
{
this.Page.RegisterStartupScript(SCRIPT_KEY, strScript);
}
}
}
}
#endregion
using System;
using System.IO;
using System.Drawing;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace WebExcel.UI.WebControls
{
/**//// <summary>
/// Summary description for AdjustableTextBox.
/// </summary>
[DefaultProperty("Text")]
[ToolboxData("<{0}:AdjustableTextBox runat=server></{0}:AdjustableTextBox>")]
public class AdjustableTextBox : TextBox
{
public Color AgentBorderColor
{
get
{
object obj = ViewState["AgentBorderColor"];
return obj == null ? Color.Gray : (Color)obj;
}
set
{
ViewState["AgentBorderColor"] = value;
}
}
public bool AutoIncrease
{
get
{
object obj = ViewState["AutoIncrease"];
return obj == null ? true : (bool)obj;
}
set
{
ViewState["AutoIncrease"] = value;
}
}
// the property is always TextBoxMode.SingleLine.
public override TextBoxMode TextMode
{
get
{
return base.TextMode;
}
set
{
base.TextMode = value;
if ( value != TextBoxMode.SingleLine )
{
this.AutoIncrease = false;
}
else
{
this.AutoIncrease = true;
}
}
}
public new Unit BorderWidth
{
get
{
if ( base.BorderWidth == Unit.Empty )
{
base.BorderWidth = 1;
}
return base.BorderWidth;
}
set
{
if ( value != Unit.Empty )
{
base.BorderWidth = value;
}
}
}
/**//// <summary>
/// Render this control to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void Render(HtmlTextWriter output)
{
if ( this.AutoIncrease )
{
this.RegisterClientScript();
base.Attributes["onfocus"] = "ATB_SwitchToInputAgent(this)";
base.Attributes.CssStyle["position"] = "relative";
if ( base.BorderWidth == Unit.Empty )
{
base.BorderWidth = 1;
}
string spanWrapper = @"<span style='z-index: 1; position: relative; border: solid 0px black;'>{0}<input type='text' onblur='ATB_GetAgentValue(this)' onpropertychange='ATB_AutoIncreaseWidth(this)' style='border: solid 1px gray; position: absolute; display:none;' /></span>";
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htw = new HtmlTextWriter(sw);
base.Render(htw);
output.Write(string.Format(spanWrapper, sb.ToString(), ColorTranslator.ToHtml(this.AgentBorderColor)));
}
else
{
// base.Attributes["onfocus"] = "this.height='100%'";
base.Render(output);
}
}
private void RegisterClientScript()
{
const string COMMON_SCRIPT_KEY = "__CommonJavaScript__";
string strCommon = @"<script language='javascript'>
function GetAbsoluteOffsetLeft(element)
{
if ( element == null || arguments.length != 1 )
{
return;
}
var offsetLeft = element.offsetLeft;
while( element = element.offsetParent )
{
offsetLeft += element.offsetLeft;
}
return offsetLeft;
}
</script>";
if ( !this.Page.IsStartupScriptRegistered(COMMON_SCRIPT_KEY) )
{
this.Page.RegisterStartupScript(COMMON_SCRIPT_KEY, strCommon);
}
const string SCRIPT_KEY = "__AdjustableTextBoxKey__";
string strScript = @"
<script language='javascript'>
function ATB_SwitchToInputAgent(input)
{
if ( input.disabled ) return;
var spanWrapper = input.parentElement;
var agentInput = spanWrapper.lastChild;
var userOffsetTop, userOffsetLeft;
with(input.style)
{
var userMarginTop = parseInt(marginTop);
var userMarginLeft = parseInt(marginLeft);
var userBorderTop = parseInt(borderTopWidth);
var userBorderLeft = parseInt(borderLeftWidth);
userMarginTop = isNaN(userMarginTop) ? 0 : userMarginTop;
userMarginLeft = isNaN(userMarginLeft) ? 0 : userMarginLeft;
userBorderTop = isNaN(userBorderTop) ? 0 : userBorderTop;
userBorderLeft = isNaN(userBorderLeft) ? 0 : userBorderLeft;
userOffsetTop = userBorderTop + userMarginTop;
userOffsetLeft = userBorderLeft + userMarginLeft;
}
var retouch = 0;
agentInput.value = input.value; // must be mdified at first
agentInput.style.top = userOffsetTop;
agentInput.style.left = userOffsetLeft-1;
spanWrapper.style.zIndex = 10;
agentInput.style.display = 'inline';
agentInput.style.borderWdith = input.style.borderWdith;
agentInput.style.borderColor = input.style.borderColor;
agentInput.style.backgroundColor = input.style.backgroundColor;
agentInput.style.color = input.style.color;
agentInput.style.fontFamily = input.style.fontFamily;
agentInput.style.fontWegith = input.style.fontWeight;
agentInput.style.fontSize = input.style.fontSize;
agentInput.style.height = input.style.height;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
var styleWidth = parseInt(agentInput.style.width);
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
agentInput.style.width = docClientWidth - absOffsetWidth;
}
else
{
agentInput.style.width = input.clientWidth+2;
}
agentInput.style.fontStyle = input.style.fontStyle;
try { agentInput.style.font = input.style.font } catch(exp){};
agentInput.style.fontVariant = input.style.fontVariant;
agentInput.style.zoom = input.style.zoom;
agentInput.readOnly = input.readOnly;
//agentInput.focus(); must remove!!!
if ( !agentInput.readOnly )
{
agentInput.select();
}
}
function ATB_GetAgentValue(input)
{
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
input.style.width = userInput.clientWidth+2;
spanWrapper.style.zIndex = 1;
userInput.value = input.value;
input.style.display = 'none';
}
function ATB_AutoIncreaseWidth(input)
{
if ( input.style.display == 'none' ) return;
var spanWrapper = input.parentElement;
var userInput = spanWrapper.firstChild;
userInput.value = input.value;
var absOffsetWidth = GetAbsoluteOffsetLeft(input);
var docClientWidth = window.document.body.clientWidth;
if ( input.scrollWidth < userInput.clientWidth )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = userInput.clientWidth+2;
}
return;
}
var styleWidth = parseInt(input.style.width);
if ( styleWidth != input.scrollWidth+2 )
{
if ( absOffsetWidth + styleWidth >= docClientWidth )
{
input.style.width = docClientWidth - absOffsetWidth;
}
else
{
input.style.width = input.scrollWidth+2;
}
}
}
</script>";
if ( !this.Page.IsStartupScriptRegistered(SCRIPT_KEY) )
{
this.Page.RegisterStartupScript(SCRIPT_KEY, strScript);
}
}
}
}
#endregion
posted on 2004-12-24 00:17 birdshome 阅读(12923) 评论(11) 编辑 收藏 举报