如何使用Prototype自动调整文本区域的大小?

132

我目前正在为所在公司开发一个内部销售应用程序,并且我有一个表单,允许用户更改交付地址。

我认为如果我用于主要地址详细信息的文本区域只占用文本区域中的文本区域,并且在更改文本时自动调整大小,那么它看起来会好得多。

这是当前的屏幕截图。

ISO Address

有什么想法吗?


@Chris

一个很好的观点,但我想让它调整大小有一些原因。我希望它占用的区域是其中包含的信息区域。正如您在屏幕截图中看到的那样,如果我有一个固定的文本区域,它将占用相当大的垂直空间。

我可以缩小字体,但我需要地址大而易读。现在我可以缩小文本区域的大小,但我有人们使用需要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;
};

你能创建一个演示网站,让我们看到它的工作吗? - Einar Ólafsson
3
这个插件看起来很不错。http://www.jacklmoore.com/autosize - Gaurav Shah
有 JQuery 版本吗?如何在 JQuery 中访问 TextArea 的 cols 和 rows? - Zach
几乎相同,但明确要求在删除文本时应变得更小:https://dev59.com/l3RB5IYBdhLWcg3w9b19 - Ciro Santilli OurBigBook.com
18个回答

2

像@memical的回答一样。

不过我发现了一些改进。您可以使用jQuery的height()函数。但要注意padding-top和padding-bottom像素。否则,您的文本区域将增长得太快。

$(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);
  });
});

2

我的解决方案不使用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
}

1

这是对Jeremy于6月4日发布的Prototype小部件的扩展:

如果您在文本区域中使用限制,它将阻止用户输入更多字符。 它会检查是否还有剩余字符。 如果用户将文本复制到文本区域中,则文本将被截断为最大长度:

/**
 * Prototype Widget: Textarea
 * Automatically resizes a textarea and displays the number of remaining chars
 * 
 * From: https://dev59.com/C3VD5IYBdhLWcg3wWaRh
 * 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'));
  }
});

1

Internet Explorer、Safari、Chrome和Opera用户需要记得在CSS中明确设置行高值。我会做一个样式表,将所有文本框的初始属性设置如下。

<style>
    TEXTAREA { line-height: 14px; font-size: 12px; font-family: arial }
</style>

1

对于那些编写IE相关代码并遇到这个问题的人来说,IE有一个小技巧,使其100%符合CSS。

<TEXTAREA style="overflow: visible;" cols="100" ....></TEXTAREA>

你甚至可以为rows="n"提供一个值,IE将忽略它,但其他浏览器将使用它。我真的很讨厌实现IE hack的编码,但这个非常有用。可能只在Quirks模式下起作用。


1

@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插件。)


1
这是我刚写的一个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上进行了测试。所有功能都正常。


1
使用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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接