Подтвердить что ты не робот

Экземпляр CKEditor уже существует

Я использую диалоги jquery для представления форм (выбираемых через AJAX). В некоторых формах я использую CKEditor для текстовых областей. Редактор отображает штраф при первой загрузке.

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

uncaught exception: [CKEDITOR.editor] The instance "textarea_name" already exists.

API включает в себя метод уничтожения существующих редакторов, и я видел, как люди утверждают, что это решение:

if (CKEDITOR.instances['textarea_name']) {
CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name');

Это не работает для меня, поскольку вместо этого я получаю новую ошибку:

TypeError: Result of expression 'i.contentWindow' [null] is not an object.

Эта ошибка, похоже, встречается на "destroy()", а не на "replace()". Кто-нибудь испытал это и нашел другое решение?

Возможно ли "повторно отобразить" существующий редактор, а не уничтожить его и заменить?

ОБНОВЛЕНО Вот еще один вопрос, касающийся одной и той же проблемы, но он предоставил загружаемый тестовый пример.

4b9b3361

Ответ 1

Для этого вам необходимо передать логический параметр true при уничтожении экземпляра:

    var editor = CKEDITOR.instances[name];
    if (editor) { editor.destroy(true); }
    CKEDITOR.replace(name);

Ответ 2

function loadEditor(id)
{
    var instance = CKEDITOR.instances[id];
    if(instance)
    {
        CKEDITOR.remove(instance);
    }
    CKEDITOR.replace(id);
}

Ответ 3

У меня тоже была эта проблема, но я решил ее гораздо проще...

Я использовал класс "ckeditor" в своем jQuery script как селектор, для которого текстовые поля, которые я хотел использовать для CKEditor. По умолчанию ckeditor JS script также использует этот класс, чтобы определить, какие текстовые области использовать для CKEditor.

Это означает, что существует конфликт между моим jQuery script и стандартным ckeditor script.

Я просто изменил класс textarea и моего jQuery script на do_ckeditor (вы могли использовать что-либо, кроме "ckeditor" ), и оно сработало.

Ответ 4

Это самое простое (и единственное) решение, которое сработало для меня:

if(CKEDITOR.instances[editorName])
   delete CKEDITOR.instances[editorName];
CKEDITOR.replace(editorName);

Удаление этой записи в массиве предотвращает эту проверку безопасности формы от уничтожения вашего приложения.

destroy() и remove() не работает для меня.

Ответ 5

Возможно, это поможет вам - я сделал что-то подобное, используя jquery, за исключением того, что загружаю неизвестное количество объектов ckeditor. Мне потребовалось некоторое время, чтобы наткнуться на это - это не ясно в документации.

function loadEditors() {
    var $editors = $("textarea.ckeditor");
    if ($editors.length) {
        $editors.each(function() {
            var editorID = $(this).attr("id");
            var instance = CKEDITOR.instances[editorID];
            if (instance) { instance.destroy(true); }
            CKEDITOR.replace(editorID);
        });
    }
}

И вот что я запускаю, чтобы получить содержимое от редакторов:

    var $editors = $("textarea.ckeditor");
    if ($editors.length) {
        $editors.each(function() {
            var instance = CKEDITOR.instances[$(this).attr("id")];
            if (instance) { $(this).val(instance.getData()); }
        });
    }

ОБНОВЛЕНИЕ. Я изменил свой ответ на использование правильного метода - это .destroy()..remove() означает, что он является внутренним, и некорректно документирован в какой-то момент.

Ответ 6

var e= CKEDITOR.instances['sample'];
e.destroy();
e= null;

Ответ 7

У меня была аналогичная проблема, когда мы делали несколько экземпляров CKeditor для содержимого, загруженного через ajax.

CKEDITOR.remove()

Удерживал DOM в памяти и не удалял все привязки.

CKEDITOR.instance [instance_id].destroy()

Выдача ошибки i.contentWindow при создании нового экземпляра с новыми данными из ajax. Но это было только до тех пор, пока я не понял, что уничтожал экземпляр после очистки DOM.

Используйте destroy(), в то время как экземпляр и его DOM присутствует на странице, тогда он отлично работает.

Ответ 8

Для запросов ajax

 for(k in CKEDITOR.instances){
    var instance = CKEDITOR.instances[k];
    instance.destroy()
 }
  CKEDITOR.replaceAll();

этот снимок удаляет все экземпляры из документа. Затем создаются новые экземпляры.

Ответ 9

Ошибка i.contentWindow is null возникает при вызове destroy в экземпляре редактора, который больше не привязан к текстовой области в DOM.

CKEDITORY.destroy принимает параметр noUpdate.

В APIdoc говорится:

Если экземпляр заменяет элемент DOM, этот параметр указывает, следует ли обновлять элемент содержимым экземпляра.

Итак, чтобы избежать ошибки, либо уничтожьте вызов перед удалением элемента textarea из DOM, либо вызовите destory (true), чтобы не пытаться обновить несуществующий элемент DOM.

if (CKEDITOR.instances['textarea_name']) {
   CKEDITOR.instances['textarea_name'].destroy(true);
}

(с использованием версии 3.6.2 с адаптером jQuery)

Ответ 10

Вы можете удалить любой экземпляр ckeditor, удалив метод ckeditor. Экземпляром будет id или имя текстового поля.

if (CKEDITOR.instances[instance_name]) {
    CKEDITOR.remove(CKEDITOR.instances[instance_name]);
}

Ответ 11

Это то, что сработало для меня:

for(name in CKEDITOR.instances)
{
  CKEDITOR.instances[name].destroy()
}

Ответ 12

CKEDITOR.instances = new Array();

Я использую это перед моими вызовами для создания экземпляра (нагрузка на одну страницу). Не уверен, как это влияет на обработку памяти, а что нет. Это будет работать, только если вы хотите заменить все экземпляры на странице.

Ответ 13

Я подготовил собственное решение на основе всех вышеперечисленных кодов.

      $("textarea.ckeditor")
      .each(function () {

                var editorId = $(this).attr("id");

                try {    
                    var instance = CKEDITOR.instances[editorId];
                    if (instance) { instance.destroy(true); }

                }
                catch(e) {}
                finally {
                    CKEDITOR.replace(editorId);
                }
            });

Он отлично работает для меня.

Иногда после запроса AJAX возникает неправильная структура DOM. Для instace:

<div id="result">
   <div id="result>
   //CONTENT
   </div>
</div>

Это также вызовет проблему, и ckEditor не будет работать. Поэтому убедитесь, что у вас есть правильная структура DOM.

Ответ 14

У меня была такая же проблема с экземплярами, я всюду смотрел, и, наконец, эта реализация работает для меня:



    //set my instance id on a variable

    myinstance = CKEDITOR.instances['info'];

    //check if my instance already exist

    if (myinstance) { 
        CKEDITOR.remove(info)
    }

    //call ckeditor again

    $('#info').ckeditor({
        toolbar: 'Basic',
        entities: false,
        basicEntities: false
    });

Ответ 15

Я узнал, что

удалить CKEDITOR.instances [имя_редактора];

сам по себе, фактически удалил экземпляр. Все другие методы, которые я прочитал и увидели, в том числе то, что было найдено здесь в stackoverflow от его пользователей, не сработало для меня.

В моей ситуации im использует вызов ajax, чтобы вытащить копию содержимого, обернутого вокруг и. Проблема заключается в том, что я использую событие jQuery.live, чтобы связать ссылку "Изменить этот документ", а затем применить экземпляр ckeditor после успеха загрузки ajax. Это означает, что, когда я нажимаю другую ссылку на ссылку с другим событием .live, я должен использовать delete CKEDITOR.instances [имя_редактора] как часть моей задачи по очистке окна содержимого (сохранение формы), затем повторное извлечение содержимого в базе данных или другом ресурсе.

Ответ 16

У меня была та же проблема с диалоговом окне jQuery.

Зачем уничтожать экземпляр, если вы просто хотите удалить предыдущие данные?

function clearEditor(id)
{
  var instance = CKEDITOR.instances[id];
  if(instance)
  {
    instance.setData( '' );
  }
}

Ответ 17

Я решил переименовать все экземпляры вместо destroy/replace - так как иногда загруженный экземпляр AJAX на самом деле не заменяет тот, который находится в ядре страницы... сохраняет больше в ОЗУ, но меньше конфликтует таким образом.

    if (CKEDITOR && CKEDITOR.instances) {
        for (var oldName in CKEDITOR.instances) {
            var newName = "ajax"+oldName;
            CKEDITOR.instances[newName] = CKEDITOR.instances[oldName];
            CKEDITOR.instances[newName].name = newName;
            delete CKEDITOR.instances[oldName];
        }
    }

Ответ 18

Я нахожусь в ситуации, когда мне нужно контролировать диалоги появления, каждый из них должен иметь встроенный cceditor внутри этих диалогов. И так бывает, что текстовые области имеют один и тот же идентификатор. (обычно это очень плохая практика, но у меня есть 2 jqGrids, один из назначенных элементов и другой из неназначенных элементов.) Они имеют почти идентичную конфигурацию. Таким образом, я использую общий код для настройки обоих.

Итак, когда я загружаю диалоговое окно, добавляя строки или редактируя их, либо из jqGrid; Я должен удалить все экземпляры CKEDITOR во всех текстовых областях.

$('textarea').each(function()
{
    try 
    {
        if(CKEDITOR.instances[$(this)[0].id] != null)
        {
            CKEDITOR.instances[$(this)[0].id].destroy();
        }
    }
    catch(e)
    {

    }
});

Это будет охватывать все текстовые области, а если есть экземпляр CKEDITOR, то уничтожьте его.

Альтернативно, если вы используете чистый jQuery:

$('textarea').each(function()
{
    try 
    {
        $(this).ckeditorGet().destroy();
    }
    catch(e)
    {

    }
});

Ответ 19

удалить class="ckeditor", возможно, это вызвало инициализацию ckeditor

Ответ 20

Действительно, удаление класса ".ckeditor" из вашего кода решает проблему. Большинство из нас следовали примеру интеграции jQuery из документации ckeditor:

$('.jquery_ckeditor')
.ckeditor( function() { /* callback code */ }, { skin : 'office2003' } );

и подумал: "Может быть, я могу просто избавиться или".jquery_ "?".

Я тратил свое время на настройку функции обратного вызова (потому что {skin: 'office2003'} действительно работал), в то время как проблема исходила из других источников.

Я думаю, что в документации должно быть указано, что использование "ckeditor" в качестве имени класса не рекомендуется, поскольку это зарезервированное ключевое слово.

Приветствия.

Ответ 21

У меня была такая же проблема, когда я получал исключение с ссылкой на null, и в редакторе отображалось слово "null". Я попробовал несколько решений, включая обновление редактора до 3.4.1 безрезультатно.

Мне пришлось редактировать источник. Примерно в строке 416 - 426 в _source\plugins\wysiwygarea\plugin.js есть такой фрагмент:

iframe = CKEDITOR.dom.element.createFromHtml( '&lt;iframe' + ... + '></iframe>' );

В FF, по крайней мере, iframe не полностью создается на время, когда это необходимо. Я окружил остальную функцию после этой строки с помощью функции setTimeout:

iframe = CKEDITOR.dom.element.createFromHtml( '<iframe' + ... + '></iframe>' );
setTimeout(function()
{ 
    // Running inside of Firefox chrome the load event doesn't bubble like in a normal page (#5689)
    ...
}, 1000);

};

// The script that launches the bootstrap logic on 'domReady', so the document
...

Текст отображается последовательно в модальных диалогах.

Ответ 22

Чтобы поддерживать динамическую (Ajax) загрузку форм (без обновления страницы между ними), которые содержат текстовые поля с тем же (одна и та же форма вызывается снова) или другой идентификатор (ранее выгруженная форма) и конвертируют их в элементы CKEditor, я сделал следующее ( с помощью адаптера JQuery):

После того, как страница завершила каждый вызов Ajax, который доставляет текстовое поле для преобразования, я делаю вызов следующей функции:

setupCKeditor()

Это выглядит так (предполагается, что ваши текстовые области, которые будут преобразованы в RTE, имеют class= "yourCKClass" ):

    /* Turns textAreas into TinyMCE Rich Text Editors where
 * class: tinymce applied to textarea.
 */
function setupCKeditor(){

    // define editor configuration      
    var config = {skin : 'kama'};

    // Remove and recreate any existing CKEditor instances
    var count = 0;
    if (CKEDITOR.instances !== 'undefined') {
        for(var i in CKEDITOR.instances) {

            var oEditor   = CKEDITOR.instances[i];
            var editorName = oEditor.name;

             // Get the editor data.
            var data = $('#'+editorName).val();

            // Check if current instance in loop is the same as the textarea on current page
            if ($('textarea.yourCKClass').attr('id') == editorName) {
                if(CKEDITOR.instances[editorName]) {

                    // delete and recreate the editor
                    delete CKEDITOR.instances[editorName];
                    $('#'+editorName).ckeditor(function() { },config);
                    count++;

                }
            }   


        }
    }

    // If no editor exist in the DOM, create any that are needed.             
    if (count == 0){

        $('textarea.yourCKClass').each( function(index) {

                var editorName = $(this).attr('id');
                $('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);

            });

    }


}

Следует отметить, что строка:

$('#'+editorName).ckeditor(function() { $('#'+editorName).val(data); },config);

может (и должен) быть просто:

$('#'+editorName).ckeditor(function() { },config);

однако я обнаружил, что редактор часто показывал правильный контент на секунду после загрузки, и они пустым редактором желаемого контента. Таким образом, строка с кодом обратного вызова заставляет контент CKEditor быть таким же, как исходный контент textarea. При использовании мерцает. Если вы можете избежать его использования, сделайте это.

Ответ 23

У меня была такая же проблема, как и Jackboberg. Я использовал динамическую загрузку формы в диалоговом окне jquery, а затем добавлял различные виджеты (datepickers, ckeditors и т.д.). И я попробовал все решения, упомянутые выше, ни один из них не работал у меня.

По какой-то причине ckeditor приложил только первый раз, когда я загрузил форму, во второй раз я получил точно такое же сообщение об ошибке jackboberg.

Я проанализировал свой код и обнаружил, что если вы прикрепляете ckeditor в "mid-air", то есть пока содержимое формы все еще не помещено в диалог, ckeditor не будет надлежащим образом прикреплять свои привязки. Это происходит потому, что ckeditor прилагается в "воздухе", во второй раз вы присоединяете его в "воздухе"... poof... ошибка вызывается, поскольку первый экземпляр не был правильно удален из DOM.

Это был мой код, который ptoduced ошибка:

var $content = $(r.content); // jQuery can create DOM nodes from html text gotten from <xhr response> - so called "mid-air" DOM creation
$('.rte-field',$content).ckeditor(function(){});
$content.dialog();

Это исправление, которое сработало:

var $content = $(r.content).dialog(); // first create dialog
$('.rte-field',$content).ckeditor(function(){}); // then attach ckeditor widget

Ответ 24

Я столкнулся с этим одним и тем же, и проблема заключалась в том, что плагин wordcount слишком долго запускался для инициализации. 30 секунд. Пользователь щелкнет мышью на представлении, отображающем ckeditor, затем отменит, тем самым ajax-загружая новую страницу в dom. Плагин жаловался, потому что iframe или любой другой контент, который указывает на него, уже не был виден к тому времени, когда он был готов добавить себя в contentWindow. Вы можете проверить это, щелкнув мышью в своем представлении, а затем ожидая, когда число слов появится в правом нижнем углу редактора. Если вы отмените сейчас, у вас не будет проблем. Если вы не дождались этого, вы получите i.contentWindow null-ошибку. Чтобы исправить это, просто отмените плагин:

if (CKEDITOR.instances['textarea_name']) 
{
   CKEDITOR.instances['textarea_name'].destroy();
}
CKEDITOR.replace('textarea_name', { removePlugins: "wordcount" } );

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

Ответ 25

Для тех, кто использует jQuery "адаптер" и имеет проблемы (как я был), поскольку супер хакерское, но работающее решение должно сделать что-то вроде этого:

// content editor plugin
(function($){
    $.fn.contentEditor = function( params ) {
        var xParams = $.extend({}, $.fn.contentEditor.defaultParams, params);
        return this.each( function() {   
            var $editor = $(this);
            var $params = $.extend({}, xParams, $editor.data());

            // if identifier is set, detect type based on identifier in $editor
            if( $params.identifier.type ) {
                $params.type = $editor.find($params.identifier.type).val();
            }

            $editor.data('type', $params.type);

            // edit functionality
            editButton = $('<button>Edit Content</button>').on('click',function(){
                // content container
                var $cc = $('#' + $editor.data('type'));

                // editor window
                var $ew = $('<form class="editorWindow" />');
                $ew.appendTo('body');

                // editor content
                $ec = $('<textarea name="editorContent" />').val($cc.html());
                $ec.appendTo($ew);
                $ec.ckeditor();


                //$ec.ckeditorGet().setMode('source');


                $ew.dialog({
                    "autoOpen": true,
                    "modal": true,
                    "draggable": false,
                    "resizable": false,
                    "width": 850,
                    "height": 'auto',
                    "title": "Content Editor",
                    "buttons": { 
                        'Save': function() {                            
                            $cc.html( $ec.val() );
                            $ec.ckeditorGet().destroy(); 
                            $ew.remove();
                        },
                        'Cancel / Close': function() { 

                            $ec.ckeditorGet().destroy();                        
                            $ew.remove();
                        }
                    },
                    'close': function() {
                        $ec.ckeditorGet().destroy(); 
                    },
                    'open': function() {
                        $ew.find('a.cke_button_source').click();

                        setTimeout(function(){
                            $ew.find('a.cke_button_source.cke_on').click();
                        }, 500);
                    }
                });

                return false;
            });

            editButton.appendTo( $editor );

        });
    }

    // set default option values
    $.fn.contentEditor.defaultParams = {
        'identifier': {
            'type': 'input[name="type"]'
        }
    };   

})(jQuery);   

$(function(){

    $('form.contentEditor').contentEditor();

});

Ключевым моментом является эта часть:

                'open': function() {
                    $ew.find('a.cke_button_source').click();

                    setTimeout(function(){
                        $ew.find('a.cke_button_source.cke_on').click();
                    }, 500);
                }

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

Ответ 26

Это полностью рабочий код для jquery.load() api и ckeditor, в моем случае я загружаю страницу ckeditor в div с некоторыми эффектами jquery. Надеюсь, это поможет вам.

 $(function() {
            runEffect = function(fileload,lessonid,act) {
            var selectedEffect = 'drop';
            var options = {};
            $( "#effect" ).effect( selectedEffect, options, 200, callback(fileload,lessonid,act) );
        };
        function callback(fileload,lessonid,act) {
            setTimeout(function() {//load the page in effect div
                $( "#effect" ).load(fileload,{lessonid:lessonid,act:act});
                 $("#effect").show( "drop", 
                          {direction: "right"}, 200 );
                $("#effect").ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) {
                    loadCKeditor(); //call the function after loading page
                });
            }, 100 );   
        };

        function loadCKeditor()
        {//you need to destroy  the instance if already exist
            if (CKEDITOR.instances['introduction']) 
            {
                CKEDITOR.instances['introduction'].destroy();
            }
            CKEDITOR.replace('introduction').getSelection().getSelectedText();
        }
    });

===================== button for call the function ================================

<input type="button" name="button" id="button" onclick="runEffect('lesson.php','','add')" >

Ответ 27

Это довольно просто. В моем случае я выполнил метод jquery ниже, который уничтожит экземпляры ckeditor во время загрузки страницы. Это сделало трюк и решило проблему -

Метод JQuery -

function resetCkEditorsOnLoad(){

    for(var i in CKEDITOR.instances) {
        editor = CKEDITOR.instances[i];
            editor.destroy();
            editor = null;
    }
}

$(function() {

            $(".form-button").button();
    $(".button").button();

    resetCkEditorsOnLoad(); // CALLING THE METHOD DURING THE PAGE LOAD

            .... blah.. blah.. blah.... // REST OF YOUR BUSINESS LOGIC GOES HERE

       });

Что это. Надеюсь, это поможет вам.

Cheers, Сириш.

Ответ 28

Эти функции работают для меня в версии 4.4.5 CKEditor, у нее нет утечек памяти

 function CKEditor_Render(CkEditor_id) {
        var instance = CKEDITOR.instances[CkEditor_id];
        if (CKEDITOR.instances.instance) {
            CKEDITOR.instances.instance.destroy();
        }
        CKEDITOR.replace(CkEditor_id);
    }

//вызываем эту функцию ниже

var id = 'ckeditor'; // Id of your textarea

CKEditor_Render(id);

Ответ 29

CKeditor 4.2.1

Здесь много ответов, но для меня мне нужно было что-то еще (немного грязно, поэтому, если кто-то может улучшить, пожалуйста, сделайте это). Для меня MODALs, где моя проблема.

Я делал CKEditor в модальном режиме, используя Foundation. В идеале я бы отстранил редактора после закрытия, однако я не хотел связываться с Фондом.

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

Я использовал textarea для заполнения не DIV.

Мое решение

//hard code the DIV removal (due to duplication of CKeditors on page however they didn't work)

    $("#cke_myckeditorname").remove();


     if (CKEDITOR.instances['myckeditorname']) {
                delete CKEDITOR.instances['myckeditorname'];
                CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
            } else {
                CKEDITOR.replace('myckeditorname', GetCKEditorSettings());
            }

Это был мой метод, чтобы вернуть мое конкретное форматирование, которое вам может не понадобиться.

    function GetCKEditorSettings()
    {
       return {
                    linkShowAdvancedTab: false,
                    linkShowTargetTab: false,
                    removePlugins: 'elementspath,magicline',
                    extraAllowedContent: 'hr blockquote div',
                    fontSize_sizes: 'small/8px;normal/12px;large/16px;larger/24px;huge/36px;',
                    toolbar: [
                        ['FontSize'],
                        ['Bold', 'Italic', 'Underline', '-', 'NumberedList', 'BulletedList', '-', 'Link', 'Unlink'],
                        ['Smiley']
                    ]
                };
    }

Ответ 30

Попробуйте следующее:

for (name in CKEDITOR.instances)
{
    CKEDITOR.instances[name].destroy(true);
}