Как заставить TinyMCE работать внутри UpdatePanel? - PullRequest
14 голосов
/ 13 февраля 2009

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

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

ОБРАЗЕЦ КОДА

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

Ответы [ 12 ]

14 голосов
/ 13 августа 2010

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

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

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

4 голосов
/ 03 января 2016

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

  }
}
4 голосов
/ 01 мая 2009

Хорошо, ваша проблема в два раза. 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>
2 голосов
/ 20 мая 2010

Правильный способ заставить tinyMCE работать в панели обновления:

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

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

3) В асинхронной обратной передаче используйте ScriptManager.RegisterStartupScript для запуска tinyMCE.execCommand ("mceAddControl", true, '<% = txtMCE.ClientID%>');

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

1 голос
/ 14 декабря 2015

Обновляя ответ на этот вопрос для тех, кто использует .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" />

И, наконец, в коде позади события 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 + "');");
1 голос
/ 21 января 2011

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

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

1 голос
/ 12 июня 2009

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

Сначала я добавил этот 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()");
}
0 голосов
/ 17 января 2013

Я ди это

<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();");
0 голосов
/ 20 июля 2012

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

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

0 голосов
/ 27 апреля 2009

Вы должны вызывать метод инициализации TinyMCE при каждом обновлении панели обновления.

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

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

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

...