99

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()」で発生するようです。誰かがこれを経験し、別の解決策を見つけましたか?

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

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

4

32 に答える 32

104

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

    var editor = CKEDITOR.instances[name];
    if (editor) { editor.destroy(true); }
    CKEDITOR.replace(name);
于 2011-02-01T00:18:10.913 に答える
28
function loadEditor(id)
{
    var instance = CKEDITOR.instances[id];
    if(instance)
    {
        CKEDITOR.remove(instance);
    }
    CKEDITOR.replace(id);
}
于 2010-03-04T06:36:49.830 に答える
19

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

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

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

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

于 2010-09-13T14:59:54.753 に答える
11

これは私のために働いた最も簡単な(そして唯一の)解決策です:

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

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

destroy() と remove() は機能しませんでした。

于 2010-08-02T18:30:05.880 に答える
7

おそらくこれはあなたを助けるでしょう - 私は 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() は内部的なものであり、ある時点で不適切に文書化されていました。

于 2009-11-25T02:15:11.230 に答える
6
var e= CKEDITOR.instances['sample'];
e.destroy();
e= null;
于 2009-12-14T14:22:26.320 に答える
5

ajax 経由で読み込まれたコンテンツに対して CKeditor のインスタンスをいくつか作成していたという同様の問題がありました。

CKEDITOR.remove()

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

CKEDITOR.instance[インスタンス ID].destroy()

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

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

于 2010-11-30T22:02:48.240 に答える
5

ajax リクエストの場合、

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

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

于 2011-07-20T12:55:23.697 に答える
3

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

for(name in CKEDITOR.instances)
{
  CKEDITOR.instances[name].destroy()
}
于 2013-08-09T14:10:48.103 に答える
2

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



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

于 2012-09-11T21:25:08.277 に答える
2
CKEDITOR.instances = new Array();

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

于 2011-09-21T19:10:42.380 に答える
2

ckeditor の remove メソッドを使用して、任意の ckeditor インスタンスを削除できます。インスタンスは、テキストエリアの ID または名前になります。

if (CKEDITOR.instances[instance_name]) {
    CKEDITOR.remove(CKEDITOR.instances[instance_name]);
}
于 2013-06-19T13:14:04.207 に答える
2

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

      $("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 構造が正しいことを確認してください。

于 2012-06-22T08:27:08.553 に答える
1

破棄/置換ではなく、すべてのインスタンスの名前を変更することを選択しました。AJAXがロードされたインスタンスが、ページのコアにあるインスタンスを実際に置き換えない場合があるためです... RAMに多く保持されますが、この方法での競合は少なくなります。

    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];
        }
    }
于 2011-07-07T15:10:27.470 に答える
1

jQuery ダイアログでも同じ問題が発生しました。

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

function clearEditor(id)
{
  var instance = CKEDITOR.instances[id];
  if(instance)
  {
    instance.setData( '' );
  }
}
于 2011-04-12T21:31:49.950 に答える
1

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

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

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

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

于 2010-12-16T02:38:45.367 に答える
1

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

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

そして、「...たぶん、「.jquery_」の部分を取り除くことができるかもしれません」と考えました。

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

「ckeditor」は予約済みのキーワードであるため、クラス名としての使用は推奨されないことをドキュメントに記載する必要があると思います。

乾杯。

于 2010-09-16T17:32:59.480 に答える
1

私は、ダイアログを生成するコントロールが必要な状況にあり、それぞれに、これらのダイアログ内に ckeditor を埋め込む必要があります。そして、たまたまテキスト領域が同じ ID を共有しています。(通常、これは非常に悪い習慣ですが、割り当てられたアイテムと割り当てられていないアイテムの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)
    {

    }
});
于 2012-02-05T13:44:55.367 に答える
0

同じ(同じフォームが再度呼び出される)または異なる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コンテンツと同じにするように強制します。使用時にちらつきが発生します。使用を避けることができる場合は、そうしてください。

于 2011-07-29T11:40:45.167 に答える
0

null 参照例外を受け取り、「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
...

モーダル ダイアログでテキストが一貫して表示されるようになりました。

于 2010-11-08T19:28:17.813 に答える
0

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

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

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

于 2011-12-21T17:56:54.097 に答える
0

CKeditor 4.2.1

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

Foundationを使用して、モーダルでCKEditorをレンダリングしていました。理想的には、エディターを閉じたときに破棄したかったのですが、Foundation を台無しにしたくありませんでした。

私は削除を呼び出し、削除と別の方法を試しましたが、これが最終的に解決したものです。

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']
                    ]
                };
    }
于 2015-01-04T15:53:32.757 に答える
0

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

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

于 2012-07-31T17:39:54.997 に答える
0

この関数は、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);
于 2014-10-20T11:00:18.177 に答える
0

これは、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')" >
于 2012-12-15T06:48:08.030 に答える
0

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

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

コードを分析したところ、フォーム コンテンツがまだダイアログに配置されていない「空中」で ckeditor をアタッチすると、ckeditor がバインディングを適切にアタッチしないことがわかりました。つまり、ckeditor は「空中」でアタッチされているため、2 回目は「空中」でアタッチします... プーフ ... 最初のインスタンスが 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
于 2011-12-14T11:23:38.090 に答える
0

これを試して:

for (name in CKEDITOR.instances)
{
    CKEDITOR.instances[name].destroy(true);
}
于 2016-03-05T10:26:27.513 に答える
-1

オブジェクト CKeditor を破棄する必要はありません。remove() が必要です。

これを変える :

CKEDITOR.instances['textarea_name'].destroy();

そのために:

CKEDITOR.remove(CKEDITOR.instances['textarea_name']);

于 2014-06-25T14:54:44.460 に答える