带有AJAX的TinyMCE(更新面板)从来没有价值

时间:2010-05-12 17:03:51

标签: .net javascript asp.net-ajax updatepanel tinymce

我想在更新面板中为文本区域使用富文本编辑器。

我发现此帖子:http://www.queness.com/post/212/10-jquery-and-non-jquery-javascript-rich-text-editors通过此问题:Need ASP.Net/MVC Rich Text Editor

决定使用TinyMCE,因为我之前在非AJAX情况下使用它,并且它在该列表中说它与AJAX兼容。好吧,我做的很好'tinyMCE.init({ //settings here }); 测试它并在更新面板更新后消失。我从这里的一个问题中找出它应该在page_load函数中,所以它甚至可以在异步回发上运行。好吧,这样做,面板停留。但是,在尝试从我的textarea提交值时,它的文本总是返回为空,因为我的表单验证器总是说“你必须输入描述”,即使我在其中输入文本。这是在页面第一次加载以及对页面执行异步回发之后发生的。

好吧,我发现这个http://www.dallasjclark.com/using-tinymce-with-ajax/Can't post twice from the same AJAX TinyMCE textarea。我尝试在tinyMCE.init之后立即将此代码添加到我的页面加载函数中。这样做会破坏我之后在page_load中调用的所有jquery,它仍然存在同样的问题。

我仍然是客户端脚本编写的初学者,所以也许我需要将代码放在与page_load不同的位置?不确定我链接的帖子对于放置代码的位置不是很有线索。

我的Javascript:

<script type="text/javascript">

var redirectUrl = '<%= redirectUrl %>';

function pageLoad() {

    tinyMCE.init({
        mode: "exact",
        elements: "ctl00_mainContent_tbDescription",
        theme: "advanced",
        plugins: "table,advhr,advimage,iespell,insertdatetime,preview,searchreplace,print,contextmenu,paste,fullscreen",
        theme_advanced_buttons1_add_before: "preview,separator",
        theme_advanced_buttons1: "bold,italic,underline,separator,justifyleft,justifycenter,justifyright, justifyfull,bullist,numlist,undo,redo,link,unlink,separator,styleselect,formatselect",
        theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,separator,removeformat,cleanup,charmap,search,replace,separator,iespell,code,fullscreen",
        theme_advanced_buttons2_add_before: "",
        theme_advanced_buttons3: "",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        extended_valid_elements: "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
        paste_auto_cleanup_on_paste: true,
        paste_convert_headers_to_strong: true,
        button_tile_map: true
    });

    tinyMCE.triggerSave(false, true);
    tiny_mce_editor = tinyMCE.get('ctl00_mainContent_tbDescription');
    var newData = tiny_mce_editor.getContent();
    tinyMCE.execCommand('mceRemoveControl', false, 'your_textarea_name');

    //QJqueryUI dialog stuff
}</script>

现在我的当前代码没有tinyMCE.execCommand("mceAddControl",true,'content');,而且还应该添加一个问题。我确实尝试添加它,但是,再次,不知道在哪里放它,只是把它放在page_load似乎没有效果。

文本框控件:

<asp:TextBox ID="tbDescription" runat="server" TextMode="MultiLine" 
                Width="500px" Height="175px"></asp:TextBox><br />

如何获取这些值,以便后面的代码可以实际获得textarea中输入的内容,而我的验证器不会出现,因为它是空的?即使在异步回发之后,由于我在表单上有多个按钮,在实际提交之前更新它。

谢谢!

编辑:为了进一步澄清,我在后端进行了表单验证,如下所示:

If tbDescription.Text = "" Or tbDescription.Text Is Nothing Then
        lblDescriptionError.Text = "You must enter a description."
        isError = True
    Else
        lblDescriptionError.Text = ""
    End If

此错误将始终导致显示错误消息。

修改

好吧,我在这里绝望了,我花了好几个小时。我终于找到了我认为在专家交流中获胜的内容,其中说明了以下内容(有一部分关于在xml中编码值,但我跳过了这一点):http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_25059848.html

  

对于任何想在AJAX.Net上使用tinyMCE的人:

  1. 将开始/结束处理程序附加到AJAX请求对象。这些将在发送数据(开始)之前删除tinyMCE控件,它将重新创建tinyMCE控件(结束):

    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function(sender, args) {
        var edID = "<%=this.ClientID%>_rte_tmce"; // the id of your textbox/textarea.
        var ed = tinyMCE.getInstanceById(edID);
      if (ed) {
        tinyMCE.execCommand('mceFocus', false, edID);
        tinyMCE.execCommand('mceRemoveControl', false, edID);
    }
        });
    
      Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args) {
         var edID = "<%=this.ClientID%>_rte_tmce";
          var ed = tinyMCE.getInstanceById(edID);
          if (ed) {
        tinyMCE.execCommand('mceAddControl', false, edID);
          }
       });
    
  2. 当用户从tinyMCE控件更改/模糊时,我们希望确保textarea / textbox正确更新:

       ed.onChange.add(function(ed, l) {
           tinyMCE.triggerSave(true, true);
     });
    
  3. 现在我已尝试将此代码放入其自己的脚本标记中,将开始和结束请求放入自己的脚本标记中,并将ed.onChange放入page_load中,将所有内容放入page_load中,并将所有3放入其中自己的脚本标签。在所有情况下,它从来没有工作,甚至有时打破了我的page_load中的jquery ...(是的,我改变了上面的代码以适合我的页面)

    任何人都可以使用此功能或提供解决方案吗?

    代码

5 个答案:

答案 0 :(得分:3)

我只是想在这篇文章中添加我的解决方案,因为我已经在同一个问题上挣扎了几天。我意识到这是一个老帖子,但也许我的回答会对某人有所帮助,因为我认为这个问题仍然有用。

我正在开发一个ASP.NET Web表单应用程序,其中一个页面包含一个包含在UpdatePanel中的textarea控件。 tinyMCE与这个textarea绑定。 textarea的文本来自转发器控件中的绑定文本框,因为我想从ObjectDataSource控件获取文本,这是一种稍微笨拙的方式。在我看来,ObjectDataSource控件很方便,而且执行起来很快。

这是我的标记,包含ObjectDataSource控件,转发器,绑定文本框和textarea(设置为多行的asp:TextBox)。请注意,绑定文本框设置为“display:none”:

<asp:ObjectDataSource ID="odsDetailText" runat="server" TypeName="Data.Document" SelectMethod="GetDocumentDetailText" />
<asp:Repeater ID="repBody" runat="server" DataSourceID="odsDetailText">
    <ItemTemplate>
        <asp:TextBox ID="tbxBodyBound" runat="server" Text='<%# Eval("Body") %>' CssClass="hidden" />
    </ItemTemplate>
</asp:Repeater>
<asp:TextBox ID="tbxBody" runat="server" TextMode="MultiLine" />

我还有一个asp:Button将tinyMCE中的文本保存到SQL Server。所有这些控件都包含在UpdatePanel中。

我已将所有jQuery和JavaScript代码放在一个单独的文件中。我在下面列出了相关的位。概述:

  • 我在JavaScript pageLoad事件中初始化tinyMCE。请注意,此事件会触发完整和部分(异步)回发,因此tinyMCE始终显示,并且不会在完全或部分回发之间消失。

  • 同样在pageLoad事件中,如果回发是异步的,我开始侦听ASP.NET PageRequestManager引发的BeginRequest事件。我停止在JavaScript pageUnload事件中侦听BeginRequest事件。这可以防止每次pageLoad触发时添加越来越多的侦听器。

  • 当BeginRequest事件的事件处理程序触发时(单击我页面上的Save按钮),我获取tinyMCE文本编辑器的HTML内容并将其保存到cookie。我使用jQuery cookie插件来执行此操作:https://github.com/carhartl/jquery-cookie。为了安全起见,HTML在cookie中编码。

  • 现在,在单击“保存”按钮时执行的服务器代码中,将检索cookie的文本(编码为HTML)并将其保存到SQL Server。该cookie现已删除。

  • ASP.NET通过ObjectDataSource控件将保存的数据绑定到隐藏的textobx,textarea控件的值设置为隐藏的文本框,UpdatePanel中的页面部分将呈现回浏览器。 / p>

  • tinyMCE现在会在textarea中显示此文本,但它是HTML编码而非人类可读。

  • 因此,在JavaScript pageLoad事件中,我通过解码HTML来格式化tinyMCE文本。

  • 完成工作!

以下是我的脚本文件的相关部分:

// #########################################################
// Events
// #########################################################
// ---------------------------------------------------------
// Check for full and partial postbacks
// ---------------------------------------------------------
function pageLoad(sender, args) {

    // Register event handler for async postback beginning
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    if (!prm.get_isInAsyncPostBack()) {
        prm.add_beginRequest(onBeginRequest);
    };

    // Configure HTML editor
    HTMLEditorConfig();

    // Format HTML editor text
    HTMLEditorFormat();
};

// ---------------------------------------------------------
// When page unloads after full or partial postback
// ---------------------------------------------------------
function pageUnload(sender, args) {

    // Deregister event handler for async postback beginning
    Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(onBeginRequest);
};

// ---------------------------------------------------------
// Event handler for async postback beginning
// ---------------------------------------------------------
function onBeginRequest() {

    // Check whether to save text editor text
    HTMLEditorSave();
};

// #########################################################
// Functions
// #########################################################
// ---------------------------------------------------------
// Configure HTML text editor. tinyMCE converts standard textarea controls
// ---------------------------------------------------------
function HTMLEditorConfig() {

    // Determine edit mode
    var editMode = $('input:hidden[id*=hfEditMode]').val().toLowerCase();

    // If not in edit mode, prevent edits
    var editorReadOnly = null;
    var editorHeight = null;
    if (editMode == 'true') {
        editorReadOnly = '';
        editorHeight = '332';
    } else {
        editorReadOnly = 'true';
        editorHeight = '342';
    };

    // Initialise HTML text editor
    tinyMCE.init({
        mode: "textareas",
        plugins: "advhr,insertdatetime,print,preview,fullscreen",
        width: "488",
        height: editorHeight,

        // Theme options
        theme: "advanced",
        theme_advanced_buttons1: "newdocument,|,print,preview,|,cut,copy,paste,|,undo,redo,removeformat,|,bold,italic,underline,strikethrough,sub,sup,|,forecolor,backcolor",
        theme_advanced_buttons2: "justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,|,fontselect,fontsizeselect",
        theme_advanced_buttons3: "insertdate,inserttime,|,advhr,|,charmap,|,fullscreen",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        theme_advanced_statusbar_location: "none",
        theme_advanced_resizing: false,

        // Skin options
        skin: "o2k7",
        skin_variant: "silver",

        // Custom css
        content_css: "../../Script/tiny_mce/custom.css",

        // Allow edits?
        readonly: editorReadOnly
    });
};

// ---------------------------------------------------------
// Format HTML editor text by ensuring its HTML is decoded
// ---------------------------------------------------------
function HTMLEditorFormat() {

    // Check bound textbox containing HTML for text editor
    var bodyText = $('input:text[id*=tbxBody]').val();

    // If HTML exists, decode it
    if (bodyText !== null) {
        tinyMCE.activeEditor.setContent(decodeURIComponent(bodyText));
    };
};

// ---------------------------------------------------------
// Save HTML text editor text to cookie for server-side processing.
// Can't save to hidden field or asp control as this function fires after viewstate is captured (I think).
// Extra content in viewstate would slow down page load anyway.
// ---------------------------------------------------------
function HTMLEditorSave() {

    // Determine edit mode
    var editMode = $('input:hidden[id*=hfEditMode]').val().toLowerCase();

    // If in edit mode, create cookie with encoded text editor HTML. Server code will save this to database.
    if (editMode == 'true') {
        var textToSave = tinyMCE.activeEditor.getContent();
        $.cookie('HTMLEditorText', textToSave);
    }
};

以下是单击“保存”按钮时触发的服务器代码的一部分:

Private Sub Save()

    'Retrieve tinyMCE text from cookie
    Dim cookieName As String = "tinyMCEText"
    Dim cookies As HttpCookieCollection = Request.Cookies
    Dim text As String = cookies(cookieName).Value

    'Save text to database...

    'Delete cookie
    cookies.Remove(cookieName)

    'Databind text for tinyMCE
    repeaterTinyMCE.DataBind()
    Dim encodedText As String = DirectCast(repeaterTinyMCE.Controls(0).Controls(1), TextBox).Text
    textboxTinyMCE.Text = encodedText
End Sub

希望这有助于某人。

答案 1 :(得分:2)

我想你想看看这个帖子: How to make TinyMCE work inside an UpdatePanel?

请务必使用init

注册scriptmanager功能
ScriptManager.RegisterStartupScript(this.Page, 
         this.Page.GetType(), mce.ClientID, "pageLoad();", true);

答案 2 :(得分:1)

发布回来时必须触发保存功能,使用Page.RegisterOnSubmitStatement注册脚本tinyMCE.triggerSave();

我注意到tinyMCE的init函数只能调用选择具有特定类的所有textareas或textareas。 exact不起作用。

答案 3 :(得分:0)

我有两种方法可以解决这个问题,但实际上并没有解决这个问题。

一个是使用FCKeditor .net控件,这对我来说重新加载速度非常慢,比如2-3秒。所以我决定让表单有两个更新面板,然后将文本区域置于其间,基本上将文本区域从更新面板中取出。这感觉有点像一个不应该是必要的廉价技巧,但它工作正常。任何人发布的解决方案或建议都没有为我工作,这就是我所做的。如果我不想将文本区域放入更新面板,这将无法正常工作。

答案 4 :(得分:0)

将TinyMCE放入更新面板时遇到的一件事是,我必须做各种各样的技巧才能使其正常工作。请记住更新面板的工作原理,当您想要刷新它时,它会完全取代其中的DOM,包括TinyMCE。

我使用的解决方法是从更新面板中删除TinyMCE,并在更新面板中包装动态刷新所需的任何其他内容。然后,如果我需要TinyMCE内容是动态的话,我会通过它提供的JavaScript API将数据添加到TinyMCE。