CKEditor 4 and jQuery UI sortable removes content after sorting

[亡魂溺海] 提交于 2020-07-20 07:35:27

问题


I've ran into an issue with CKEditor 4 and jQuery UI's sortable method where if I sort a container that has a CKEditor instance, it removes the value and throws an error "Uncaught TypeError: Cannot call method 'getSelection' of undefined". It also makes the editor uneditable. I was able to get around this in CKEditor 3 with one of the following hacks found here: CKEditor freezes on jQuery UI Reorder

In looking at the Chrome DOM inspector, it appears that the contents of the iframe are removed.

Below is crude test code:


    <html>
    <head>
        <title>test</title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js"></script>
        <script src="ckeditor.js"></script>
        <script type="text/javascript">
        $(function(){

            var tmpStore = {};
            $('#sortable').sortable({
                cursor: 'move',

                // Hack that use to work on V3 but not on V4:
                // https://stackoverflow.com/questions/3379653/ckeditor-freezes-on-jquery-ui-reorder
                start:function (event,ui) {
                    $('textarea').each(function(){
                        var id = $(this).attr('id');
                        tmpStore[id] = CKEDITOR.instances[id].getData();
                    })
                 },
                stop: function(event, ui) { 
                    $('textarea').each(function(){
                        var id = $(this).attr('id');
                        CKEDITOR.instances[id].setData(tmpStore[id]);
                    })
                  }
            });
            $('textarea').each(function(){
                var ckId = $(this).attr('id');
                config = {};
                CKEDITOR.replace(ckId, config);
            })
        })

        
        
        li { padding: 10px; width: 800px; height: 300px; }
        
    </head>
    <body>
        <ul id="sortable">
            <li><textarea id="test1" name="test1">test1</textarea></li>
            <li><textarea id="test2" name="test1">test2</textarea></li>
            <li><textarea id="test3" name="test1">test3</textarea></li>
        </ul>
    </body>
    </html>


回答1:


I was facing the same problem and have fixed based on answers here. Please see fiddles below

ISSUE: https://jsfiddle.net/33qt24L9/1/

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

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

  });

RESOLVED ISSUE: 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' );

  });

EDIT: If like me you had seperate configs per editor here's updated code that will help:

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

Thanks to: https://github.com/trsteel88/TrsteelCkeditorBundle/issues/53




回答2:


You have to re-create CKEditor once underlying DOM structure is modified. Save editor data with editor.getData() before editor.destroy() and restore contents with editor.setData( data ) once you create a new instance. There's no other way to fix this since CKEditor strongly depends on the DOM structure.




回答3:


i ve solved this kind of problem by instantiating the CKEditor after having opened the jquery dialog




回答4:


The code below works for me, we have to destroy the editor on start and recreate it when the drag is ended getting the value of the textarea which come the data from :

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

Hope it helps someone.




回答5:


I had the Similar issue with CKEDITOR , The Code Below worked for me. Destroy the Ckeditor instance and Remove the Ckeditor and when the dragging ends replace the current textarea with Ckeditor again

 $("#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();

Here #sortable is the id of the DIV which is sortable and '.dynamic' is the Class assigned to DIV that are eligible to sort and '.ckeditor' is the class for the Textarea .

I got my solution from Here , Hope this helps for someone in future.




回答6:


Remove 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]);
  });
 }
});



回答7:


I simply use the ckeditorOff() and ckeditorOn() functions to keep data and re/de-instance ckeditor instances during movement.

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

I put the typeof ckeditorOff statement to make the code compatible with future versions of ckeditor in case they decide to remove these two functions.



来源:https://stackoverflow.com/questions/15124860/ckeditor-4-and-jquery-ui-sortable-removes-content-after-sorting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!