События Javascript: получение уведомлений об изменениях в управляющем значении <input>

У меня есть следующая проблема:

У меня есть текстовое поле HTML (<input type="text">), содержимое которого изменено с помощью script Я не могу трогать (это моя страница, но я использую внешние компоненты).

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

Я пробовал это:

txtStartDate.observe('change', function() { alert('change' +  txtStartDate.value) });

который (предсказуемо) не работает. Он запускается только в том случае, если я сам меняю значение текстового поля на клавиатуре, а затем перемещаю фокус в другом месте, но он не выполняется, если script изменяет значение.

Есть ли другое событие, которое я могу слушать, о котором я не знаю?



Я использую библиотеку Prototype, и в случае ее соответствия внешнему компоненту, изменяющему значение текстового поля, является Basic Date Picker (www.basicdatepicker.com)

Ответ 1

Как вы подразумевали, изменения (и другие события) срабатывают только тогда, когда пользователь предпринимает некоторые действия. Изменчивые вещи script не будут запускать какие-либо события. Ваше единственное решение - найти крючок в элементе управления, который вы можете подключить к слушателю.

Вот как я это сделаю:

basicDatePicker.selectDate = basicDatePicker.selectDate.wrap(function(orig,year,month,day,hide) {
  myListener(year,month,day);
  return orig(year,month,day,hide);
});

Это основано на беглом взгляде с Firebug (я не знаком с компонентом). Если есть другие способы выбора даты, вам также нужно будет обернуть эти методы.

Ответ 2

addEventListener ( " DOMControlValueChanged" будет срабатывать при изменении значения управления, даже если оно будет script.

addEventListener ( " input" - это фильтрованная версия DOMControlValueChanged, инициированная прямым пользователем.

К сожалению, DOMControlValueChanged поддерживается только Opera, а поддержка входных событий в webkit нарушена. Событие ввода также имеет различные ошибки в Firefox и Opera.

Этот материал, вероятно, будет скоро прояснен в HTML5, fwiw.

Update:

По состоянию на 9/8/2012 поддержка DOMControlValueChanged была удалена из Opera (поскольку она была удалена из HTML5), а поддержка событий ввода в браузерах (включая меньше ошибок) намного лучше.

Ответ 3

IE имеет onpropertychange событие, которое может быть использовано для этой цели.

Для реальных веб-браузеров (;)) существует событие DOMAttrModified мутации, но за пару минут стоит экспериментировать в Firefox, Я не смог заставить его запускать текстовый ввод, когда значение изменяется программно (или с помощью обычного ввода с клавиатуры), но оно срабатывает, если я буду изменять имя ввода программно. Любопытный и любопытный...

Если вы не можете надежно работать, вы всегда можете просто правильно опросить входное значение:

var value = someInput.value;

setInterval(function()
{
    if (someInput.value != value)
    {
        alert("Changed from " + value + " to " + someInput.value);
        value = someInput.value;
    }
}, 250);

Ответ 4

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

Мне приходилось делать это раньше со сценариями, которые были вне моего контроля.

Вам просто нужно найти внешнюю функцию, скопировать ее целиком как новую функцию с тем же именем и перезаписать script, чтобы сделать то, что вы хотите.

Конечно, если script был правильно написан с использованием закрытий, вы не сможете легко его изменить...

Ответ 5

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

Ответ 6

Мне нужно было модифицировать YUI datable paginator control один раз в соответствии с рекомендацией Дэна. Это грубая сила, но она работала в решении моей проблемы. То есть найдите метод, записывающий в поле, скопируйте его код и добавьте оператор, запускающий событие изменения, и в вашем коде просто обработайте это событие изменения. Вам просто нужно переопределить исходную функцию с помощью этой новой версии. Опрос, работая отлично, кажется мне гораздо более ресурсоемким решением.