JS使用者介面事件(UI事件)

2020-07-16 10:05:12
使用者介面(User Interface,UI)事件負責響應使用者與頁面元素的互動。

焦點處理

焦點處理主要包括獲取焦點(focus)和失去焦點(blur)事件型別。所謂焦點,就是啟用表單欄位,使其可以相應鍵盤事件。

focus

當單擊或使用 Tab 鍵切換到某個表單元素或超連結物件時,會觸發該事件。focus 事件是確定頁面內滑鼠當前定位的一種方式。在預設情況下,整個文件處於焦點狀態,但是單擊或使用 Tab 鍵可以改變焦點的位置。

blur

blur 事件型別表示在元素失去焦點時響應,它與 focus 事件型別是相對的,主要作用於表單元素和超連結物件。

【範例1】在下面範例中為所有輸入表單元素系結了 focus 和 blur 事件處理常式,設定當元素獲取焦點時呈凸起顯示,失去焦點時則顯示為預設的凹陷效果。
<input type="text" />
<input type="text" />
<script>
    var o = document.getElementsByTagName("input");  //獲取表單元素集合
    for (var i = 0; i < o.length; i ++ ) {  //遍歷所有表單元素
        o[i].onfocus = function () {  //註冊focus事件處理常式
            this.style.borderStyle = "outset";
        }
        o[i].blur = function () {  //註冊focus事件處理常式
            this.style.borderStyle = "inset";
        }
    }
</script>
每個表單欄位都有兩個方法:focus() 和 blur(),其中 focus() 方法用於設定表單欄位為焦點。

【範例2】在下面範例中設計在頁面載入完畢後將焦點轉移到表單中的第 1 個文字方塊欄位中,讓其準備接收使用者輸入。
<form id="myform" method="post" action="#">
    姓名<input type="text" name="name" /><br />
    密碼<input type="password" name="pass" /><br />
</form>
<script>
    var form = document.getElementById("myform");
    var field = form.elements["name"];
    window.onload = function () {
        field.focus();
    }
</script>

如果是隱藏欄位(<input type="hidden">)或者使用 CSS 的 display 和 visibility 隱藏欄位顯示,設定其獲取焦點將引發異常。

blur() 方法的作用時從元素中移走焦點。在呼叫 blur() 方法時,並不會把焦點轉移到某個特定的元素上,僅僅時將焦點移走。早期開發中有使用者使用 blur() 方法代替 readonly 屬性,建立唯讀欄位。

選擇文字

當在文字方塊或文字區域內選擇文字時,將觸發 select 事件。通過該事件可以設計使用者選擇操作的互動行為。

在 IE 9+、Opera、Firefox、Chrome 和 Safari 中,只有使用者選擇了文字且釋放滑鼠,才會觸發 select 事件;但是在 IE8 及更早版本中,只要使用者選擇了一個字母,不必釋放滑鼠,就會觸發 select 事件。另外,在呼叫 select() 方法時也會觸發 select 事件。

【範例】在下面的範例中,當選擇第 1 個文字方塊中的文字時,則在第 2 個文字方塊中會動態顯示使用者所選擇的文字。
<input type="text" id="a" value="請隨意選擇字串" />
<input type="text" id="b" />
<script>
    var a = document.getElementsByTagName("input")[0];
    // 獲取第一個文字方塊的參照指標
    var b = document.getElementsByTagName("input")[1];
    // 獲取第二個文字方塊的參照指標
    a.onselect = function(){  // 為第一個文字方塊系結select事件處理常式
        if (document.selection){  // 相容IE
            o = document.selection.createRange(); // 建立一個選擇區域
            if(o.text.length > 0)  // 如果選擇區域記憶體在文字
            b.value = o.text;   // 則把該區域內的文字賦值給第二個文字方塊
        }else{  // 相容DOM
            p1 = a.selectionStart;  // 獲取文字方塊中選擇的初始位置
            p2 = a.selectionEnd;  // 獲取文字方塊中選擇的結束位置
            b.value = a.value.substring(p1, p2);
            // 擷取文字方塊中被選取的文字字串,然後賦值給第二個文字方塊
        }
    }
</script>

欄位值變化監測

change 事件型別時在表單元素的值發生變化時觸發,它主要用於 input、select 和 textarea 元素。對於 input 和 textarea 元素來說,當它們失去焦點且 value 值改變時觸發;對於 select 元素,在其選項改變時觸發,也就是不是去焦點,也會觸發 change 事件。

範例1

在下面範例中,當在第 1 個文字方塊中輸入或修改值時,則第 2 個文字方塊內會立即顯示第 1 個文字方塊中的當前值。
<input type="text" id="a" />
<input type="text" id="b" />
<script>
    var a = document.getElementsByTagName("input")[0];
    var b = document.getElementsByTagName("input")[1];
    a.onchange = function(){  // 為第一個文字方塊系結change事件處理常式
        b.value = this.value;   // 把第一個文字方塊中的值傳遞給第二個文字方塊
    }
</script>

範例2

下面範例演示了當在下拉選單框中選擇不同的網站時,會自動開啟該網站的首頁。
<select>
    <option value="http://www.baidu.com/">百度</option>
    <option value="http://www.google.cn/">Google</option>
</select>
<script>
    var a = document.getElementsByTagName("select")[0];
    a.onchange = function(){
       window.open(this.value,"");   // 根據下拉選單框的當前值開啟指定的網址
    }
</script>

範例3

在其他表單元素中也可以應用 change 事件型別。下面範例演示了如何在無線電鈕選項組中動態顯示變化的值。
<input type="radio" name="r" value="1"  checked="checked" /> 1
<input type="radio" name="r" value="2" /> 2
<input type="radio" name="r" value="3" /> 3
<script>
    var r = document.getElementsByTagName("input");
    for(var i = 0; i < r.length; i ++ ){
        r[i].onchange = function(){
            alert(this.value);
        }
    }
</script>
對於 input 元素來說,由於 change 事件型別僅在使用者已經離開了元素且失去焦點時觸發,所以當執行上面 3 個範例時會明顯感覺延遲響應現象。為了更好地提升使用者體驗,很多時候會根據需要定義在按鍵鬆開或滑鼠單擊時執行響應,這樣速度會快很多。

focus、blur 和 change 事件經常配合使用。一般可以使用 focus 和 blur 事件來以某種方式改變使用者介面,要麼是向使用者給出視覺提示,要麼是向介面中新增額外的功能。例如,為文字方塊顯示一個下拉選項選單。而 change 事件則經常用於驗證使用者在欄位中輸入的資料。

範例4

下面範例設計一個文字方塊,只允許使用者輸入數值。此時,可以利用 focus 事件修改文字方塊的背景顏色,以便更清楚的表明這個欄位獲得了焦點。可以利用 blur 事件恢復文字方塊的背景顏色,利用 change 事件在使用者輸入了非數位字元時再次修改背景顏色。
<form id="myform"  method="post" action="javascript:alert('表單提交啦!')">
    <p>
        <label for="comments">請輸入數位:</label>
        <br />
        <input type="text" id="txtNumbers" name="numbers" />
    </p>
    <p>
        <input type="submit" value="提交表單" id="submit-btn" />
    </p>
</form>
<script>
    var form = document.getElementById("myform");
    var numbers = form.elements["numbers"];
    numbers.onfocus = function(event){
    event = event || window.event;
    var target = event.target || event.srcElement;
    target.style.backgroundColor = "yellow";
    }
    numbers.onblur = function(event){  
        event = event || window.event;
        var target = event.target || event.srcElement;
        if (/[^d]/.test(target.value)){
            target.style.backgroundColor = "red";
        } else {
            target.style.backgroundColor = "";
        }
    }
    numbers.onchange = function(event){  
        event = event || window.event;
        var target = event.target || event.srcElement;
        if (/[^d]/.test(target.value)){
            target.style.backgroundColor = "red";
        } else {
            target.style.backgroundColor = "";
        }
    }
    numbers.focus();
</script>
在上面程式碼中,onfocus 事件處理程式將文字方塊的背景顏色修改為黃色,以清楚地表示當前欄位已經啟用。onblur 和 onchange 事件處理程式則會在發現非數值字元時,將文字方塊背景色修改為紅色。為了測試使用者輸入的是不是非數值,這裡針對文字方塊的 value 屬性使用了簡單的正規表示式。而且,為確保無論文字方塊的值如何變化,驗證規則始終如一,onblur 和 onchange 事件處理程式中使用了相同的正規表示式。

關於 blur 和 change 事件發生順序並沒有嚴格的規定,不同的瀏覽器沒有統一規定。因此,不能假定這兩個事件總會以某種順序一次觸發。

剪貼簿資料

HTML 5 規範了剪貼簿資料操作,主要包括以下 6 個剪貼簿事件:
  • beforecopy:在發生複製操作前觸發。
  • copy:在發生複製操作時發生。
  • beforecut:在發生剪下操作前觸發。
  • cut:在發生剪下操作時觸發。
  • beforepaset:在發生貼上操作前觸發。
  • paset:在發生貼上操作時觸發。

瀏覽器支援狀態:IE、Safari 2+、Chrome 和 Firefox 3+,Opera 不支援存取剪貼簿資料。

在 Safari、Chrome 和 Firefox 中,beforecopy、beforecut 和 beforepaste 事件只會顯示針對文字方塊的上下文選單的情況下觸發。IE 則會在觸發 copy、cut 和 paste 事件之前先行觸發這些事件。

至於 copy、cut 和 paste 事件,只要是在上下文選單中選擇了響應選項,或者使用了相應的鍵盤組合鍵,所有瀏覽器都會觸發它們。在實際的事件發生之前,通過 beforecopy、beforecut 和 beforepaste 事件可以在向剪貼簿傳送資料,或者從剪貼簿取得資料之前修改資料。

使用 clipboardData 物件可以存取剪貼簿中的資料。在 IE 中,可以任何狀態下使用 window.clipboardData 存取剪貼簿;在 Fiirefox 4+、Safari 和 Chrome 中,通過事件物件的 clipboardData 屬性存取剪貼簿,且只有在處理剪貼簿事件期間,clipboardData 物件才有效。

clipboardData 物件定義了兩個方法:
  • getData():從剪貼簿中讀取資料。包含 1 個 引數,設定取得的資料的格式。IE 提供兩種資料格式:“text”和“URL”;Firefox、Safari 和 Chrome 中定義引數為 MIME 型別,可以用“text”代表“text/plain”。
  • setData():設定剪貼簿資料。包含兩個引數,其中第 1 個引數設定資料型別,第 2 個引數是要放在剪貼簿中的文字。對於第 1 個引數,IE 支援“text”和“URL”,而 Safari 和 Chrome 仍然只支援 MIME 型別,但不再識別“text”型別。在成功將文字放到剪貼簿中後,都會返回 true;否則,返回 false。

範例1

可以使用下面兩個函數相容 IE 和非 IE 的剪貼簿資料操作。
var getClipboardText = function(event){
    var clipboardData =  (event.clipboardData || window.clipboardData);
    return clipboardData.getData("text");
}
var  setClipboardText = function(event, value){
    if (event.clipboardData){
        event.clipboardData.setData("text/plain", value);
    } else if (window.clipboardData){
        window.clipboardData.setData("text", value);
    }
}
在上面程式碼中,getClipboardText() 方法比較簡單,它只要存取 clipboardData 物件,然後以 text 型別呼叫 getData() 方法;setClipboardText() 方法相對複雜,它在取得 clipboardData 物件之後需要根據不同的瀏覽器實現為 setData() 傳入不同的型別。

範例2

下面範例利用剪貼簿事件,當使用者向文字方塊貼上文字時,先檢測剪貼簿中的資料是否都為數位,如果不是數位,取消預設的行為,則禁止貼上操作,這樣可以確保文字方塊只能接收數位字元。
<script>
    var form = document.getElementById("myform");
    var field1 = form.elements[0];
    var getClipboardText = function(event){
        var clipboardData =  (event.clipboardData || window.clipboardData);
        return clipboardData.getData("text");
    }
    var  setClipboardText = function(event, value){
        if (event.clipboardData){
            event.clipboardData.setData("text/plain", value);
        } else if (window.clipboardData){
            window.clipboardData.setData("text", value);
        }
    }
    var  addHandler = function(element, type, handler){
        if (element.addEventListener){
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    }
    addHandler(field1, "paste", function(event){
        event = event || window.event;
        var text =  getClipboardText(event);
        if (!/^d*$/.test(text)){
            if (event.preventDefault){
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
        }
    })
</script>