web-dev-qa-db-ja.com

ckeditorインライン保存/送信

編集したデータをCKEditorインスタンスから取得してURLに投稿する方法がわかりません。

私はこれを見ています:

http://nightly.ckeditor.com/3995/samples/inlineall.html

変更を保存する方法がわかりません。新しく編集したデータを、編集中の要素のIDとともにPHPに投稿できますか?

これと同様に:

editor.on('configLoaded', function(){
    // do some stuff
});

私はこのようなことができることを望んでいました:

editor.on('clickAway', function(e){
    id = e.id();
    // do some ajax stuff
});

しかし、どこにも何も見つからないようです。

誰かがこれを行う方法を考え出しましたか?

ありがとうございました。

13
Mr Goobri

これを実現する方法はたくさんあると思いますが、これが私の解決策です。 Smartyテンプレートエンジンを使用していますが、この手法はVanillaHTMLでも機能するはずです。

まず、「dog_fleas.tpl」という名前のテンプレートファイルに保存されているHTMLの例を次に示します。

<script type="text/javascript" src="/js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/js/admin/mycms.js"></script>
<div>
  <div id="flea-blurb" tpl="/templates/dog_fleas.tpl" contenteditable="true">
    <h1>My Dog Has Fleas</h1>
    <p>This text is editable via the CMS!</p>
  </div>
  <p>This text is not editable</p>
</div>

インライン編集を処理するJavaScript(mycms.js)は次のとおりです。

$(document).ready(function() {

    CKEDITOR.disableAutoInline = true;

    $("div[contenteditable='true']" ).each(function( index ) {

        var content_id = $(this).attr('id');
        var tpl = $(this).attr('tpl');

        CKEDITOR.inline( content_id, {
            on: {
                blur: function( event ) {
                    var data = event.editor.getData();

                    var request = jQuery.ajax({
                        url: "/admin/cms-pages/inline-update",
                        type: "POST",
                        data: {
                            content : data,
                            content_id : content_id,
                            tpl : tpl
                        },
                        dataType: "html"
                    });

                }
            }
        } );

    });

});

上記のコードはいくつかのことを行います:

  1. 属性contenteditable = "true"を持つdivタグをインライン編集可能に変換します。
  2. コンテンツが(ぼかしで)編集された後、編集可能な要素ID、tplファイル名、および編集されたコンテンツがajax呼び出しを介してサーバーに送信されます。

私の状況では、編集中のファイルを識別するためにtpl属性が必要です。要素IDは、変更された要素を指定します。

私の例には編集可能な領域が1つしか含まれていませんが、このコードは1つのファイルで複数の編集可能な領域をサポートしています。

サーバー側では、これが私のPHPコードです。フレームワークを使用しているので、$ this-> _ POST()関数は少し変わっているように見えるかもしれませんが、うまくいけば、次のようになります。

    // Get the posted parameters
    $new_content = $this->_POST('content');
    $content_id  = $this->_POST('content_id');
    $tpl_filename = $this->_POST('tpl');

    // Get the contents of the .tpl file to edit
    $file_contents = file_get_contents(APPPATH . 'views' . $tpl_filename);

    // create revision as a backup in case of emergency
    $revised_filename = str_replace('/', '.', $tpl_filename);
    $revised_filename = ltrim ($revised_filename, '.');
    file_put_contents(APPPATH . 'views/templates/revisions/' . $revised_filename . '.' . time(), $file_contents);

    // Prepare to match the DIV tag
    // Credit to: http://stackoverflow.com/questions/5355452/using-a-regular-expression-to-match-a-div-block-having-a-specific-id
    $re = '% # Match a DIV element having id="content".
        <div\b             # Start of outer DIV start tag.
        [^>]*?             # Lazily match up to id attrib.
        \bid\s*+=\s*+      # id attribute name and =
        ([\'"]?+)          # $1: Optional quote delimiter.
        \b' . $content_id . '\b        # specific ID to be matched.
        (?(1)\1)           # If open quote, match same closing quote
        [^>]*+>            # remaining outer DIV start tag.
        (                  # $2: DIV contents. (may be called recursively!)
          (?:              # Non-capture group for DIV contents alternatives.
          # DIV contents option 1: All non-DIV, non-comment stuff...
            [^<]++         # One or more non-tag, non-comment characters.
          # DIV contents option 2: Start of a non-DIV tag...
          | <            # Match a "<", but only if it
            (?!          # is not the beginning of either
              /?div\b    # a DIV start or end tag,
            | !--        # or an HTML comment.
            )            # Ok, that < was not a DIV or comment.
          # DIV contents Option 3: an HTML comment.
          | <!--.*?-->     # A non-SGML compliant HTML comment.
          # DIV contents Option 4: a nested DIV element!
          | <div\b[^>]*+>  # Inner DIV element start tag.
            (?2)           # Recurse group 2 as a nested subroutine.
            </div\s*>      # Inner DIV element end tag.
          )*+              # Zero or more of these contents alternatives.
        )                  # End 2$: DIV contents.
        </div\s*>          # Outer DIV end tag.
        %isx';

    if (preg_match($re, $file_contents, $matches))
    {
        $content_to_replace = $matches[0];

        $replacement_content = $content_to_replace;

        // Replace the inner content of $replacement_content with $new_content
        $replacement_content = preg_replace('/(<div(?:.*?)>)(?:.*)(<\/div>)/msi',"$1" . $new_content . "$2", $replacement_content);

        // Now replace the content_to_replace with $replacement content in the HTML
        $new_file_contents = str_replace($content_to_replace, $replacement_content, $file_contents);

        // write out the new .tpl file
        file_put_contents(APPPATH . 'views' . $tpl_filename, $new_file_contents);
    }

上記のPHPコードは、基本的にHTMLをロードし、適切なIDでdivタグを見つけてから、そのdivタグのコンテンツをajax呼び出しを介して送信されたコンテンツに置き換えます。HTMLは次のようになります。サーバーに再保存しました。問題がひどい場合に備えて、バックアップリビジョンを保存するためのコードもいくつか含めます。

正規表現が常に最善の解決策であるとは限らないことを私は理解しています。私の場合、HTMLコンテンツが有効なHTMLではないため、PHP Dom Object Modelを使用するのは困難でした。システムが私のものよりも単純な場合は、代わりにDom ObjectModelを使用することを検討してください。 。

これがお役に立てば幸いです。

28
clone45

次の解決策を見つけました: インラインエディターのコンテンツをサーバーに保存するにはどうすればよいですか?

ぼかしイベントを使用しています

1
Mateu

@ clone45の上記の回答を使用して、変更しました。データはSaveボタンを使用して保存され、実行されたいくつかの変更が古いものであり、新しいデータが比較された後にのみ保存されます。

インラインエディタの既存の保存ボタンを上書きし、@ clone45の回答の一部のみを警告しました。

<script>

CKEDITOR.disableAutoInline = true;
$("div[contenteditable='true']").each(function(index) {
    var content_id = $(this).attr('id');
    var tpl = $(this).attr('tpl');
    var oldData = null;
    CKEDITOR.inline(content_id, {
        on: {
            instanceReady: function(event) {
                //get current data and save in variable
                oldData = event.editor.getData();
                // overwrite the default save function
                event.editor.addCommand("save", {
                    modes: {
                        wysiwyg: 1,
                        source: 1
                    },
                    exec: function() {
                        var data = event.editor.getData();
                        //check if any changes has been carried out
                        if (oldData !== data) {
                            oldData = data;
                            $.ajax({
                                    type: 'POST',
                                    url: 'process.php',
                                    data: {
                                        content: data,
                                        content_id: content_id,
                                        tpl: tpl
                                    }
                                })
                                .done(function(data) {
                                    alert('saved');
                                })
                                .fail(function() {
                                    alert('something went wrong');
                                });
                        } else
                            alert('looks like nothing has been changed');
                    }
                });
            }
        }
    });
});

</script> 

お役に立てれば!!

0
Rohan Khude