搜索
首页web前端js教程基于 jQuery的键盘事件监听控件的介绍(代码示例)

本篇文章给大家带来的内容是关于基于 jQuery的键盘事件监听控件的介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

最近项目里要做一个画板,需要对键盘事件进行监听,来进行诸如撤回、重做、移动、缩放等操作,因此顺手实现了一个键盘事件监听控件,期间略有收获,整理出来,希望对大家有所帮助,更希望能获得高手的指点。

1. 自动获取焦点

似乎浏览器的键盘事件只能被那些可以获得焦点的元素设置监听,而通常需要监听事件的

元素都不能获得焦点,因此需要修改目标元素的某些属性使其可以获得焦点,另外一种可行的方法是将事件委托给诸如 标签。这里采用的是第一类方法,当然,可以修改的属性也不止一种,例如,对于

标签可以将其 “editable” 属性设为 true,而这里采用的是给其设一个 tabindex 值。代码如下:

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

另外,焦点事件的触发需要点击元素或者 TAB 切换,而这并不符合人类的直觉,因此需要监听鼠标移入事件,使目标元素“自动”地获得焦点:

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

2. 监听键盘事件

由于项目面向的客户所使用的浏览器以chrome为主(实际上是36x浏览器),因此没有针对浏览器做任何适配,仅仅使用了 jQuery的事件监听:

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

由于实现是控件化的,所以定义了一个私有方法 _keyDownHandler 来响应键盘的动作。

3. 按键事件甄别

jQuery事件监听器返回的事件对象信息较多,因此需要进行甄别,为此定义了一个私有方法 _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按钮的各种类型组合,每种组合下又分别按照按键码存储一个自定义事件类型字符串,事件发生之后会从这里返回这个字符串,当然,没有对应自定义事件的时候,就老老实实地返回空字符串。

4. 事件分发

_keyCodeProcess 方法从事件中提取出了事件类型,我们提前将监听的回调函数存储在一个查找表 callback 中,并且“巧妙”地使得其键名刚好为自定义事件字符串前面加个“on”前缀,就可以方便地调用了,前述 _keyDownHandler 正是为此而设计的:

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

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

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

        return null;
    };

5. 事件订阅与解除订阅

前面说了,我们是把回调函数存储起来适时调用的,因此需要对外暴露一个“订阅”接口,让开发者可以方便地把自己的回调函数存储到对象实例中去,为此,我定义了一个 .bind接口:

function bind(type, callback, description){
        var allType = this.allEventType;
        if(allType.indexOf(type) === -1){
            throwError('不支持改事件类型,请先扩展该类型,或采用其他事件类型');
        }

        if(!(callback instanceof Function)){
            throwError('绑定的事件处理回调必须是函数类型');
        }

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

        this.eventDiscibeSet[type] = description || '没有该事件的描述';

        return this;
    };

由于是给人用的,所以顺带做了下类型检查。
根据接口的“对称性”,有订阅最好也有解除订阅,因此定义了 .unbind接口,只有一句代码,实现如下:

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

        return this;
    };

6.扩展自定义事件类型

键盘事件的组合丰富多彩,如果全部内置在控件中的话,会是很臃肿的,因此除了少数几个常见的组合键之外,开发者可以通过 .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 是一个私有方法,用来写入自定义键盘事件的方法:

_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;
        }

        return null;
    };

这样,一个键盘事件监听控件就大功告成了,下面是完整实现代码:

/**
 * @constructor 键盘事件监听器
 * */
function KeyboardListener(param){
    this._init(param);
}

!function(){
    /**
     * @private {String} param.ele 事件对象选择器
     * */
    KeyboardListener.prototype._init = function _init(param){
        this.$ele = $(param.ele);

        this._initEvents();

        this._initEventType();

        return null;
    };

    /**
     * @private _emptyEventHandler 空白事件响应
     * */
    KeyboardListener.prototype._emptyEventHandler = function _emptyEventHandler(){
        return null;
    };

    /**
     * @private _initEventType 初始化所有初始自定义事件类型
     * */
    KeyboardListener.prototype._initEventType = function _initEventType(){
        var allType = ['up', 'down', 'left', 'right', 'undo', 'redo', 'zoomIn', 'zoomOut', 'delete'];
        var intLen = allType.length;
        this.allEventType = allType;
        this.callback = {};
        this.eventDiscibeSet = {};

        for(var intCnt = 0; intCnt < intLen; intCnt++){
            this.callback[&#39;on&#39; + allType[intCnt]] = KeyboardListener.prototype._emptyEventHandler;
        }

        return null;
    };

    /**
     * @private _initEvents 绑定 DOM 事件
     * */
    KeyboardListener.prototype._initEvents = function _initEvents(){
        var $ele = this.$ele;

        $ele.attr(&#39;tabindex&#39;, 1);

        $ele.on(&#39;mouseenter&#39;, function(){
            $ele.focus();
        });

        $ele.on(&#39;keydown&#39;, this._keyDownHandler.bind(this));

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

        // 支持一些内建的键盘事件类型
        this.extendEventType([
            {
                type: &#39;redo&#39;,
                ctrl: true,
                shift: true,
                code: 90
            },
            {
                type: &#39;undo&#39;,
                ctrl: true,
                code: 90
            },
            {
                type: &#39;copy&#39;,
                ctrl: true,
                code: 67
            },
            {
                type: &#39;paste&#39;,
                ctrl: true,
                code: 86
            },
            {
                type: &#39;delete&#39;,
                code: 46
            },
            {
                type: &#39;right&#39;,
                code: 39
            },
            {
                type: &#39;down&#39;,
                code: 40
            },
            {
                type: &#39;left&#39;,
                code: 37
            },
            {
                type: &#39;up&#39;,
                code: 38
            }
        ]);

        return null;
    };

    /**
     * @private _keyDownHandler 自定义键盘事件分发
     * */
    KeyboardListener.prototype._keyDownHandler = function _keyDownHandler(e){
        var strCommand = this._keyCodeProcess(e);

        var objEvent = {
            type: &#39;&#39;,
            originEvent: e.originEvent
        };

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

        return null;
    };

    /**
     * @private _keyCodeProcess 处理按键码
     * */
    KeyboardListener.prototype._keyCodeProcess = function _keyCodeProcess(e){
        var code = e.keyCode + &#39;&#39;;
        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 = &#39;&#39;;

        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 + &#39;&#39;;

        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;
        }

        return null;
    };

    /**
     * @method extendEventType 扩展键盘事件类型
     * @param {Object|Array<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.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 回调函数,参数为一个自定义的仿事件对象
     * @param {String} description 对绑定事件的用途进行说明
     * */
    KeyboardListener.prototype.bind = function bind(type, callback, description){
        var allType = this.allEventType;
        if(allType.indexOf(type) === -1){
            throwError('不支持改事件类型,请先扩展该类型,或采用其他事件类型');
        }

        if(!(callback instanceof Function)){
            throwError('绑定的事件处理回调必须是函数类型');
        }

        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;
    };
}();

【相关推荐:jQuery视频教程

以上是基于 jQuery的键盘事件监听控件的介绍(代码示例)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除
JavaScript在行动中:现实世界中的示例和项目JavaScript在行动中:现实世界中的示例和项目Apr 19, 2025 am 12:13 AM

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

了解JavaScript引擎:实施详细信息了解JavaScript引擎:实施详细信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:学习曲线和易用性Python vs. JavaScript:学习曲线和易用性Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境