CKEDITOR拖放插件集成在销毁和重新创建编辑器实例后停止工作

时间:2016-01-20 11:59:57

标签: javascript drag-and-drop ckeditor ckeditor4.x

在尝试使用CKEditor的拖放集成时,我遇到了很多麻烦。

首先,拖放到编辑器中可以使用dataTransfer和all进行操作。但每当我必须销毁并重新创建编辑器的实例时,拖放内容就会停止按预期工作。

我直接从CKEditor's SDK page about DnD integration修改了示例代码,您可以在其中看到正在复制的问题。 (我只是缩小了示例,使其更加简洁,并在列表底部添加了“Destroy and recreate”按钮。)

无法让它在JSFiddle中运行,很抱歉,但这是代码:

        'use strict';

        var CONTACTS = [{
          name: 'Huckleberry Finn',
          tel: '+48 1345 234 235',
          email: 'h.finn@example.com',
          avatar: 'hfin'
        }, {
          name: 'D\'Artagnan',
          tel: '+45 2345 234 235',
          email: 'dartagnan@example.com',
          avatar: 'dartagnan'
        }];

        CKEDITOR.disableAutoInline = true;

        CKEDITOR.plugins.add('drag_list', {
          requires: 'widget',

          init: function(editor) {
            editor.widgets.add('drag_list', {
              allowedContent: true,
              pathName: 'drag_list',

              upcast: function(el) {
                return el.name == 'table' && el.hasClass('product_widget');
              }
            });

            editor.addFeature(editor.widgets.registered.drag_list);

            editor.on('paste', function(evt) {
              var contact = evt.data.dataTransfer.getData('contact');
              if (!contact) {
                return;
              }

              evt.data.dataValue =
                '<span class="h-card">' +
                '<a href="mailto:' + contact.email + '" class="p-name u-email">' + contact.name + '</a>' +
                ' ' +
                '<span class="p-tel">' + contact.tel + '</span>' +
                '</span>';
            });
          }
        });

        CKEDITOR.document.getById('contactList').on('dragstart', function(evt) {
          var target = evt.data.getTarget().getAscendant('div', true);

          CKEDITOR.plugins.clipboard.initDragDataTransfer(evt);

          var dataTransfer = evt.data.dataTransfer;

          dataTransfer.setData('contact', CONTACTS[target.data('contact')]);

          dataTransfer.setData('text/html', target.getText());

          if (dataTransfer.$.setDragImage) {
            dataTransfer.$.setDragImage(target.findOne('img').$, 0, 0);
          }
        });

        CKEDITOR.inline('editor1', {
          extraPlugins: 'drag_list,sourcedialog,justify'
        });

        function destroy_recreate() {
          for (var instance in CKEDITOR.instances) {
            console.log(CKEDITOR.instances[instance])
            CKEDITOR.instances[instance].destroy();
          }
          CKEDITOR.inline('editor1', {
            extraPlugins: 'drag_list,sourcedialog,justify'
          });
        }
.columns {
  background: #fff;
  padding: 20px;
  border: 1px solid #E7E7E7;
}
.columns:after {
  content: "";
  clear: both;
  display: block;
}
.columns > .editor {
  float: left;
  width: 65%;
  position: relative;
  z-index: 1;
}
.columns > .contacts {
  float: right;
  width: 35%;
  box-sizing: border-box;
  padding: 0 0 0 20px;
}
#contactList {
  list-style-type: none;
  margin: 0 !important;
  padding: 0;
}
#contactList li {
  background: #FAFAFA;
  margin-bottom: 1px;
  height: 56px;
  line-height: 56px;
  cursor: pointer;
}
#contactList li:nth-child(2n) {
  background: #F3F3F3;
}
#contactList li:hover {
  background: #FFFDE3;
  border-left: 5px solid #DCDAC1;
  margin-left: -5px;
}
.contact {
  padding: 0 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.contact .u-photo {
  display: inline-block;
  vertical-align: middle;
  margin-right: 10px;
}
#editor1 .h-card {
  background: #FFFDE3;
  padding: 3px 6px;
  border-bottom: 1px dashed #ccc;
}
#editor1 {
  border: 1px solid #E7E7E7;
  padding: 0 20px;
  background: #fff;
  position: relative;
}
#editor1 .h-card .p-tel {
  font-style: italic;
}
#editor1 .h-card .p-tel::before,
#editor1 .h-card .p-tel::after {
  font-style: normal;
}
#editor1 .h-card .p-tel::before {
  content: "(☎ ";
}
#editor1 .h-card .p-tel::after {
  content: ")";
}
#editor1 h1 {
  text-align: center;
}
#editor1 hr {
  border-style: dotted;
  border-color: #DCDCDC;
  border-width: 1px 0 0;
}
<script src="http://cdn.ckeditor.com/4.5.5/standard-all/ckeditor.js"></script>
<div class="columns">
  <div class="editor">
    <div cols="10" id="editor1" name="editor1" rows="10" contenteditable="true">
      <h3>Drop stuff here then press the Destroy/Recreate button and try again.</h3>

    </div>
  </div>
  <div class="contacts">
    <h3>List of Droppable Contacts</h3>
    <ul id="contactList">
      <li>
        <div class="contact h-card" data-contact="0" draggable="true" tabindex="0">
          <img src="http://sdk.ckeditor.com/samples/assets/draganddrop/img/hfin.png" alt="avatar" class="u-photo">Huckleberry Finn
        </div>
      </li>
      <li>
        <div class="contact h-card" data-contact="1" draggable="true" tabindex="0">
          <img src="http://sdk.ckeditor.com/samples/assets/draganddrop/img/dartagnan.png" alt="avatar" class="u-photo">D'Artagnan
        </div>
      </li>
    </ul>
    <button class='destroy_recreate' onclick='destroy_recreate()'>Destroy and recreate editors</button>
  </div>
</div>

像sourcedialog和justify这样的其他插件似乎仍能正常运行,但是drag_list却没有。

有谁知道为什么会这样?为了能够在新创建的CKEditor实例中拖放示例的hcards等内容,我该怎么做?

提前致谢。

1 个答案:

答案 0 :(得分:3)

它看起来像编辑器核心中的一个讨厌的bug。我检查了它并报告了一张票:https://dev.ckeditor.com/ticket/14339在修复票证之前,我所能建议的是在编辑器娱乐中重新连接dragstart事件。您可以在插件CKEDITOR.document.getById('contactList').on('dragstart', ... );方法中添加:init。在这样的更改拖放应该工作,但dragstart将被多次触发。您可以在再次附加dragstart事件之前将其分离,以便一切正常。