首页 / 知识

关于javascript:如何使用原型自动调整文本区域的大小?

2023-04-11 23:49:00

How to autosize a textarea using Prototype?

我目前正在为所工作的公司开发内部销售应用程序,并且我有一张表格,允许用户更改收货地址。

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

这是当前的屏幕截图。

ISO Address

有任何想法吗?

@克里斯

很好,但是我有理由要调整大小。我希望占用的区域是其中包含的信息的区域。从屏幕截图中可以看到,如果我有固定的textarea,它将占据相当大的垂直空间。

我可以减少字体,但是我需要地址大并且可读。现在,我可以减小文本区域的大小,但是对于地址行占用3或4(一行占用5)行的人来说,我遇到了问题。需要用户使用滚动条是主要的禁忌。

我想我应该更具体一些。我需要垂直调整大小,宽度也没关系。唯一发生的问题是,当窗口宽度太小时(如屏幕截图所示),ISO数字(大的" 1")被推到地址下方。

这并不是要有个花哨的东西。这是关于用户可以编辑的文本字段,它不会占用不必要的空间,但会显示其中的所有文本。

尽管如果有人想出另一种方法来解决问题,我也很乐意。

我对代码进行了一些修改,因为它的行为有些奇怪。我将其更改为在键入时激活,因为它不会考虑刚刚键入的字符。

1
2
3
4
5
6
7
8
9
10
11
12
resizeIt = function() {
  var str = $('iso_address').value;
  var cols = $('iso_address').cols;
  var linecount = 0;

  $A(str.split("\
"
)).each(function(l) {
    linecount += 1 + Math.floor(l.length / cols); // Take into account long lines
  })

  $('iso_address').rows = linecount;
};

当您在人们的墙上写字时,Facebook会这样做,但只能垂直调整大小。

由于自动换行,长行等原因,水平调整大小令我感到混乱,但是垂直调整大小似乎非常安全且不错。

我认识的所有使用Facebook的新手都没有提及或困惑过。我会将其用作传闻,说"继续前进,实施它"。

使用Prototype来执行此操作的一些JavaScript代码(因为这是我所熟悉的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!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 language="javascript">
            google.load('prototype', '1.6.0.2');
       
    </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("\
"
)).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
       
    </body>
</html>

PS:显然,此JavaScript代码非常幼稚且未经良好测试,您可能不想在其中装有小说的文本框中使用它,但您已掌握了总体思路。


其中一些答案的一种改进是让CSS做更多的工作。

基本路线似乎是:

  • 创建一个容器元素来容纳textarea和一个隐藏的div
  • 使用Javascript,使textarea的内容与div的内容保持同步
  • 让浏览器完成计算该div高度的工作
  • 由于浏览器可以处理隐藏的div或调整其大小,因此我们避免
    明确设置textarea的高度。
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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(/\
    /g, '<br/>')
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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;
    }
    1
        <textarea id="textArea"></textarea>


    这是用于自动化文本区域的另一种技术。

    • 使用像素高度而不是线条高度:如果使用比例字体,则更精确地处理换行。
    • 接受ID或元素作为输入
    • 接受可选的最大高度参数-如果您不想让文本区域超过特定大小(将其保留在屏幕上,避免破坏布局等),则非常有用。
    • 在Firefox 3和InternetExplorer6上测试

    码:
    (普通香草JavaScript)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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,请将这两个示例粘贴到控制台中并在此页面上进行测试)

    1
    2
    3
    4
    $("#post-text").keyup(function()
    {
       FitToContent(this, document.documentElement.clientHeight)
    });

    可能是最短的解决方案:

    1
    2
    3
    4
    5
    6
    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";,这取决于您对文本区域的样式设置(行高,填充和类似内容)。


    这是调整文本区域大小的原型版本,该文本区域不依赖于文本区域中的列数。这是一项出色的技术,因为它允许您通过CSS控制文本区域以及可变宽度的textarea。此外,此版本显示剩余字符数。不需要时,它是一项非常有用的功能,如果不需要,可以轻松删除。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    //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(/\
    /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})。如果要为页面上的所有文本区域创建它,请执行以下操作:

    1
    2
    3
    4
    5
    Event.observe(window, 'load', function() {
      $$('textarea').each(function(textarea) {
        new Widget.Textarea(textarea);
      });  
    });

    这是JQuery的解决方案:

    1
    2
    3
    4
    $(document).ready(function() {
        var $abc = $("#abc");
        $abc.css("height", $abc.attr("scrollHeight"));
    })

    abcteaxtarea


    检查以下链接:
    http://james.padolsey.com/javascript/jquery-plugin-autoresize/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $(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
        });
    });

    我做了一些很容易的事情。首先,我将TextArea放入DIV中。其次,我已调用此脚本的ready函数。

    1
    2
    3
    4
    5
    6
    7
    8
      <textarea ID="txt" Rows="1" TextMode="MultiLine" />


    $(document).ready(function () {
      var heightTextArea = $('#txt').height();
      var divTable = document.getElementById('divTable');
      $('#txt').attr('rows', parseInt(parseInt(divTable .style.height) / parseInt(altoFila)));
    });

    简单。它是div呈现后的最大高度,除以一行的一个TextArea的高度。


    只是回顾一下,我已经做了一些整理(尽管对Prototype / JavaScript满口的人可能会建议改进?)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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("\
    "
    )).each(function(l) {
          // We take long lines into account via the cols divide.
          linecount += 1 + Math.floor(l.length / cols);
        })

        this.element.rows = linecount;
      }
    }

    只需调用:

    1
    new TextAreaResize('textarea_id_name_here');


    下面是我不使用jQuery的解决方案(因为有时它们不必是同一个东西)。尽管仅在InternetExplorer7中对其进行了测试,但是社区可以指出所有错误的原因:

    1
    textarea.onkeyup = function () { this.style.height = this.scrollHeight + 'px'; }

    到目前为止,我真的很喜欢它的工作方式,并且我不在乎其他浏览器,因此我可能会将其应用于我的所有文本区域:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 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
    }

    就像@memical的答案一样。

    但是我发现了一些改进。您可以使用jQuery height()函数。但是要注意顶部和底部的像素。否则您的textarea将会增长得太快。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $(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);
      });
    });

    我自己需要此功能,但是我需要的这些功能都不起作用。

    因此,我使用了Orion的代码并进行了更改。

    我添加了最小高度,以便在破坏时不会变得太小。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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("\
    "
    );
        $(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;
    };

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

    如果您在文本区域中使用限制,它将阻止用户输入更多字符。它检查是否还有字符。如果用户将文本复制到文本区域中,则文本将被最大程度地剪切掉。长度:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    /**
     * Prototype Widget: Textarea
     * Automatically resizes a textarea and displays the number of remaining chars
     *
     * From: http://stackoverflow.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(/\
    /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'));
      }
    });

    这是我刚刚在jQuery中编写的一个函数,可以将其移植到Prototype,但是它们不支持jQuery的"活动性",因此Ajax请求添加的元素将不会响应。

    此版本不仅可以扩展,而且在按Delete或Backspace时也可以收缩。

    此版本依赖jQuery 1.4.2。

    请享用 ;)

    http://pastebin.com/SUKeBtnx

    用法:

    1
    $("#sometextarea").textareacontrol();

    或(例如,任何jQuery选择器)

    1
    $("textarea").textareacontrol();

    已在InternetExplorer7 / InternetExplorer8,Firefox 3.5和Chrome上进行了测试。一切正常。


    对于那些正在为IE编码并遇到此问题的人。 IE有一个小技巧,使其成为100%CSS。

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

    您甚至可以为IE提供的rows =" n"提供一个值,但其他浏览器将使用该值。我真的很讨厌实现IE hacks的编码,但是这一步非常有帮助。可能仅在Quirks模式下有效。


    @memical有一个很棒的解决方案,可使用jQuery在pageload上设置文本区域的高度,但是对于我的应用程序,我希望能够随着用户添加更多内容而增加文本区域的高度。我使用以下内容构建了memical的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $(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插件。)


    使用ASP.NET,只需执行以下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            Automatic Resize TextBox
            <script type="text/javascript">
                function setHeight(txtarea) {
                    txtarea.style.height = txtdesc.scrollHeight +"px";
                }
           
        </head>

        <body>
            <form id="form1" runat="server">
               
            </form>
        </body>
    </html>

    Internet Explorer,Safari,Chrome和Opera用户需要记住在CSS中明确设置line-height值。我做一个样式表,为所有文本框设置初始属性,如下所示。

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


    文本区域原型调整

    最新内容

    相关内容

    热门文章

    推荐文章

    标签云

    猜你喜欢