【问题标题】:CKEditor 4 and jQuery UI sortable removes content after sortingCKEditor 4 和 jQuery UI 可排序在排序后删除内容
【发布时间】:2026-01-18 01:05:01
【问题描述】:

我遇到了 CKEditor 4 和 jQuery UI 的 sortable 方法的问题,如果我对具有 CKEditor 实例的容器进行排序,它会删除该值并抛出错误“Uncaught TypeError: Cannot call method 'getSelection' of undefined ”。它还使编辑器无法编辑。我能够在 CKEditor 3 中通过以下技巧之一解决这个问题: CKEditor freezes on jQuery UI Reorder

在查看 Chrome DOM 检查器时,iframe 的内容似乎已被删除。

下面是粗略的测试代码:

测试

标签: jquery-ui ckeditor jquery-ui-sortable


【解决方案1】:

我遇到了同样的问题,并根据此处的答案进行了修复。请看下面的小提琴

问题: https://jsfiddle.net/33qt24L9/1/

  $(function() {
        $( "#sortable" ).sortable({
      placeholder: "ui-state-highlight"
    });

       CKEDITOR.replace( 'editor1' );
       CKEDITOR.replace( 'editor2' );
       CKEDITOR.replace( 'editor3' );
       CKEDITOR.replace( 'editor4' );

  });

已解决的问题:https://jsfiddle.net/57djq2bh/2/

  $(function() {
        $( "#sortable" ).sortable({
      placeholder: "ui-state-highlight",

             start: function (event, ui) 
        {
            var id_textarea = ui.item.find(".ckeditor").attr("id");
            CKEDITOR.instances[id_textarea].destroy();
        },
        stop: function (event, ui) 
        {
            var id_textarea = ui.item.find(".ckeditor").attr("id");
            CKEDITOR.replace(id_textarea);
        }           

    });

       CKEDITOR.replace( 'editor1' );
       CKEDITOR.replace( 'editor2' );
       CKEDITOR.replace( 'editor3' );
       CKEDITOR.replace( 'editor4' );

  });

编辑:如果像我一样,您对每个编辑器都有单独的配置,这里的更新代码会有所帮助:

start: function (event, ui)
        {
            $('.wysiwyg', ui.item).each(function(){
                var tagId = $(this).attr('id');
                var ckeClone = $(this).next('.cke').clone().addClass('cloned');
                ckeConfigs[tagId] = CKEDITOR.instances[tagId].config;
                CKEDITOR.instances[tagId].destroy();
                $(this).hide().after(ckeClone);
            });
        },

        stop: function(event, ui) {
            // for each textarea init ckeditor anew and remove the clone
            $('.wysiwyg', ui.item).each(function(){
                var tagId = $(this).attr('id');
                CKEDITOR.replace(tagId, ckeConfigs[tagId]);
                $(this).next('.cloned').remove();
            });
        }

感谢:https://github.com/trsteel88/TrsteelCkeditorBundle/issues/53

【讨论】:

    【解决方案2】:

    一旦底层 DOM 结构被修改,您必须重新创建 CKEditor。使用editor.getData()editor.destroy() 之前保存编辑器数据,并在创建新实例后使用editor.setData( data ) 恢复内容。由于 CKEditor 强烈依赖 DOM 结构,因此没有其他方法可以解决此问题。

    【讨论】:

    • 使用 destroy() 并重新创建实例似乎可以解决问题。
    • 有没有简单的方法来保留撤销/重做数据?
    【解决方案3】:

    下面的代码对我有用,我们必须在启动时销毁编辑器,并在拖动结束时重新创建它,获取来自数据的 textarea 的值:

    jQuery(function($) 
    {
        var panelList = $("#nameofyourdiv");
        panelList.sortable(
        {
            handle: ".classofyourdivforsorting", 
            start: function (event, ui) 
            {
                var id_textarea = ui.item.find("textarea").attr("id");
                CKEDITOR.instances[id_textarea].destroy();
            } 
            stop: function (event, ui) 
            {
                var id_textarea = ui.item.find("textarea").attr("id");
                CKEDITOR.replace(id_textarea);
            }           
        });
    });
    

    希望对某人有所帮助。

    【讨论】:

      【解决方案4】:

      删除CKEditor start Sortable

      var ckeConfigs = [];
      $('.ui-sortable').sortable({
       start:function (event,ui) {
        $('.lineItemCommentBox', ui.item).each(function(){
          var tagId = $(this).attr('id');
              ckeConfigs[tagId] = CKEDITOR.instances[tagId].config;
          CKEDITOR.instances[tagId].destroy();
        });
       },
       stop: function(event, ui) {
        $('.lineItemCommentBox', ui.item).each(function(){
         var tagId = $(this).attr('id');
         CKEDITOR.replace(tagId, ckeConfigs[tagId]);
        });
       }
      });
      

      【讨论】:

        【解决方案5】:

        我已经通过在打开 jquery 对话框后实例化 CKEditor 解决了此类问题

        【讨论】:

          【解决方案6】:

          我遇到了与 CKEDITOR 类似的问题,下面的代码对我有用。销毁 Ckeditor 实例并删除 Ckeditor 并在拖动结束时再次用 Ckeditor 替换当前文本区域

           $("#sortable").sortable({
                  items: '.dynamic',
                  start: function (event , ui) {
          
                          var editorId = $(ui.item).find('.ckeditor').attr('id');// get the id of your Ckeditor
                          editorInstance = CKEDITOR.instances[editorId]; // Get the Ckeditor Instance
                          editorInstance.destroy(); // Destroy it
                          CKEDITOR.remove(editorId);// Remove it
          
                  },
                  stop: function(event, ui) { 
                          var editorId = $(ui.item).find('.ckeditor').attr('id');// Get the Id of your Ckeditor 
                          CKEDITOR.replace(editorId);// Replace it
                      }
                  } 
          
              });
              $("#sortable").disableSelection();
          

          这里#sortable可排序的DIV的id'.dynamic'是分配给有资格排序的 DIV 的类,'.ckeditor' 是 Textarea 的类。

          我从 Here 获得了我的解决方案,希望这对将来的某人有所帮助。

          【讨论】:

            【解决方案7】:

            我只是使用 ckeditorOff() 和 ckeditorOn() 函数在移动过程中保存数据和重新/取消实例化 ckeditor 实例。

            $('#sortable').sortable({
                cursor: 'move',
                start:function (event,ui) {
                    if(typeof ckeditorOff=='function')ckeditorOff();
                },
                stop: function(event, ui) { 
                    if(typeof ckeditorOn=='function')ckeditorOn();
                } 
            });
            

            我添加了typeof ckeditorOff 语句以使代码与ckeditor 的未来版本兼容,以防他们决定删除这两个功能。

            【讨论】:

            • CKEditor 是否提供了特定的“ckeditorOff”和“ckeditorOn”功能?
            • 不,我只是按原样粘贴代码。我认为 ckeditorOff 和 On 是全局命令。我认为他们不会在不久的将来移除它们。
            • ckeditorOff() 和 ckeditorOn()?它们是 ckeditor 原生的。当您包含源代码时,它们会由 ckeditor js 自动定义。
            • 不幸的是,他们不是。只需尝试在source 中查找它们。虽然缩小了函数名称必须在某个地方,但它们不是。
            • 好的,请告诉我您正在使用哪个版本的 ckeditor,我会制作一个适用于您正在使用的版本的 sol。我使用的是 wordpress ckeditor 插件附带的 ckeditor。我使用的主题是动态创建搞砸 ckeditor 的评论字段。我想我可以发布 ckeditorOn / Off 的定义,这样其他人就不必受苦了。