C# 如何使 TinyMCE 在 UpdatePanel 内工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/547327/
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
How to make TinyMCE work inside an UpdatePanel?
提问by jpsimard-nyx
I'm trying to do something that many people seem to have been able to do but which I am unable to implement any solution. The TinyMCEcontrol works pretty well in an asp.net form until you enclose it with an UpdatePanel, which then breaks after postback. I have tried some fixes like the RegisterClientScriptBlock method, but am still unsuccessful, I still lose the tinyMCE control after postback.
我正在尝试做很多人似乎能够做到但我无法实施任何解决方案的事情。该TinyMCE的控制工作得很好,在一个asp.net的形式,直到你有一个UpdatePanel,然后回传后休息括起来。我尝试了一些修复程序,如 RegisterClientScriptBlock 方法,但仍然不成功,回发后我仍然失去了 tinyMCE 控制。
Below is a full test project (VS 2008) provided with a Control outside UpdatePanel and one inside, with a button on each to generate postback. Also in the project I have a EditorTest control which include commented code of some calls I tried, in case it gives anyone any ideas.
下面是一个完整的测试项目 (VS 2008),在 UpdatePanel 外部提供一个控件,在里面提供一个控件,每个项目上都有一个按钮来生成回发。同样在项目中,我有一个 EditorTest 控件,其中包含我尝试过的一些调用的注释代码,以防它给任何人任何想法。
Here are some sources for some solutions on the MCE forum :
AJAX
UpdatePanel
以下是 MCE 论坛上一些解决方案的一些来源:
AJAX
UpdatePanel
回答by Nirav
Not sure if you've looked at these.
不确定你是否看过这些。
http://joakimk.blogspot.com/2007/07/tinymce-inside-of-aspnet-ajax.html
http://joakimk.blogspot.com/2007/07/tinymce-inside-of-aspnet-ajax.html
and
和
http://codeodyssey.com/archive/2007/7/18/updatepanel-tinymce-demo-with-project-zip-file
http://codeodyssey.com/archive/2007/7/18/updatepanel-tinymce-demo-with-project-zip-file
Here is a tinymce forum post on it
这是一个关于它的tinymce论坛帖子
http://tinymce.moxiecode.com/punbb/viewtopic.php?id=12682
http://tinymce.moxiecode.com/punbb/viewtopic.php?id=12682
Good luck.
祝你好运。
回答by MJJames
TinyMCE (as well as other WYSIWYG editors, FCKEditor etc) suffers from postback validation issues. By default any ASP.Net page on postback has its contents checked, and any unencoded HTML throws the postback validation error.
TinyMCE(以及其他 WYSIWYG 编辑器、FCKEditor 等)存在回发验证问题。默认情况下,任何 ASP.Net 回发页面都会检查其内容,任何未编码的 HTML 都会引发回发验证错误。
Now many people, including on those forums suggest disabling the postback validation, validaterequest="false" , but this makes you susceptible to scripting attacks, the best thing to do is bind a function to the async postback event that fires off just before async postback. This JavaScript function needs to HTML encode the TinyMCE data being posted back to the server, this will then pass the postback validation and you'll be OK.
现在很多人,包括那些论坛上的人都建议禁用回发验证 validaterequest="false" ,但这会让你容易受到脚本攻击,最好的办法是将一个函数绑定到异步回发之前触发的异步回发事件. 这个 JavaScript 函数需要对回发到服务器的 TinyMCE 数据进行 HTML 编码,然后这将通过回发验证,你就可以了。
I believe TinyMCE and other editors correctly do this on postbacks but not async postbacks hence the issue, in fact if you look at TinyMCE's source you can probably find their function that does this and simply add the event binding.
我相信 TinyMCE 和其他编辑器在回发上正确执行此操作,但在异步回发上没有正确执行此操作,因此存在问题,事实上,如果您查看 TinyMCE 的源代码,您可能会找到执行此操作的函数,只需添加事件绑定即可。
Hope this helps
希望这可以帮助
回答by Stefan Filip
You have to call the initializing method of the TinyMCE whenever the update panel is refreshed.
无论何时刷新更新面板,您都必须调用 TinyMCE 的初始化方法。
For this, you have either to call this method (tinyMCE.init) from a RegisterStartupScript method, or to create a page load javascript function in the head section of the page like this:
为此,您必须从 RegisterStartupScript 方法调用此方法 (tinyMCE.init),或者在页面的 head 部分创建一个页面加载 javascript 函数,如下所示:
function pageLoad() {
tinyMCE.init();
}
This function will be executed each time the update panel is refreshed.
每次刷新更新面板时都会执行此函数。
回答by rick schott
Ok, your problem is two fold. Stefy supplied you with part of the answer, which is you have to initialize TinyMCE on the postback by registering startup script like so:
好的,你的问题是双重的。Stefy 为您提供了部分答案,即您必须通过注册启动脚本在回发时初始化 TinyMCE,如下所示:
using System.Web.UI;
namespace TinyMCEProblemDemo
{
public partial class EditorClean : UserControl
{
protected void Page_Load(object sender, System.EventArgs e)
{
ScriptManager.RegisterStartupScript(this.Page,
this.Page.GetType(), mce.ClientID, "callInt" + mce.ClientID + "();", true);
}
}
}
The second problem you have is with your implementation of a custom control. Designing custom controls is out of scope of this answer. Google can help you there.
您遇到的第二个问题是自定义控件的实现。设计自定义控件超出了本答案的范围。谷歌可以帮助你。
You have multiple instances of your control on the page which can cause you issues with script, as it get rendered multiple times. This is how I modified your markup to solve your issue(notice dynamic naming of your script functions, custom controls should be self contained and mode: "exact" on the tinyMCE.init):
您在页面上有多个控件实例,这可能会导致脚本出现问题,因为它会多次呈现。这就是我修改您的标记以解决您的问题的方式(注意脚本函数的动态命名,自定义控件应该是自包含的,并且模式:tinyMCE.init 上的“精确”):
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditorClean.ascx.cs"
Inherits="TinyMCEProblemDemo.EditorClean" %>
<script type="text/javascript" src="Editor/tiny_mce.js"></script>
<script type="text/javascript">
function myCustomCleanup<%= mce.ClientID%>(type, value) {
if (type == "insert_to_editor") {
value = value.replace(/</gi, "<");
value = value.replace(/>/gi, ">");
}
return value;
}
function myCustomSaveContent<%= mce.ClientID%>(element_id, html, body) {
html = html.replace(/</gi, "<");
html = html.replace(/>/gi, ">");
return html;
}
function callInt<%= mce.ClientID%>() {
tinyMCE.init({
mode: "exact",
elements: "<%= mce.ClientID%>",
theme: "advanced",
skin: "o2k7",
plugins: "inlinepopups,paste,safari",
theme_advanced_buttons1: "fontselect,fontsizeselect,|,forecolor,backcolor,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,cut,copy,paste,pastetext,pasteword",
theme_advanced_buttons2: "",
theme_advanced_buttons3: "",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
cleanup_callback: "myCustomCleanup<%= mce.ClientID%>",
save_callback: "myCustomSaveContent<%= mce.ClientID%>"
});
}
</script>
<textarea runat="server" id="mce" name="editor" cols="50" rows="15">Enter your text here...</textarea>
回答by rick schott
I did the following:
我做了以下事情:
First I added the this Javascript to my page:
首先,我将这个 Javascript 添加到我的页面:
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
function endRequestHandler(sender,args)
{
tinyMCE.idCounter=0;
tinyMCE.execCommand('mceAddControl',false,'htmlContent');
}
function UpdateTextArea()
{
tinyMCE.triggerSave(false,true);
}
</script>
Because I'm creating an ASP.NET and using and ASP.NET Button in my page, I had to add the following to the Page Load:
因为我正在创建一个 ASP.NET 并在我的页面中使用 ASP.NET 按钮,所以我必须将以下内容添加到页面加载中:
protected void Page_Load(object sender, EventArgs e)
{
Button1.Attributes.Add("onclick", "UpdateTextArea()");
}
回答by Kevin
The correct way to make tinyMCE work in an updatepanel:
使 tinyMCE 在更新面板中工作的正确方法:
1) Create a handler for the OnClientClick of your "submit" button.
1) 为“提交”按钮的 OnClientClick 创建一个处理程序。
2) Run tinyMCE.execCommand("mceRemoveControl", false, '<%= txtMCE.ClientID %>'); in the handler, so as to remove the tinyMCE instance before the postback.
2) 运行 tinyMCE.execCommand("mceRemoveControl", false, '<%= txtMCE.ClientID %>'); 在处理程序中,以便在回发之前删除 tinyMCE 实例。
3) In your async postback, use the ScriptManager.RegisterStartupScript to run tinyMCE.execCommand("mceAddControl", true, '<%= txtMCE.ClientID %>');
3) 在异步回发中,使用 ScriptManager.RegisterStartupScript 运行 tinyMCE.execCommand("mceAddControl", true, '<%= txtMCE.ClientID %>');
Basically, all you need to do is use the mceRemoveControl command before the async postback and register a startup script to run the mceAddControl command after the async postback. Not too tough.
基本上,您需要做的就是在异步回发之前使用 mceRemoveControl 命令并注册一个启动脚本以在异步回发之后运行 mceAddControl 命令。不太硬。
回答by BrunoLM
To execute the init
everytime the UpdatePanel
changes you need to register the script using ScriptManager
:
要执行init
每次UpdatePanel
更改,您需要使用ScriptManager
以下命令注册脚本:
// control is your UpdatePanel
ScriptManager.RegisterStartupScript(control, control.GetType(), control.UniqueID, "your_tinymce_initfunc();", true);
NOTE:You cannot use exact
mode on your init function, you can use either textareas
or a class selector
, or else it won't work properly.
注意:您不能exact
在 init 函数上使用mode,您可以使用textareas
或 a class selector
,否则它将无法正常工作。
You also have to use
你还必须使用
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "", "tinyMCE.triggerSave();");
On a postback of a UpdatePanel the editor content isn't saved on the Textbox, because the default behavior is only for form.submit
, so when you submit anything it will save the text before it posts.
在 UpdatePanel 的回发中,编辑器内容不会保存在文本框中,因为默认行为仅适用于form.submit
,因此当您提交任何内容时,它会在发布之前保存文本。
On the code behind to get the value you will just need to access TextBox.Text
property.
在获取值的背后代码中,您只需要访问TextBox.Text
属性。
NOTE:If you are using the .NET GZipped you probably will have to drop it, I couldn't get it working, I had to remove this completely.
注意:如果您使用的是 .NET GZipped,您可能不得不放弃它,我无法让它工作,我不得不完全删除它。
回答by Dave
This is an old question, but after hours searching and messing around looking for the answer, I feel obligated to post the solution I came up with.
这是一个老问题,但经过数小时的搜索和寻找答案后,我觉得有必要发布我想出的解决方案。
It appears that, at least in the implementation I'm using (multiple editors inside an UpdatePanel) that tinyMCE must be informed the control is going away when the UpdatePanel submits, or else it will refuse to load it again.
看来,至少在我使用的实现中(UpdatePanel 内有多个编辑器),必须通知 tinyMCE 在 UpdatePanel 提交时控件将消失,否则它将拒绝再次加载它。
So, in addition to the code to Init TinyMCE (which only needs to run when the whole page loads) you need to do this for each of your MCE textboxes:
因此,除了 Init TinyMCE 的代码(它只需要在整个页面加载时运行)之外,您还需要为每个 MCE 文本框执行此操作:
ScriptManager.RegisterStartupScript(this, this.GetType(), elm1.UniqueID+"Add",
"tinyMCE.execCommand('mceAddControl', true,'" + elm1.ClientID + "');", true);
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), elm1.UniqueID + "Remove",
"tinyMCE.execCommand('mceRemoveControl', true,'" + elm1.ClientID + "');");
elm1 is whatever the tinyMCE element is. Mine is a textarea residing in a UserControl, but you can apply it to any item you want to bind/unbind your textarea.
elm1 是 tinyMCE 元素。我的是一个驻留在 UserControl 中的 textarea,但您可以将它应用于要绑定/取消绑定 textarea 的任何项目。
回答by hemc4
i solved this problem as call tiny mce after the response generation of the ajax call
我在 ajax 调用的响应生成后通过调用 tiny mce 解决了这个问题
function edittemp(name) {
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null)
{
alert ("Your browser does not support XMLHTTP!");
return;
}
var url="edit_temp.php";
url=url+"?id="+name;
xmlhttp.onreadystatechange=stateChanged3;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}
function stateChanged3()
{
if (xmlhttp.readyState==4)
{
spl_txt=xmlhttp.responseText.split("~~~");
document.getElementById("edit_message").innerHTML=spl_txt[0];
tinyMCE.init({
theme : "advanced",
mode: "exact",
elements : "elm1",
theme_advanced_toolbar_location : "top",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,"
+ "justifyleft,justifycenter,justifyright,justifyfull,formatselect,"
+ "bullist,numlist,outdent,indent",
theme_advanced_buttons2 : "link,unlink,anchor,image,separator,"
+"undo,redo,cleanup,code,separator,sub,sup,charmap",
theme_advanced_buttons3 : "",
height:"350px",
width:"600px"
});
}
}
and the page caaled by ajax call is
由 ajax 调用的页面是
<?php
$name=$_GET['id'];
include 'connection.php';
$result=mysql_query("SELECT * FROM `templete` WHERE temp_name='$name' and status=1");
$row = mysql_fetch_array($result);
$Content=$row['body'];
?>
<html>
<head>
<title>editing using tiny_mce</title>
<script language="..." src="tinymce/jscripts/tiny_mce /tiny_mce.js"></script>
</head>
<body>
<h2>change the template here</h2>
<form method="post" action="save_temp.php?name=<?php echo $name;?>">
<textarea id="elm1" name="elm1" rows="15" cols="80"><?php echo $Content;?></textarea>
<br />
<input type="submit" name="save" value="Submit" />
<input type="reset" name="reset" value="Reset" />
</form>
</body>
</html>
may be helpful in such situation.
在这种情况下可能会有所帮助。
回答by user1985500
I di this
我做这个
<script language="javascript" type="text/javascript">
function pageLoad(sender, args) {
aplicartinyMCE();
}
function aplicartinyMCE() {
tinyMCE.init({
mode: "specific_textareas",
editor_selector: "mceEditor",
.....
});
}
</script>
That initialize the editor after each asynchronous postback even if
即使在每次异步回发后初始化编辑器
Then in page_load event
然后在 page_load 事件中
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "salvarEditorMCE", "tinyMCE.triggerSave();");