JS事件:钩取文本输入值改变事件

31
我有一个文本输入框,其内容被脚本而非用户更改。因此,我希望在值更改时触发事件。我找不到适合的事件。 我甚至在StackOverflow上找到了相应的问题,但那不是我要寻找的解决方案。
如何使用jQuery和文本输入框使这个实现:
myTextControl.value = someValue

我想触发一个事件来查看新值。


注意:我无法访问更改控件的部分,因此无法手动触发更改事件。 - Esteban Feldman
@Esteban Feldman:你说的话有矛盾之处。首先,"我想在这里触发一个事件来查看新值",但是接着就说"我无法手动触发更改事件"。这到底是哪一个? - Crescent Fresh
你找到解决方案了吗?请回答你的问题。 - noitseuq
很好的问题...我也遇到了编程上处理动态更改输入值的问题:( - Chris Allinson
6个回答

19

我找不到合适的事件。

是的,确实没有这样的事件。

虽然有DOM变动事件,但它们跨浏览器支持不好,而且表单值的更改也无法触发这些事件,因为表单值并未反映在属性中(除了IE以外,由于一个错误,它可以反映在属性中)。

只有在Mozilla中,可以通过javascript的watch来捕捉脚本更改。在IE中,可以设置JScript的onpropertychange处理程序来捕捉脚本更改和用户驱动的更改。在其他浏览器中,您必须使用自己的间隔轮询程序来查找更改。

function watchProperty(obj, name, handler) {
    if ('watch' in obj) {
        obj.watch(name, handler);
    } else if ('onpropertychange' in obj) {
        name= name.toLowerCase();
        obj.onpropertychange= function() {
            if (window.event.propertyName.toLowerCase()===name)
                handler.call(obj);
        };
    } else {
        var o= obj[name];
        setInterval(function() {
            var n= obj[name];
            if (o!==n) {
                o= n;
                handler.call(obj);
            }
        }, 200);
    }
}

watchProperty(document.getElementById('myinput'), 'value', function() {
    alert('changed!');
});

这非常不令人满意。它不会响应Mozilla中用户驱动的更改,IE中每个对象只允许一个观察属性,并且在其他浏览器中,处理函数将在执行流程中被调用得更晚。

几乎肯定更好的做法是重写脚本中设置value的部分,改为调用setValue包装函数,您可以监视您想要捕获的更改。


1
IE可以通过obj.attachEvent('onpropertychange', ...)处理多个处理程序,而在FF2+(包括FF2,在其中虽然文档记录为在DOM节点上不起作用,但我可以验证它的工作),Opera 9.5,Safari 3和Chrome 1中可以使用__defineSetter__('value', ...)来实现类似的效果。与IE的实现唯一的分歧是IE不仅在编程设置时而且在键事件期间也触发处理程序。 - Crescent Fresh
我写了这个小片段来基于轮询检测表单/输入更改:https://gist.github.com/Nemesarial/841b0aca7af762e459d63b77f93d63e1 - Nemesarial

6
您可以像这样为输入字段添加普通事件监听器(使用jQuery)。
$(myTextControl).change(function() {
    ...
    /* do appropriate event handling here */
    ...
});

好的,考虑到改变输入值的javascript不是由您控制的,这会让事情变得困难。您有两个选择:

1.) 跨浏览器兼容:使用一个函数来轮询输入值,并持续检查值是否发生了变化(类似于以下方式)。

//at beginning before other scripts changes the value create a global variable
var oldValue = myTextControl.value;

function checkIfValueChanged() {
    if(myTextControl.value != oldValue) {
        $(myTextControl).trigger("change");
        clearInterval(checker);
    }
}

//every 500ms check if value changed
var checker = setInterval('checkIfValueChanged()', 500);

注意: 如果您的脚本或用户可以更改值,则必须实现某些内容以捕获此,以便不会多次触发更改事件。

如果外部脚本可以多次更改值,请让间隔函数继续运行而不是取消它,并只更新oldValue;

2.) 据我所知,尚未被所有浏览器支持(?在您需要支持的浏览器上进行测试)

您可以绑定到特殊的DOM Level 3事件:DOMAttrModified(在Firefox中,可能也有其他浏览器,我认为Opera也有,Safari??,Chrome??),而在IE中,它当然有一个不同的名称propertychange(且是专有的,与W3C行为不同)

现在理想情况下,您可以结合这两个选项,检查是否支持DOMAttrModifiedpropertychange,并相应地使用或回退到轮询解决方案。


阅读链接

W3C DOM变异事件

W3C DOMAttrModified事件

MSDN DHTML propertychange事件

更新的jQuery CSS属性监视插件

最后一个链接是一些人基本上已经制作了一个jQuery插件,该插件执行我描述的操作(未经过我的测试,仅作为参考提供)


我无法访问控件变化的部分,因此无法手动触发该事件。这就是为什么我希望在值更改时触发事件。 - Esteban Feldman

-1

使用Jquery

您还可以将这些事件监听器应用于输入字段,例如

$("yourid").on("change",function(){
//here do something
});
$("yourid").on("keypress",function(){
//here do something
});

$("yourid").on("keydown",function(){
//here do something
});

$("yourid").on("keyup",function(){
//here do something
});

-2

试一下这个

$('#myTextControl').bind('input', function(){
  console.log('value changed');
});

只有在我自己更改值时才有效,但当输入由datetimepicker填充时它不起作用。我该如何检测到这一点? - Pathros

-6
var oldVal = $('#myTextControl').val();

//Your script that changes the value

if(oldVal != $('#myTextControl').val())
{
//Your content has changed, do something
}

1
我需要一个事件,以便我知道它什么时候发生了变化,并且可以对其进行操作。在您的示例中存在显式流程,但不是我的情况...该值可能会在 AJAX 调用或其他方式中更改,我无法对其进行挂钩,因此我需要触发一个事件。或者使用.decorator 对 .value 进行修饰? - Esteban Feldman

-10

当你所观察的元素获得焦点时,你需要监听键盘事件。


2
正如问题所暗示的那样,它不是由用户交互而改变的,那么你的答案有什么有效性呢? """我有一个文本输入框,其内容是通过脚本而非用户更改的。""" - Esteban Feldman

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