如何使用原型自动调整文本区域的大小?
Posted
技术标签:
【中文标题】如何使用原型自动调整文本区域的大小?【英文标题】:How to autosize a textarea using Prototype? 【发布时间】:2010-09-05 16:02:21 【问题描述】:我目前正在为我工作的公司开发一个内部销售应用程序,并且我有一个允许用户更改收货地址的表单。
现在我认为它看起来会更好,如果我用于主要地址详细信息的文本区域只占用其中的文本区域,并在文本发生更改时自动调整大小。
这是目前的截图。
有什么想法吗?
@克里斯
说得好,但我希望它调整大小是有原因的。我希望它占用的区域是其中包含的信息的区域。正如您在屏幕截图中看到的,如果我有一个固定的文本区域,它会占用相当多的垂直空间。
我可以缩小字体,但我需要地址大且可读。现在我可以减小文本区域的大小,但是对于地址行需要 3 或 4 行(一个需要 5 行)的人,我会遇到问题。需要让用户使用滚动条是一个主要的禁忌。
我想我应该更具体一点。我在垂直调整大小之后,宽度并不重要。唯一的问题是,当窗口宽度太小时(如屏幕截图所示)时,ISO 编号(大的“1”)会被推送到地址下方。
这不是噱头;它是关于拥有一个用户可以编辑的文本字段,它不会占用不必要的空间,但会显示其中的所有文本。
如果有人想出另一种方法来解决这个问题,我也愿意接受。
我稍微修改了代码,因为它的行为有点奇怪。我将其更改为在按键时激活,因为它不会考虑刚刚输入的字符。
resizeIt = function()
var str = $('iso_address').value;
var cols = $('iso_address').cols;
var linecount = 0;
$A(str.split("\n")).each(function(l)
linecount += 1 + Math.floor(l.length / cols); // Take into account long lines
)
$('iso_address').rows = linecount;
;
【问题讨论】:
你能创建一个演示网站,让我们可以在工作中看到这个吗? 这个插件看起来不错jacklmoore.com/autosize 有 JQuery 版本吗?如何在 JQuery 中访问 TextArea 的列和行? 几乎相同,但明确要求在删除文本时应变小:***.com/questions/454202/… 【参考方案1】:当你在人们的墙上写字时,Facebook 会这样做,但只会垂直调整大小。
由于自动换行、长行等原因,水平调整大小让我觉得一团糟,但垂直调整大小似乎相当安全和美观。
我认识的使用 Facebook 的新手都没有提到过任何关于它的事情或感到困惑。我会用这个作为轶事证据来说'继续执行它'。
使用 Prototype 的一些 javascript 代码(因为这是我熟悉的):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://www.google.com/jsapi"></script>
<script language="javascript">
google.load('prototype', '1.6.0.2');
</script>
</head>
<body>
<textarea id="text-area" rows="1" cols="50"></textarea>
<script type="text/javascript" language="javascript">
resizeIt = function()
var str = $('text-area').value;
var cols = $('text-area').cols;
var linecount = 0;
$A(str.split("\n")).each( function(l)
linecount += Math.ceil( l.length / cols ); // Take into account long lines
)
$('text-area').rows = linecount + 1;
;
// You could attach to keyUp, etc. if keydown doesn't work
Event.observe('text-area', 'keydown', resizeIt );
resizeIt(); //Initial on load
</script>
</body>
</html>
PS:显然,这段 JavaScript 代码非常幼稚,没有经过很好的测试,你可能不想在包含小说的文本框上使用它,但你明白了。
【讨论】:
这假定浏览器在任何字符处中断,这是不正确的。试试<textarea cols='5'>0 12345 12345 0</textarea>
。 (我写了一个几乎相同的实现,直到使用它一个月后才发现它。)它也因空行而失败。
这个有 JQuery 版本吗?
$A(str.split("\n")) 中的反斜杠需要另一个。 (由于某种原因,我对上述答案的编辑未能幸存。)【参考方案2】:
对其中一些答案的改进是让 CSS 完成更多工作。
基本路线好像是:
-
创建一个容器元素来保存
textarea
和一个隐藏的div
使用 Javascript,保持textarea
的内容与div
的内容同步
让浏览器来计算那个div的高度
因为浏览器处理隐藏div
的渲染/调整大小,我们避免
明确设置textarea
的高度。
document.addEventListener('DOMContentLoaded', () =>
textArea.addEventListener('change', autosize, false)
textArea.addEventListener('keydown', autosize, false)
textArea.addEventListener('keyup', autosize, false)
autosize()
, false)
function autosize()
// Copy textarea contents to div browser will calculate correct height
// of copy, which will make overall container taller, which will make
// textarea taller.
textCopy.innerHTML = textArea.value.replace(/\n/g, '<br/>')
html, body, textarea
font-family: sans-serif;
font-size: 14px;
.textarea-container
position: relative;
.textarea-container > div, .textarea-container > textarea
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
box-sizing: border-box;
padding: 2px;
width: 100%;
.textarea-container > textarea
overflow: hidden;
position: absolute;
height: 100%;
.textarea-container > div
padding-bottom: 1.5em; /* A bit more than one additional line of text. */
visibility: hidden;
<div class="textarea-container">
<textarea id="textArea"></textarea>
<div id="textCopy"></div>
</div>
【讨论】:
这是一个很棒的解决方案!唯一需要注意的是,不支持 box-sizing (IE 我冒昧地将这个解决方案实现为独立的、易于使用的 jQuery 插件,不需要任何标记或样式。 xion.io/jQuery.xarea 万一有人可以使用它:) 将 textCopy 设置为 hidden 仍然允许隐藏的 div 占用标记中的空间,因此随着 textCopy 内容变大,您最终会在页面的整个长度上得到一个滚动条...跨度> 对此的另一个不错的调整;var text = $("#textArea").val().replace(/\n/g, '<br/>') + '&nbsp;';
确保从 textarea 末尾的空新行转到非空行时不会出现生涩的行为,因为隐藏的 div 确保包裹到 nbsp。
@unwitting 伟大的呼吁添加一个' '当您将第一个字母添加到新行时,摆脱突然增加的大小 - 对我来说,没有这个就坏了 - 这应该添加到答案中!【参考方案3】:
这是另一种自动调整文本区域大小的技术。
使用像素高度而不是行高:如果使用比例字体,则更准确地处理换行。 接受 ID 或元素作为输入 接受可选的最大高度参数 - 如果您不想让文本区域超过一定大小(将其全部保留在屏幕上,避免破坏布局等),这很有用 在 Firefox 3 和 Internet Explorer 6 上测试代码: (普通的 JavaScript)
function FitToContent(id, maxHeight)
var text = id && id.style ? id : document.getElementById(id);
if (!text)
return;
/* Accounts for rows being deleted, pixel value may need adjusting */
if (text.clientHeight == text.scrollHeight)
text.style.height = "30px";
var adjustedHeight = text.clientHeight;
if (!maxHeight || maxHeight > adjustedHeight)
adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
if (maxHeight)
adjustedHeight = Math.min(maxHeight, adjustedHeight);
if (adjustedHeight > text.clientHeight)
text.style.height = adjustedHeight + "px";
演示: (使用 jQuery,我现在正在输入的文本区域上的目标 - 如果您安装了 Firebug,请将两个示例粘贴到控制台并在此页面上进行测试)
$("#post-text").keyup(function()
FitToContent(this, document.documentElement.clientHeight)
);
【讨论】:
@SMB - 这可能不会太难实现,只需添加另一个条件 @Jason:当框内的文字没有填满时,clientHeight
和scrollHeight
是相等的,所以如果你想让你的textarea也缩小,你不能使用这个方法随着成长。
为了简单地缩小到,你只需要在第6行之前添加这个代码:if (text.clientHeight == text.scrollHeight) text.style.height = "20px";
【参考方案4】:
可能是最短的解决方案:
jQuery(document).ready(function()
jQuery("#textArea").on("keydown keyup", function()
this.style.height = "1px";
this.style.height = (this.scrollHeight) + "px";
);
);
这样你就不需要任何隐藏的 div 或类似的东西了。
注意:您可能需要使用this.style.height = (this.scrollHeight) + "px";
,这取决于您对文本区域的样式(行高、填充和那种东西)。
【讨论】:
不介意滚动条闪烁的最佳解决方案。 只捕获 keyup 事件就足够了。你不这么认为吗? 将 textarea 溢出属性设置为“隐藏”以避免滚动条闪烁。keyup
可能就足够了,但我不确定。我很高兴我想通了,我不再尝试其他任何事情。
我还在努力了解你为什么要添加 this.style.height = "1px";或 this.style.height = "auto";前。我知道,如果我们不添加这一行,当我们删除内容时,textarea 不会调整大小。有人可以解释一下吗?【参考方案5】:
这是一个调整文本区域大小的原型版本,它不依赖于文本区域中的列数。这是一种优越的技术,因为它允许您通过 CSS 控制文本区域以及具有可变宽度的文本区域。此外,此版本显示剩余的字符数。虽然没有要求,但它是一个非常有用的功能,如果不需要,很容易删除。
//inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
if (window.Widget == undefined) window.Widget = ;
Widget.Textarea = Class.create(
initialize: function(textarea, options)
this.textarea = $(textarea);
this.options = $H(
'min_height' : 30,
'max_length' : 400
).update(options);
this.textarea.observe('keyup', this.refresh.bind(this));
this._shadow = new Element('div').setStyle(
lineHeight : this.textarea.getStyle('lineHeight'),
fontSize : this.textarea.getStyle('fontSize'),
fontFamily : this.textarea.getStyle('fontFamily'),
position : 'absolute',
top: '-10000px',
left: '-10000px',
width: this.textarea.getWidth() + 'px'
);
this.textarea.insert( after: this._shadow );
this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
this.textarea.insert(after: this._remainingCharacters);
this.refresh();
,
refresh: function()
this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
this.textarea.setStyle(
height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
);
var remaining = this.options.get('max_length') - $F(this.textarea).length;
this._remainingCharacters.update(Math.abs(remaining) + ' characters ' + (remaining > 0 ? 'remaining' : 'over the limit'));
);
通过调用new Widget.Textarea('element_id')
创建小部件。默认选项可以通过将它们作为对象传递来覆盖,例如new Widget.Textarea('element_id', max_length: 600, min_height: 50)
。如果要为页面上的所有文本区域创建它,请执行以下操作:
Event.observe(window, 'load', function()
$$('textarea').each(function(textarea)
new Widget.Textarea(textarea);
);
);
【讨论】:
【参考方案6】:这是JQuery
的解决方案:
$(document).ready(function()
var $abc = $("#abc");
$abc.css("height", $abc.attr("scrollHeight"));
)
abc
是 teaxtarea
。
【讨论】:
【参考方案7】:查看以下链接: http://james.padolsey.com/javascript/jquery-plugin-autoresize/
$(document).ready(function ()
$('.ExpandableTextCSS').autoResize(
// On resize:
onResize: function ()
$(this).css( opacity: 0.8 );
,
// After resize:
animateCallback: function ()
$(this).css( opacity: 1 );
,
// Quite slow animation:
animateDuration: 300,
// More extra space:
extraSpace:20,
//Textarea height limit
limit:10
);
);
【讨论】:
死链接。代码在这里james.padolsey.com/demos/plugins/jQuery/autoresize.jquery.js/…【参考方案8】:只是重新审视一下,我已经把它整理得更整齐了(尽管有人对Prototype/JavaScript 满瓶的人可以提出改进建议?)。
var TextAreaResize = Class.create();
TextAreaResize.prototype =
initialize: function(element, options)
element = $(element);
this.element = element;
this.options = Object.extend(
,
options || );
Event.observe(this.element, 'keyup',
this.onKeyUp.bindAsEventListener(this));
this.onKeyUp();
,
onKeyUp: function()
// We need this variable because "this" changes in the scope of the
// function below.
var cols = this.element.cols;
var linecount = 0;
$A(this.element.value.split("\n")).each(function(l)
// We take long lines into account via the cols divide.
linecount += 1 + Math.floor(l.length / cols);
)
this.element.rows = linecount;
只需调用:
new TextAreaResize('textarea_id_name_here');
【讨论】:
【参考方案9】:我做了一些很简单的事情。首先,我将 TextArea 放入 DIV。其次,我在这个脚本中调用了ready
函数。
<div id="divTable">
<textarea ID="txt" Rows="1" TextMode="MultiLine" />
</div>
$(document).ready(function ()
var heightTextArea = $('#txt').height();
var divTable = document.getElementById('divTable');
$('#txt').attr('rows', parseInt(parseInt(divTable .style.height) / parseInt(altoFila)));
);
简单。 div渲染后的最大高度,除以一行TextArea的高度。
【讨论】:
【参考方案10】:我自己需要这个功能,但这里没有一个能像我需要的那样工作。
所以我使用了 Orion 的代码并进行了更改。
我添加了一个最小高度,这样在破坏时它不会变得太小。
function resizeIt( id, maxHeight, minHeight )
var text = id && id.style ? id : document.getElementById(id);
var str = text.value;
var cols = text.cols;
var linecount = 0;
var arStr = str.split( "\n" );
$(arStr).each(function(s)
linecount = linecount + 1 + Math.floor(arStr[s].length / cols); // take into account long lines
);
linecount++;
linecount = Math.max(minHeight, linecount);
linecount = Math.min(maxHeight, linecount);
text.rows = linecount;
;
【讨论】:
【参考方案11】:喜欢@memical 的回答。
但是我发现了一些改进。您可以使用 jQuery height()
函数。但请注意 padding-top 和 padding-bottom 像素。否则你的 textarea 会增长得太快。
$(document).ready(function()
$textarea = $("#my-textarea");
// There is some diff between scrollheight and height:
// padding-top and padding-bottom
var diff = $textarea.prop("scrollHeight") - $textarea.height();
$textarea.live("keyup", function()
var height = $textarea.prop("scrollHeight") - diff;
$textarea.height(height);
);
);
【讨论】:
【参考方案12】:我不使用 jQuery 的解决方案(因为有时它们不必是相同的东西)如下。虽然只在Internet Explorer 7进行了测试,所以社区可以指出所有错误的原因:
textarea.onkeyup = function () this.style.height = this.scrollHeight + 'px';
到目前为止,我真的很喜欢它的工作方式,而且我不关心其他浏览器,所以我可能会将它应用到我所有的文本区域:
// Make all textareas auto-resize vertically
var textareas = document.getElementsByTagName('textarea');
for (i = 0; i<textareas.length; i++)
// Retain textarea's starting height as its minimum height
textareas[i].minHeight = textareas[i].offsetHeight;
textareas[i].onkeyup = function ()
this.style.height = Math.max(this.scrollHeight, this.minHeight) + 'px';
textareas[i].onkeyup(); // Trigger once to set initial height
【讨论】:
【参考方案13】:这是 Jeremy 在 6 月 4 日发布的 Prototype 小部件的扩展:
如果您在 textareas 中使用限制,它会阻止用户输入更多字符。它检查是否还有字符。如果用户将文本复制到 textarea 中,则文本在最大处被截断。长度:
/**
* Prototype Widget: Textarea
* Automatically resizes a textarea and displays the number of remaining chars
*
* From: http://***.com/questions/7477/autosizing-textarea
* Inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
*/
if (window.Widget == undefined) window.Widget = ;
Widget.Textarea = Class.create(
initialize: function(textarea, options)
this.textarea = $(textarea);
this.options = $H(
'min_height' : 30,
'max_length' : 400
).update(options);
this.textarea.observe('keyup', this.refresh.bind(this));
this._shadow = new Element('div').setStyle(
lineHeight : this.textarea.getStyle('lineHeight'),
fontSize : this.textarea.getStyle('fontSize'),
fontFamily : this.textarea.getStyle('fontFamily'),
position : 'absolute',
top: '-10000px',
left: '-10000px',
width: this.textarea.getWidth() + 'px'
);
this.textarea.insert( after: this._shadow );
this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
this.textarea.insert(after: this._remainingCharacters);
this.refresh();
,
refresh: function()
this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
this.textarea.setStyle(
height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
);
// Keep the text/character count inside the limits:
if($F(this.textarea).length > this.options.get('max_length'))
text = $F(this.textarea).substring(0, this.options.get('max_length'));
this.textarea.value = text;
return false;
var remaining = this.options.get('max_length') - $F(this.textarea).length;
this._remainingCharacters.update(Math.abs(remaining) + ' characters remaining'));
);
【讨论】:
【参考方案14】:@memical 有一个很棒的解决方案,可以使用 jQuery 在页面加载时设置 textarea 的高度,但是对于我的应用程序,我希望能够在用户添加更多内容时增加 textarea 的高度。我使用以下方法构建了 memical 的解决方案:
$(document).ready(function()
var $textarea = $("p.body textarea");
$textarea.css("height", ($textarea.attr("scrollHeight") + 20));
$textarea.keyup(function()
var current_height = $textarea.css("height").replace("px", "")*1;
if (current_height + 5 <= $textarea.attr("scrollHeight"))
$textarea.css("height", ($textarea.attr("scrollHeight") + 20));
);
);
它不是很流畅,但也不是面向客户端的应用程序,所以流畅度并不重要。 (如果这是面向客户端的,我可能会使用自动调整大小的 jQuery 插件。)
【讨论】:
【参考方案15】:对于那些正在为 IE 编码并遇到此问题的人。 IE 有个小技巧可以让它 100% 使用 CSS。
<TEXTAREA style="overflow: visible;" cols="100" ....></TEXTAREA>
您甚至可以为 rows="n" 提供一个值,IE 会忽略该值,但其他浏览器会使用该值。我真的很讨厌实现 IE hack 的编码,但是这个非常有帮助。它可能只适用于 Quirks 模式。
【讨论】:
【参考方案16】:Internet Explorer、Safari、Chrome 和Opera 用户需要记住在 CSS 中明确设置行高值。我做了一个样式表,为所有文本框设置初始属性,如下所示。
<style>
TEXTAREA line-height: 14px; font-size: 12px; font-family: arial
</style>
【讨论】:
【参考方案17】:这是我刚刚在 jQuery 中编写的一个函数 - 你可以将它移植到 Prototype,但它们不支持 jQuery 的“活跃性”,因此 Ajax 请求添加的元素将不会响应。
此版本不仅会扩展,而且还会在按下删除或退格键时收缩。
此版本依赖于 jQuery 1.4.2。
享受;)
http://pastebin.com/SUKeBtnx
用法:
$("#sometextarea").textareacontrol();
或(例如任何 jQuery 选择器)
$("textarea").textareacontrol();
它在Internet Explorer 7/Internet Explorer 8、Firefox 3.5 和 Chrome 上进行了测试。一切正常。
【讨论】:
【参考方案18】:使用 ASP.NET,只需这样做:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Automatic Resize TextBox</title>
<script type="text/javascript">
function setHeight(txtarea)
txtarea.style.height = txtdesc.scrollHeight + "px";
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="txtarea" runat= "server" TextMode="MultiLine" onkeyup="setHeight(this);" onkeydown="setHeight(this);" />
</form>
</body>
</html>
【讨论】:
以上是关于如何使用原型自动调整文本区域的大小?的主要内容,如果未能解决你的问题,请参考以下文章