onvaluechange事件


這不是一個真實的瀏覽器事件,不過的確曾經存在這樣一個事件滿足我們的需求。

很多時候,我們需要對文本域的值進行變化檢測,不論是這變化是用戶通過鍵盤敲打引發的,或是通過el.setAttribute("value","aaa")引發的,還是el.value = "bbb"引發的,還是用戶通過復制粘貼引發的,更惡心的是HTML通過語音輸入引發的。只要里面的文字發生變化,我們希望都能比較及時調用相應的程序進行處理。

在舊式IE(IE6-8)下,onpropertychange可以滿足上述所有需求(由於IE不支持input[speed]),因此不用考慮最后一種輸入)。

IE9開始區分attribute和property了,從許多場合來是好事,但在這場合則是壞事,它相當於DOM3變動事件中的DOMAttrModified。只對用戶輸入與setAttribute見效,不支持直接賦值方式的檢測。

標准瀏覽器也提供了一個input,但它也不支持直接賦值方式的檢測。即便最新式的mutationObserver API,對el.value ="zzz"這種屬性賦值法也無濟於事。因此自己動手富衣足食。

取一個文本域的值最簡單不過,對兩個字符串進行比較也最簡單不過。我們要做的是得到先后兩個值。因此需要用最通用的事件進行冒允。當我們在PC上輸入內容,肯定會觸發mousedown事件,也肯定觸發mousedown。進行輸入時確定會觸發鍵盤事件,根據我的知識庫,keypress會對一些系統鍵失靈,因此最好用keyup,keydown。但用戶不一定通過鍵盤輸入,HTML5還提供了語音輸入,只要點了那個麥風筒圖案就可以口述了,麥風筒也在input上,因此mousedown肯定也有。當我們輸入后肯定會繼續其他表單元素的填寫或進行提交,因此會觸發blur事件。從mousedown到blur這段時間,我們可以通過定時器加keydown, keyup, webkitspeechchange的回調進行值變化判定,變化了就執行用戶回調,把前后兩個值放到事件對象中。

下面是mass Framework的實現:

define("valuechange", ["$event"], function(){
    var DATA = "valuechangeData";
    var ID  = "valuechangeID"
    var interval = 50;
    //如果值前后發生改變,觸發綁定回調
    function testChange(elem, type, poll) {
        if(poll){
            $._data(elem, ID, setTimeout(function(){
                testChange(elem, type, poll);
            },interval));
        }
        var old = $._data(elem, DATA);
        var neo = elem.value;
        if(old !== neo){
            $._data(elem, DATA, neo);
            var event = new $.Event("valuechange")
            event.oldType = type
            event.oldValue = old;
            event.newValue = neo;
            $.event.fire.call(elem, event)
        }
    }
    function unTestChange(elem){
        var id = $._removeData(elem, ID)
        clearTimeout( id )
        $.log($._removeData)
        $._removeData(elem, DATA);
    }
   
    function startTest(event) {
        var elem = event.target;
        if (event.type == 'focus' ) {
            $._data(elem, DATA , elem.value);
        }
        testChange(elem,event.type, true);
    }
    function stopTest(event){
        unTestChange(event.target)
    }
    
    function listen(elem) {
        unlisten(elem);
        "keydown keyup mousedown focus".replace($.rword, function(name){
            $(elem).bind(name+"._valuechange", startTest)
        })
        $(elem).bind('blur._valuechange', stopTest);
        //http://liumiao.me/html/wd/W3C/264.html
        $(elem).bind('webkitspeechchange._valuechange', function(e){
            testChange(e.target,e.type)
        });
    }
    function unlisten(elem){
        unTestChange(elem)
        $(elem).unbind("._valuechange")
    }
    $.fn.valuechange = function(callback){
         return callback?  this.bind( "valuechange", callback ) : this.fire( "valuechange" );
    }
    $.eventAdapter.valuechange = {
        setup: function(desc){
            var elem = desc.currentTarget, nodeName = elem.tagName;
            if (nodeName == 'INPUT' || nodeName == 'TEXTAREA') {
                listen(elem);
                return false
            }
        },
        tearDown: function (desc) {
            unlisten(desc.currentTarge);
            return false
        }
    }
})

它的事件系統的架構與jQuery的很相近,都是通過setup, teardown方法來綁定特殊的事件。我們只對INPUT元素及文本區進行操作,一定進入分支,就調用listen監聽函數。接下來綁定的事件的作用依次是:

  • mousedown:監聽粘貼。
  • keyup,keydown:監聽鍵盤輸入。
  • focus:監聽一切引發聚焦的事件,比如在觸摸屏下。
  • webkitspeechchange:監聽語音輸入。
  • blur:清理定時器,比如雖然已經放在文本域中啊,但長期沒有動,那么只有等keyup再次觸發新的定時器了。

具體例子可見這里

有了這個onvaluechange事件,以后做表單驗證或自動完成及MVVM的輸入雙向綁定就輕松多了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM