触发对程序化更改为输入值的操作

Chr*_*phe 29 javascript html-input defineproperty

我的目标是观察输入值并在其值以编程方式更改时触发处理程序.我只需要它用于现代浏览器.

我尝试了很多组合使用defineProperty,这是我最新的迭代:

var myInput=document.getElementById("myInput");
Object.defineProperty(myInput,"value",{
    get:function(){
        return this.getAttribute("value");
    },
    set:function(val){
        console.log("set");
        // handle value change here
        this.setAttribute("value",val);
    }
});
myInput.value="new value"; // should trigger console.log and handler
Run Code Online (Sandbox Code Playgroud)

这似乎做了我的预期,但感觉就像一个黑客,因为我重写现有的价值属性和玩value(属性和属性)的双重身份.它还打破了change似乎不喜欢修改属性的事件.

我的其他尝试:

  • 一个setTimeout/setInterval循环,但这也不干净
  • 各种watch和observepolyfill,但它们打破输入值属性

什么是获得相同结果的正确方法?

现场演示:http://jsfiddle.net/L7Emx/4/

[编辑]澄清一下:我的代码正在观看一个输入元素,其他应用程序可以推送更新(例如,由于ajax调用,或者由于其他字段的更改).我无法控制其他应用程序如何推送更新,我只是一个观察者.

[编辑2]为了澄清"现代浏览器"的含义,我对能够在IE 11和Chrome 30上运行的解决方案感到非常满意.

[更新]根据接受的答案更新了演示:http://jsfiddle.net/L7Emx/10/

@ mohit-jain建议的技巧是为用户交互添加第二个输入.

Moh*_*hit 17

如果解决方案的唯一问题是在值集上打破更改事件.你可以在集合上手动触发该事件.(但是如果用户通过浏览器对输入进行更改,则不会监视此设置 - 请参阅下面的编辑)

<html>
  <body>
    <input type='hidden' id='myInput' />
    <input type='text' id='myInputVisible' />
    <input type='button' value='Test' onclick='return testSet();'/>
    <script>
      //hidden input which your API will be changing
      var myInput=document.getElementById("myInput");
      //visible input for the users
      var myInputVisible=document.getElementById("myInputVisible");
      //property mutation for hidden input
      Object.defineProperty(myInput,"value",{
        get:function(){
          return this.getAttribute("value");
        },
        set:function(val){
          console.log("set");

          //update value of myInputVisible on myInput set
          myInputVisible.value = val;

          // handle value change here
          this.setAttribute("value",val);

          //fire the event
          if ("createEvent" in document) {  // Modern browsers
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent("change", true, false);
            myInput.dispatchEvent(evt);
          }
          else {  // IE 8 and below
            var evt = document.createEventObject();
            myInput.fireEvent("onchange", evt);
          }
        }
      });  

      //listen for visible input changes and update hidden
      myInputVisible.onchange = function(e){
        myInput.value = myInputVisible.value;
      };

      //this is whatever custom event handler you wish to use
      //it will catch both the programmatic changes (done on myInput directly)
      //and user's changes (done on myInputVisible)
      myInput.onchange = function(e){
        console.log(myInput.value);
      };

      //test method to demonstrate programmatic changes 
      function testSet(){
        myInput.value=Math.floor((Math.random()*100000)+1);
      }
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

更多关于手动触发事件


编辑:

手动事件触发和mutator方法的问题是当用户从浏览器更改字段值时,value属性不会更改.解决方法是使用两个字段.隐藏的一个我们可以与程序化交互.另一个是可见的,用户可以与之交互.在这种考虑方法之后很简单.

  1. 隐藏输入字段上的mutate value属性,以观察更改和触发手动onchange事件.设置值更改可见字段的值以提供用户反馈.
  2. on visible field value change更新观察者隐藏的值.