【问题标题】:How to make TinyMCE work inside an UpdatePanel?如何让 TinyMCE 在 UpdatePanel 中工作?
【发布时间】:2009-02-13 19:24:57
【问题描述】:

我正在尝试做很多人似乎都能够做到但我无法实施任何解决方案的事情。 TinyMCE 控件在 asp.net 表单中运行良好,直到您使用 UpdatePanel 将其括起来,然后在回发后中断。我已经尝试了一些修复,比如 RegisterClientScriptBlock 方法,但仍然不成功,回发后我仍然失去了 tinyMCE 控制。

下面是一个完整的测试项目 (VS 2008),在 UpdatePanel 外部提供一个控件,在内部提供一个控件,每个控件上都有一个用于生成回发的按钮。同样在项目中,我有一个 EditorTest 控件,其中包含我尝试过的一些调用的注释代码,以防它给任何人任何想法。

CODE SAMPLE

这里是 MCE 论坛上一些解决方案的一些来源:
AJAX
UpdatePanel

【问题讨论】:

    标签: c# asp.net javascript updatepanel tinymce


    【解决方案1】:

    要在每次UpdatePanel 更改时执行init,您需要使用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,您可能不得不放弃它,我无法让它工作,我必须完全删除它。

    【讨论】:

    • 这在我的 .ascx 用户控件中对我有用,将它放在 Page_Load 中。有人可能会觉得此评论有帮助。
    • 截至本周,我所有代码中的每个实例都停止工作。 2020-09-01 - 努力寻找解决方案,但 tinyMCE.triggerSave() 现在每次都会抛出 [Cannot read property 'body' of null] 异常。
    【解决方案2】:

    好的,你的问题有两个。 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);
            }
        }
    }
    

    您遇到的第二个问题是自定义控件的实现。设计自定义控件超出了此答案的范围。谷歌可以帮助你。

    页面上有多个控件实例,这可能会导致脚本出现问题,因为它会被多次渲染。这就是我修改您的标记以解决您的问题的方式(注意脚本函数的动态命名,自定义控件应该是自包含的,并且模式: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>
    

    【讨论】:

    • 你不能使用mode "exact",它在更新面板中不能正常工作。您可以改用textareasclass selector。对我来说,save_callback 非常有问题,我使用RegisterOnSubmitStatement 来调用tinyMCE.triggerSave()。它对我来说很好用。
    • 我在 UpdatePanels 中使用的模式完全没有问题,每个人的要求和实现细节都不一样。
    【解决方案3】:

    此解决方案不再适用于 TinyMCE 4.2.3。您现在需要使用 tinymce.remove(),而不是使用 tinymce.mceRemoveControl()。这是一个完整的工作示例:

    页面

        <%@ 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)
      {
    
      }
    }
    

    【讨论】:

    • 这绝对是解决方案。它也适用于 TinyMCE 版本 4.5.4 并且适用于所有浏览器(在 Chrome 版本 56、IE 9、10、11 和 Microsoft Edge 38 上测试)。其他不使用 .remove() 的可能解决方案无法在 IE 以外的浏览器上运行。此外,您可以将类名传递给 .remove(),这是我所做的并且效果很好。感谢 @bperniciaro 提供此解决方案!
    • 很好的解决方案(y)
    【解决方案4】:

    让 tinyMCE 在更新面板中工作的正确方法:

    1) 为“提交”按钮的 OnClientClick 创建一个处理程序。

    2) 运行 tinyMCE.execCommand("mceRemoveControl", false, '');在处理程序中,以便在回发之前删除 tinyMCE 实例。

    3) 在您的异步回发中,使用 ScriptManager.RegisterStartupScript 运行 tinyMCE.execCommand("mceAddControl", true, '');

    基本上,您需要做的就是在异步回发之前使用 mceRemoveControl 命令,并注册一个启动脚本以在异步回发之后运行 mceAddControl 命令。不太难。

    【讨论】:

      【解决方案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 按钮,所以我必须在页面加载中添加以下内容:

      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 元素。我的是一个驻留在 UserControl 中的 textarea,但您可以将其应用于您想要绑定/取消绑定 textarea 的任何项目。

        【讨论】:

        【解决方案7】:

        为使用 .NET 框架 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 + "');");
        

        【讨论】:

          【解决方案8】:
          【解决方案9】:

          每当刷新更新面板时,您必须调用 TinyMCE 的初始化方法。

          为此,您必须从 RegisterStartupScript 方法调用此方法 (tinyMCE.init),或者在页面的 head 部分中创建页面加载 javascript 函数,如下所示:

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

          每次刷新更新面板时都会执行该函数。

          【讨论】:

            【解决方案10】:

            我解决了这个问题 在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"
            });
            }
            }
            

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

              我做这个

              <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(以及其他所见即所得编辑器、FCKEditor 等)存在回发验证问题。默认情况下,任何回发的 ASP.Net 页面都会检查其内容,并且任何未编码的 HTML 都会引发回发验证错误。

                现在很多人,包括那些论坛上的人都建议禁用回发验证, validaterequest="false" ,但这会使您容易受到脚本攻击,最好的办法是将函数绑定到仅触发的异步回发事件在异步回发之前。这个 JavaScript 函数需要对被回传到服务器的 TinyMCE 数据进行 HTML 编码,然后这将通过回发验证,然后就可以了。

                我相信 TinyMCE 和其他编辑器正确地在回发上执行此操作,但不是异步回发因此问题,事实上,如果您查看 TinyMCE 的源代码,您可能会找到执行此操作的函数并简单地添加事件绑定。

                希望对你有帮助

                【讨论】:

                • 这与我的回发工作的问题无关,它是不重建的 tinyMCE 布局。编码 标签修复了validationRequest问题,我已经做到了。提供的代码示例不包含此类错误。
                猜你喜欢
                • 2011-04-30
                • 1970-01-01
                • 2011-02-25
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-10-22
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多