我有最新的ckeditor版本4.5.7和拖放API,我有一个案例,我需要将一个小部件从一个编辑器拖放到另一个编辑器。 正如这张票说的那样建议的功能是无声地失败并且什么都不做。
在我的情况下,我需要复制小部件,如果它被拖动到另一个编辑器并移动,如果它在同一编辑器中拖动。第二种情况已经在工作
有关如何做的任何想法?
editor.on( 'contentDom', function() {
var dropTarget = CKEDITOR.plugins.clipboard.getDropTarget( editor );
editor.editable().attachListener( dropTarget, 'drop', function( evt ) {
// The target may be some element inside the draggable div (e.g. the image), so get the div.h-card.
var target = evt.data.getTarget().getAscendant( 'div', true );
// Initialization of CKEditor data transfer facade is a necessary step to extend and unify native
// browser capabilities. For instance, Internet Explorer does not support any other data type than 'text' and 'URL'.
// Note: evt is an instance of CKEDITOR.dom.event, not a native event.
CKEDITOR.plugins.clipboard.initDragDataTransfer( evt );
var dataTransfer = evt.data.dataTransfer;
// Pass an object with contact details. Based on it, the editor#paste listener in the hcard plugin
// will create HTML to be inserted into the editor. We could set text/html here as well, but:
// * It is a more elegant and logical solution that this logic is kept in the hcard plugin.
// * We do not know now where the content will be dropped and the HTML to be inserted
// might vary depending on the drop target.
dataTransfer.setData( 'contact', CONTACTS[ target.data( 'contact' ) ] );
// We need to set some normal data types to backup values for two reasons:
// * In some browsers this is necessary to enable drag and drop into text in editor.
// * The content may be dropped in another place than the editor.
dataTransfer.setData( 'text/html', target.getText() );
} );
} );
此外,如果ckeditor是readOly通过readOnly选项,我可以选择一些内容并将其拖到另一个编辑器,从而将其从源编辑器中删除
答案 0 :(得分:3)
我在这里发现了3个问题:
我设法解决了前两个问题。
广告。 1.
要在交叉编辑器中插入联系人,请按照从联系人列表中插入联系人的方式进行拖放,您需要在数据传输对象contact
上设置dataTransfer.getData( 'contact' );
数据。遗憾的是,您拖动的小部件不会将联系人存储为对象。最简单的方法是将字符串化的联系人存储为附加属性:
<span class="h-card" data-contact=\'' + JSON.stringify( contact ) + '\'>...</span>
广告。 2。
实际上CKEditor块小部件在编辑器之间拖放。为了解决这个问题,您可以创建一个drop
侦听器,它将在默认侦听器(优先级2)之前调用,并将子站点类型从窗口小部件更改为联系人,因此它的处理方式与从中拖动的联系人相同。编辑下面的列表。
// Create a drop listener which change the object from the widget to the contact.
editor.on( 'drop', function( evt ) {
var dataTransfer = evt.data.dataTransfer,
sourceEditor = dataTransfer.sourceEditor;
id = dataTransfer.getData( 'cke/widget-id' );
// If it was a widget from another editor...
if( sourceEditor && typeof id == "number" ) {
// ...get contact info from the data attribute...
var contact = sourceEditor.widgets.instances[ id ].element.data( 'contact' );
contact = JSON.parse( contact );
// ...set the contact info...
dataTransfer.setData( 'contact', contact );
// ...and remove the information that it was a widget.
dataTransfer.setData( 'cke/widget-id', null );
}
}, null, null, 2 );
广告。 3。
我无法阻止CKEditor表单删除拖动的元素而不会阻止掉落。删除由以下代码完成:https://github.com/ckeditor/ckeditor-dev/blob/06362a8715809f23d439986a122b87a37eef2e13/plugins/clipboard/plugin.js#L1409并且不准备被阻止。我的另一个想法是防止这种拖放和火灾单独的下降事件,但不幸的是,我没有下降位置。您可以更改剪贴板插件以防止删除源元素并添加如下内容:
if( dataTransfer.getData( 'doNotRemoveSource' )
dataTransfer.sourceEditor.editable().extractHtmlFromRange( dragRange );
但是我不保证它会正常工作,它可能需要在小部件系统中进行一些更改,这些更改也会监听掉落事件。
整个解决方案都是一个黑客,完美的解决方案需要在剪贴板插件中进行更深层次的更改。
您可以在此处找到我的解决方案:http://codepen.io/pjasiun/pen/aNLWWM
答案 1 :(得分:0)
我已经成功地按照你说的优先事项
来说首先在新的widget插件中我使用了dragstart事件
chmod 644
然后我使用优先级为2的drop事件(1是在此之前调用的默认事件)。
我使用验证来检查小部件是否在编辑器中拖动。如果是,那么我不想创建新的小部件,但移动现有小部件,以便我们取消此活动
editor.on("dragstart", function (evt) {
evt.stop();
var target = evt.data.target;
if (isDomDragHandler(target)) {
var widget = evt.editor.widgets.getByElement(target);
CKEDITOR.plugins.clipboard.initDragDataTransfer(evt, evt.editor);
evt.data.dataTransfer.setData('cke/widget-id', widget.id);
evt.data.dataTransfer.setData('cke/editor-name', evt.editor.name);
evt.data.dataTransfer.setData('text/html', widget.element.getOuterHtml());
// IE needs focus.
editor.focus();
// and widget need to be focused on drag start (#12172#comment:10).
widget.focus();
}
}, null, null, 1);
最后,我们必须使用另一个侦听器,再次使用drop效果来判断事件是来自同一编辑器还是来自其他编辑器,以设置数据。
editor.on('drop', function (evt) {
// do nothing if widget is dragged in source segment
if (evt.editor.name.indexOf("sourceSegment") != -1) {
evt.cancel();
return;
}
//get hold of global data transfer object
var dataTransfer = evt.data.dataTransfer;
var sourceEditorName = dataTransfer.getData('cke/editor-name');
if (sourceEditorName == evt.editor.name) return;
}, null, null, 2); // 2rd called
最后的改变是评论小部件插件中取消事件
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/widget/plugin.js#L2381
editor.on('drop', function (evt) {
var dataTransfer = evt.data.dataTransfer,
id = dataTransfer.getData('cke/widget-id'),
transferType = dataTransfer.getTransferType(editor);
// Disable cross-editor drag & drop for widgets - #13599.
if (id !== '' && transferType === CKEDITOR.DATA_TRANSFER_CROSS_EDITORS) {
//do nothing
}
if (id === '' || transferType == CKEDITOR.DATA_TRANSFER_INTERNAL) {
return;
}
evt.data.dataTransfer.setData('text/html', evt.data.dataTransfer.getData('text/html'));
}, null, null, 9999); // 3rd called
通过这种方式,您可以在编辑器之间拖动小部件,从源代码复制到目标编辑器,并在同一个编辑器中移动小部件。
声明: 我提出的这个解决方案是我发现的最好的,没有过多地操纵ckeditor本身的核心功能(仅1行)。但是,如果有人有更好的解决方案,请发表评论!