Как обнаружить текстовое поле изменилось

417

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

  1. Проверьте явно, является ли код ascii нажатой клавиши буквой \ backspace \ delete
  2. Используйте замыкания, чтобы запомнить, какой текст был в текстовом поле до нажатия клавиши, и проверьте, изменилось ли это.

Оба выглядят довольно громоздко.

olamundo
источник
7
Да, ловить ключ для этого плохо. Вы можете вставить вещи без каких-либо нажатий клавиш вообще.
спонсор
2
есть ли шанс, что вы можете опубликовать свое окончательное решение? Мне тоже нужно решить эту проблему :)
Мэтт Дотсон
1
или .keyup()событие ... подробнее здесь: stackoverflow.com/questions/3003879/…
Victor S
1
Смотрите $ ("# some-input"). ChangePolling () ; для оболочки, которая проверяет текущее значение и запускает, .change()если оно изменилось.
Джоэл Пурра
Вы должны проверить это тоже stackoverflow.com/a/23266812/3160597
azerafati

Ответы:

714

Начните наблюдать событие «ввода» вместо «изменения».

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... что красиво и чисто, но может быть расширено до:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Атул Вани
источник
12
'live' устарела. так что используйте 'on' stackoverflow.com/a/15111970/1724777
NavaRajan
21
Единственным недостатком «ввода» является то, что он не совместим с IE <9.
Catfish
5
input - это событие html5, которое поддерживается не во всех браузерах. developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike
18
Вы также можете охватить больше базисов, используя: .on ('input inputchange paste', function () {
Graeck
23
Единственным недостатком IE <9 является то, что никто не использует его!
Сохаиби
67

Используйте событие onchange в HTML / стандартном JavaScript.

В jQuery это событие change () . Например:

$('element').change(function() { // do something } );

РЕДАКТИРОВАТЬ

После прочтения некоторых комментариев, как насчет:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Валид Амджад
источник
3
Да, это похоже на то, что я предложил в варианте № 2 в моем вопросе. Я предпочитаю замыкания, так как использование global сделает эту функцию работающей только для одного текстового поля. В любом случае кажется странным, что jquery не имеет более простого способа сделать это.
olamundo
1
Это действительно странно, но я сомневаюсь, что есть лучший способ сделать это. Вы можете использовать setInterval, а затем проверять, менялось ли содержимое каждые 0,1 секунды, а затем что-то делать. Это также будет включать пасты мыши и так далее. Но это не звучит слишком элегантно.
Валид Амджад
4
Все еще возможно, что содержимое может быть изменено без нажатия клавиши, например, путем вставки с помощью мыши. Если вы заботитесь об этом, вы можете теоретически перехватывать события мыши, но эта установка еще более ужасна. С другой стороны, если вы готовы игнорировать изменения, управляемые мышью, это подойдет.
Адам Беллер
45

Событие 'change' не работает правильно, но 'input' идеален.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
schwarzkopfb
источник
7
Это прекрасно работает в моей ситуации, хотя .onрекомендуется использовать с 1.7 (а не .bind).
Ник
8
В OP не указана необходимость кросс-браузерной совместимости. @schwarzkopfb предоставил решение. Нет причин голосовать, потому что у вас есть представитель, чтобы сделать это.
Дэвид Ист
3
@ Дэвид также не уточнил, какой браузер
ozz
9
@ jmo21 Я думаю, мы можем предположить, что для веб-разработки, когда браузер не является конкретным, решение должно быть кросс-функциональным. Норма поддерживает все браузеры.
Крис
3
@Chris "Норма поддерживает все браузеры" - только если вы садист. Нет веских оснований избегать HTML5-блага для 2% глобальных пользователей IE 8/9. caniuse.com/#feat=input-event
Ярин
39

Как насчет этого:

<JQuery 1,7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> JQuery 1,7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Это работает в IE8 / IE9, FF, Chrome

Сом
источник
1
Проблема с этим ответом заключается в том, что он срабатывает после размытия текстового поля, даже если значение не изменилось. Виновником является «изменение».
Джастин,
Вы используете Chrome? Кажется, это ошибка в Chrome, а не событие изменения jQuery bugs.jquery.com/ticket/9335
Catfish
работает, но имеет небольшую ошибку, если вы делаете console.logзначение поля, оно регистрируется дважды, когда вы вводите символ.
Самуэль М.
21

Используйте замыкания, чтобы запомнить, какой был текст в флажке до нажатия клавиши, и проверьте, изменилось ли это.

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

Однако! Это по-прежнему не учитывает каждое изменение, потому что есть способы редактирования содержимого текстового поля, которые не требуют нажатия клавиш. Например, выделение диапазона текста, затем щелчок правой кнопкой мыши. Или перетаскивая его. Или сбросив текст из другого приложения в текстовое поле. Или изменение слова с помощью проверки правописания в браузере. Или...

Так что, если вы должны обнаружить каждое изменение, вы должны опросить его. Вы можете window.setIntervalпроверять поле по его предыдущему значению каждую (скажем) секунду. Можно также подключить onkeyupк одной и той же функции , так что изменения, которые вызваны нажатиями отражаются быстрее.

Громоздкий? Да. Но это так или просто делайте это обычным способом обмена HTML и не пытайтесь мгновенно обновлять его.

bobince
источник
1
В наши дни inputсобытие HTML5 является жизнеспособным и работает в текущих версиях всех основных браузеров.
Тим Даун
13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Вы можете использовать событие 'input', чтобы обнаружить изменение содержимого в текстовом поле. Не используйте «live» для привязки события, так как оно устарело в Jquery-1.7, поэтому используйте «on».

NavaRajan
источник
@NavaRajan Только что проверил это снова в IE9. действительно не работает на забой.
Флорес
Я не хочу использовать .live, но проблема, с которой я столкнулся, заключается в том, что я каким-то образом ушел «назад в будущее» и в проект mvc3, в котором руководитель группы хочет придерживаться «из коробки», поэтому только EF 4.0, но используется jquery 1.5.1 ТАК .on () не было в 1.5.1, как это было добавлено в jquery версии 1.7 api.jquery.com/on
Том Стиккель
5

Я предполагаю, что вы хотите сделать что-то интерактивное, когда текстовое поле изменяется (то есть получить некоторые данные через ajax). Я искал такую ​​же функциональность. Я знаю, что использование глобального - не самое надежное и элегантное решение, но именно с этим я и поехал. Вот пример:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Здесь следует отметить одну ключевую вещь: я использую setTimeout, а не setInterval, поскольку не хочу отправлять несколько запросов одновременно. Это гарантирует, что таймер «останавливается» при отправке формы и «запускается» по завершении запроса. Я делаю это, вызывая checkSearchChanged, когда мой вызов ajax завершается. Очевидно, вы можете расширить это, чтобы проверить минимальную длину и т. Д.

В моем случае я использую ASP.Net MVC, чтобы вы могли увидеть, как связать это с MVC Ajax, а также в следующем посте:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

Дуг Лампе
источник
4

Я бы порекомендовал взглянуть на виджет автозаполнения jQuery UI. Они рассмотрели большинство случаев там, так как их кодовая база более зрелая, чем большинство из них.

Ниже приведена ссылка на демонстрационную страницу, чтобы вы могли убедиться, что она работает. http://jqueryui.com/demos/autocomplete/#default

Вы получите наибольшую выгоду от чтения источника и просмотра того, как они его решили. Вы можете найти его здесь: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

В основном они делают все это, они связывают input, keydown, keyup, keypress, focus and blur. Тогда у них есть специальная обработка для всех видов ключей, таких как page up, page down, up arrow key and down arrow key. Таймер используется перед получением содержимого текстового поля. Когда пользователь вводит клавишу, которая не соответствует команде (клавиша «вверх», клавиша «вниз» и т. Д.), Появляется таймер, который исследует содержимое примерно через 300 миллисекунд. В коде это выглядит так:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

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

Таким образом, вы можете использовать виджет или скопировать код в свой собственный виджет, если вы не используете jQuery UI (или в моем случае разработку пользовательского виджета).

Михаил Ягудаев
источник
2

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

Альтернативой может быть установка таймера (через setIntval?) И сравнение последнего сохраненного значения с текущим, а затем сброс таймера. Это гарантировало бы отлов ЛЮБОГО изменения, вызванного клавишами, мышью, другим устройством ввода, которое вы не рассматривали, или даже JavaScript, изменяющим значение (еще одна возможность, о которой никто не упомянул) из другой части приложения.

DVK
источник
Моя ситуация (которая привела меня к этому вопросу) заключается в том, что мне нужно показать кнопку «Обновить корзину» при изменении количества в текстовом поле. пользователь понятия не имеет, что ему нужно потерять фокус, и в противном случае он может не увидеть кнопку.
Simon_Weaver
Извините, я не уверен, что это отвечает на вопрос «почему бы не проверить различия в расписании». Просто проверяйте достаточно часто (каждую 1/4 секунды), и пользователь не почувствует никакой разницы.
ДВК,
1

Вы считаете, использовать событие изменения ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
источник
5
AFAIK, он срабатывает только тогда, когда фокус элемента потерян. Кто-то, кто знаком с замыканиями, вероятно, знает об этом. :)
Симон
да, этого не произойдет - событие изменения вызывается только тогда, когда текстовое поле теряет фокус. Я хочу обработать изменение сразу после нажатия клавиши.
olamundo
1

Используйте textchangeсобытие через настроенный jQuery shim для кросс-браузерной inputсовместимости. http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (последний разветвленный github: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Это обрабатывает все входные теги, в том числе <textarea>content</textarea>, что не всегда работает с change keyupт. Д. (!) Только jQuery последовательно on("input propertychange")обрабатывает <textarea>теги, а вышеприведенное - шим для всех браузеров, которые не понимают inputсобытие.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

JS Bin test

Это также обрабатывает вставку, удаление и не дублирует усилие при keyup.

Если шим не используется, используйте on("input propertychange")события jQuery .

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
Бер
источник
0

Там есть полный рабочий пример здесь .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
worldofjr
источник
0

Что - то , как это должно работать, в основном потому , что focusи focusoutбудет в конечном итоге с двумя отдельными значениями. Я использую dataздесь, потому что он хранит значения в элементе, но не касается DOM. Это также простой способ сохранить значение, связанное с его элементом. Вы также можете легко использовать переменную с более высокой областью действия.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
smcjones
источник
0

Этот код обнаруживает всякий раз, когда содержимое текстового поля изменяется пользователем и изменяется кодом Javascript.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
Сандип Ядав
источник