CKEditor中拖放的问题

时间:2015-06-12 15:32:46

标签: javascript jquery html drag-and-drop ckeditor

我正在编写一个使用CKEditor作为HTML编辑器的小型webetapp。我已经能够很好地集成它,只有一个例外 - 拖放功能。它主要起作用 - 但是尽管尝试了很多不同的方法,但我仍然能够解决两个怪癖。

我的要求很简单 - 我从应用程序外部将任何文件拖到CKEditor中,它应该在可编辑文本中插入一个简单的锚标记,并带有指向该文件的本地链接。目前,我正在我自己的CKEditor插件中实现拖放操作,名为filemanager:

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


这确实很好用,所以该功能的基本实现似乎有效。但是,这是我的两个问题:

  1. 将文件拖放到编辑器中但在实际文本区域之外(例如编辑器中最后一行文本下方)不会禁用默认行为。如何为编辑器的这个区域运行preventDefault()?在所有类型的地方尝试没有结果的活动。
  2. 即使CKEditor在那里预览插入符号,HTML也不会插入鼠标光标的位置。相反,它插入到插入符号当前位于文档中的位置,与您放置的位置无关。这破坏了该功能的核心功能 - 有没有办法在鼠标位置插入HTML?我假设是这样的,因为CKEditor实际上预览了鼠标所在的插入符号,但是我查看了没有结果的文档。
  3. 有没有人有关于如何解决上述两个问题的想法?如果它有帮助,我使用的是nw.js,因此webapp将始终在Chromium中运行。感谢任何回复!

1 个答案:

答案 0 :(得分:0)

我最终设法解决了这些问题。

为了防止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);

这一切都按预期工作了!

希望这可能有助于将来遇到类似问题的其他人:)