Виявлення обміну текстовими зонами


132

Як я можу виявити подію зміни на textarea за допомогою JavaScript?
Я намагаюся виявити, скільки символів залишилось під час введення.

Я спробував використовувати подію onchange, але це, здається, розпочинає лише тоді, коли фокус знаходиться поза.

Відповіді:


97

Вам потрібно буде використовувати onkeyup і onchange для цього. Змінення перешкоджатиме вставленню контекстного меню, і натискання клавіші активізується для кожного натискання клавіші.

Дивіться мою відповідь про те, як накласти максимальну довжину textArea для зразка коду.


3
Просто хотів наголосити на тому, що Джош уже сказав, що вам слід використовувати клавіш, а не клавіш для цього: здається, що виклик клавіш ще до того, як зміна буде фактично внесена в текстову область, тому ви будете використовувати неправильну довжину (і ви не робите ' t дійсно знаю, як у вас є: можна вводити чи видаляти, а текст може бути вибраний, тобто більше, ніж просто +/- 1).
brianmearns

65
Я даю -1 тут, вибачте! onkeyup- жахлива подія для виявлення входу. Використовуйте oninputта onpropertychange(для підтримки IE).
Енді Е

6
«Тільки» проблема onchangeбуде НЕ спрацьовує , коли виникає контекстне меню вирізати / вставити.
Том

4
Набагато чутливіше використовувати onkeydown та setTimeout, щоб ви могли миттєво виявити зміни, а не чекати, коли ключ буде відпущений. Якщо вам також потрібно зловити вирізати та вставити, використовуйте події вирізання та вставки.
Кевін Б

1
Попередження: onkeyup може доставити вам проблеми. Приклад: скажемо, що ви повинні робити щось лише в тому випадку, якщо зміна вхідного тексту змінилася. Якщо ви припускаєте, що клавіатура змінить вхід, це неправда. Поставте фокус на вході. Щоб перейти до наступного поля, використовуйте "вкладку". Тепер використовуйте "shift + tab", щоб повернутися до вводу. запускається клавіатура, але користувач фактично не змінив користувач.
Зіг Мандель

117

Настав 2012 рік, ера після ПК є тут, і нам ще належить боротися з чимось таким базовим, як це. Це повинно бути дуже просто .

До тих пір, поки ця мрія не здійсниться, ось найкращий спосіб зробити це, крос-браузер: використовувати комбінацію inputта onpropertychangeподії , як-от так:

var area = container.querySelector('textarea');
if (area.addEventListener) {
  area.addEventListener('input', function() {
    // event handling code for sane browsers
  }, false);
} else if (area.attachEvent) {
  area.attachEvent('onpropertychange', function() {
    // IE-specific event handling code
  });
}

inputЗахід бере на IE9 +, FF, Chrome, Opera і Safari , і onpropertychangeпіклується про IE8 (він також працює з IE6 і 7, але є деякі помилки).

Перевага використання inputі в onpropertychangeтому , що вони не спрацьовують без необхідності (наприклад , при натисканні кнопки Ctrlабо Shiftклавіші); тож якщо ви хочете виконати відносно дорогу операцію, коли зміст вмісту текстових областей змінюється, це шлях .

Тепер IE, як завжди, виконує напівдоступну роботу щодо підтримки цього: ні в IE, inputні onpropertychangeв пожежних файлах, коли символи видаляються з текстової області. Отже, якщо вам потрібно обробляти видалення символів в IE, використовуйте keypress(на відміну від використання keyup/ keydown, оскільки вони спрацьовують лише один раз, навіть якщо користувач натискає та утримує клавішу).

Джерело: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/

EDIT: Здається, навіть вищезазначене рішення не є ідеальним, як справедливо вказувалося в коментарях: наявність addEventListenerвластивості в textarea не означає, що ви працюєте з розумним браузером; аналогічно наявність attachEventвластивості не означає IE. Якщо ви хочете, щоб ваш код був справді повітронепроникним, вам варто змінити це. Дивіться коментар Тіма Дауна для покажчиків.


1
Це найкращий підхід. Мені тут не подобаються умовиводи (підтримка браузера addEventListenerне передбачає підтримки inputподії, або навпаки); виявлення функцій було б краще. Дивіться цю публікацію в блозі для обговорення цього питання.
Тім Даун

Повністю згоден з Тімом щодо цього. oninputтак ми повинні це зробити, але ви, мабуть, не повинні використовуватись addEventListenerяк тест для підтримки браузера. +1 у будь-якому випадку.
Бен Д

1
Не погоджуючись, введення не потурбується про IE9. Вирізати / вставити через контекстні меню, на жаль, також є вхідними даними, як і зворотній простір. Я не намагався тестувати, але не ставлю грошей на ставку, що IE10 + вирішив цю проблему.
Стефан Штайгер

1
@StefanSteiger, тому моя відповідь пропонує також використовувати keypressподію для обробки цього випадку в IE9 (і, можливо, пізніших версіях).
Vicky Chijwani

inputПодія Оброблювач також може бути визначений шляхом реалізації .oninputвластивості об'єкта.
обробляти

20
  • Для Google-Chrome вхідний вхід буде достатнім (випробувано в Windows 7 з версією 22.0.1229.94 м).
  • Для IE 9 oninput буде захоплювати все, крім вирізаного через контекстне меню та зворотній простір.
  • Для IE 8 необхідна зміна властивостей для ловлі вставлення на додаток до входу.
  • Для IE 9 + 8 потрібно ввімкнути підключення ключа, щоб увімкнути резервну область.
  • Для IE 9 + 8, onmousemove - єдиний спосіб, за яким я знайшов різання за допомогою контекстного меню

Не тестується на Firefox.

    var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...

    function SuperDuperFunction() {
        // DoSomething
    }


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
        if(isIE) // For Chrome, oninput works as expected
            SuperDuperFunction();
    }

<textarea id="taSource"
          class="taSplitted"
          rows="4"
          cols="50"
          oninput="SuperDuperFunction();"
          onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>

1
Дивовижні імена функцій :)
Jonas Gröger

8

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

var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);

text.onkeyup = function(){
var callcount = 0;
    var action = function(){
        alert('changed');
    }
    var delayAction = function(action, time){
        var expectcallcount = callcount;
        var delay = function(){
            if(callcount == expectcallcount){
                action();
            }
        }
        setTimeout(delay, time);
    }
    return function(eventtrigger){
        ++callcount;
        delayAction(action, 1200);
    }
}();

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


1
+1 за відстрочену дію "заглушення"! Я використовую щось подібне у своєму додатку.
psulek

7

Я знаю, що це питання було специфічним для JavaScript, однак, здається, немає хорошого, чистого способу ЗАВЖДИ виявити, коли текстова область змінюється у всіх поточних браузерах. Я дізнався, що jquery подбав про це за нас. Він навіть обробляє зміни контекстного меню в текстових областях. Той самий синтаксис використовується незалежно від типу введення.

    $('div.lawyerList').on('change','textarea',function(){
      // Change occurred so count chars...
    });

або

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });

4
Я виявив, що подія зміни не більше відповідає jQuery, ніж звичайному JS. Я використовував jQuery's, bind("input cut paste"...і він працює як шарм - вводити, вирізати та вставляти за допомогою клавіатури або контекстного меню; рівномірне перетягування тексту.
Лоуренс Дол

2
На жаль, FF не займає changeподії для textarea.
dma_k

4

Ви можете прослухати подію на зміну textarea та вносити зміни згідно з вашим бажанням. Ось один приклад.

(() => {
	const textArea = document.getElementById('my_text_area');
  textArea.addEventListener('input', () => {
    let textLn =  textArea.value.length;
    if(textLn >= 100) {
      textArea.style.fontSize = '10pt';
    }

  })
})()
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>


1

Клавіатури має бути достатньо, якщо вона поєднана з атрибутом перевірки вводу HTML5 / атрибутом шаблону. Отже, створіть шаблон (регулярний вираз), щоб перевірити вхід і діяти на статус .checkValidity (). Щось подібне нижче може спрацювати. У вашому випадку ви хочете, щоб регулярний вираз відповідав довжині. Моє рішення в використанні / демо-можливості онлайн тут .

<input type="text" pattern="[a-zA-Z]+" id="my-input">

var myInput = document.getElementById = "my-input";

myInput.addEventListener("keyup", function(){
  if(!this.checkValidity() || !this.value){
    submitButton.disabled = true;
  } else {
    submitButton.disabled = false;
  }
});

0

Код, який я використовував для IE 11 без jquery і лише для однієї текстової області:

Javascript:

// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{ 
    if (internalChange == 1)
    {
        internalChange= 0;
        return;
    }
    internalChange= 1;
    // <form> and <textarea> are the ID's of your form and textarea objects
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}

та html:

<TEXTAREA onpropertychange='limit_char(5)' ...

-1

Спробуйте це. Це просто, і оскільки це 2016 рік, я впевнений, що він працюватиме в більшості браузерів.

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div>

function check(){
    var string = document.getElementById("url").value
    var left = 15 - string.length;
    document.getElementById("spn").innerHTML = left;
}

Отже, ви отримуєте URL за id, але він не відображається у вашому коді.
AbsoluteƵERØ

-8

Найкраще, що ви можете зробити, це встановити функцію, яку потрібно викликати протягом певного часу, і цю функцію перевірити вміст вашої текстової області.

self.setInterval('checkTextAreaValue()', 50);

7
опитування - дуже погана ідея. Це просто знищить продуктивність. Також, як і інші опубліковані, існує якесь рішення
П’єр-Олів'є Тібо

2
Це 21 століття. Жоден веб-переглядач не повинен мати проблем із порівнянням рядків кожні 50 мс. Кешуйте своїх селекторів, і це цілком прийнятне рішення.
знесення нанівець
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.