1. 程式人生 > >input事件在ie9以下不兼容問題完美解決

input事件在ie9以下不兼容問題完美解決

change != 失效 蛋疼 事件 失去焦點 htm ie瀏覽器 定義

上周四好不容易加了幾天班把剛接手的一個pc頁面做完,周五同事說要兼容ie7~ie9,結果在上面一跑,輸入都沒法輸入。

我的需求是用6個span作為虛擬的密碼輸入框,實際上是用一個藏在頁面裏的input來實現輸入的。如下圖

技術分享圖片

技術分享圖片

上面是我要實現的頁面,和頁面結構dom,就是點擊span的的父節點div的時候,要讓input獲取焦點。左邊是input,為了給大家展示就先不藏起來了,對了,千萬別用display:none來隱藏input,否則無法獲取焦點。

先來給大家復習一下input標簽的所有事件:

1. focus 當input 獲取到焦點時觸發

2. blur 當input失去焦點時

觸發,註意:這個事件觸發的前提是已經獲取了焦點再失去焦點的時候會觸發相應的js

3. change 當input失去焦點並且它的value值發生變化時觸發

4. keydown 在 input中有鍵按住的時候執行一些代碼

5. keyup 在input中有鍵擡起的時候觸發的事件,在此事件觸發之前一定觸發了onkeydown事件

6. click 主要是用於 input type=button,當被點擊時觸發此事件

7. select 當input裏的內容文本被選中後執行一段,只要選擇了就會觸發,不是非得全部選中

8. input 當input的value值發生變化時就會觸發,不用等到失去焦點(與onchange的區別)

開始我一直是用谷歌瀏覽器調試的,用的input事件,每次用戶的輸入和刪除都可以完美的監聽到,但一到ie8上,input事件就失效了,ie9以下版本根本不支持。

這時就需要用到ie專屬的onpropertychange事件

<input id="test" onpropertychange="alert(‘change‘);" type="text" />

經過調試後馬上就會發現,這個屬性是在元素的任何屬性變化時都會起作用,包括我們這裏所提到的value,但至少是起作用了,那接下來的任務就是篩選出property為value的變化。以下的attachEvent是ie的綁事件方法。

document.getElementById(‘test‘).attachEvent(‘onpropertychange‘,function(e) {
    if(e.propertyName!=‘value‘) return;
    /*
    
input值變化觸發回調方法
    ...
  */
});

但經過我測試,ie8上點backspace按鈕刪除的時候,不進事件啊,怎麽ie會有這麽多蛋疼的問題,查了很多資料都無法很好的解決這個問題,只能自己來用keydown事件實現了。

$(‘input‘).bind(‘keydown‘,function(e){
      if(e.keyCode==8||e.keyCode==46){ //處理回退與刪除    
     //每刪除input末位一個字符時的回調方法
  } 
}) 

但是keydown事件,每次進入,都是在value裏的最後一個字符未被刪除之前,比如我開始輸入了123,我按下刪除按鈕,斷點進了keydown事件,但此時獲取input的value還是123,這該如何是好。於是我先記錄刪除前的value,再在事件裏面獲取刪除後的value,如果刪除後的value長度比刪除前的小,就進我的回調方法。

var len=self.setpsd.value().length;  //獲取刪除前長度
this.setpsd.bind(‘keydown‘,function(e){
       if(e.keyCode==8||e.keyCode==46){
               var newlen=self.setpsd.value().length;  //獲取刪除後長度
               if(newlen<len){
                     //每刪除input末位一個字符時的回調方法
               }
       }
})                

處理完以上這些,又遇到個問題,就是在ie8中當我輸入過程中,點了下頁面其他地方,失去了焦點,再點到span上,重新獲取焦點,但此時光標不在我已輸入字符的後面,而跑到最前面去了,這樣我就死活刪除不了已輸入的內容了,因為用戶是無法操作那藏起來的input的。

要操作光標的位置我們都有耳聞,textRange對象,沒錯,你答對了一半。因為textRange是IE私有對象

那麽我們怎麽獲取textRange對象呢?查看IE的DHTML文檔。

技術分享圖片

從文檔中我們得到了creatTextRange方法可以創建textRange對象。

技術分享圖片

通過文檔api的篩選,我們看到,紅框中的幾個方法對我們有用。這裏,我提一下select方法,select方法文檔上的翻譯是“將當前選中區置為當前對象”。這句話怎麽理解呢?

這句話是說,我們通過createTextRange方法創建了textRange對象,註意是創建,也就是說原本不存在這個對象。然後我們使用這個對象的collapse或者move,moveStart方法的時候,操作的都是textRange對象,而最後的狀態表現是在input對象上的,select方法的作用就是,把textRange對象上的操作影印到input對象上的文本區域中。

明白了select方法,我們看collapse方法:將插入點移動到當前範圍的開始或者結束。

技術分享圖片

有點英語水平的,上面的介紹應該能看懂,就是說我們要想讓光標移動到末尾話應該傳入false,

那麽使用collapse的方法代碼應該是(我們定義是在itext上的onfocus事件)

document.getElementById("psd").onfocus=focushandler;
    function focushandler(){
        if(this.createTextRange){
            var rg=this.createTextRange();
            rg.collapse(false);
            rg.select();
        }
    }

就這麽幾句,完美解決我的問題,不需要用到什麽move、moveStart、moveEnd方法。更詳細的請看http://webfront-js.com/articaldetail/29.html

對了,最後介紹下如果判斷是ie瀏覽器,最簡單的方法就是

if(!!document.all){
    //ie瀏覽器處理
}

在 IE 中 document.all 的布爾值是 true ,其他瀏覽器都是 false。

input事件在ie9以下不兼容問題完美解決