CKEditor 4 and jQuery UI sortable remove content after sort

I have a problem with CKEditor 4 and jQuery UI sortable method, where if I sort the container with the CKEditor instance, it deletes the value and gives the error message "Uncaught TypeError: Cannot call getSelection from undefined". It also makes the editor unchanged. I was able to get around this in CKEditor 3 using one of the following hacks found here: CKEditor hangs when jQuery UI reorders

When you look at the Chrome DOM inspector, you will see that the contents of the iframe are deleted.

The following is the raw 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 : // / questions / 870955 / 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> 
+6
source share
6 answers

You need to recreate CKEditor after changing the structure of the DOM. Save the editor data with editor.getData() to editor.destroy() and restore the contents with editor.setData( data ) after creating a new instance. There is no other way to fix this, since CKEditor is highly dependent on the DOM structure.

+3
source

I ran into the same problem and fixed the answers to them. Please see the scripts below.

QUESTION: 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 QUESTION: 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 I had separate configurations for each editor, the code was updated here to 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: https://github.com/trsteel88/TrsteelCkeditorBundle/issues/53

+2
source

I solved this problem by creating an instance of CKEditor after opening the jquery dialog

0
source

The code below works, we need to destroy the editor at startup and recreate it when the drag and drop is completed, getting the textarea value from which the data comes:

 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 this helps someone.

0
source

I had a similar problem with CKEDITOR, The Code Below worked for me. Destroy the Ckeditor instance and delete the Ckeditor, and when the drag is done, replace the current text area 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 sorted and '. dynamic ' is the Class assigned by the DIV that has the right to sort, and '. Ckeditor ' is a class for Textarea.

I got my decision from Here , Hope this helps someone in the future.

0
source

I just use the functions ckeditorOff () and ckeditorOn () to store data and re-instances of ckeditor during the move.

 $('#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 so that the code is compatible with future versions of ckeditor if they decide to remove these two functions.

-1
source

All Articles