Автоматичне розширення текстової області за допомогою jQuery


128

Як я можу змусити текстову область автоматично розширюватися за допомогою jQuery?

У мене є текстове поле для пояснення порядку денного засідання, тому я хочу розгорнути це поле, коли текст мого порядку денного постійно зростає в цій області.


i thik textarea автоматично розширюється.
— andrew Sullivan


Будь ласка, подумайте про те, щоб змінити своє питання та видалити слово "jQuery"
— vsync

Відповіді:


113

Я пробував багато, і це чудово. Посилання мертва. Більш нова версія доступна тут . Дивіться старішу версію нижче.
Ви можете спробувати, натиснувши і утримуючи клавішу введення в текстовій області. Порівняйте ефект з іншими автоматично розширюваними плагінами textarea ....

редагувати на основі коментаря

$(function() {
   $('#txtMeetingAgenda').autogrow();
});

Примітка: ви повинні включити необхідні файли js ...

Для запобігання прокрутки в текстовому полі з мерехтіти і вимикання під час розширення / стиснення, ви можете встановити overflowдо , hiddenа також:

$('#textMeetingAgenda').css('overflow', 'hidden').autogrow()




Оновлення:

Посилання вище перервано. Але ви все одно можете отримати тут файли javascript .


якщо мій ідентифікатор текстового поля txtMeetingAgenda, то як я можу реалізувати властивість Auto textArea в jquery
— Piyush

тут подія натискання визначена чи ні
— Піюш

це все про textarea, але як щодо textbox.is цей плагін також працює для textbox?
— Піюш

1
цей плагін не працює добре, спробуйте автоматизувати, це набагато краще
— julesbou

Це добре працює лише одним способом, коли текстареа розростається. Але коли ви починаєте видаляти текст, висота не зменшується автоматично.
— екшакінг

166

Якщо ви не хочете плагін, є дуже просте рішення

$("textarea").keyup(function(e) {
    while($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))) {
        $(this).height($(this).height()+1);
    };
});

Дивіться, як це працює у jsFiddle, який я використовував для відповіді на інше текстове запитання тут .

Щоб відповісти на запитання про те, як зробити це в зворотному порядку або зменшити його в міру видалення тексту: jsFiddle

А якщо ви хочете плагін

@Jason створив тут один


1
Мені довелося видалити + parseFloat ($ (this) .css ("borderTopWidth")) + parseFloat ($ (this) .css ("borderBottomWidth")), інакше це нескінченно
— циклічне текстові області,

3
версія без jQuery:if (this.clientHeight < this.scrollHeight) { this.style.height = this.scrollHeight + 'px'; }
— Георгій Іванкін

3
@metakungfu Ну, а не просто зволікати, можливо, ви можете допомогти покращити відповідь. У мене немає ніякого способу тестування яблучних лайм-атмів і сафарі для Windows було припинено давно. Тому я реально нічого не можу визначити, чому це не вийде. З точки зору коду, в цьому рішенні немає нічого поганого. Ви впевнені, що код зламається, а не сафарі, який порушує jsfiddle? safari досить вибагливий, і загадка просто пройшла через основне оновлення. Mayeb, ви можете відкрити розробник і надати детальніше?
— SpYk3HH

1
також потрібно textarea overflow-y встановити на прихований, щоб запобігти миготіння прокрутки
— липня

2
Якщо я хочу видалити додані рядки, збільшений розмір текстового поля залишається колишнім, чи можливо він також може автоматично змінити розмір назад?
— Стівен

33

Росте / скорочується textarea. Ця демонстрація використовує jQuery для прив'язки подій, але це не обов'язково.
( немає підтримки IE - IE не відповідає на зміну атрибутів рядків )

DEMO PAGE


HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
}

javascript (оновлено)

$(document)
    .one('focus.textarea', '.autoExpand', function(){
        var savedValue = this.value;
        this.value = '';
        this.baseScrollHeight = this.scrollHeight;
        this.value = savedValue;
    })
    .on('input.textarea', '.autoExpand', function(){
        var minRows = this.getAttribute('data-min-rows')|0,
            rows;
        this.rows = minRows;
        rows = Math.ceil((this.scrollHeight - this.baseScrollHeight) / 16);
        this.rows = minRows + rows;
    });

2
тому що код повинен трохи почекати, щоб лист, який ви ввели, буде надрукований у текстовій області, а потім змінити розміри textarea
— vsync

1
Я бачу, рішення розбивається, коли текст копіюється (CTRL + V) з будь-якого джерела. Хоча, якщо текст вводиться вручну - це приголомшливо і дуже гладко.
— Сатья Каллурі

1
@vsync: як би ви змінили для кількох текстових областей? Тобто у вас є textarea1 і textarea2 і ви хочете дозволити обом рости?
— jmoreno

1
Це має бути головна відповідь! Я відповідав на питання , заснований на тому , що якщо кому - то цікаво: stackoverflow.com/questions/29930300 / ...
— gsamaras

1
@AllyMurray - я пішов зараз і оновив його до 16, оскільки, здається, дає кращий результат. і так, це очікувана висота лінії
— vsync


20

Ви можете спробувати це

$('#content').on('change keyup keydown paste cut', 'textarea', function () {
        $(this).height(0).height(this.scrollHeight);
    }).find('textarea').change();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content">
  <textarea>How about it</textarea><br />
  <textarea rows="5">111111
222222
333333
444444
555555
666666</textarea>
</div>


якщо ви хочете отримати scrollHeight від $ (this), ви можете використовувати $ (this) .prop ('scrollHeight'); натомість;)
— Самуель Вікент

3
він блимає кожен розрив рядка
— Джо

11

Завдяки SpYk3HH я почав з його рішення і перетворив його на це рішення, яке додає функціональність, що скорочується, і ще простіше і швидше, я вважаю.

$("textarea").keyup(function(e) {
    $(this).height(30);
    $(this).height(this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth")));
});

Тестовано в поточних браузерах Chrome, Firefox та Android 2.3.3.

У деяких браузерах ви можете побачити спалахи смуг прокрутки. Додайте цей CSS, щоб вирішити це.

textarea{ overflow:hidden; }

це зовсім не добре: / кожен тип персонажа я додає висоти.
— vsync

1
Це прекрасно працює для мене! У простому коді точно немає нічого, що можна зробити, як ти кажеш, це робить.
— drolex

1
так, я бачу це зараз, у вашому коді повинен бути рядок, який встановлює висоту спочатку 30. це, мабуть, не потрібна ilne, оскільки вона змушує розробника налаштувати код, а не код зрозуміти та адаптуватись до textarea,
— vsync

1
Це неправильно. Розробнику не потрібно підробляти код. Встановити висоту в 30 потрібно, і вона працює на все. Користувач ніколи не бачить, щоб це сталося. Ось так воно здатне скоротити текстиль. Код розуміє та адаптується до текстової області. У цьому вся суть.
— drolex

Ви праві. демонстраційна сторінка: jsbin.com/ObEcoza/2/edit (встановлення висоти, 1pxздається, краще)
— vsync

10

Щоб визначити автоматичну текстову область, що розширюється, вам потрібно зробити дві речі:

  1. Розгорніть його, натиснувши клавішу Enter всередині нього або введіть вміст більше одного рядка.
  2. І зменшіть його при розмитті, щоб отримати фактичний розмір, якщо користувач ввів пробіли. ( Бонус )

Ось функція ручної роботи для виконання завдання.

Відмінно працює майже з усім браузером (<IE7) . Ось метод:

    //Here is an event to get TextArea expand when you press Enter Key in it.
    // intiate a keypress event
    $('textarea').keypress(function (e) {  
       if(e.which == 13)   {   
       var control = e.target;                     
       var controlHeight = $(control).height();          
      //add some height to existing height of control, I chose 17 as my line-height was 17 for the control    
    $(control).height(controlHeight+17);  
    }
    }); 

$('textarea').blur(function (e) {         
    var textLines = $(this).val().trim().split(/\r*\n/).length;      
    $(this).val($(this).val().trim()).height(textLines*17);
    });

ТУТ - пост про це.


6

Раніше я використовував плагін Textarea Expander jQuery з хорошими результатами.


1
Текстове поле (вхідний текстовий елемент, який я вважаю) не є багаторядковим. Використовуйте textarea, але стилі його належним чином - рядки, стовпці тощо, а потім використовуйте плагін для автоматичного зростання, як зазначено вище.
— богатир

4

Кожен повинен спробувати цей плагін jQuery: xautoresize-jquery . Це дійсно добре і повинно вирішити вашу проблему.


Цей дав мені найкращі результати, а також його легко здійснити.
— блицкід

4
function autosize(textarea) {
    $(textarea).height(1); // temporarily shrink textarea so that scrollHeight returns content height when content does not fill textarea
    $(textarea).height($(textarea).prop("scrollHeight"));
}

$(document).ready(function () {
    $(document).on("input", "textarea", function() {
        autosize(this);
    });
    $("textarea").each(function () {
        autosize(this);
    });
});

(Це не буде працювати в Internet Explorer 9 або старшої версії, оскільки він використовує inputподію)


у моєму проекті, коли я перекладаю цілі речі на сторінці за допомогою Jquery та машинопису, ваше рішення було єдиним способом, що я міг вирішити свою проблему завдяки
— Гаррі Саршо

3

Я просто побудував цю функцію для розширення текстових областей при завантаженні сторінки. Просто змініть eachна, keyupі це відбудеться при введенні текстової області.

// On page-load, auto-expand textareas to be tall enough to contain initial content
$('textarea').each(function(){
    var pad = parseInt($(this).css('padding-top'));
    if ($.browser.mozilla) 
        $(this).height(1);
    var contentHeight = this.scrollHeight;
    if (!$.browser.mozilla) 
        contentHeight -= pad * 2;
    if (contentHeight > $(this).height()) 
        $(this).height(contentHeight);
});

Тестували в Chrome, IE9 та Firefox. На жаль, у Firefox є ця помилка, яка повертає невірне значення для scrollHeight, тому вищевказаний код містить (хакі) спосіб вирішення.


3

Я виправив кілька помилок у відповіді, наданій Рейгелем (прийнята відповідь):

  1. Порядок, в якому замінюються об'єкти html зараз, не викликає несподіваного коду в тіньовому елементі. (Оригінал замінив ">" на "& ampgt;", викликаючи неправильний розрахунок висоти в деяких рідкісних випадках).
  2. Якщо текст закінчується новим рядком, тінь тепер отримує додатковий символ "#", замість того, щоб мати фіксовану додану висоту, як це має місце в оригіналі.
  3. Змінення розміру текстової області після ініціалізації актуалізує ширину тіні.
  4. додано обгортання слів: слово розбиття для тіні, тож воно порушує те саме, що і текстареа (змушує перерви на дуже довгі слова)

Залишилося кілька питань, що стосуються пробілів. Я не бачу рішення для подвійних пробілів, вони відображаються як одиничні пробіли в тіні (html-рендерінг). Це неможливо вирішити за допомогою & nbsp ;, тому що пробіли повинні бути розбиті. Крім того, textarea розриває лінію після пробілу, якщо для цього простору немає місця, вона перерве лінію в більш ранній точці. Пропозиції вітаються.

Виправлений код:

(function ($) {
    $.fn.autogrow = function (options) {
        var $this, minHeight, lineHeight, shadow, update;
        this.filter('textarea').each(function () {
            $this = $(this);
            minHeight = $this.height();
            lineHeight = $this.css('lineHeight');
            $this.css('overflow','hidden');
            shadow = $('<div></div>').css({
                position: 'absolute',
                'word-wrap': 'break-word',
                top: -10000,
                left: -10000,
                width: $this.width(),
                fontSize: $this.css('fontSize'),
                fontFamily: $this.css('fontFamily'),
                lineHeight: $this.css('lineHeight'),
                resize: 'none'
            }).appendTo(document.body);
            update = function () {
                shadow.css('width', $(this).width());
                var val = this.value.replace(/&/g, '&amp;')
                                    .replace(/</g, '&lt;')
                                    .replace(/>/g, '&gt;')
                                    .replace(/\n/g, '<br/>')
                                    .replace(/\s/g,'&nbsp;');
                if (val.indexOf('<br/>', val.length - 5) !== -1) { val += '#'; }
                shadow.html(val);
                $(this).css('height', Math.max(shadow.height(), minHeight));
            };
            $this.change(update).keyup(update).keydown(update);
            update.apply(this);
        });
        return this;
    };
}(jQuery));

3

Код SpYk3HH з додаванням для зменшення розміру.

function get_height(elt) {
    return elt.scrollHeight + parseFloat($(elt).css("borderTopWidth")) + parseFloat($(elt).css("borderBottomWidth"));
}

$("textarea").keyup(function(e) {
    var found = 0;
    while (!found) {
        $(this).height($(this).height() - 10);
        while($(this).outerHeight() < get_height(this)) {
            $(this).height($(this).height() + 1);
            found = 1;
        };
    }
});

Ви бачили мою відповідь перед вашою?
— drolex

1
Ваше рішення мене не влаштовує, була якась помилка, я не пам’ятаю, яка.
— DSblizzard

2

Це працювало для мене краще:

$('.resiText').on('keyup input', function() { 
$(this).css('height', 'auto').css('height', this.scrollHeight + (this.offsetHeight - this.clientHeight));
});
.resiText {
    box-sizing: border-box;
    resize: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="resiText"></textarea>


2

Люди, здається, мають надто відпрацьовані рішення ...

Ось як я це роблю:

  $('textarea').keyup(function()
  {
    var 
    $this  = $(this),
    height = parseInt($this.css('line-height'),     10),
    padTop = parseInt($this.css('padding-top'),     10),
    padBot = parseInt($this.css('padding-bottom'),  10);

    $this.height(0);

    var 
    scroll = $this.prop('scrollHeight'),
    lines  = (scroll  - padTop - padBot) / height;

    $this.height(height * lines);
  });

Це буде працювати з довгими лініями, а також з розривами ліній .. зростає і скорочується ..


1

Я написав цю функцію jquery, яка, здається, працює.

Потрібно вказати мінімальну висоту в css, і якщо ви не хочете зробити якесь кодування, воно повинно мати дві цифри. тобто 12 пікселів;

$.fn.expand_ta = function() {

var val = $(this).val();
val = val.replace(/</g, "&lt;");
val = val.replace(/>/g, "&gt;");
val += "___";

var ta_class = $(this).attr("class");
var ta_width = $(this).width();

var min_height = $(this).css("min-height").substr(0, 2);
min_height = parseInt(min_height);

$("#pixel_height").remove();
$("body").append('<pre class="'+ta_class+'" id="pixel_height" style="position: absolute; white-space: pre-wrap; visibility: hidden; word-wrap: break-word; width: '+ta_width+'px; height: auto;"></pre>');
$("#pixel_height").html(val);

var height = $("#pixel_height").height();
if (val.substr(-6) == "<br />"){
    height = height + min_height;
};
if (height >= min_height) $(this).css("height", height+"px");
else $(this).css("height", min_height+"px");
}

1

Для всіх, хто використовує плагін, опублікований Reigel, будь ласка, майте на увазі, що це відключить функцію скасування в Internet Explorer (ідіть, демонструйте демонстрацію).

Якщо це проблема для вас, то я б запропонував використати плагін, опублікований @richsage, оскільки він не страждає від цієї проблеми. Додаткову інформацію див. У другій точці пункту " Пошук остаточного розміру текстової області" .



1

Мені хотілося анімації та автоматичного скорочення. Поєднання, мабуть, важке, тому що люди придумали досить інтенсивні рішення для нього. Я також зробив його багатотекстовим. І це не так смішно важко, як плагін jQuery.

Я грунтувався на відповіді vsync (і поліпшенні, які він зробив для цього), http://codepen.io/anon/pen/vlIwj - це кодек для мого вдосконалення.

HTML

<textarea class='autoExpand' rows='3' data-min-rows='3' placeholder='Auto-Expanding Textarea'></textarea>

CSS

body{ background:#728EB2; }

textarea{  
  display:block;
  box-sizing: padding-box;
  overflow:hidden;

  padding:10px;
  width:250px;
  font-size:14px;
  margin:50px auto;
  border-radius:8px;
  border:6px solid #556677;
  transition:all 1s;
  -webkit-transition:all 1s;
}

JS

var rowheight = 0;

$(document).on('input.textarea', '.autoExpand', function(){
    var minRows = this.getAttribute('data-min-rows')|0,
        rows    = this.value.split("\n").length;
    $this = $(this);
    var rowz = rows < minRows ? minRows : rows;
    var rowheight = $this.attr('data-rowheight');
    if(!rowheight){
      this.rows = rowz;
      $this.attr('data-rowheight', (this.clientHeight  - parseInt($this.css('padding-top')) - parseInt($this.css('padding-bottom')))/ rowz);
    }else{
      rowz++;
      this.style.cssText = 'height:' + rowz * rowheight + 'px'; 
    }
});

Примітка: я помітив, що іноді краще спрацьовує з розміром вікна: content-box. Я не зовсім впевнений, чому все-таки слід правильно обробити прокладку :(
— Lodewijk

1

На це є багато відповідей, але я знайшов щось дуже просте, приєднайте подію клавіатури до текстової області та перевірте наявність клавіші введення, натисніть клавішу, код 13

keyPressHandler(e){ if(e.keyCode == 13){ e.target.rows = e.target.rows + 1; } }

Це додасть ще один рядок текстовій області, і ви можете стилізувати ширину за допомогою CSS.


1

Скажімо, ви намагаєтеся досягти цього за допомогою Knockout ... ось як:

На сторінці:

<textarea data-bind="event: { keyup: $root.GrowTextArea }"></textarea>

У моделі перегляду:

self.GrowTextArea = function (data, event) {
    $('#' + event.target.id).height(0).height(event.target.scrollHeight);
}

Це має спрацювати, навіть якщо у вас є кілька текстових областей, створених інструментом Knockout, як я.



1

Найпростіше рішення:

html:

<textarea class="auto-expand"></textarea>

css:

.auto-expand {
    overflow:hidden;
    min-height: 80px;
}

js (jquery):

$(document).ready(function () {
 $("textarea.auto-expand").focus(function () {
        var $minHeight = $(this).css('min-height');
        $(this).on('input', function (e) {
            $(this).css('height', $minHeight);
            var $newHeight = $(this)[0].scrollHeight;
            $(this).css('height', $newHeight);
        });
    });       
});

1

Розчин з чистим JS

function autoSize() {
  if (element) {
    element.setAttribute('rows', 2) // minimum rows
    const rowsRequired = parseInt(
      (element.scrollHeight - TEXTAREA_CONFIG.PADDING) / TEXTAREA_CONFIG.LINE_HEIGHT
    )
    if (rowsRequired !== parseInt(element.getAttribute('rows'))) {
      element.setAttribute('rows', rowsRequired)
    }
  }
}

https://jsfiddle.net/Samb102/cjqa2kf4/54/


1

Це рішення, яке я закінчив використовувати. Я хотів вбудованого рішення, і це поки що, здається, працює чудово:

<textarea onkeyup="$(this).css('height', 'auto').css('height', this.scrollHeight + this.offsetHeight - this.clientHeight);"></textarea>

1

function autoResizeTextarea() {
  for (let index = 0; index < $('textarea').length; index++) {
    let element = $('textarea')[index];
    let offset = element.offsetHeight - element.clientHeight;
    $(element).css('resize', 'none');
    $(element).on('input', function() {
      $(this).height(0).height(this.scrollHeight - offset - parseInt($(this).css('padding-top')));
    });
  }
}

https://codepen.io/nanachi1/pen/rNNKrzQ

це має працювати.


0

@ Георгій Іванкін зробив пропозицію в коментарі, я її успішно використав :) - але з незначними змінами:

$('#note').on('keyup',function(e){
    var maxHeight = 200; 
    var f = document.getElementById('note'); 
    if (f.clientHeight < f.scrollHeight && f.scrollHeight < maxHeight ) 
        { f.style.height = f.scrollHeight + 'px'; }
    });      

Він припиняє розширюватися після досягнення максимальної висоти 200 пікселів


0

Старе питання, але ви можете зробити щось подібне:

html:

<textarea class="text-area" rows="1"></textarea>

jquery:

var baseH; // base scroll height

$('body')
    .one('focus.textarea', '.text-area', function(e) {
        baseH = this.scrollHeight;
    })
    .on('input.textarea', '.text-area', function(e) {
        if(baseH < this.scrollHeight) {
            $(this).height(0).height(this.scrollHeight);
        }
        else {
            $(this).height(0).height(baseH);
        }
    });

Таким чином автоматичний розмір застосовуватиметься до будь-яких текстових областей із класом "текстова область". Також стискається при видаленні тексту.

jsfiddle:

https://jsfiddle.net/rotaercz/46rhcqyn/


0

Спробуйте це:

  $('textarea[name="mytextarea"]').on('input', function(){
    $(this).height('auto').height($(this).prop('scrollHeight') + 'px');
  }).trigger('input');

0

Просте рішення jQuery:

$("textarea").keyup(function() {
    var scrollHeight = $(this).prop('scrollHeight') - parseInt($(this).css("paddingTop")) - parseInt($(this).css("paddingBottom"));

    if (scrollHeight > $(this).height()) {
        $(this).height(scrollHeight + "px");
    }
});

HTML:

<textarea rows="2" style="padding: 20px; overflow: hidden; resize: none;"></textarea>

Переповнення слід приховати . Зміни розміру - це жодне, якщо ви не хочете робити його зміною за допомогою миші.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.