JavaScript事件:获取<input>控件值的更改通知

8
我有以下问题:
我有一个HTML文本框(<input type="text">),其内容由我无法接触的脚本修改(这是我的页面,但我正在使用外部组件)。
我希望在我的脚本中每次文本框的值发生更改时得到通知,以便我可以做出反应。
我已经尝试过这个:
txtStartDate.observe('change', function() { alert('change' +  txtStartDate.value) });

这段代码(可以预测地)不起作用。只有在我自己使用键盘更改文本框的值并将焦点移动到其他位置时,它才会被执行,但如果脚本更改了该值,则不会被执行。

是否有其他事件可以监听,我不知道吗?



我正在使用Prototype库,并且如果相关,修改文本框值的外部组件是Basic Date Picker(www.basicdatepicker.com)。

6个回答

5

addEventListener("DOMControlValueChanged"会在控件的值更改时触发,即使是通过脚本更改。

addEventListener("input"是DOMControlValueChanged的直接用户启动的过滤版本。

不幸的是,目前只有Opera支持DOMControlValueChanged,而webkit中的input事件支持存在问题。Firefox和Opera中的input事件也存在各种错误。

这些问题很快就会在HTML5中得到解决。

更新:

截至2012年9月8日,Opera已经取消了对DOMControlValueChanged的支持(因为它已经从HTML5中删除),浏览器中的“input”事件支持也更加完善(包括较少的错误)。


5

就像你所暗示的那样,改变(和其他事件)只有在用户采取某些操作时才会触发。修改内容的脚本不会触发任何事件。你唯一的解决方案是找到一些接口可以连接到你的监听器。

以下是我的解决方案:

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

这是基于使用Firebug的粗略查看(我不熟悉该组件)得出的结论。如果有其他选择日期的方法,那么您也需要包装这些方法。


1
有没有办法在jQuery中做同样的事情? - Esteban Feldman

2

IE有一个onpropertychange事件可用于此目的。

对于真正的Web浏览器(;)),有一个DOMAttrModified变异事件,但在Firefox中进行了几分钟的实验后,我无法使它在文本输入时触发值被程序化地更改(或通过常规键盘输入更改),但如果我程序化地更改输入的名称,则会触发。越来越奇怪......

如果您无法可靠地使其正常工作,您始终可以定期轮询输入的值:

var value = someInput.value;

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

1
表单元素的 value 属性与其属性 value="..." 的值是不同的,后者仅仅指定了初始值。通过脚本或用户操作设置值并不会更新 value 属性(),因此也不会触发 DOMAttrModified 事件。(: 除了 IE 存在一个 bug,但是 IE 不支持 DOMAttrModified 事件。) - bobince

1

根据外部JavaScript的编写方式,您可以在自己的脚本中重新编写相关部分,并覆盖外部定义,以触发更改事件。

我曾经不得不处理那些我无法控制的脚本。

您只需要找到外部函数,将其完整复制为一个具有相同名称的新函数,并重新编写脚本以实现您想要的功能。

当然,如果脚本使用闭包正确编写,则不太容易更改...


我考虑过这个问题。我的问题是它是一个很大的压缩脚本。找到正确的更改位置可能需要几个小时。我正在寻找一种快速的方法来钩入它。如果需要2个小时,那么我尝试做的小功能就不值得这样的努力了 :-) - Daniel Magliola

0

除了像 Noah 解释的那样解决问题,你也可以创建一个定时器,每隔几百毫秒检查一次值。


0

我曾经按照Dan的建议修改过YUI datable paginator控件。这种方法很暴力,但它解决了我的问题。也就是说,找到写入字段的方法,复制其代码并添加一个触发更改事件的语句,在您的代码中只需处理该更改事件即可。您只需要使用新版本覆盖原始函数即可。轮询虽然工作正常,但在我看来是一种更耗费资源的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接