我正在编写一个小的笔记网络应用程序,它使用CKEditor作为HTML编辑器。我已经能够很好地集成它,但有一个例外 - 拖放功能。它大部分有效 - 但尽管尝试了很多不同的方法,但我仍然无法解决两个怪癖。
我的要求很简单 - 我将任何文件从应用程序外部拖到 CKEditor 中,它应该在可编辑文本中插入一个简单的锚标签,并带有指向该文件的本地链接。目前,我正在我自己的CKEditor插件中实现拖放,称为文件管理器:
CKEDITOR.plugins.add( 'filemanager', {
init: function( editor ) {
editor.on('contentDom', function(contentDom) {
//Runs upon dropping a file into the editor
contentDom.editor.document.on('drop', function(e) {
//prevents default behavior as long as it's an actual file drag and drop (if it's dragging text etc. inside the editor, keep default behavior)
if(e.data.$.dataTransfer.files.length)
{
e.data.preventDefault();
}
//Goes through all the dropped files and insert HTML with links
for (var i = 0; i < e.data.$.dataTransfer.files.length; ++i) {
CopyData(e.data.$.dataTransfer.files[i].path);
}
});
});
//Creates the link in the editor
function CopyData(path, range)
{
//Link HTML
var fileHTML;
/* Code to parse the path into HTML to be inserted */
editor.insertHtml(fileHTML);
}
}
});
我省略了大部分 CopyData 函数,因为格式无关紧要,但它会生成如下div:
fileHTML = "<a href=""+path+"" class="fileLink" target="_blank">"+fileName+"</a>";
这确实工作得很好,因此该功能的基本实现似乎可以正常工作。但是,这是我的两个问题:
- 将文件拖放到编辑器中但在实际文本区域之外(例如编辑器中最后一行文本下方)不会禁用默认行为。如何为编辑器的此区域运行 preventDefault()?一直在各种地方尝试活动但没有结果。
- HTML 不会插入到鼠标光标的位置,即使 CKEditor 在那里预览插入符号也是如此。相反,它会插入到文档中插入符号当前所在的位置,与放置的位置无关。这会破坏该功能的核心功能 - 有没有办法在鼠标位置插入 HTML?我会这样假设,因为 CKEditor 实际上预览了鼠标所在的插入符号,但我浏览了文档但没有结果。
有没有人对如何解决上述两个问题有想法?如果有帮助,我使用的是 nw.js因此网络应用程序将始终在 Chromium 中运行。感谢任何回复!
我最终设法解决了这些问题。
为了防止 DOM 元素之外的默认行为,我将这段代码添加到我的 CKEditor 插件中:
var iframeWin = window.document.getElementsByTagName('iframe')[0].contentWindow;
iframeWin.addEventListener("dragover",function(e){
e = e || iframeWin.event;
if(e.dataTransfer.files.length)
{
e.preventDefault();
}
},false);
iframeWin.addEventListener("drop",function(e){
e = e || iframeWin.event;
if(e.dataTransfer.files.length)
{
e.preventDefault();
}
},false);
这正确地标识了我需要在其中禁用默认行为的 iframe。if(e.dataTransfer.files.lenght) 条件确保这仅适用于拖入应用程序的文件,而不是在编辑器中拖动内容。
在鼠标光标处插入 HTML 更棘手!这不能归功于我 - 我找到了一个在 CKEditor 错误跟踪器上完成大部分工作的函数,并对其进行了编辑以在这种情况下工作:
function moveSelectionToDropPosition( editor, dropEvt )
{
var $evt = dropEvt.data.$,
$range,
range = editor.createRange();
// Make testing possible.
if ( dropEvt.data.testRange ) {
dropEvt.data.testRange.select();
return;
}
// Webkits.
if ( document.caretRangeFromPoint ) {
$range = editor.document.$.caretRangeFromPoint( $evt.clientX, $evt.clientY );
range.setStart( CKEDITOR.dom.node( $range.startContainer ), $range.startOffset );
range.collapse( true );
}
// FF.
else if ( $evt.rangeParent ) {
range.setStart( CKEDITOR.dom.node( $evt.rangeParent ), $evt.rangeOffset );
range.collapse( true );
}
// IEs.
else if ( document.body.createTextRange ) {
$range = editor.document.getBody().$.createTextRange();
$range.moveToPoint( $evt.clientX, $evt.clientY );
var id = 'cke-temp-' + ( new Date() ).getTime();
$range.pasteHTML( '<span id="' + id + '">u200b</span>' );
var span = editor.document.getById( id );
range.moveToPosition( span, CKEDITOR.POSITION_BEFORE_START );
span.remove();
}
range.select();
}
在下降事件中,我然后简单地添加了
moveSelectionToDropPosition(editor, e);
一切都按预期工作!
希望这可以帮助将来遇到类似问题的任何其他人:)