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

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

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

Здесь снимок экрана.

ISO Address

Любые идеи?


@Крис

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

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

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

Это не о том, чтобы иметь gimick; он о том, что текстовое поле пользователь может редактировать, который не займет лишнее пространство, но покажет весь текст в нем.

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


Я немного изменил код, потому что он немного странный. Я изменил его, чтобы активировать 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;
};

Ответ 1

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 does not work
            Event.observe('text-area', 'keydown', resizeIt );

            resizeIt(); //Initial on load
        </script>
    </body>
</html>

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

Ответ 2

Уточнение некоторых из этих ответов - позволить CSS выполнять больше работы.

Основной маршрут выглядит следующим образом:

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

Ответ 3

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

  • Используется высота пикселя вместо высоты строки: более точная обработка переноса строки, если используется пропорциональный шрифт.
  • Принимает идентификатор или элемент в качестве ввода
  • Принимает необязательный параметр максимальной высоты - полезно, если вы не хотите, чтобы текстовая область увеличивалась до определенного размера (сохраняйте все это на экране, избегая нарушения макета и т.д.)
  • Протестировано на 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";
   }
}

Demo: (использует jQuery, цели в текстовой области, в которую я сейчас набираю - если у вас установлен Firebug, вставьте оба примера в консоль и протестируйте на этой странице)

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

Ответ 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"; в зависимости от того, как вы создаете текстовое пространство (строка-высота, отступы и т.д.).

Ответ 5

Здесь приведена Прототип для изменения размера текстовой области, которая не зависит от количества столбцов в текстовом поле. Это превосходный метод, потому что он позволяет вам управлять текстовой областью с помощью CSS, а также иметь переменную ширину 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'
    });

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

Ответ 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 для этого script.

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

Simple. Это максимальная высота 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(). Но имейте в виду прописные и нижние пиксели. В противном случае ваше текстовое поле будет расти слишком быстро.

$(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 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

Вот расширение для виджета 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'));
  }
});

Ответ 14

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

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

Ответ 15

Вот функция, которую я только что написал в jQuery, чтобы сделать это - вы можете перенести ее на Prototype, но они не поддерживают "liveness" jQuery, поэтому элементы, добавленные запросами Ajax, не будут отвечать.

Эта версия не только расширяется, но и сжимается, когда нажата кнопка delete или backspace.

Эта версия основана на jQuery 1.4.2.

Наслаждайтесь;)

http://pastebin.com/SUKeBtnx

Использование:

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

или (например, любой селектор jQuery)

$("textarea").textareacontrol();

Он был протестирован на Internet Explorer 7/Интернет &nbsp, Explorer 8, Firefox 3.5 и Chrome. Все работает нормально.

Ответ 16

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

$(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 с автоматическим изменением размера.)

Ответ 17

Используя 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>

Ответ 18

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

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

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