2016-03-30 5 views
1

У меня есть последняя версия ckeditor 4.5.7 с API перетаскивания и у меня есть случай, когда мне нужно перетащить виджет из одного редактора в другой. Поскольку этот билет говорит, что предлагаемое функциональное свойство - терпеть неудачу молча и ничего не делать.ckeditor drag drop widgets

link to ckeditor ticket

В моем случае мне нужно скопировать виджет, если он потащил в другой редактор и двигаться, если он тащится в том же editor.Second случае уже работает

Любые мысли о как это сделать?

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()); 
    }); 
}); 

link to codepen example

Кроме того, если CKEditor доступен только для чтения через READONLY вариант я могу выбрать некоторое содержимое и перетащите его в другой редактор в результате удаления из редактора исходного кода

ответ

3

Я нашел 3 проблемы здесь :

  1. это не просто, чтобы получить контактную информацию обратно от элемента,
  2. , как вы упомянули перемещение виджета блока CKEditor между редакторами,
  3. CKEditor удаляет элемент drop из области источника при перетаскивании.

Мне удалось решить первые два вопроса.

Объявление. 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

0

мне удалось это сделать, как вы сказали посредством приоритезации событий

Во-первых, в новом виджете плагин я использовал событие dragstart

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 с приоритетом 2 (1 - это значение по умолчанию, которое вызывается до этого).

Я использую проверку, чтобы проверить, перетаскивается ли виджет внутри редактора. Если после этого я не хочу, чтобы создать новый виджет, но переместить существующий поэтому мы отменить это событие

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 

Наконец, мы должны использовать другой слушатель, опять же эффект снижения сказать, если событие происходит от тот же редактор или из другого редактора, чтобы установить данные.

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 

Окончательное изменение было закомментировать отмену мероприятия в виджете плагин

https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/widget/plugin.js#L2381

// Disable cross-editor drag & drop for widgets - #13599. 
if (id !== '' && transferType === CKEDITOR.DATA_TRANSFER_CROSS_EDITORS) { 
    //evt.cancel(); <---- I commented this one 
    return; 
} 

Таким образом, вы можете перетаскивать виджеты между редакторами скопировать из источника в целевой редактора, и перемещать виджеты внутри одного и того же редактора.

Отказ от ответственности: Это решение, которое я выбрал, - это лучшее, что я нашел, не слишком сильно манипулируя основной функциональностью самого ckeditor (только 1 строка). Однако, если у кого-то есть лучшее решение, прокомментируйте!