AJAX Extender for TinyMCE. Including fix for UpdatePanels.

The information in this article is no longer valid. Please go to the new version found at http://weblogs.asp.net/cjdevos/archive/2008/06/19/ajax-extender-for-tinymce-continued.aspx. The current downloads are removed.


A while ago I was looking for a usable editor in one of the web applications I am working on. There are quite a few alternatives but I ended up picking TinyMCE.
TinyMCE is a very easy to use editor. Both for users and developers. It's great to write 1 small line of code to have textareas turned automatically into usable editors!

Using TinyMCE would be like:

   1:  <script type=”text/javascriptsrc=”/tinymce/jscripts/tiny_mce/tiny_mce.js></script>
   2:  <script type=”text/javascript”>tinyMCE.init({mode : ‘textareas’, theme : ’simple’});</script>

However – this control actually turned into a small nightmare when textareas lived INSIDE an UpdatePanel.

Some of the problems:
1. After an asynchronous postback the editor was gone.
2. Values were not submitted to the server.

When searching the web for these issues, you’d find several links which would help you out a bit. Some of the solutions where:

a. before the postback is made the following statement must be issued: tinyMCE.saveTrigger(false, true);
b. issue an mceAddControl after the postback is finished.
c. Issue an mceRemoveControl before the postback starts.
d. Reset the idCounter to 0.

Only part d. was absolutely incorrect. It can lead to strange behaviors with textareas both inside and outside an updatepanel.

For my solution I took part of the input given by steho706 (http://forums.asp.net/members/steho706.aspx) in the discussion at http://forums.asp.net/p/1131150/2154829.aspx. He actually nailed the problem by mentioning the mceRemoveControl statement with the right event.
For me, however, the solution had one drawback. Textareas which were not inside an UpdatePanel refreshed as well…

And to nail this particular issue I decided to write an AJAX Control Extension, which you can find attached to this article.

The control will be usable by writing the following code:
   1:  <asp:TextBox ID=”TextBox1runat=”serverWidth=”100%” Height=”200TextMode=”MultiLine/>
   2:  <cc:TinyMCETextBoxExtender TargetControlID=”txtTextBox1ID=”TinyMCETextBoxExtender1runat=”server/>


For completeness sake here are excerpts of the code as well:

From the Behavior 
   1:  this.registerPartialUpdateEvents();
   2:  this._pageLoadingHandler = Function.createDelegate(this, this._pageLoading);
   3:  this._pageRequestManager.add_pageLoading(this._pageLoadingHandler);
   4:   
   5:  var element = this.get_element();
   6:  if (tinyMCE.getInstanceById(element.id) == null || tinyMCE.getInstanceById(element.id) == “undefined”)
   7:      tinyMCE.execCommand(‘mceAddControl’,false,element.id);
   8:   
   9:   
  10:   
  11:  ...
  12:   
  13:  _pageLoading : function(sender, args) {
  14:      if (this._postBackPending) {
  15:          this._postBackPending = false;
  16:   
  17:          var element = this.get_element();
  18:          var panels = args.get_panelsUpdating();
  19:          for (var i = 0; i < panels.length; i++) {
  20:          var el=element;
  21:          while(el!=null)
  22:          {
  23:              if(el==panels[i]) break;
  24:              el = el.parentNode;
  25:          }
  26:          if(el!=null)
  27:          {
  28:              if (tinyMCE.getInstanceById(element.id) != null && tinyMCE.getInstanceById(element.id) != “undefined”)
  29:              {
  30:                  tinyMCE.execCommand(‘mceFocus’, false, element.id);
  31:                  tinyMCE.execCommand(‘mceRemoveControl’,false,element.id);
  32:              }
  33:              break;
  34:          }
  35:      }
  36:  }
  37:    
From the Extender

   1:  [Designer(typeof(TinyMCETextBoxDesigner))]
   2:  [ClientScriptResource(“TinyMCETextBox.TinyMCETextBoxBehavior”, “TinyMCETextBox.TinyMCETextBoxBehavior.js”)]
   3:  [TargetControlType(typeof(TextBox))]
   4:  public class TinyMCETextBoxExtender : ExtenderControlBase
   5:  {
   6:      protected override void OnLoad(EventArgs e)
   7:      {
   8:          // ** load scripts
   9:          if (Page.Items[“tinymce”] == null)
  10:          {
  11:              HtmlGenericControl Include = new HtmlGenericControl(“script”);
  12:              Include.Attributes.Add(“type”, “text/javascript”);
  13:              Include.Attributes.Add(“src”, Page.ResolveUrl(“~/tinymce/jscripts/tiny_mce/tiny_mce.js”));
  14:              this.Page.Header.Controls.Add(Include);
  15:   
  16:              //Config MCE
  17:              HtmlGenericControl Include2 = new HtmlGenericControl(“script”);
  18:              Include2.Attributes.Add(“type”, “text/javascript”);
  19:              Include2.InnerHtml = “tinyMCE.init({mode : ’specific_textareas’, theme : ’simple’});”;
  20:              this.Page.Header.Controls.Add(Include2);
  21:   
  22:              Page.Items[“tinymce”] = true;
  23:   
  24:              if (!Page.ClientScript.IsOnSubmitStatementRegistered(this.GetType(), “tinymcetriggersave”))
  25:              {
  26:                  Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), “tinymcetriggersave”, “tinyMCE.triggerSave(false,true);”);
  27:              }
  28:          }
  29:          base.OnLoad(e);
  30:      }
  31:  }

16 Comments

  • It works with the compression module (GZIP) for TinyMCE?

  • Not yet - but that is a great idea to add to this extender.

  • This is such a needed extender. I'm having a couple issues using it though. I'm using VS 2008 which may or may not be a factor here. I'm trying to use the extender inside an updatepanel which is inside a modalpopup. The tinyMCE text area shows fine initially, however once I do any sort of postback I get a server 500 error on any subsequent postback attempts.
    Any thoughts as to what may be causing this and what I could do to fix it? I'm also using masterpages which I've heard can complicate matters as well.

  • Thank you for your comment epicNorth.

    Unfortunately I am unable to reproduce the errors you receive, but that might be due to the fact that I use VS2005 atm (VS2008 has not yet arrived here). Do you get the error in any specific browser?

    I don't think the errors is related to using masterpages - I use them as well and am not getting those errors. I'll try and see if I can get the error to pop up but unfortunately I am a busy man at the moment. Will get back on this though.



    Currently on the list is:
    1. Use Compression Module
    2. Allow configurable editors

  • As it turns out my issues were totally programmer related. I had some pathing and permissions errors that were unrelated to the use of the extender itself.

    I'm definitely looking forward to further customization options in the extender.

  • Hello epicNorth,

    To avoid de 500 error, you must set in the @Page directive the attributte ValidateRequest="false".

  • Hello,

    I have the same scenario than epicNorth:
    Use MasterPage with a ModalPopup acosiated to an Panel. This Panel have a FormView with an TinyMCETextBoxExtender inside.

    My problem is that when I close the modalpopup, all the textboxes in the page are as 'readonly' apparently.... but if press several times the Tab control I can edit the textboxes (the page loss the focus!!?).

    Can anybody help me? Thanks!

  • Thank you for this extender!!! I have been tearing my hair out trying to get TinyMCE working inside an UpdatePanel.

    I am using this in an UpdatePanel on a ModalPopup inside a TabPanel on a page that uses Masterpages, so if any of that complexity causes problems I'm probably going to see it ;-)

    The extender control works great for me with one slightly odd exception. When the control first loads the textbox is seemingly "readonly". But when I click a button on the tinymce panel (for example the "B" (bold) button) The cursor shows up and I can use the control.

    Any thoughts on what that is about?

    Also, a slight tweak to the code:

    I replaced the line:

    Include2.InnerHtml = "tinyMCE.init({mode : 'specific_textareas', theme : 'simple'});";

    with:

    Include2.InnerHtml = "tinyMCE.init({mode:'exact', elements:'" + TargetControl.ClientID + "',theme:'advanced'});";

    to make it ONLY apply to the TextBox I was intending to work with rather than all Multiline textboxes on the page.

  • When I use your extender, it brings the control up, but it's in a read-only mode. I can't do any typing.

    Ideas?

  • Small update - I am currently adding styling options as well as looking into the other comments. Might be a while before the update is put online but at least you know I am working on it. ;-)

  • First off,
    You = da man.

    I had some custom configuration stuff that varied with where you were in the admin area so I added this to the code to control configuration options.



    private string _Configuration = "mode : 'specific_textareas', theme : 'simple'";
    public string Configuration
    {
    get
    {
    try
    {
    _Configuration = ViewState["Configuration"].ToString();
    }
    catch {}
    return _Configuration;
    }
    set
    {
    _Configuration = value;
    ViewState["Configuration"] = _Configuration;
    }
    }

  • John,

    Thank you for your comment.

    The version I have worked on the past few days in some spare time will have some great adjustments, like multiple configurations, support for Skins&amp;Theming and autocompletion and am currently looking into hooking into the events.

    More on this later.

    Cheers,

    CJ.

  • Thanks soo much Siets this extender has helped me alot.

    I'm really really looking forward to your update.

    Thanks !

  • For a sneak preview take a look at

    http://www.cdevos.nl/examples/example1.aspx

    Code will be available for download once I get to write a short article.

    Cheers,
    CJ.

  • Hello!

    I use this great extender in an UpdatePanel where I placed two text areas:

















    The OnClick method switches from a simple text area (first textbox control) to the tinymce editor (second textbox control) and persists the values:

    public void Switch_Click(object sender, EventArgs e)
    {
    if (btSwitchRTE.Visible)
    {
    tb.Visible = false;
    rte.Visible = true;
    rte.Text = tb.Text;
    }
    else
    {
    tb.Visible = true;
    rte.Visible = false;
    tb.Text = rte.Text;

    }
    btSwitchRTE.Visible = tb.Visible;
    btSwitchSimple.Visible = rte.Visible;
    }


    That works fine using IE or Firefox 2.x, but using Firefox 3 it doesn't work correctly. If I click the button to activate tinymce it's shown but I cannot click to the text area to add some text. If I click any icon on the editor (e.g. bold) it's working. Even if I define a default text for the tinymce textbox it's not shown after activating.

    If the tiny mce is initially shown (visible) on startup it's working normally, even in Firefox 3. The problem is the switch which activates the tiny mce textarea on click. Why?? Any ideas? Can I get that working?

    Best Regards,
    Andreas

  • Please look at the following continuation of the AJAX extender. The version in this article is no longer 'supported' :)

    http://weblogs.asp.net/cjdevos/archive/2008/06/19/ajax-extender-for-tinymce-continued.aspx

    Andreas,
    You might want to check the new version. I think it will work due to the adjustment of the initialization. If it still does not work, please let me know!

Comments have been disabled for this content.