Существует множество способов изменения значения <input type="text">
, в том числе:
Я хочу, чтобы моя функция JavaScript вызывалась (с текущим значением ввода) в любое время, когда она изменяется. И я хочу, чтобы он сразу вызывался, а не только когда вход теряет фокус.
Я ищу самый чистый и самый надежный способ сделать это во всех браузерах (желательно с помощью jQuery).
Пример использования: на странице Twitter Registration значение поля имени пользователя отображается в URL-адресе " http://twitter/ имя пользователя" ниже.
К сожалению, я думаю, что setInterval
выигрывает приз:
<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>
Это самое чистое решение, всего в 1 строке кода. Он также является самым надежным, так как вам не нужно беспокоиться обо всех различных событиях/способах, которые input
может получить значение.
Недостатки использования 'setInterval', похоже, не применяются в этом случае:
input
через Javascript, не будет ли альтернативой перехват всех событий, которые может инициировать модификация пользователем, а также чтобы все модификации элементов ввода посредством кода использовали функцию-обертку что явно вызывает событие изменения на элементе ввода? Это будет иметь свои недостатки (риск неосторожного отказа от использования функции-обертки; не будет работать для библиотеки / плагина на чужой странице; требует изменения существующего кода), но устранит задержку; возможно перечислить оба подхода и сравнить?
Этот код jQuery мгновенно заменяет любой элемент и должен работать во всех браузерах:
$('.myElements').each(function() {
var elem = $(this);
// Save current value of element
elem.data('oldVal', elem.val());
// Look for changes in the value
elem.bind("propertychange change click keyup input paste", function(event){
// If value has changed...
if (elem.data('oldVal') != elem.val()) {
// Updated stored value
elem.data('oldVal', elem.val());
// Do action
....
}
});
});
input
- это событие HTML5, которое, как я считаю, должно охватывать все современные браузеры ( ссылка на MDN ). keyup
должен поймать все остальное, хотя и с небольшой задержкой ( input
запускается при нажатии клавиши). propertychange
- это проприетарное событие MS, и я не уверен, действительно ли необходима paste
.
.live()
(или .on()
в полезных случаях), если вы не связываете его непосредственно с самим элементом ввода.
Приятное решение в режиме реального времени для jquery >= 1.9
$("#input-id").on("change keyup paste", function(){
dosomething();
})
если вы также хотите обнаружить событие "click", просто:
$("#input-id").on("change keyup paste click", function(){
dosomething();
})
если ваш jquery <= 1.4, просто используйте "live" вместо "on".
Привязка к событию oninput
, похоже, отлично работает в большинстве здравомыслящих браузеров. IE9 также поддерживает его, но реализация ошибочна (событие не запускается при удалении символов).
С помощью jQuery версии 1.7+ метод on
полезен для привязки к событию следующим образом:
$(".inputElement").on("input", null, null, callbackFunction);
oninput
не работает с input[type=reset]
или редактированием javascript, как вы видите в этом тесте: codepen.io/yukulele/pen/xtEpb
2017 ответ: входное событие делает именно это для чего-то более нового, чем IE8.
$(el).on('input', callback)
input
не может обнаружить изменения JS.
К сожалению, нет событий или событий, соответствующих вашим критериям. Ключи и копирование/вставка могут обрабатываться с событием keyup
. Изменения через JS более сложны. Если у вас есть контроль над кодом, который устанавливает текстовое поле, лучше всего изменить его, чтобы либо вызвать вашу функцию напрямую, либо вызвать пользовательское событие в текстовом поле:
// Compare the textbox current and last value. Report a change to the console.
function watchTextbox() {
var txtInput = $('#txtInput');
var lastValue = txtInput.data('lastValue');
var currentValue = txtInput.val();
if (lastValue != currentValue) {
console.log('Value changed from ' + lastValue + ' to ' + currentValue);
txtInput.data('lastValue', currentValue);
}
}
// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());
// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);
// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
$('#txtInput').val('abc def').trigger('set');
});
Если у вас нет контроля над этим кодом, вы можете использовать setInterval()
для просмотра текстового поля для изменений:
// Check the textbox every 100 milliseconds. This seems to be pretty responsive.
setInterval(watchTextbox, 100);
Такой активный мониторинг не будет сразу же проверять обновления, но он кажется достаточно быстрым, чтобы не было заметного отставания. Как отметил ДрЛуи в комментариях, это решение, вероятно, не очень хорошо масштабируется, если вам нужно смотреть много материалов. Вы всегда можете настроить 2-й параметр на setInterval()
, чтобы проверить более или менее часто.
myTextBox.value = 'foo';
этой ситуации нет событий JavaScript.
Вот несколько другое решение, если вы не представили ни одного из других ответов:
var field_selectors = ["#a", "#b"];
setInterval(function() {
$.each(field_selectors, function() {
var input = $(this);
var old = input.attr("data-old-value");
var current = input.val();
if (old !== current) {
if (typeof old != 'undefined') {
... your code ...
}
input.attr("data-old-value", current);
}
}
}, 500);
Считайте, что вы не можете полагаться на клик и клавиатуру для захвата вставки контекстного меню.
$("input[id^=Units_]").each(function() {
Добавьте этот код где-нибудь, это сделает трюк.
var originalVal = $.fn.val;
$.fn.val = function(){
var result =originalVal.apply(this,arguments);
if(arguments.length>0)
$(this).change(); // OR with custom event $(this).trigger('value-changed');
return result;
};
Нашел это решение в val() не вызывает change() в jQuery
Я создал образец. Пусть это сработает для вас.
var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;
var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
clearTimeout(typingTimer);
if ($('#tyingBox').val) {
typingTimer = setTimeout(function () {
$("p.content").html('Typing...');
}, doneTypingInterval);
}
});
$('#tyingBox').keyup(function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(function () {
$("p.content").html(oldData);
}, finaldoneTypingInterval);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>
На самом деле нам не нужно настраивать циклы для обнаружения изменений javaScript. Мы уже настраиваем множество прослушивателей событий для элемента, который мы хотим обнаружить. просто запуск любого нежелательного события сделает работу.
$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});
$("input[name='test-element']").val("test").trigger("blur");
и ofc это доступно только в том случае, если у вас есть полный контроль над изменениями javascript в вашем проекте.
Здесь рабочий пример, который я использую для реализации вариации автозаполнения, заполняет селектор (список) jqueryui, но я не хочу, чтобы он функционировал точно так же, как автозаполнение jqueryui, которое выдает раскрывающееся меню.
$("#tagFilter").on("change keyup paste", function() {
var filterText = $("#tagFilter").val();
$("#tags").empty();
$.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
function(data) {
var i;
for (i = 0; i < data.length; i++) {
var tag = data[i].value;
$("#tags").append("<li class=\"tag\">" + tag + "</li>");
}
});
});
Хорошо, лучший способ состоит в том, чтобы покрыть те три базы, которые вы указали сами. Простой: onblur,: onkeyup и т.д. Не будут работать для того, что вы хотите, поэтому просто соедините их.
KeyUp должен охватывать первые два, и если Javascript изменяет поле ввода, я уверен, надеюсь, что это ваш собственный javascript, поэтому просто добавьте обратный вызов в функцию, которая его модифицирует.
Не можете ли вы использовать элемент <span contenteditable="true" spellcheck="false">
вместо <input type="text">
?
<span>
(с contenteditable="true" spellcheck="false"
в качестве атрибутов) выделяется <input>
главным образом потому, что:
<input>
.value
, но текст отображается как innerText
и составляет часть его внутреннего тела.<input>
нет, хотя вы устанавливаете атрибут multiline="true"
.Чтобы выполнить внешний вид, вы можете, конечно, стилизовать его в CSS, а записывая значение innerText
, вы можете получить для него событие:
Здесь fiddle.
К сожалению, есть что-то, что на самом деле не работает в IE и Edge, которые я не могу найти.
вы можете увидеть этот пример и выбрать, какие события вас интересуют:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>evetns</title>
</head>
<body>
<form>
<input class="controlevents" id="i1" type="text" /><br />
<input class="controlevents" id="i2" type="text" /><br />
<input class="controlevents" id="i3" type="text" /><br />
<input class="controlevents" id="i4" type="text" /><br />
<input class="controlevents" id="i5" type="text" /><br />
</form>
<div id="datatext"></div>
</body>
</html>
<script>
$(function(){
function testingevent(ev){
if (ev.currentTarget.tagName=="INPUT")
$("#datatext").append("<div>id : " + ev.currentTarget.id + ", tag: " + ev.currentTarget.tagName + ", type: "+ ev.type +"</div>");
}
var eventlist = ["resizeend","rowenter","dragleave","beforepaste","dragover","beforecopy","page","beforeactivate","beforeeditfocus","controlselect","blur",
"beforedeactivate","keydown","dragstart","scroll","propertychange","dragenter","rowsinserted","mouseup","contextmenu","beforeupdate",
"readystatechange","mouseenter","resize","copy","selectstart","move","dragend","rowexit","activate","focus","focusin","mouseover","cut",
"mousemove","focusout","filterchange","drop","blclick","rowsdelete","keypress","losecapture","deactivate","datasetchanged","dataavailable",
"afterupdate","mousewheel","keyup","movestart","mouseout","moveend","cellchange","layoutcomplete","help","errorupdate","mousedown","paste",
"mouseleave","click","drag","resizestart","datasetcomplete","beforecut","change","error","abort","load","select"];
var inputs = $(".controlevents");
$.each(eventlist, function(i, el){
inputs.bind(el, testingevent);
});
});
</script>
Возможно, я опаздываю на вечеринку, но не могу ли вы просто использовать событие .change(), которое предоставляет jQuery.
Вы должны иметь возможность сделать что-то вроде...
$(#CONTROLID).change(function(){
do your stuff here ...
});
Вы всегда можете привязать его к списку элементов управления с чем-то вроде...
var flds = $("input, textarea", window.document);
flds.live('change keyup', function() {
do your code here ...
});
Связывание в реальном времени гарантирует, что все элементы, которые существуют на странице сейчас и в будущем, обрабатываются.
Это самый быстрый & чистый способ сделать это:
Я использую JQuery →
$('selector').on('change', function () {
console.log(this.id+": "+ this.value);
});
Он работает отлично для меня.