autotest_platform/app/static/minder/src/runtime/receiver.js

145 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @fileOverview
*
* 键盘事件接收/分发器
*
* @author: techird
* @copyright: Baidu FEX, 2014
*/
define(function(require, exports, module) {
var key = require('../tool/key');
var hotbox = require('hotbox');
function ReceiverRuntime() {
var fsm = this.fsm;
var minder = this.minder;
var me = this;
// 接收事件的 div
var element = document.createElement('div');
element.contentEditable = true;
/**
* @Desc: 增加tabindex属性使得element的contenteditable不管是trur还是false都能有focus和blur事件
* @Editor: Naixor
* @Date: 2015.09.14
*/
element.setAttribute("tabindex", -1);
element.classList.add('receiver');
element.onkeydown = element.onkeypress = element.onkeyup = dispatchKeyEvent;
this.container.appendChild(element);
// receiver 对象
var receiver = {
element: element,
selectAll: function() {
// 保证有被选中的
if (!element.innerHTML) element.innerHTML = ' ';
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
element.focus();
},
/**
* @Desc: 增加enable和disable方法用于解决热核态的输入法屏蔽问题
* @Editor: Naixor
* @Date: 2015.09.14
*/
enable: function() {
element.setAttribute("contenteditable", true);
},
disable: function() {
element.setAttribute("contenteditable", false);
},
/**
* @Desc: hack FF下div contenteditable的光标丢失BUG
* @Editor: Naixor
* @Date: 2015.10.15
*/
fixFFCaretDisappeared: function() {
element.removeAttribute("contenteditable");
element.setAttribute("contenteditable", "true");
element.blur();
element.focus();
},
/**
* 以此事件代替通过mouse事件来判断receiver丢失焦点的事件
* @editor Naixor
* @Date 2015-12-2
*/
onblur: function (handler) {
element.onblur = handler;
}
};
receiver.selectAll();
minder.on('beforemousedown', receiver.selectAll);
minder.on('receiverfocus', receiver.selectAll);
minder.on('readonly', function() {
// 屏蔽minder的事件接受删除receiver和hotbox
minder.disable();
editor.receiver.element.parentElement.removeChild(editor.receiver.element);
editor.hotbox.$container.removeChild(editor.hotbox.$element);
});
// 侦听器,接收到的事件会派发给所有侦听器
var listeners = [];
// 侦听指定状态下的事件,如果不传 state侦听所有状态
receiver.listen = function(state, listener) {
if (arguments.length == 1) {
listener = state;
state = '*';
}
listener.notifyState = state;
listeners.push(listener);
};
function dispatchKeyEvent(e) {
e.is = function(keyExpression) {
var subs = keyExpression.split('|');
for (var i = 0; i < subs.length; i++) {
if (key.is(this, subs[i])) return true;
}
return false;
};
var listener, jumpState;
for (var i = 0; i < listeners.length; i++) {
listener = listeners[i];
// 忽略不在侦听状态的侦听器
if (listener.notifyState != '*' && listener.notifyState != fsm.state()) {
continue;
}
/**
*
* 对于所有的侦听器,只允许一种处理方式:跳转状态。
* 如果侦听器确定要跳转,则返回要跳转的状态。
* 每个事件只允许一个侦听器进行状态跳转
* 跳转动作由侦听器自行完成(因为可能需要在跳转时传递 reason返回跳转结果即可。
* 比如:
*
* ```js
* receiver.listen('normal', function(e) {
* if (isSomeReasonForJumpState(e)) {
* return fsm.jump('newstate', e);
* }
* });
* ```
*/
if (listener.call(null, e)) {
return;
}
}
}
this.receiver = receiver;
}
return module.exports = ReceiverRuntime;
});