Как автоматически изменить размер текстовой области с помощью Prototype?

В настоящее время я работаю над приложением внутренних продаж для компании, в которой я работаю, и у меня есть форма, которая позволяет пользователю изменить адрес доставки.

Теперь я думаю, что это выглядело бы намного лучше, если бы текстовое поле, которое я использую для основных деталей адреса, просто заняло бы область текста в нем и автоматически изменило бы размер, если текст был изменен.

Вот скриншот этого в настоящее время.

ISO-адрес

Есть идеи?


@Крис

Хороший вопрос, но есть причины, по которым я хочу изменить его размер. Я хочу, чтобы область, которую он занимает, была областью информации, содержащейся в нем. Как вы можете видеть на скриншоте, если у меня фиксированная текстовая область, она занимает довольно много места в вертикальном пространстве.

Я могу уменьшить шрифт, но мне нужно, чтобы адрес был крупным и читабельным. Теперь я могу уменьшить размер текстовой области, но у меня проблемы с людьми, у которых адресная строка занимает 3 или 4 (одна занимает 5) строк. Потребность в том, чтобы пользователь использовал полосу прокрутки, является основной нет-нет.

Я думаю, я должен быть более конкретным. Я после вертикального изменения размера, и ширина не имеет большого значения. Единственная проблема, которая возникает при этом, заключается в том, что число ISO (большое «1») помещается под адресом, когда ширина окна слишком мала (как вы можете видеть на скриншоте).

Дело не в том, чтобы иметь уловку; Речь идет о текстовом поле, которое пользователь может редактировать, которое не будет занимать ненужного места, но покажет весь текст в нем.

Хотя, если кто-то придумает другой способ решения проблемы, я тоже открыт для этого.


Я немного изменил код, потому что он немного странный. Я изменил его, чтобы активировать при keyup, потому что он не будет учитывать только что набранный символ.

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;
};
11.08.2008 01:43:13
Можете ли вы создать демонстрационный сайт, где мы можем увидеть это на работе?
Einar Ólafsson 14.08.2012 13:26:29
этот плагин кажется хорошим jacklmoore.com/autosize
Gaurav Shah 27.11.2012 10:26:05
Есть ли версия JQuery? Как получить доступ к столбцам и строкам TextArea в JQuery?
Zach 18.12.2012 08:47:59
Почти то же самое, но с явным требованием, которое должно
Ciro Santilli 冠状病毒审查六四事件法轮功 19.09.2014 15:50:45
18 ОТВЕТОВ
РЕШЕНИЕ

Facebook делает это, когда вы пишете на стенах людей, но изменяете размеры только по вертикали.

Горизонтальное изменение размера кажется мне беспорядком из-за переноса слов, длинных строк и т. Д., Но вертикальное изменение размера кажется довольно безопасным и приятным.

Никто из новичков в использовании Facebook, которых я знаю, никогда не упоминал об этом и не был сбит с толку. Я бы использовал это в качестве неподтвержденного доказательства, чтобы сказать «давай, реализуй».

Некоторый код JavaScript для этого, используя Prototype (потому что это то, с чем я знаком):

<!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 очень наивен и не очень хорошо протестирован, и вы, вероятно, не хотите использовать его в текстовых полях с новеллами в них, но вы поймете общую идею.

74
13.02.2016 00:56:16
Это предполагает, что браузер ломается на любом символе, что неверно. Попробуй это <textarea cols='5'>0 12345 12345 0</textarea>. (Я написал почти идентичную реализацию и не уловил ее до тех пор, пока через месяц не использовал ее.) Она также не работает для пустых строк.
st-boost 21.09.2012 11:03:45
Есть ли для этого версия JQuery?
emeraldhieu 28.09.2015 07:56:34
Обратная косая черта в $ A (str.split ("\ n")) нуждается в другом. (Моя редакция приведенного выше ответа по какой-то причине не сохранилась.)
gherson 21.04.2019 03:33:08

Вот еще один метод автоматического определения размера текстовой области.

  • Использует высоту пикселя вместо высоты строки: более точная обработка переноса строки, если используется пропорциональный шрифт.
  • Принимает 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)
});
39
13.02.2016 00:31:05
@ SMB - это, вероятно, не будет слишком сложно реализовать, просто добавьте еще одно условие
Jason 9.01.2010 07:57:58
@Jason: когда текст в поле не заполняет его, clientHeightа scrollHeightравен, поэтому вы не можете использовать этот метод, если хотите, чтобы текстовая область уменьшалась и росла.
Brant Bobby 17.12.2010 22:35:03
Чтобы просто уменьшить его, вам просто нужно добавить этот код перед строкой 6:if (text.clientHeight == text.scrollHeight) text.style.height = "20px";
Gapipro 20.10.2011 07:18:36

Просто вернувшись к этому, я сделал его немного более аккуратным (хотя кто-то, кто полон бутылок на 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');
3
13.02.2016 00:33:51

Я нуждался в этой функции для себя, но ни один из них не работал так, как я нуждался в них.

Поэтому я использовал код Ориона и изменил его.

Я добавил минимальную высоту, чтобы при разрушении она не становилась слишком маленькой.

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;
};
2
13.02.2016 00:35:03

Вот прототипная версия изменения размера текстовой области, которая не зависит от количества столбцов в текстовой области. Это превосходный метод, потому что он позволяет вам контролировать текстовую область с помощью 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);
  });   
});
8
7.02.2016 18:08:34

Вот расширение виджета Prototype, который Джереми разместил 4 июня:

Он запрещает пользователю вводить больше символов, если вы используете ограничения в текстовых областях. Он проверяет, остались ли символы. Если пользователь копирует текст в текстовое поле, текст обрезается на макс. длина:

/**
 * 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(/\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
30.11.2009 14:39:24

Одно из уточнений некоторых из этих ответов - позволить CSS делать больше работы.

Основной маршрут выглядит так:

  1. Создайте элемент контейнера для хранения textareaи скрытогоdiv
  2. Используя Javascript, textareaсинхронизируйте содержимое divс
  3. Пусть браузер выполняет работу по вычислению высоты этого div
  4. Поскольку браузер обрабатывает рендеринг / определение размера скрытого 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>

64
22.08.2019 21:04:38
Это отличное решение! Единственное предостережение заключается в том, что браузеры, которые не поддерживают размеры блоков (IE <7), не будут правильно рассчитывать ширину, и, следовательно, вы потеряете некоторую точность, но если вы в конце оставляете стоимость строки, с тобой должно быть все в порядке. Определенно люблю это для простоты.
Antonio Salazar Cardozo 25.01.2011 22:12:05
Я взял на себя смелость реализовать это решение как самостоятельный, простой в использовании плагин jQuery, без разметки или стилизации. xion.io/jQuery.xarea на случай, если кто-то может его использовать :)
Xion 2.07.2012 20:28:18
установка textCopy в значение hidden по-прежнему позволяет скрытому элементу div занимать пространство в разметке, так что по мере увеличения содержимого textCopy вы в конечном итоге получаете полосу прокрутки по всей длине вашей страницы ...
topwik 22.01.2013 16:56:51
Еще один приятный твик к этому; var text = $("#textArea").val().replace(/\n/g, '<br/>') + '&nbsp;';гарантирует, что вы не получите прерывистого поведения при переходе от пустой новой строки в конце текстовой области к непустой, так как скрытый div гарантирует перенос в nbsp.
unwitting 19.02.2015 21:36:07
@ неуместно призывать к добавлению '& nbsp;' чтобы избавиться от этого внезапного увеличения размера, когда вы добавляете первую букву в новую строку - для меня это разрывается без этого - это должно быть добавлено к ответу!
davnicwil 11.07.2015 03:07:13

Пользователям Internet Explorer, Safari, Chrome и Opera необходимо помнить, чтобы точно установить значение высоты строки в CSS. Я делаю таблицу стилей, которая устанавливает начальные свойства для всех текстовых полей следующим образом.

<style>
    TEXTAREA { line-height: 14px; font-size: 12px; font-family: arial }
</style>
1
13.02.2016 00:37:44

Вот функция, которую я только что написал в 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
13.02.2016 00:40:11

Проверьте ссылку ниже: 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
    });
});
5
7.02.2016 18:09:04
Мертвая ссылка. Код здесь james.padolsey.com/demos/plugins/jQuery/autoresize.jquery.js/…
Matthew Hui 23.09.2012 06:50:56

Вот решение с JQuery:

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

abcявляется teaxtarea.

7
23.02.2017 10:29:31

У @memical было отличное решение для установки высоты текстовой области при загрузке страниц с помощью jQuery, но для моего приложения я хотел иметь возможность увеличить высоту текстовой области, поскольку пользователь добавил больше контента. Я построил решение мемула со следующим:

$(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
23.05.2017 12:34:18

Как и ответ @memical.

Однако я нашел некоторые улучшения. Вы можете использовать height()функцию jQuery . Но следует помнить о пикселях 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
13.02.2016 00:41:40

Я сделал что-то довольно легко. Сначала я помещаю 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 одной строки.

3
13.02.2016 00:43:33

Используя 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>
1
13.02.2016 00:45:29

Мое решение не использовать 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
}
2
13.02.2016 00:48:10

Вероятно, самое короткое решение:

jQuery(document).ready(function(){
    jQuery("#textArea").on("keydown keyup", function(){
        this.style.height = "1px";
        this.style.height = (this.scrollHeight) + "px"; 
    });
});

Таким образом, вам не нужны никакие скрытые элементы или что-то подобное.

Примечание: вам, возможно, придется поиграть в this.style.height = (this.scrollHeight) + "px";зависимости от стиля текстовой области (высота строки, отступы и тому подобное).

13
13.02.2016 00:49:35
Лучшее решение, если вы не против мигания полосы прокрутки.
cfillol 8.08.2014 09:41:46
Этого было бы достаточно с перехватом только события keyup. Тебе так не кажется?
cfillol 8.08.2014 09:44:15
Установите свойство переполнения textarea в значение «hidden», чтобы избежать мигания полосы прокрутки.
cfillol 8.08.2014 09:52:43
keyupможет быть достаточно, но я не уверен. Я был так счастлив, что понял, что перестал пробовать что-то еще.
Eduard Luca 8.08.2014 10:03:43
Я все еще пытаюсь понять, почему вы добавили this.style.height = "1px"; или this.style.height = "auto"; перед. Я знаю, что textarea не изменит размер при удалении контента, если мы не добавим эту строку. Может ли кто-нибудь все равно объяснить?
Balasubramani M 29.11.2019 13:57:27

Для тех, кто кодирует IE и сталкивается с этой проблемой. IE имеет небольшой трюк, который делает его 100% CSS.

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

Вы даже можете указать значение для row = "n", которое IE будет игнорировать, но другие браузеры будут его использовать. Я действительно ненавижу кодирование, которое реализует взломы IE, но этот очень полезен. Возможно, он работает только в режиме Quirks.

1
13.06.2013 22:26:22