Javascript ckeditor 内联保存/提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13603575/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ckeditor inline save/submit
提问by Mr Goobri
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.
谢谢你。
回答by clone45
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 模板引擎,但这种技术也适用于普通 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:
上面的代码做了几件事:
- It converts any div tag with the attribute contenteditable = "true" to inline-editable.
- After content is edited (on blur), the editable element id, tpl filename, and edited content are sent to the server via an ajax call.
- 它将任何具有 contenteditable = "true" 属性的 div 标签转换为内联可编辑。
- 内容编辑后(模糊),可编辑元素 id、tpl 文件名和编辑的内容通过 ajax 调用发送到服务器。
The tpl attribute is necessary in my situation to identify the file being edited. The element id specifies which element was modified.
在我的情况下,tpl 属性对于识别正在编辑的文件是必要的。元素 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. I'm using a framework, so my $this->_POST() functions might look a little unusual, but hopefully you get the idea:
在服务器端,这是我的 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 =
([\'"]?+) # : Optional quote delimiter.
\b' . $content_id . '\b # specific ID to be matched.
(?(1)) # If open quote, match same closing quote
[^>]*+> # remaining outer DIV start tag.
( # : 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',"" . $new_content . "", $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. The HTML is then re-saved to the server. I also include some code to store backup revisions just in case things go terribly wrong.
上面的 PHP 代码基本上是加载 HTML,使用正确的 id 定位 div 标签,然后用通过 ajax 调用发送的内容替换该 div 标签的内容。然后将 HTML 重新保存到服务器。我还包括一些代码来存储备份修订,以防万一出现严重错误。
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. You might look into using the Dom Object Model instead if your system is simpler than mine.
我意识到正则表达式并不总是最好的解决方案。就我而言,很难使用 PHP Dom 对象模型,因为我的 HTML 内容不是有效的 HTML。如果您的系统比我的简单,您可能会考虑使用 Dom 对象模型。
I hope this helps!
我希望这有帮助!
回答by Mateu
I've found the following solution: How do I save inline editor contents on the server?
我找到了以下解决方案:如何在服务器上保存内联编辑器内容?
I'm using the blur event
我正在使用模糊事件
回答by Rohan Khude
Using above answer of @clone45 and modified it. The data will be saved busing Savebutton and only after some changes carried out were old and new data is compared.
使用@clone45的上述答案并修改它。数据将被保存总线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!!
希望这可以帮助!!

