1. 程式人生 > >js模擬Ctrl+C複製、Ctrl+V貼上功能之tabindex、focus、keyCode

js模擬Ctrl+C複製、Ctrl+V貼上功能之tabindex、focus、keyCode

話不多說,今天遇到了一個大坑,是這樣的,一顆DOM樹中有一個節點,要對其實現Ctrl+C複製、Ctrl+V貼上功能。起初拿到這個任務,我首先想到的是選中它,然後按下Ctrl、C實現複製,再按下Ctrl、V實現貼上功能。嗯,大體流程就是這樣。
問題來了,選中它,也就是說這個節點處於焦點狀態,按下Ctrl+C實現複製功能,不急,這步走通了,下一步貼上就好辦多了。
節點處於焦點狀態,之前用得最多的恐怕就是input元素了吧,在input上用得一帆風順,可今天的這個節點並不是input,而是一個div,按照input的思路,往下寫了幾行程式碼,經斷點測試,發現怎麼也進不了節點處於焦點狀態下的方法函式fun,程式碼如下:

$("div").on("focus",function(){
    $(this).on("keydown",function(event){
        if(event.ctrlKey == true){
            alert("你使用了Ctrl功能!");
            if(event.keyCode == 67){
                alert("你使用了Ctrl+C組合件功能!");
            }
        }
    })

無奈之餘,上網搜了些資料,發現出現這個問題的原因在於,預設狀態下,想要對普通節點監聽獲得焦點功能是無效的,只有input才能監聽焦點事件。具體解決方案如下:
在對普通節點(input節點除外)欲對其監聽焦點事件之前,必須做一件事,那就是對其設定tabindex值,如:
$(“div”).attr(“tabindex”,”0”);
tabindex屬性:用於設定元素在控制元件中的焦點順序;
-1:(預設值,input節點除外)表示當前元素不能獲得焦點
0:表示當前節點的焦點根據在程式碼中的位置順序被選擇
大於0:根據遞增的值順序和程式碼中的位置順序來被選擇

於是乎,問題得以解決!完整程式碼如下:

$("div").attr("tabindex","0");
$("div").on("focus",function(){
    $(this).on("keydown",function(event){
        if(event.ctrlKey == true){
            alert("你使用了Ctrl功能!");
            if(event.keyCode == 67){
                alert("你使用了Ctrl+C組合件功能!");
            }
        }
    })
})

這樣就真的OK了嗎!no。。。雖然功能成形了,正當喜出望外的時候問題來了,我首次ctrl+C、Ctrl+V某個元素的時候沒問題,可當我再次Ctrl+V或Ctrl+C、Ctrl+V某個元素的時候蹭蹭地冒出來一大堆,我明明就按了一下ctrl+V,怎麼就憑空跳出那麼多來了呢,頭都大了,涉及到的JS檔案也比較多,打了好多斷點,於事無補,旁邊的同事也一起來搞了好半天,沒搞定,不經意間他跑去Ctrl+C功能判斷裡面alert了一下,又在Ctrl+V判斷裡面去alert了一下,我發現他們兩個alert的次數是一樣的!而整個js檔案只執行了一次!為啥呢。。。我也不知道是怎麼想到那個點子上去的,或許是感覺,我說要不Ctrl+C功能判斷(true)完成後,將 event.keyCode = 0 ;試試!
一語中的,還還真就可以了,每次Ctrl+V都只貼上一次!於是乎!任務終於完成!完整程式碼如下:

var isCopy = false; //判斷是否能執行'複製貼上(新增)節點到dom'功能的判斷條件,初始為false(不允許 )
$("div").attr("tabindex","0");
$("div").on("focus",function(){
    $(this).on("keydown",function(event){
        if(event.ctrlKey){
            if(event.keyCode == 67){
                alert("你使用了Ctrl+C組合件功能!");
                event.keyCode = 0;
            }
            if(event.keyCode == 86){
                if(isCopy){ 
                    var max = $(this).size()+1;
                    var addId = "HKFlow_cnode_"+max;
                    var type = $(this).find("b").attr("class").split("_")[1];

                    HKPM.addNode(addId,{name: "cnode_"+max, left: 38, top: 28, type: type});//呼叫增加節點方法函式,預設貼上到畫布左上角  

                }               
            }
        }
    })
})