我有一个非常简单的用例。我的页面有一些可配置的快捷键。我在文档节点处理keydown事件,如果keypress是可配置的快捷方式之一,那么我执行一系列操作并调用event.preventDefault()
等,以防止发生标准操作(例如,覆盖Ctrl键/ Cmd的+ S)。
CKEditor创建一个iframe,使文档级事件处理变得复杂。我在SO上找到了一篇非常有用的帖子,解释了如何将自定义文档级事件处理程序注入编辑器的iframe:
How to use custom keyboard shortcuts within CKeditor with jQuery?
不幸的是,CKEditor没有传递原始事件对象。在我的开发控制台中探索之后,我发现了一个似乎暴露原始事件对象(event.data.$
)的属性,但实际上是事件对象的副本。例如,type
属性是继承的,这会混淆jQuery的trigger()
函数(由于某种原因,它正在调用hasOwnProperty('type')
。)
我可以通过制作事件对象的副本来修复jQuery问题,但这会改变"这个"的含义。这似乎搞砸了父处理程序中的preventDefault()
函数。
我需要原始事件对象,我可以在其上调用preventDefault()
并传递给jQuery的trigger()
函数,而无需操作任何内容。父文档应处理处理keydown事件并确定要采取的操作:复制CKEditor contentDom处理程序中的所有可配置快捷方式代码是不可行的。
不幸的是,SO对iframe操作的限制比jsfiddle更严格,所以我创造了两者。您可以在下面的代码段中查看代码,但是您必须访问jsfiddle以实际看到此工作:
http://jsfiddle.net/cyborgx37/swywgb7g/
var doc = $(document).on('keydown',function(e){
if (e.keyCode === 83){
e.preventDefault();
}
});
CKEDITOR.replace( 'foobar', {
on : {
contentDom : function() {
this.document.on( 'keydown',
function(e){
var originalEvent = e.data.$;
console.log({
type: originalEvent.type,
hasOwnResult: originalEvent.hasOwnProperty('type')
});
// type is "keydown" (type is defined!)
// but type is an inherited property so
// jQuery .trigger() ignores it and attempts
// to process the event as a string
doc.trigger( 'keydown', originalEvent );
// doesn't have desired effect, because the original
// event (with keyCode) has been replaced by a generic
// event object (without keyCode)
doc.trigger(e.data.$);
// causes error, because jQuery thinks that I've sent
// in a event name string rather than an event object
doc.trigger($.extend({},e.data.$));
// causes error, "this" is no longer the original event
// resulting in an "illegal invocation" exception
}
);
}
}
}
);
var doc = $(document).on('keydown',function(e){
if (e.keyCode === 83){
e.preventDefault();
}
});
CKEDITOR.replace( 'foobar', {
on : {
contentDom : function() {
this.document.on( 'keydown',
function(e){
var originalEvent = e.data.$;
console.log({
type: originalEvent.type,
hasOwnResult: originalEvent.hasOwnProperty('type')
});
// type is "keydown" (type is defined!)
// but type is an inherited property so
// jQuery .trigger() ignores it and attempts
// to process the event as a string
doc.trigger( 'keydown', originalEvent );
// doesn't have desired effect, because the original
// event (with keyCode) has been replaced by a generic
// event object (without keyCode)
doc.trigger(e.data.$);
// causes error, because jQuery thinks that I've sent
// in a event name string rather than an event object
doc.trigger($.extend({},e.data.$));
// causes error, "this" is no longer the original event
// resulting in an "illegal invocation" exception
}
);
}
}
}
);

#debug{
font-family: monospace;
color: red;
margin: 20px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.ckeditor.com/4.4.7/standard/ckeditor.js"></script>
<h1>Typing "s" should be prevented, since we are calling "preventDefault()" if the keyCode is 83.</h1>
<h2>Works fine when typing in an input (you can't type an "s").</h2>
<input type="text">
<h2>Breaks for CKEditor, because we either can't pass along the original event, or jQuery breaks because, for some reason, jQuery cares whether or not type is an inherited property.</h2>
<textarea id="foobar"></textarea>
<h2>Error message (when attempting to use .trigger with the "original" (or as close as I can find in CKEditor) event object):</h2>
&#13;
答案 0 :(得分:0)
我找到了答案。事实证明,CKEditor实现了自己的(在我看来有点不可思议)事件系统。我使用的editor.document
不是jQuery对象,而是CKEditor对象。
修复结果非常简单:
var doc = $(document).on('keydown',function(e){
if (e.keyCode === 83){
e.preventDefault();
}
});
CKEDITOR.replace( 'foobar', {
on : {
contentDom : function() {
// Get the low-level DOM element and
// wrap it in a jQuery object, then call .on()
$(this.document.$).on( 'keydown',
function(e){
// now I've got a jQuery event, which
// trigger() is much happier with
doc.trigger(e);
}
);
}
}
}
);