Как заставить TinyMCE работать внутри UpdatePanel?
Я пытаюсь сделать то, что многие люди, похоже, смогли сделать, но я не могу реализовать какое-либо решение. Элемент TinyMCE работает очень хорошо в форме asp.net, пока вы не приложите его с помощью UpdatePanel, который затем ломается после обратной передачи. Я пробовал некоторые исправления, такие как метод RegisterClientScriptBlock, но я все еще не увенчался успехом, я все еще теряю элемент управления tinyMCE после обратной передачи.
Ниже представлен полный тестовый проект (VS 2008), снабженный элементом управления вне UpdatePanel и одним внутри, с каждой кнопкой для создания обратной передачи. Также в проекте у меня есть элемент управления EditorTest, который включает в себя код с комментариями некоторых вызовов, которые я пробовал, в случае, если он дает какие-либо идеи.
ПРИМЕР КОДА
Вот некоторые источники для некоторых решений на форуме MCE:
AJAX
UpdatePanel
Ответы
Ответ 1
Для выполнения init
при каждом изменении UpdatePanel
вам необходимо зарегистрировать script с помощью ScriptManager
:
// control is your UpdatePanel
ScriptManager.RegisterStartupScript(control, control.GetType(), control.UniqueID, "your_tinymce_initfunc();", true);
ПРИМЕЧАНИЕ.. Вы не можете использовать режим exact
в своей функции init, вы можете использовать либо textareas
, либо class selector
, иначе он не будет работать должным образом.
Вы также должны использовать
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "", "tinyMCE.triggerSave();");
В обратном порядке UpdatePanel содержимое редактора не сохраняется в текстовом поле, потому что поведение по умолчанию только для form.submit
, поэтому, когда вы отправляете что-либо, он сохраняет текст перед его сообщением.
В коде, чтобы получить значение, вам просто нужно получить доступ к свойству TextBox.Text
.
ПРИМЕЧАНИЕ.. Если вы используете .NET GZipped, вам, вероятно, придется отказаться от него, я не смог бы заставить его работать, мне пришлось полностью удалить его.
Ответ 2
Хорошо, ваша проблема в два раза. Stefy предоставил вам часть ответа, который вам нужно инициализировать TinyMCE на обратной передаче, зарегистрировав запуск script следующим образом:
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);
}
}
}
Вторая проблема заключается в реализации пользовательского элемента управления. Разработка пользовательских элементов управления выходит за рамки этого ответа. Google может вам помочь.
У вас есть несколько экземпляров вашего элемента управления на странице, которые могут вызывать проблемы с script, поскольку он получает визуализацию несколько раз. Вот как я изменил вашу разметку, чтобы решить вашу проблему (обратите внимание на динамическое именование ваших функций script, пользовательские элементы управления должны быть автономными и режим: "точный" на 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>
Ответ 3
Правильный способ заставить tinyMCE работать в обновленной панели:
1) Создайте обработчик для OnClientClick вашей кнопки "отправить".
2) Запустите tinyMCE.execCommand( "mceRemoveControl", false, '<% = txtMCE.ClientID% > '); в обработчике, чтобы удалить экземпляр tinyMCE до обратной передачи.
3) В вашем async postback используйте ScriptManager.RegisterStartupScript для запуска tinyMCE.execCommand( "mceAddControl", true, '<% = txtMCE.ClientID% > ');
В принципе, все, что вам нужно сделать, это использовать команду mceRemoveControl перед обратной записью async и зарегистрировать запуск script для запуска команды mceAddControl после обратной пересылки async. Не слишком жестко.
Ответ 4
Это решение больше не работает для TinyMCE 4.2.3. Вместо использования tinymce.mceRemoveControl() теперь вам нужно использовать tinymce.remove(). Вот полный рабочий пример:
Страница
<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPages/Frame.master" AutoEventWireup="true" CodeFile="FullImplementation.aspx.cs"
Inherits="TinyMCE" ValidateRequest="false" %>
<asp:Content ID="Content1" ContentPlaceHolderID="cphContent" Runat="Server">
<asp:ScriptManager runat="server"/>
<asp:UpdatePanel runat="server" id="upUpdatPanel">
<ContentTemplate>
<asp:TextBox runat="server" id="tbHtmlEditor" TextMode="MultiLine">
Default editor text
</asp:TextBox>
<asp:Dropdownlist runat="server" ID="ddlTest" AutoPostBack="true" OnSelectedIndexChanged="ddlTest_SelectedIndexChanged">
<Items>
<asp:ListItem Text="A"></asp:ListItem>
<asp:ListItem Text="B"></asp:ListItem>
</Items>
</asp:Dropdownlist>
<asp:Button runat="server" ID="butSaveEditorContent" OnClick="butSaveEditorContent_Click" Text="Save Html Content"/>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
$(document).ready(function () {
/* initial load of editor */
LoadTinyMCE();
});
/* wire-up an event to re-add the editor */
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler_Page);
/* fire this event to remove the existing editor and re-initialize it*/
function EndRequestHandler_Page(sender, args) {
//1. Remove the existing TinyMCE instance of TinyMCE
tinymce.remove( "#<%=tbHtmlEditor.ClientID%>");
//2. Re-init the TinyMCE editor
LoadTinyMCE();
}
function BeforePostback() {
tinymce.triggerSave();
}
function LoadTinyMCE() {
/* initialize the TinyMCE editor */
tinymce.init({
selector: "#<%=tbHtmlEditor.ClientID%>",
plugins: "link, autolink",
default_link_target: "_blank",
toolbar: "undo redo | bold italic | link unlink | cut copy paste | bullist numlist",
menubar: false,
statusbar: false
});
}
</script>
</asp:Content>
Код позади:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class TinyMCE : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// we have to tell the editor to re-save the date on Submit
if (!ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
{
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "SaveTextBoxBeforePostBack", "SaveTextBoxBeforePostBack()");
}
}
protected void butSaveEditorContent_Click(object sender, EventArgs e)
{
string htmlEncoded = WebUtility.HtmlEncode(tbHtmlEditor.Text);
}
private void SaveToDb(string htmlEncoded)
{
/// save to database column
}
protected void ddlTest_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
Ответ 5
Я сделал следующее:
Сначала я добавил этот 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>
Поскольку я создаю ASP.NET и используя и кнопку ASP.NET на моей странице, мне пришлось добавить на страницу Load:
protected void Page_Load(object sender, EventArgs e)
{
Button1.Attributes.Add("onclick", "UpdateTextArea()");
}
Ответ 6
Это старый вопрос, но после нескольких часов поиска и возиться с поиском ответа я чувствую себя обязанным опубликовать решение, которое я придумал.
Похоже, что, по крайней мере, в реализации, которую я использую (несколько редакторов внутри UpdatePanel), о том, что tinyMCE должен быть проинформирован, элемент управления уходит, когда отправляется UpdatePanel, иначе он откажется загрузить его снова.
Итак, в дополнение к коду 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 - это любой элемент tinyMCE. Mine - это текстовое поле, находящееся в UserControl, но вы можете применить его к любому элементу, который вы хотите связать/развязать текстовое поле.
Ответ 7
Обновление ответа на этот вопрос для тех, кто использует .NET framework 4, мне удалось установить TinyMCE в TextBox внутри панели обновлений, вставив следующее:
В разметке внутри <head> </head> регион:
<script src="scripts/tinymce/tinymce.min.js" type="text/javascript"></script>
<script type="text/javascript">
tinyMCE.init({
selector: ".tinymcetextarea",
mode: "textareas",
plugins: [
"advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker",
"searchreplace visualblocks visualchars code fullscreen autoresize insertdatetime media nonbreaking",
"save table contextmenu directionality emoticons template paste textcolor",
"autosave codesample colorpicker image imagetools importcss layer"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | print preview media | forecolor backcolor emoticons",
style_formats: [
{ title: 'Bold text', inline: 'b' },
{ title: 'Red text', inline: 'span', styles: { color: '#ff0000' } },
{ title: 'Red header', block: 'h1', styles: { color: '#ff0000' } },
{ title: 'Example 1', inline: 'span', classes: 'example1' },
{ title: 'Example 2', inline: 'span', classes: 'example2' },
{ title: 'Table styles' },
{ title: 'Table row 1', selector: 'tr', classes: 'tablerow1' }
]
});
</script>
В разметке внутри <body> </body> регион:
<asp:TextBox ID="tbContentHtml" CssClass="tinymcetextarea" Wrap="true" runat="server" Width="90%" TextMode="MultiLine" />
И, наконец, в codebehind в событии Page_Load:
ScriptManager.RegisterStartupScript(this, this.GetType(), tbContentHtml.UniqueID + "Add", "tinyMCE.execCommand('mceAddEditor', true,'" + tbContentHtml.ClientID + "');", true);
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), tbContentHtml.UniqueID + "Remove", "tinyMCE.execCommand('mceRemoveEditor', true,'" + tbContentHtml.ClientID + "');");
Ответ 8
Не уверен, что вы посмотрели на них.
http://joakimk.blogspot.com/2007/07/tinymce-inside-of-aspnet-ajax.html
и
http://codeodyssey.com/archive/2007/7/18/updatepanel-tinymce-demo-with-project-zip-file
Вот сообщение форума tinymce на нем
http://tinymce.moxiecode.com/punbb/viewtopic.php?id=12682
Удачи.
Ответ 9
Вы должны вызвать метод инициализации TinyMCE всякий раз, когда обновляется панель обновления.
Для этого вам нужно либо вызвать этот метод (tinyMCE.init) из метода RegisterStartupScript, либо создать функцию javascript для загрузки страницы в главном разделе страницы следующим образом:
function pageLoad() {
tinyMCE.init();
}
Эта функция будет выполняться каждый раз, когда обновляется панель обновления.
Ответ 10
я решил эту проблему как
вызвать крошечный mce после генерации ответа на вызов ajax
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"
});
}
}
а страница, заключенная в 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>
может оказаться полезным в такой ситуации.
Ответ 11
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>
Это инициализирует редактор после каждой асинхронной обратной передачи, даже если
Затем в событии page_load
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "salvarEditorMCE", "tinyMCE.triggerSave();");
Ответ 12
TinyMCE (как и другие редакторы WYSIWYG, FCKEditor и т.д.) страдает от проблем проверки обратной связи. По умолчанию любая страница ASP.Net в postback проверяет содержимое, а любой незашифрованный HTML генерирует ошибку проверки обратной связи.
Теперь многие люди, в том числе и на тех форумах, предлагают отключить проверку postback, validaterequest = "false", но это делает вас восприимчивыми к сценариям атак, лучше всего привязать функцию к событию postback async, которое срабатывает просто перед асинхронной обратной передачей. Эта функция JavaScript должна кодировать HTML-данные TinyMCE, отправляемые обратно на сервер, после чего будет проведена проверка после обратной связи, и все будет в порядке.
Я считаю, что TinyMCE и другие редакторы правильно делают это при обратных передачах, но не async postbacks, следовательно, проблема, на самом деле, если вы посмотрите на источник TinyMCE, вы, вероятно, можете найти свою функцию, которая делает это и просто добавляет привязку события.
Надеюсь, что это поможет