由chrome剪貼簿問題研究到了js模擬滑鼠鍵盤事件

靜逸發表於2015-05-24

寫在前面

最近公司在搞瀏覽器相容的事情,所有瀏覽器相容的問題不得不一個人包了。下面來說一下今天遇到的一個問題吧

大家都知道IE下面如果要獲得剪貼簿裡面的資訊的話,程式碼應該如下所示

 window.clipboardData.getData("Text")

可是在chrome下面就行不通了,chrome下面沒有類似ie的這種方法,那應該怎麼辦呢,百度了一下,發現還真有辦法。

只要在HTML介面上放上一個text型別的控制元件,如下所示

 <textarea id="textArea" ></textarea>

然後js程式碼這樣寫就可以了,不過要在body上繫結keydown事件,寫上

<body onkeydown="return cellkeydown(event)">

 

        function cellkeydown(event) {
            if (event.ctrlKey && event.keyCode == 86) {
                var ss = document.getElementById("textArea");
                ss.focus();
                ss.select();
                // 等50毫秒,keyPress事件發生了再去處理資料
                setTimeout("dealwithData()", 50);
            }
        }
        function dealwithData(event) {
            var ss = document.getElementById("textArea");
            alert(ss.value);
            ss.blur();

        }

把程式碼這樣一寫就發現在任何其它應用程式複製的資訊,在當前執行的介面上只要按ctrl+v就可以把剪貼簿裡面的資訊獲得。

哈哈,以為大功告成,卻發現事件遠沒那麼簡單!

事件沒完沒了了

原來在原先的介面上,只有一個“貼上”按鈕,跟測試那邊溝通,沒法聊下去,不能按ctrl+v來獲得剪貼簿裡面的資訊,必須按按鈕,不能改變使用者之前的行為。好吧,既然這樣,只能想想用js模擬鍵盤事件啦。

找了好多一堆資料,總結了如下規則。

Dom 事件模擬可以通過document上的createEvent()方法,有如下一些事件

UIEvents:通用的UI 事件,滑鼠事件鍵盤事件都是繼承自UI事件,在DOM 3 級上使用的是 UIEvent。
MouseEvents:通用的滑鼠事件,在DOM 3 級上使用的是 MouseEvent。
MutationEvents:通用的突變事件,在DOM 3 級上使用的是 MutationEvent。
HTMLEvents:通用的HTML事件,在DOM3級上還沒有等效的。

鍵盤事件initKeyBoadEvent()方法初始化,初始化鍵盤事件的引數有以下幾個:

type (string) - 要觸發的事件型別,例如“keydown”.
bubbles (Boolean) — 代表事件是否應該冒泡. 
cancelable (Boolean) — 代表事件是否可以被取消. 
view (AbstractView) — 被授予事件的是圖. 通常值為:document.defaultView.
key (string) — 按下的鍵對應的code.
location (integer) — 按下鍵所在的位置. 0 :預設鍵盤, 1 左側位置, 2 右側位置, 3 數字鍵盤區, 4 虛擬鍵盤區, or 5 遊戲手柄.
modifiers (string) — 一個有空格分開的修飾符列表.
repeat (integer) — 一行中某個鍵被按下的次數.

在FF下,允許你通過使用document.createEvent('KeyEvents'),這種方式來建立鍵盤事件,初始化的方法為initKeyEvent(),這個方法接受10個引數,
type (string) — 要觸發的事件型別,例如“keydown”.
bubbles (Boolean) — 代表事件是否應該冒泡.
cancelable (Boolean) — 代表事件是否可以被取消. 
view (AbstractView) — 被授予事件的是圖. 通常值為:document.defaultView.
ctrlKey (Boolean) — 代表ctrol鍵是否按下. 預設 false.
altKey (Boolean) — 代表alt鍵是否按下. 預設 false.
shiftKey (Boolean) — 代表shift鍵是否按下. 預設 false.
metaKey (Boolean) — 代表meta鍵是否按下. 預設 false.
keyCode (integer) — 鍵按下或釋放時鍵所對應的鍵碼. 預設是0;
charCode (integer) — 按下的鍵的字元所對應的ASCII code.是共keypress事件使用的 預設是0.

具體API詳細資訊可以參考淺談Javascript事件模擬

琢磨了好久終於找到解決方案(可是還有瑕疵)

具體解決方案還參考瞭如下網頁鍵盤按鍵事件的fireEvent

先把程式碼貼上,終於解決了js模擬事件了,也觸發了ctrl+v,卻發現獲得的剪貼簿裡面的資料是空。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>fireKeyEvent</title>

</head>

<body onkeydown="return cellkeydown(event)" id="mytest">
    <!--這裡設定textarea不能為display為none  否則就貼上不了資訊-->
    <textarea id="textArea" style="width:0px;height:0px; overflow:hidden;margin:0px;padding:0px;"></textarea>
    <input type="button" id="btn1" value="fire" /><!--按鈕在這模擬ctrl+v事件-->

    <script type="text/javascript">
        /*
        *@desc keypress事件
        */
        function cellkeydown(event) {            
            if ((event.ctrlKey && event.keyCode == 86) ) {      //如果使用者按的是ctrl+v          
                var ss = document.getElementById("textArea");
                ss.focus();
                ss.select();
                // 等50毫秒,keyPress事件發生了再去處理資料
                setTimeout("dealwithData()", 50);
            }
        }
        /*
        *@desc 處理資料
        */
        function dealwithData(event) {
            var ss = document.getElementById("textArea");
            alert(ss.value);//這裡獲得的是剪貼簿裡面的資訊
            ss.blur();
        }

        function $(id) {
            return document.getElementById(id);
        }
        function addEvent(el, type, fn) {           

            if (document.addEventListener) {
                el.addEventListener(type, fn, true);
            } else if (document.attachEvent) {
                el.attachEvent("on" + type, fn);
            } else {
                el["on" + type] = fn;
            }
        }

        /*
        *@desc 觸發事件
        */
        function fireKeyEvent(el, evtType, keyCode) {
            var evtObj;
            if (document.createEvent) {
                if (window.KeyEvent) {//firefox 瀏覽器下模擬事件
                    evtObj = document.createEvent('KeyEvents');
                    evtObj.initKeyEvent(evtType, true, true, window, true, false, false, false, keyCode, 0);
                } else {//chrome 瀏覽器下模擬事件
                    evtObj = document.createEvent('UIEvents');
                    evtObj.initUIEvent(evtType, true, true, window, 1);

                    delete evtObj.keyCode;
                    if (typeof evtObj.keyCode === "undefined") {//為了模擬keycode
                        Object.defineProperty(evtObj, "keyCode", { value: keyCode });                       
                    } else {
                        evtObj.key = String.fromCharCode(keyCode);
                    }

                    if (typeof evtObj.ctrlKey === 'undefined') {//為了模擬ctrl鍵
                        Object.defineProperty(evtObj, "ctrlKey", { value: true });
                    } else {
                        evtObj.ctrlKey = true;
                    }
                }

                el.dispatchEvent(evtObj);

            } else if (document.createEventObject) {//IE 瀏覽器下模擬事件
                evtObj = document.createEventObject();
                evtObj.keyCode = keyCode
                el.fireEvent('on' + evtType, evtObj);
            }
        }
        /*
        *@desc 繫結按鍵觸發ctrl+v事件
        */
        addEvent($("btn1"), "click", function () {            
            fireKeyEvent($("mytest"), "keydown", 86);
        });

    </script>

</body>
</html>

 

最後的問題

搞了一下午,搗鼓出來怎樣用js模擬事件觸發,卻發現即使觸發了事件,可是卻不能如按ctrl+v一樣獲得剪貼簿裡面的資料了。

這究竟是怎麼一回事,不知道有哪位大神可以告訴我原因!

非常感謝哦!

相關文章