2009-02-13 4 views
13

Я пытаюсь сделать то, что многие люди, похоже, смогли сделать, но я не в состоянии реализовать какое-либо решение. Элемент управления TinyMCE работает очень хорошо в форме asp.net, пока вы не приложите его с помощью UpdatePanel, который затем ломается после обратной передачи. Я пробовал некоторые исправления, такие как метод RegisterClientScriptBlock, но я все еще не увенчался успехом, я все еще теряю элемент управления tinyMCE после обратной передачи.Как заставить TinyMCE работать внутри UpdatePanel?

Ниже представлен полный тестовый проект (VS 2008), снабженный элементом управления вне UpdatePanel и один внутри, с каждой кнопкой для создания обратной передачи. Также в проекте у меня есть элемент управления EditorTest, который включает в себя код с комментариями некоторых звонков, которые я пробовал, в случае, если он дает какие-либо идеи.

CODE SAMPLE

Вот некоторые источники для некоторых решений на MCE форуме:
AJAX
UpdatePanel

ответ

-2

TinyMCE (как и другие редакторы WYSIWYG, FCKEditor и т. Д.) Страдает от вопросов проверки обратной связи. По умолчанию любая страница ASP.Net в postback проверяет содержимое, а любой некодированный HTML выдает ошибку проверки после обратной связи.

Теперь многие люди, в том числе и на тех форумах, предлагают отключить проверку после проверки, validaterequest = "false", но это делает вас восприимчивыми к атакам с использованием сценариев, лучше всего привязать функцию к событию postback async, которое срабатывает перед асинхронной обратной передачей. Эта функция JavaScript должна кодировать HTML-данные TinyMCE, отправляемые обратно на сервер, после чего будет проведена проверка обратной связи, и все будет в порядке.

Я считаю, что TinyMCE и другие редакторы правильно делают это на обратной стороне, но не async postbacks, следовательно, проблема, на самом деле, если вы посмотрите на источник TinyMCE, вы, вероятно, можете найти свою функцию, которая делает это и просто добавляет привязку события.

Надеется, что это помогает

+0

Это не имеет ничего общего с моей проблемой, где мои постбэки работают, это макет TinyMCE, что не восстанавливается. Кодирование тега <> исправляет проблему validationRequest, и я уже сделал это. Представленный образец кода не содержит таких ошибок. –

0

Вы должны вызвать инициализирующий метод TinyMCE всякий раз, когда обновление панели обновляется.

Для этого вам нужно либо вызвать этот метод (tinyMCE.init) из метода RegisterStartupScript или создать загрузку страницы Javascript функцию в головной части страницы, как это:

function pageLoad() { 
    tinyMCE.init(); 
} 

Этот функция будет выполняться каждый раз, когда обновляется панель обновления.

4

Хорошо, ваша проблема в два раза.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); 
     } 
    } 
} 

Вторая проблема у вас есть с реализацией таможенного контроля. Разработка пользовательских элементов управления выходит за рамки этого ответа. Google может вам помочь.

У вас есть несколько экземпляров вашего элемента управления на странице, которые могут вызывать проблемы со сценарием, поскольку он получает визуализацию несколько раз. Это, как я изменил разметку, чтобы решить вашу проблему (заметьте, динамическое присвоение имен ваших функций сценария, пользовательские элементы управления должны быть самодостаточными и режим: «точный» на 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(/&lt;/gi, "<"); 
      value = value.replace(/&gt;/gi, ">"); 
     } 
     return value; 
    } 
    function myCustomSaveContent<%= mce.ClientID%>(element_id, html, body) { 
     html = html.replace(/</gi, "&lt;"); 
     html = html.replace(/>/gi, "&gt;"); 
     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> 
+0

Помог ли мой ответ решить вашу проблему? –

+1

Вы не можете использовать «режим» точно », он не работает должным образом в UpdatePanel. Вместо этого вы можете использовать 'textareas' или' class selector'. И для меня «save_callback» был довольно глючным, вместо этого я использовал «RegisterOnSubmitStatement» для вызова 'tinyMCE.triggerSave()'. Он работает отлично для меня. – BrunoLM

+1

Я использовал режим точно в UpdatePanels без проблем, требования каждого пользователя и детали реализации различны. –

1

я сделал следующее :

Сначала я добавил этот 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 в моей странице, я должен был добавить следующее к Нагрузка на страницу:

protected void Page_Load(object sender, EventArgs e) 
{ 
    Button1.Attributes.Add("onclick", "UpdateTextArea()"); 
} 
2

Правильный способ сделать TinyMCE работу в качестве UpdatePanel:

1) Создание обработчика для OnClientClick вашей кнопки «Отправить».

2) Запустите tinyMCE.execCommand ("mceRemoveControl", false, '<% = txtMCE.ClientID%>'); в обработчике, чтобы удалить экземпляр tinyMCE до обратной передачи.

3) В вашем async postback используйте ScriptManager.RegisterStartupScript для запуска tinyMCE.execCommand ("mceAddControl", true, '<% = txtMCE.ClientID%>');

В принципе, все, что вам нужно сделать, это использовать команду mceRemoveControl перед обратной записью async и зарегистрировать сценарий запуска для запуска команды mceAddControl после обратной пересылки async. Не слишком жестко.

12

Чтобы выполнить init Каждый раз, когда UpdatePanel изменения, вам нужно зарегистрировать скрипт, используя ScriptManager:

// control is your UpdatePanel 
ScriptManager.RegisterStartupScript(control, control.GetType(), control.UniqueID, "your_tinymce_initfunc();", true); 

ПРИМЕЧАНИЕ: Вы не можете использовать режим exact на вашей функции инициализации, вы можете использовать либо textareas или class selector , иначе он не будет работать должным образом.

Вы также должны использовать

ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "", "tinyMCE.triggerSave();"); 

На постбэка из UpdatePanel в содержание редактор не сохранен на Textbox, поскольку по умолчанию только для form.submit, поэтому, когда вы отправляете что-нибудь это сэкономит текст перед этим.

По кодексу для получения значения вам просто нужно будет получить доступ к TextBox.Text.

ПРИМЕЧАНИЕ: Если вы используете .NET GZipped, вам, вероятно, придется отказаться от него, я не смог бы заставить его работать, мне пришлось полностью удалить его.

1

Это старый вопрос, но после нескольких часов поиска и беспорядочного поиска ответа я обязан опубликовать решение, которое я придумал.

Похоже, что, по крайней мере, в реализации, которую я использую (несколько редакторов внутри UpdatePanel), о том, что tinyMCE должен быть проинформирован, элемент управления уходит, когда отправляется UpdatePanel, иначе он откажется загружать его снова.

Таким образом, в дополнение к коду для инициализации 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, но вы можете применить его к любому элементу, который вы хотите связать/развязать текстовое поле.

+2

Я тоже потратил часы на поиск. Оказалось, что в версии 4 вышеупомянутые команды TinyMCE были заменены на 'mceAddEditor' /' mceRemoveEditor' http://www.tinymce.com/forum/viewtopic.php?id=31256 –

0

я решить эту проблему, как вызова крошечного 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" 
}); 
} 
} 

и страницы caaled с помощью 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> 

может быть полезным в такой ситуации.

0

Я ди это

<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();"); 
1

Обновление ответа на этот вопрос для тех, кто использует .NET Framework 4, мне удалось установить TinyMCE в TextBox внутри панели обновлений, вставив следующее:

В разметке внутри < головы > </голова > область:

<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> 

В разметке внутри < тела > </тело > область:

<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 + "');"); 
2

Это решение больше не работает для 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> 

Кодекс-Behind:

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) 
    { 

    } 
} 
+0

Это, безусловно, решение. Он также работает для TinyMCE версии 4.5.4 и работает во всех браузерах (протестирован в Chrome версии 56, IE 9, 10, 11 и Microsoft Edge 38). Другие возможные решения, которые не используют .remove(), не работают в браузерах, отличных от IE. Кроме того, вы можете передать имя класса в .remove (), что я и делаю и отлично работает. Спасибо @bperniciaro за это решение! – Jaime

+0

Отличное решение (y) –

Смежные вопросы