web-dev-qa-db-ja.com

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.

このエラーは、「replace()」ではなく「destroy()」で発生するようです。誰かがこれを経験し、別の解決策を見つけましたか?

既存のエディターを破棄して置き換えるのではなく、「再レンダリング」することは可能ですか?

更新ここに別の質問があります 同じ問題に対処していますが、彼は ダウンロード可能なテストケースを提供しています

97
jackboberg

これを機能させるには、インスタンスを破棄するときにブールパラメータtrueを渡す必要があります。

    var editor = CKEDITOR.instances[name];
    if (editor) { editor.destroy(true); }
    CKEDITOR.replace(name);
97
Tomas Kirda
function loadEditor(id)
{
    var instance = CKEDITOR.instances[id];
    if(instance)
    {
        CKEDITOR.remove(instance);
    }
    CKEDITOR.replace(id);
}
27
Jim

私もこの問題を抱えていましたが、もっと簡単な方法で解決しました...

私はjQueryスクリプトでCKEditorに使用したいテキストエリアのセレクターとしてクラス「ckeditor」を使用していました。デフォルトのckeditor JSスクリプトもこのクラスを使用して、CKEditorに使用するテキストエリアを識別します。

これは、jQueryスクリプトとデフォルトのckeditorスクリプトの間に矛盾があることを意味します。

テキストエリアのクラスとjQueryスクリプトを「do_ckeditor」(「ckeditor」以外のものを使用できます)に変更しただけで機能しました。

19
MintDeparture

これは私のために働いた最も簡単な(そして唯一の)ソリューションです:

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

配列内のこのエントリを削除すると、このフォームの安全性チェックでアプリケーションが破壊されなくなります。

destroy()およびremove()が機能しませんでした。

11
adu

おそらくこれはあなたを助けるでしょう-未知の数のckeditorオブジェクトをロードしていることを除いて、jqueryを使用して同様のことをしました。これに出くわすのにしばらく時間がかかりました-ドキュメントでは明確ではありません。

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

UPDATE:正しい方法を使用するように答えを変更しました-.destroy()です。 .remove()は内部的なものであり、ある時点では不適切に文書化されていました。

7
ScottE

Ajaxリクエストの場合、

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

これにより、ドキュメントからすべてのインスタンスが削除されます。次に、新しいインスタンスを作成します。

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

私は、ajaxを介してロードされたコンテンツ用にCKeditorのインスタンスをいくつか作成していたという同様の問題を抱えていました。

CKEDITOR.remove()

DOMをメモリに保持し、すべてのバインディングを削除しませんでした。

CKEDITOR.instance [instance_id] .destroy()

エラーを与えましたi.contentWindow ajaxからの新しいデータで新しいインスタンスを作成するたびにエラーが発生しました。しかし、これは、DOMをクリアした後にインスタンスを破壊していることが判明するまででした。

インスタンスとそのDOMがページに存在している間にdestroy()を使用すると、完全に正常に動作します。

5
Tejas

これは私のために働いたものです:

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

i.contentWindow is nullエラーは、DOMに存在しないtextareaに関連付けられたエディターインスタンスでdestroyを呼び出すときに発生するようです。

CKEDITORY.destroyはパラメーターnoUpdateを取ります。

APIdocの状態:

インスタンスがDOM要素を置き換える場合、このパラメーターは、インスタンスの内容で要素を更新するかどうかを示します。

したがって、エラーを回避するには、DOMからtextarea要素を削除する前にdestroyを呼び出すか、destory(true)を呼び出して、存在しないDOM要素を更新しないようにします。

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

(jQueryアダプターでバージョン3.6.2を使用)

3
Scott Nelson

私はインスタンスで同じ問題を抱えていました、私はどこでも見ていて、最終的にこの実装は私のために機能します:



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

2
e_0910

上記のすべてのコードに基づいて独自のソリューションを準備しました。

      $("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構造が存在する場合があります。インスタンスの場合:

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

これも問題を引き起こし、ckEditorは機能しません。したがって、正しいDOM構造を持っていることを確認してください。

2
Tomasz Maj
CKEDITOR.instances = new Array();

インスタンス(ページの読み込みごとに1つ)を作成する呼び出しの前にこれを使用しています。これがメモリ処理にどのように影響するか、また何が影響しないかはわかりません。これは、ページ上のすべてのインスタンスを置き換える場合にのみ機能します。

2
Andrew

Ckeditorのremoveメソッドにより、ckeditorインスタンスを削除できます。インスタンスは、idまたはtextareaの名前になります。

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

実際、コードから「.ckeditor」クラスを削除することで問題が解決します。私たちのほとんどは、ckeditorのドキュメントのjQuery統合の例に従いました。

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

そして「...多分私はただ取り除くことができるか、「。jquery_」部分」と考えました。

問題が他の場所から来ている間、コールバック関数を微調整するのに時間を無駄にしています({skin: 'office2003'}が実際に機能したため)。

ドキュメンテーションでは、「ckeditor」をクラス名として使用することは予約キーワードであるため推奨されていないと記載すべきだと思います。

乾杯。

1
ramkam

私はダイアログを生成するコントロールをしなければならない状況にあり、それぞれのダイアログ内にckeditorを埋め込む必要があります。そして、テキスト領域が同じIDを共有するのはまさにそのためです。 (通常、これは非常に悪い習慣ですが、割り当てられたアイテムの1つと未割り当てのアイテムの2つのjqGridがあります。)それらはほとんど同じ構成を共有しています。したがって、私は共通のコードを使用して両方を構成しています。

そのため、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)
    {

    }
});
1
DragonZero

私は、それをもう学びました

cKEDITOR.instances [editorName];を削除します。

それ自体で、実際にインスタンスを削除しました。ここでユーザーからstackoverflowで見つかったものを含め、私が読んで見た他のすべての方法は、私にとってはうまくいきませんでした。

私の状況では、ajax呼び出しを使用してandの周りにラップされたコンテンツのコピーをプルします。問題は、jQuery .liveイベントを使用して「このドキュメントを編集」リンクをバインドし、ajaxロードの成功後にckeditorインスタンスを適用しているためです。つまり、別のリンクをクリックして別の.liveイベントとのリンクを作成する場合、コンテンツウィンドウをクリア(フォームを保持)し、保持されているコンテンツを再取得するタスクの一部としてdelete CKEDITOR.instances [editorName]を使用する必要がありますデータベースまたは他のリソース内。

1

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];
        }
    }
1
zeroasterisk

JQuery Dialogでも同じ問題が発生しました。

以前のデータを削除したいだけなのに、なぜインスタンスを破壊するのですか?

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

class="ckeditor"を削除し、ckeditorの初期化をトリガーした可能性があります

1
VKGS

CKeditor 4.2.1

ここにはたくさんの答えがありますが、私にはもっと何かが必要でした(少し汚いので、改善できる人がいればやってください)。私にとっては私の問題のMODAL。

Foundationを使用して、CKEditorをモーダルでレンダリングしていました。理想的には、私は編集者を閉じたときに破壊したでしょうが、私は財団を台無しにしたくありませんでした。

削除と呼ばれ、削除と別の方法を試しましたが、これが最終的に解決しました。

テキスト領域を使用して、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']
                    ]
                };
    }
0
Adam

私はこれとまったく同じことに遭遇し、問題はwordcountプラグインの初期化に時間がかかりすぎたことでした。 30秒以上。ユーザーは、ckeditorを表示するビューをクリックしてからキャンセルし、新しいページをAJAXでdomにロードします。 iFrameまたはcontentWindowが指しているものがcontentWindowに追加する準備が整うまでに表示されなくなったため、プラグインは不平を言っていました。これを確認するには、ビューをクリックし、エディターの右下にワードカウントが表示されるのを待ちます。今すぐキャンセルしても問題はありません。待たないと、i.contentWindow is nullエラーが発生します。修正するには、プラグインを破棄します。

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

Wordカウンターが必要な場合は、エディターで貼り付けイベントとキーアップイベントに登録し、単語をカウントする機能を使用します。

0
Sean Roy

この関数は、CKEditorバージョン4.4.5で機能します。メモリリークはありません。

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

Null参照例外を受け取っていたときに同じ問題が発生し、Wordの「null」がエディターに表示されました。エディターを3.4.1にアップグレードして使用できないようにするなど、いくつかのソリューションを試しました。

ソースを編集する必要がありました。 _source\plugins\wysiwygarea\plugin.jsの行416〜426には、次のようなスニペットがあります。

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
...

テキストは、モーダルダイアログで一貫してレンダリングされるようになりました。

0
Aaron Stemen

これはjquery .load()apiおよびckeditorの完全に機能するコードです。私の場合は、ckqueryorを使用してページをいくつかのjquery効果でdivにロードしています。それがあなたのお役に立てば幸いです。

 $(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')" >
0
Khandad Niazi

これを試して:

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

私は、ジャックボバーグとまったく同じ問題を抱えていました。私はjqueryダイアログに動的なフォームのロードを使用してから、さまざまなウィジェット(datepicker、ckeditorsなど)を添付していました。そして、私は上記のすべての解決策を試しましたが、どれも私にとってはうまくいきませんでした。

なんらかの理由で、ckeditorはフォームを初めてロードしたときにのみ添付され、2回目にはjackbobergが行ったのとまったく同じエラーメッセージが表示されました。

私はコードを分析し、フォームコンテンツがまだダイアログに配置されていない間に「空中」でckeditorをアタッチすると、ckeditorはそのバインディングを適切にアタッチしないことを発見しました。これは、ckeditorが「空中」でアタッチされ、2回目は「空中」でアタッチされるためです... poof ...最初のインスタンスがDOMから適切に削除されなかったため、エラーがスローされます。

これはエラーを発生させた私のコードでした:

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
0
Ivan Hušnjak

Jquery "adapter"を使用していて(私がそうであったように)問題を抱えている人にとって、非常にハック的でありながらも有効な解決策は次のようなことです。

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

これにより、次回ダイアログを開いたときにエディターのテキストが表示されないという問題が修正されます。私はこれが非常にハッキングされていることを理解していますが、これらのほとんどが管理ツールに使用されることを考えると、それが通常のように大きな懸念ではないと思います..これはうまくいくので、うまくいけば誰かを救うでしょう時間;)

0
Eva

とても簡単です。私の場合、ページの読み込み中にckeditorインスタンスを破棄する以下のjqueryメソッドを実行しました。これはトリックを行い、問題を解決しました-

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

       });

それでおしまい。それがあなたのお役に立てば幸いです。

乾杯、シリッシュ。

0
Sirish

エディタの名前がわかっている場合、これは非常に簡単です。

たとえば、エディターの名前がeditor1 (this is the id of div or textarea)の場合、次のようにチェックするだけです。

if(CKEDITOR.instances['editor1']){
   // Instance present
}else{
   // Instance not present 
} 

初期化されたエディターの数を取得したい場合は、次のようにします

for(let inst of CKEDITOR.instances){
   // inst is an Obj of editor instance
   // inst.name will give the name of the editor instance
}
0
Mari Selvan

同じ(同じフォームが再び呼び出される)または異なるID(以前にアンロードされたフォーム)を持つテキストエリアを含むフォーム(ページ更新なし)の動的(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's 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);

ただし、エディターはロード後に1秒間正しいコンテンツを表示することが多く、目的のコンテンツのエディターが空になることがわかりました。そのため、コールバックコードを含む行は、CKEditorコンテンツを元のtextareaコンテンツと同じものにします。使用するとフリッカーが発生します。使用を避けられる場合は、そうしてください。

0
Leafy