简体   繁体   English

ckeditor内联保存/提交

[英]ckeditor inline save/submit

I can't work out how to grab the edited data from a CKEditor instance and post it to a url. 我无法弄清楚如何从CKEditor实例中获取已编辑的数据并将其发布到URL。

I'm looking at something this: 我在看这个:

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

and I can't work out how the changes can be saved. 我无法弄清楚如何保存更改。 Can I post the newly edited data to be posted to a PHP along with the ID of the element being edited? 我可以将要编辑的新编辑的数据与要编辑的元素的ID一起发布到PHP吗?

Similarly to this: 与此类似:

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

I was hoping I could do something like this: 我希望我能做到这样的事情:

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

But I can't seem to find anything, anywhere. 但我似乎无处可寻。

Has anyone worked out how to do this? 有没有人知道如何做到这一点?

Thank you. 谢谢。

I'm sure there are many ways to pull this off, but here's my solution. 我确信有很多方法可以解决这个问题,但这是我的解决方案。 I'm using the Smarty Template Engine, but this technique should work with vanilla HTML too. 我正在使用Smarty模板引擎,但这种技术也适用于vanilla HTML。

First off, here's an example of some HTML stored in my template file named "dog_fleas.tpl": 首先,这是一个存储在名为“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>

The javascript (mycms.js) to handle the inline editing is: 处理内联编辑的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"
                    });

                }
            }
        } );

    });

});

The above code does a few things: 上面的代码做了一些事情:

  1. It converts any div tag with the attribute contenteditable = "true" to inline-editable. 它将具有属性contenteditable =“true”的任何div标记转换为内联可编辑。
  2. After content is edited (on blur), the editable element id, tpl filename, and edited content are sent to the server via an ajax call. 编辑内容后(模糊),可编辑元素id,tpl文件名和编辑内容通过ajax调用发送到服务器。

The tpl attribute is necessary in my situation to identify the file being edited. 在我的情况下,tpl属性对于识别正在编辑的文件是必要的。 The element id specifies which element was modified. 元素id指定修改了哪个元素。

Although my example only contains one editable region, this code supports multiple editable regions in a single file. 虽然我的示例仅包含一个可编辑区域,但此代码支持单个文件中的多个可编辑区域。

On the server-side, here's my PHP code. 在服务器端,这是我的PHP代码。 I'm using a framework, so my $this->_POST() functions might look a little unusual, but hopefully you get the idea: 我正在使用一个框架,所以我的$ 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);
    }

The PHP code above is basically loading the HTML, locating the div tag with the proper id, then replacing the contents of that div tag with the content sent down via the ajax call. 上面的PHP代码基本上是加载HTML,使用正确的id定位div标签,然后用通过ajax调用发送的内容替换该div标签的内容。 The HTML is then re-saved to the server. 然后将HTML重新保存到服务器。 I also include some code to store backup revisions just in case things go terribly wrong. 我还包括一些代码来存储备份修订,以防万一出现严重错误。

I realize that regular expressions aren't always the best solution. 我意识到正则表达式并不总是最好的解决方案。 In my case, it was difficult to use the PHP Dom Object Model because my HTML content isn't valid HTML. 就我而言,很难使用PHP Dom对象模型,因为我的HTML内容不是有效的HTML。 You might look into using the Dom Object Model instead if your system is simpler than mine. 如果您的系统比我的系统简单,您可能会考虑使用Dom对象模型。

I hope this helps! 我希望这有帮助!

I've found the following solution: How do I save inline editor contents on the server? 我找到了以下解决方案: 如何在服务器上保存内联编辑器内容?

I'm using the blur event 我正在使用模糊事件

Using above answer of @clone45 and modified it. 使用@ clone45的上述答案并对其进行修改。 The data will be saved busing Save button and only after some changes carried out were old and new data is compared. 数据将保存总线Save按钮,并且只有在执行了一些更改后才会比较新数据。

Overridden existing save button of inline editor and included below only alerted part of @clone45's answer. 覆盖内联编辑器的现有保存按钮,并在下面仅提醒@ 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> 

Hope this helps!! 希望这可以帮助!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM