国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

基于 jQuery 的鍵盤事件監(jiān)聽控件

付倫 / 642人閱讀

摘要:最近項(xiàng)目里要做一個畫板,需要對鍵盤事件進(jìn)行監(jiān)聽,來進(jìn)行諸如撤回重做移動縮放等快捷鍵操作,因此順手實(shí)現(xiàn)了一個鍵盤事件監(jiān)聽控件,略有收獲,整理出來,希望對大家有所幫助,更希望能獲得高手的指點(diǎn)。

最近項(xiàng)目里要做一個畫板,需要對鍵盤事件進(jìn)行監(jiān)聽,來進(jìn)行諸如撤回、重做、移動、縮放等快捷鍵操作,因此順手實(shí)現(xiàn)了一個鍵盤事件監(jiān)聽控件,略有收獲,整理出來,希望對大家有所幫助,更希望能獲得高手的指點(diǎn)。

1. 自動獲取焦點(diǎn)

似乎瀏覽器的鍵盤事件只能被那些可以獲得焦點(diǎn)的元素設(shè)置監(jiān)聽,而通常需要監(jiān)聽事件的

元素都不能獲得焦點(diǎn),因此需要修改目標(biāo)元素的某些屬性使其可以獲得焦點(diǎn),另外一種可行的方法是將事件委托給諸如 標(biāo)簽。這里采用的是第一類方法,當(dāng)然,可以修改的屬性也不止一種,例如,對于
標(biāo)簽可以將其 “editable” 屬性設(shè)為 true,而這里采用的是給其設(shè)一個 tabindex 值。代碼如下:

        $ele.attr("tabindex", 1);     

另外,焦點(diǎn)事件的觸發(fā)需要點(diǎn)擊元素或者 TAB 切換,而這并不符合人類的直覺,因此需要監(jiān)聽鼠標(biāo)移入事件,使目標(biāo)元素“自動”地獲得焦點(diǎn):

$ele.on("mouseenter", $ele.focus);
2. 監(jiān)聽鍵盤事件

由于項(xiàng)目面向的客戶所使用的瀏覽器以chrome為主(實(shí)際上是36x瀏覽器),因此沒有針對瀏覽器做任何適配,僅僅使用了 jQuery的事件監(jiān)聽:

        $ele.on("keydown", this._keyDownHandler.bind(this));
        

由于實(shí)現(xiàn)是控件化的,所以定義了一個私有方法 _keyDownHandler 來響應(yīng)鍵盤的動作。

3. 按鍵事件甄別

jQuery事件監(jiān)聽器返回的事件對象信息較多,因此需要進(jìn)行甄別,為此定義了一個私有方法 _keyCodeProcess 來處理按鍵

function _keyCodeProcess(e){
        var code = e.keyCode + "";
        var altKey = e.altKey;
        var ctrlKey = e.ctrlKey;
        var shiftKey = e.shiftKey;

        var threeKey = altKey && ctrlKey && shiftKey;
        var ctrlAlt = altKey && ctrlKey;
        var altShift = altKey && shiftKey;
        var ctrlShift = shiftKey && ctrlKey;

        var keyTypeSet = this.keyTypeSet;
        var resStr = "";

        if(threeKey){
            resStr = keyTypeSet.threeKey[code];
        } else if(ctrlAlt) {
            resStr = keyTypeSet.ctrlAlt[code];
        } else if(ctrlShift) {
            resStr = keyTypeSet.ctrlShift[code];
        } else if(altShift) {
            resStr = keyTypeSet.altShift[code];
        } else if(altKey) {
            resStr = keyTypeSet.altKey[code];
        } else if(ctrlKey) {
            resStr = keyTypeSet.ctrlKey[code];
        } else if(shiftKey) {
            resStr = keyTypeSet.shiftKey[code];
        } else {
            resStr = keyTypeSet.singleKey[code];
        }

        return resStr
    };
    

這里的 keyTypeSet 是一個類似于查找表的對象,里面存儲了 ctrl、shift、alt按鈕的各種類型組合,每種組合下又分別按照按鍵碼存儲一個自定義事件類型字符串,事件發(fā)生之后會從這里返回這個字符串,當(dāng)然,沒有對應(yīng)自定義事件的時候,就老老實(shí)實(shí)地返回空字符串。

4. 事件分發(fā)

_keyCodeProcess 方法從事件中提取出了事件類型,我們提前將監(jiān)聽的回調(diào)函數(shù)存儲在一個查找表 callback 中,并且“巧妙”地使得其鍵名剛好為自定義事件字符串前面加個“on”前綴,就可以方便地調(diào)用了,前述 _keyDownHandler 正是為此而設(shè)計(jì)的:

function _keyDownHandler(e){
        var strCommand = this._keyCodeProcess(e);

        var objEvent = {
            type: "",
            originEvent: e.originEvent
        };

        strCommand && this.callback["on" + strCommand](objEvent);

        return null;
    };
    
    
5. 事件訂閱與解除訂閱

前面說了,我們是把回調(diào)函數(shù)存儲起來適時調(diào)用的,因此需要對外暴露一個“訂閱”接口,讓開發(fā)者可以方便地把自己的回調(diào)函數(shù)存儲到對象實(shí)例中去,為此,我定義了一個 .bind接口:

function bind(type, callback, description){
        var allType = this.allEventType;
        if(allType.indexOf(type) === -1){
            throwError("不支持的事件類型,請先擴(kuò)展該類型,或采用其他事件類型");
        }

        if(!(callback instanceof Function)){
            throwError("綁定的事件處理回調(diào)必須是函數(shù)類型");
        }

        this.callback["on" + type] = callback;

        this.eventDiscibeSet[type] = description || "沒有該事件的描述";

        return this;
    };
    

由于是給人用的,所以順帶做了下類型檢查。
根據(jù)接口的“對稱性”,有訂閱最好也有解除訂閱,因此定義了 .unbind接口,只有一句代碼,實(shí)現(xiàn)如下:

function unbind(type){
        this.callback["on" + type] = this._emptyEventHandler;

        return this;
    };
    
6.擴(kuò)展自定義事件類型

鍵盤事件的組合豐富多彩,如果全部內(nèi)置在控件中的話,會是很臃腫的,因此除了少數(shù)幾個常見的組合鍵之外,開發(fā)者可以通過 .extendEventType 方法,來自定義組合鍵和返回的字符串:

function extendEventType(config){
        var len = 0;
        if(config instanceof Array){
            len = config.length;
            while(len--){
                this._setKeyComposition(config[len]);
            }
        } else {
            this._setKeyComposition(config);
        }
        return this;
    };
    

其中的 ._setKeyComposition 是一個私有方法,用來寫入自定義鍵盤事件:

function _setKeyComposition(config){
        var altKey = config.alt;
        var ctrlKey = config.ctrl;
        var shiftKey = config.shift;

        var threeKey = altKey && ctrlKey && shiftKey;
        var ctrlAlt = altKey && ctrlKey;
        var altShift = altKey && shiftKey;
        var ctrlShift = shiftKey && ctrlKey;
        var code = config.code + "";

        if(threeKey){
            this.keyTypeSet.threeKey[code] = config.type;
        } else if(ctrlAlt) {
            this.keyTypeSet.ctrlAlt[code] = config.type;
        } else if(ctrlShift) {
            this.keyTypeSet.ctrlShift[code] = config.type;
        } else if(altShift) {
            this.keyTypeSet.altShift[code] = config.type;
        } else if(altKey) {
            this.keyTypeSet.altKey[code] = config.type;
        } else if(ctrlKey) {
            this.keyTypeSet.ctrlKey[code] = config.type;
        } else if(shiftKey) {
            this.keyTypeSet.shiftKey[code] = config.type;
        } else {
            this.keyTypeSet.singleKey[code] = config.type;
        }
        
        this.allEventType.push(type);
        this.callback["on" + type] = this._emptyEventHandler;

        return null;
    };
    

這樣,一個鍵盤事件監(jiān)聽控件就大功告成了,下面是完整實(shí)現(xiàn)代碼:

/**
 * @constructor 鍵盤事件監(jiān)聽器
 * */
function KeyboardListener(param){
    this._init(param);
}

!function(){
    "use strict";

    /**
     * @private {String} param.ele 事件對象選擇器
     * */
    KeyboardListener.prototype._init = function _init(param){
        this.$ele = $(param.ele);

        this._initEvents();

        return null;
    };

    /**
     * @private _emptyEventHandler 空白事件響應(yīng)
     * */
    KeyboardListener.prototype._emptyEventHandler = function _emptyEventHandler(){
        return null;
    };

    /**
     * @private _initEvents 綁定 DOM 事件
     * */
    KeyboardListener.prototype._initEvents = function _initEvents(){
        this.allEventType = [];
        this.callback = {};
        this.eventDiscibeSet = {};

        var $ele = this.$ele;

        $ele.attr("tabindex", 1);

        $ele.on("mouseenter", function(){
            $ele.focus();
        });

        $ele.on("keydown", this._keyDownHandler.bind(this));

        this.keyTypeSet = {
            altKey: {},
            ctrlAlt: {},
            ctrlKey: {},
            threeKey: {},
            altShift: {},
            shiftKey: {},
            ctrlShift: {},
            singleKey: {}
        };

        // 支持一些內(nèi)建的鍵盤事件類型
        this.extendEventType([
            {
                type: "redo",
                ctrl: true,
                shift: true,
                code: 90
            },
            {
                type: "undo",
                ctrl: true,
                code: 90
            },
            {
                type: "copy",
                ctrl: true,
                code: 67
            },
            {
                type: "paste",
                ctrl: true,
                code: 86
            },
            {
                type: "delete",
                code: 46
            },
            {
                type: "right",
                code: 39
            },
            {
                type: "down",
                code: 40
            },
            {
                type: "left",
                code: 37
            },
            {
                type: "up",
                code: 38
            }
        ]);

        return null;
    };

    /**
     * @private _keyDownHandler 自定義鍵盤事件分發(fā)
     * */
    KeyboardListener.prototype._keyDownHandler = function _keyDownHandler(e){
        var strCommand = this._keyCodeProcess(e);

        var objEvent = {
            type: "",
            originEvent: e.originEvent
        };

        strCommand && this.callback["on" + strCommand](objEvent);

        return null;
    };

    /**
     * @private _keyCodeProcess 處理按鍵碼
     * */
    KeyboardListener.prototype._keyCodeProcess = function _keyCodeProcess(e){
        var code = e.keyCode + "";
        var altKey = e.altKey;
        var ctrlKey = e.ctrlKey;
        var shiftKey = e.shiftKey;

        var threeKey = altKey && ctrlKey && shiftKey;
        var ctrlAlt = altKey && ctrlKey;
        var altShift = altKey && shiftKey;
        var ctrlShift = shiftKey && ctrlKey;

        var keyTypeSet = this.keyTypeSet;
        var resStr = "";

        if(threeKey){
            resStr = keyTypeSet.threeKey[code];
        } else if(ctrlAlt) {
            resStr = keyTypeSet.ctrlAlt[code];
        } else if(ctrlShift) {
            resStr = keyTypeSet.ctrlShift[code];
        } else if(altShift) {
            resStr = keyTypeSet.altShift[code];
        } else if(altKey) {
            resStr = keyTypeSet.altKey[code];
        } else if(ctrlKey) {
            resStr = keyTypeSet.ctrlKey[code];
        } else if(shiftKey) {
            resStr = keyTypeSet.shiftKey[code];
        } else {
            resStr = keyTypeSet.singleKey[code];
        }

        return resStr
    };

    /**
     * @private _setKeyComposition 自定義鍵盤事件
     * @param {Object} config 鍵盤事件配置方案
     * @param {String} config.type 自定義事件類型
     * @param {keyCode} config.code 按鍵的碼值
     * @param {Boolean} [config.ctrl] 是否與 Ctrl 形成組合鍵
     * @param {Boolean} [config.alt] 是否與 Alt 形成組合鍵
     * @param {Boolean} [config.shift] 是否與 Shift 形成組合鍵
     * */
    KeyboardListener.prototype._setKeyComposition = function _setKeyComposition(config){
        var altKey = config.alt;
        var ctrlKey = config.ctrl;
        var shiftKey = config.shift;

        var threeKey = altKey && ctrlKey && shiftKey;
        var ctrlAlt = altKey && ctrlKey;
        var altShift = altKey && shiftKey;
        var ctrlShift = shiftKey && ctrlKey;
        var code = config.code + "";
        var type = config.type;

        if(threeKey){
            this.keyTypeSet.threeKey[code] = type;
        } else if(ctrlAlt) {
            this.keyTypeSet.ctrlAlt[code] = type;
        } else if(ctrlShift) {
            this.keyTypeSet.ctrlShift[code] = type;
        } else if(altShift) {
            this.keyTypeSet.altShift[code] = type;
        } else if(altKey) {
            this.keyTypeSet.altKey[code] = type;
        } else if(ctrlKey) {
            this.keyTypeSet.ctrlKey[code] = type;
        } else if(shiftKey) {
            this.keyTypeSet.shiftKey[code] = type;
        } else {
            this.keyTypeSet.singleKey[code] = type;
        }
        this.allEventType.push(type);
        this.callback["on" + type] = this._emptyEventHandler;
        // this.eventDiscibeSet = {};

        return null;
    };

    /**
     * @method extendEventType 擴(kuò)展鍵盤事件類型
     * @param {Object|Array} config 鍵盤事件配置方案
     * @param {String} config.type 自定義事件類型
     * @param {keyCode} config.code 按鍵的碼值
     * @param {Boolean} [config.ctrl] 是否與 Ctrl 形成組合鍵
     * @param {Boolean} [config.alt] 是否與 Alt 形成組合鍵
     * @param {Boolean} [config.shift] 是否與 Shift 形成組合鍵
     * */
    KeyboardListener.prototype.extendEventType = function extendEventType(config){
        var len = 0;
        if(config instanceof Array){
            len = config.length;
            while(len--){
                this._setKeyComposition(config[len]);
            }
        } else {
            this._setKeyComposition(config);
        }
        return this;
    };

    /**
     * @method bind 綁定自定義的鍵盤事件
     * @param {String} type 事件類型 如:["up", "down", "left", "right", "undo", "redo", "delete", zoomIn, "zoomOut"]
     * @param {Function} callback 回調(diào)函數(shù),參數(shù)為一個自定義的仿事件對象
     * @param {String} description 對綁定事件的用途進(jìn)行說明
     * */
    KeyboardListener.prototype.bind = function bind(type, callback, description){
        var allType = this.allEventType;
        if(allType.indexOf(type) === -1){
            throwError("不支持該事件類型,請先擴(kuò)展該類型,或采用其他事件類型");
        }

        if(!(callback instanceof Function)){
            throwError("綁定的事件處理回調(diào)必須是函數(shù)類型");
        }

        this.callback["on" + type] = callback;

        this.eventDiscibeSet[type] = description || "沒有該事件的描述";

        return this;
    };

    /**
     * @method unbind 解除事件綁定
     * @param {String} type 事件類型
     * */
    KeyboardListener.prototype.unbind = function unbind(type){
        this.callback["on" + type] = this._emptyEventHandler;

        return this;
    };
    
    return null;
}();           
               
                                           
                       
                 
            
                     
             
               

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/103208.html

相關(guān)文章

  • javascript功能插件大集合 前端常用插件 js常用插件

    摘要:轉(zhuǎn)載來源包管理器管理著庫,并提供讀取和打包它們的工具。能構(gòu)建更好應(yīng)用的客戶端包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。很棒的組件集合。隱秘地使用和用戶數(shù)據(jù)。 轉(zhuǎn)載來源:https://github.com/jobbole/aw... 包管理器管理著 javascript 庫,并提供讀取和打包它們的工具。?npm – npm 是 javasc...

    netmou 評論0 收藏0
  • javascript功能插件大集合 前端常用插件 js常用插件

    摘要:轉(zhuǎn)載來源包管理器管理著庫,并提供讀取和打包它們的工具。能構(gòu)建更好應(yīng)用的客戶端包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。很棒的組件集合。隱秘地使用和用戶數(shù)據(jù)。 轉(zhuǎn)載來源:https://github.com/jobbole/aw... 包管理器管理著 javascript 庫,并提供讀取和打包它們的工具。?npm – npm 是 javasc...

    Hydrogen 評論0 收藏0
  • javascript功能插件大集合,寫前端親們記得收藏

    摘要:一個專注于瀏覽器端和兼容的包管理器。一個整合和的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。完全插件化的工具,能在中識別和記錄模式。健壯的優(yōu)雅且功能豐富的模板引擎。完整的經(jīng)過充分測試和記錄數(shù)據(jù)結(jié)構(gòu)的庫。 【導(dǎo)讀】:GitHub 上有一個 Awesome – XXX 系列的資源整理。awesome-javascript 是 sorrycc 發(fā)起維護(hù)的 JS 資源列表...

    cfanr 評論0 收藏0
  • jQuery 事件(一) 鼠標(biāo)與鍵盤事件

    jQuery 鼠標(biāo)事件 click與dbclick事件 用交互操作中,最簡單直接的操作就是點(diǎn)擊操作。jQuery提供了兩個方法一個是click方法用于監(jiān)聽用戶單擊操作,另一個方法是dbclick方法用于監(jiān)聽用戶雙擊操作。這兩個方法的用法是類似的,下面以click()事件為例 方法一:$ele.click() 綁定$ele元素,不帶任何參數(shù)一般是用來指定觸發(fā)一個事件,用的比較少 點(diǎn)擊觸發(fā) $(ele...

    Gemini 評論0 收藏0
  • JavaScript 資源大全中文版

    摘要:官網(wǎng)全新的靜態(tài)包管理器。官網(wǎng)一個整合和官網(wǎng)的最佳思想,使開發(fā)者能快速方便地組織和編寫前端代碼的下一代包管理器。官網(wǎng)小巧的兼容的所見即所得的富文本編輯器。官網(wǎng)富文本編輯器。官網(wǎng)由制作,適用于每天寫作的富文本編輯器。 1. 包管理器 管理著 javascript 庫,并提供讀取和打包它們的工具。 npm:npm 是 javascript 的包管理器。官網(wǎng) cnpm:cnpm 是 由于國...

    jzman 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<