Aucun élément ne peut obtenir le focus, vous devez donc modifier certaines propriétés de l'élément cible afin qu'il puisse obtenir le focus. Une autre méthode possible consiste à déléguer l'événement à une balise telle que . Le premier type de méthode est utilisé ici. Bien entendu, plusieurs attributs peuvent être modifiés. Par exemple, pour la balise , vous pouvez définir son attribut "modifiable" sur true, mais ce qui est utilisé ici. est de définir une valeur tabindex pour cela. Le code est le suivant :
$ele.attr('tabindex', 1);
De plus, le déclenchement de l'événement focus nécessite de cliquer sur l'élément ou de changer de TAB, ce qui n'est pas conforme à l'intuition humaine. Il est donc nécessaire de surveiller le. événement de déplacement de la souris afin que l'élément cible puisse "automatiquement" obtenir le focus. :
$ele.on('mouseenter', function(){
$ele.focus();
});
2. Écoute des événements de clavier
Puisque les navigateurs utilisés par les clients du projet sont principalement Chrome (en fait un navigateur 36x), il n'y a pas de spécifique au navigateur. Toute adaptation utilise uniquement l'écoute d'événements de jQuery :
$ele.on('keydown', this._keyDownHandler.bind(this));
L'implémentation étant orientée contrôle, une méthode privée _keyDownHandler est définie pour répondre aux actions du clavier .
3. Filtrage des événements clés
L'écouteur d'événements jQuery renvoie de nombreuses informations sur les objets d'événement, il doit donc être filtré. À cette fin, une méthode privée _keyCodeProcess est définie pour gérer les pressions sur les touches.
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
};
Le keyTypeSet ici est un objet similaire à une table de recherche, qui stocke différents types de combinaisons de boutons ctrl, shift et alt. Chaque combinaison stocke une chaîne de type d'événement personnalisée en fonction du code clé. Cette chaîne sera renvoyée à partir d'ici après que l'événement se soit produit. Bien sûr, lorsqu'il n'y a pas d'événement personnalisé correspondant, une chaîne vide sera renvoyée honnêtement.
4. Distribution d'événements
La méthode _keyCodeProcess extrait le type d'événement de l'événement. Nous stockons la fonction de rappel d'écoute dans un rappel de table de recherche à l'avance et faisons "intelligemment" sa clé Le nom. ajoute le préfixe "on" devant la chaîne d'événement personnalisée, et il peut être facilement appelé. Le _keyDownHandler susmentionné est conçu pour cela :
function _keyDownHandler(e){
var strCommand = this._keyCodeProcess(e);
var objEvent = {
type: '',
originEvent: e.originEvent
};
strCommand && this.callback['on' + strCommand](objEvent);
return null;
};
5. mentionné précédemment, nous stockons la fonction de rappel et l'appelons au bon moment, nous devons donc exposer une interface « d'abonnement » au monde extérieur afin que les développeurs puissent facilement stocker leur fonction de rappel dans l'instance d'objet. Par conséquent, j'ai défini un . interface de liaison :
Comme il s'agit d'un usage humain, j'ai d'ailleurs fait une vérification de type. 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;
}; Selon la "symétrie" de l'interface, il est préférable de s'abonner et de se désabonner, l'interface .unbind est donc définie, avec une seule ligne de code, et l'implémentation est la suivante :
6. Étendre les types d'événements personnalisésfunction unbind(type){
this.callback['on' + type] = this._emptyEventHandler;
return this;
};
Il existe des combinaisons riches et colorées d'événements de clavier s'ils étaient tous intégrés au contrôle, ce serait donc très volumineux, en plus de quelques combinaisons de touches courantes. les développeurs peuvent personnaliser les combinaisons de touches via la méthode .extendEventType. Et la chaîne renvoyée :
où ._setKeyComposition est une méthode privée utilisée pour écrire des événements de clavier personnalisés : 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;
};
Dans ceci façon, un écouteur d'événement clavier Le contrôle est effectué. Voici le code d'implémentation complet : _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;
};
[Recommandations associées : /**
* @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['on' + allType[intCnt]] = KeyboardListener.prototype._emptyEventHandler;
}
return null;
};
/**
* @private _initEvents 绑定 DOM 事件
* */
KeyboardListener.prototype._initEvents = function _initEvents(){
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: {}
};
// 支持一些内建的键盘事件类型
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 自定义键盘事件分发
* */
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 + '';
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;
};
}(); Tutoriel vidéo jQuery]
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!