The Code Page
A series of development tips and code examples by Gabriel McAdams
Feb 10

There are a lot of really great controls in the ASP.Net AJAX Control Toolkit.  For those of you who are unfamiliar with the toolkit, it is an open source project that is built on top of the Microsoft ASP.Net AJAX framework (the framework was formerly known by its code-name: Atlas).  It contains over 40 controls that you can use to build highly responsive and interactive Ajax-enabled Web applications.  It is a joint effort between Microsoft and the development community.

Today, I’m going to talk about one of the controls specifically.  The HTMLEditor control.  This control allows you to create and edit html content directly from within your browser.  There are a lot of toolbar buttons available, and you can edit your content using the WYSIWYG (What you see is what you get) pane or the html text pane, and view the results using the Preview pane.

The control allows a good deal of customization.  By modifying the CSS stylesheet, you can change the look and feel of the editor.  By creating your own editor class and inheriting the editor control, you can specify which toolbar buttons should be available, and which panes to enable.  Unfortunately, you can’t easily change the state of a toolbar button on startup.  A user on stackoverflow.com asked if it were possible to pre-set the ‘right to left direction’ toggle button from the server.  The control’s server-side properties do not allow this, but I was able to help him find a solution.  Here is what we found:

When you add the editor control on your page like this:

<HTMLEditor:Editor runat="server" Id="editor" />

You end up with a few lines like this at the bottom of your page (one for each toolbar button, one for the toolbar itself, and one – like this one - for the editor):

Sys.Application.add_init(function() {
    $create(AjaxControlToolkit.HTMLEditor.Editor, null, null, { "changingToolbar": "ctl00_SampleContent_editor_ctl01", "editPanel": "ctl00_SampleContent_editor_ctl02" }, $get("ctl00_SampleContent_editor"));
});

Notice that the line starts with a Sys.Application.add_init function call.  This adds an event handler to the init event (the init event is raised after all scripts have been loaded but before page objects are created).  This is when the objects are created.  If we want to set the state of a button, we have to at least wait until the button is created.

While looking at the JavaScript code for the editor, I found that although the editor is created during init, it is not actually initialized until the load phase (it must ensure that all of its objects are created before it can initialize itself).  The way it ensures that all objects are created before it initializes is by calling the Sys.Application.add_load function (the load event is raised after all scripts have been loaded and the objects in the application have been created and initialized).

We need to attach our own code after the editor has been initialized.  This means that we need to inject code AFTER the load event, but before the user interacts with it.  To do this, add this code to your page, or to an external JavaScript file referenced by the page.  When adding this script to the page, be sure to add it below the ScriptManager.  By adding the ScriptManager to your page, you’re including the ASP.Net AJAX framework (which is needed in order to access the Sys namespace).

Sys.Application.add_load(myFunction);
 
function myFunction() {
    window.setTimeout(myOnLoad, 0);
}

This will tell the framework to call the myFunction during the load event.  We can’t customize the editor or its buttons yet, though, because it may not be finished with its initialization.  Remember, we have to inject our code AFTER the load event.  So our ‘myFunction’ function calls window.setTimeout.

By using setTimeout, we are setting up myOnLoad to be called in 0 milliseconds.  This seems pointless, but its not.  Before myOnLoad can run, it has to wait until the current stack has completed (then it waits the specified amount of time).  The current stack includes all load event handlers).  When myOnLoad is called, we can be sure that the editor has been initialized, and it is ready to be modified.

In order to modify the control, we need to access its JavaScript object.  The framework exposes methods to find components in the page.  Here is what we’ll need in order to find the editor and its toolbar buttons:

var editor = $find('<%=editor.ClientID %>');

We start by using the $find function, which returns the specified Component object.  You may have noticed the server tags in the above code.  When you add a control to a page in ASP.Net, it ensures a unique id in the page by prefixing the id with text that is based on the control tree (for example, in the sample page, the editor’s id is ‘ctl00_SampleContent_editor’).  The id rendered is not yet known at design time.  In order to render the correct id in my script at runtime, I use this server tag and reference the ClientID property of the editor control.

If you added this script into an external JavaScript file, then you wont have access to server side properties and the server tags will not be replaced by anything.  Therefore, you will have to do something different to get the id of the editor.  Instead, add this script to your page:

var myEditorId = '<%=editor.ClientID %>';

and then change the above code to this:

var editor = $find(myEditorId);

Once we have access to the editor, we need to use it to get access to its toolbar, and then to its buttons.

var editor = $find('<%=editor.ClientID %>');
var toolbar = editor.get_changingToolbar();
var toolbarButtons = toolbar.get_buttons();

The above code will result in an array of objects that represent the toolbar buttons in the editor.  From here, we can loop through the buttons until we find what we’re looking for.  Once we find it, we can change its properties or run methods against it.

Here is the entire script:

// Attach a handler to the load event.
Sys.Application.add_load(myFunction);
 
function myFunction() {
    //Setup myOnLoad to run AFTER the load event handlers have all completed
    window.setTimeout(myOnLoad, 0);
}
 
function myOnLoad() {
    //Find the instance of editor
    var editor = $find('<%=editor.ClientID %>');
    //Access the editor's toolbar
    var toolbar = editor.get_changingToolbar();
    //Get an array of toolbar buttons
    var toolbarButtons = toolbar.get_buttons();
    //Loop through the buttons array looking for the one we need
    for (var i = 0; i < toolbarButtons.length; i++) {
        //If this button is the right to left direction button, then toggle
        if (toolbarButtons[i] instanceof AjaxControlToolkit.HTMLEditor.ToolbarButton.Rtl) {
            //first, make sure the button has an edit panel set
            toolbarButtons[i].set_activeEditPanel(editor.get_editPanel());
            //Call the callMethod function (toggles the button)
            toolbarButtons[i].callMethod();
        }
    }
}

In this case, we were looking for the ‘right to left direction’ button.  We found it by checking each button to see if it was an instance of the ToolbarButton.Rtl object.

The first line after that sets the active edit panel.  The control itself will do this, but not until later.  We need this to be done before we can call the callMethod function (which is used to change the toggle state of a toggle button in the editor’s toolbar).

So that’s it.  We’ve changed the default state of the toolbar button.  Check back soon for more ways to customize the controls that are part of the toolkit.


Comments

Victor said:    

Also you can use

toolbarButtons.get_buttonName() == "Rtl"

instead of

[i]toolbarButtons[i] instanceof AjaxControlToolkit.HTMLEditor.ToolbarButton.Rtl

Comment Posted: February 11 2010, 02:21 AM

Victor said:    

The previous comment has an error because of [ i ] use...

Also you can use

toolbarButtons[ i ].get_buttonName() == "Rtl"

instead of

toolbarButtons[ i ] instanceof AjaxControlToolkit.HTMLEditor.ToolbarButton.Rtl

Comment Posted: February 11 2010, 02:24 AM

ghmcadams said:    

@Victor: Thanks.  I didn't see that property in the version I had.  I will have to look into that.

Comment Posted: February 11 2010, 04:32 AM

Moises said:    

where i have to put this code, if i put in my aspx page send me an error

Comment Posted: June 24 2010, 07:15 PM

ghmcadams said:    

Moises, the best thing to do would be to add it to an external JavaScript file.  Then, you just add the javascript file to your ScriptManager.

Comment Posted: June 29 2010, 03:15 AM

Manju said:    

How could I remove few features from an Ajax Text Editor Control?

Comment Posted: October 03 2010, 12:05 PM

ghmcadams said:    

Manju: You can use this same technique to hide a button, if that's what you mean.  When you find the button you're looking to hide, just add a style to it (display: none)

Comment Posted: October 05 2010, 05:29 PM

Janesh Hari said:    

Hi,
I am using ajaxtoolkit htmleditor client side
     Sys.Application.add_load(myFunction);
     function myFunction() {
    //Setup myOnLoad to run AFTER the load event handlers have all completed
    window.setTimeout(myOnLoad, 0);
}

   function myOnLoad() {
    var editor = $find('editor');
alert(editor.get_changingToolbar());//getting error here , not supprt the property or method
  
}
    
I am getting an error when trying to access this proprty get_changingToolbar
Please help

Comment Posted: December 11 2011, 10:20 AM

ghmcadams said:    

Janesh: My only thought after looking at your code, is that the id of the editor may be incorrect.  Have you looked at what is returned from the $find function?  Are you sure it is the right object?

Comment Posted: December 12 2011, 03:50 AM
Add comment








biuquote
  • Comment
  • Preview


Loading



.