This is a migrated thread and some comments may be shown as answers.

jQuery - Single RadEditor For Multiple Editable Bodies On Page

11 Answers 233 Views
Editor
This is a migrated thread and some comments may be shown as answers.
Debbie Roberts
Top achievements
Rank 1
Debbie Roberts asked on 25 Mar 2010, 11:34 AM

I have written this jQuery code that allows a single RadEditor instance to be used to edit multiple different editable areas (editable bodies)  on the same page. It is very efficient and vastly improves page loading time but there are a few problems that I am unable to resolve and I hope you may be able to help.

To use the jQuery code, the markup on the page needs to be similar to this:

<div class="SKEditorWrapper">  
    <telerik:RadEditor using PageTop Toolbar goes here/> 
</div> 
 
<div id="BodyBlockPanel1" class="SKEditableBody">  
    <textarea name="BodyBlockHTML1" rows="2" cols="20" id="BodyBlockHTML1" class="SKEditableBodyText" style="display:none;">  
        This is editable body 1.  
    </textarea> 
</div> 
 
<div id="BodyBlockPanel2" class="SKEditableBody">  
    <textarea name="BodyBlockHTML2" rows="2" cols="20" id="BodyBlockHTML2" class="SKEditableBodyText" style="display:none;">  
        This is editable body 2.  
    </textarea> 
</div> 
 
<!-- ... and so on. We have 40 editable bodies on our page.--> 

The jQuery code hides the textareas and inserts a DIV after each of them, to render a WYSIWYG version of the markup. When the user clicks on the DIV, it is replaced with the RadEditor. The RadEditor is used with 'PageTop' toolbar and design mode only, to provide WYSIWYG in-place editing.

The jQuery code is as follows:

$(document).ready(function(){  
 
    var $bodyBlock;  
    var $editorBody;  
    var firstEdit = true;  
    var $prevEditableBody = null;  
      
    //Hide the RadEditor and its wrapper.  
    $('SKEditorWrapper').hide();  
    var $radEditor = $('div.RadEditor').hide();  
      
    var saveEditorContent = function(){  
        //Copy the content from the RadEditor back into the TextArea.  
        var editor = $find($radEditor.attr('id'));  
        var edContent = editor.get_html('true');  
        $prevEditableBody  
            .find('.SKEditableBodyText')  
            .val(edContent);  
    };  
 
    var moveEditorToBody = function(event){  
      
        var $editorPanel = $('.SKEditorWrapper');  
        var $editableBody = $(this);  
          
        //Switch off the mouse-over styling on all editable bodies on the page.  
        $('.SKEditableBody')  
            .removeClass('SKEditableBodyHighlight');  
 
        //Attach highlighter class and mousout handlers to transfer editor content  
        //to TextArea when the user clicks 'save'.              
        $editableBody  
            .addClass('SKEditableBodyHighlight')  
            .unbind('mouseenter mouseleave')  
            .mouseleave(saveEditorContent)  
            .blur(saveEditorContent);  
 
        //Remove the RadEditor from its current position in the DOM, replace  
        //it with a DIV to render the markup and copy the editor content into  
        //the TextArea ready for AJAX postback.              
        if (firstEdit){  
            firstEdit = false;  
            $editorPanel.remove();  
        }  
        else {  
            var editor = $find($radEditor.attr('id'));  
            var edContent = editor.get_html('true');  
            $('<div/>')  
                .addClass('SKEditableBodyBlockContent')  
                .html(edContent)  
                .replaceAll($editorPanel);  
            saveEditorContent();  
        }  
 
        //Insert the RadEditor into its new position in the DOM, i.e. in the  
        //editable body the user clicked on.  
        $editableBody.append($editorPanel);  
          
        //Find the DIV showing the rendered markup of this editable body and  
        //replace it with the RadEditor.  
        var editor = $find($radEditor.attr('id'));  
        $bodyBlock = $(event.target).closest('.SKEditableBodyBlockContent');  
        editor.set_html($bodyBlock.html());  
        var editorBody = document.all ? editor.get_document().body : editor.get_document();  
        $editorBody = $(editorBody);  
        $bodyBlock.remove();  
 
        //Show the RadEditor and its wrapper.  
        $editorPanel.show();  
        $radEditor.show();  
          
        //Delay a short time and then apply focus to editor to cause text cursor  
        //to be displayed in the RadEditor.  
        setTimeout(function(){  
            editor.setFocus();  
        },200);  
          
        //Prevent the click event from activating any links from anchor tags in the  
        //editable body.  
        event.preventDefault();  
          
        //Re-Attach click and hover handlers to the editable body that was being  
        //edited previously.  
        if ($prevEditableBody){  
            $prevEditableBody  
                .one('click', moveEditorToBody)  
                .unbind('mouseenter mouseleave')  
                .hover(function(){  
                    $(this).addClass('SKEditableBodyHighlight');  
                }, function(){  
                    $(this).removeClass('SKEditableBodyHighlight');  
            });  
        }  
        $prevEditableBody = $editableBody;  
 
    };  
      
    //Find the TextAreas for every editable body, hide them and insert a  
    //DIV to show their rendered markup.  
    $('.SKEditableBodyText').each(function(index){  
        $(this).hide();  
        $('<div/>')  
            .addClass('SKEditableBodyBlockContent')  
            .html($(this).val())  
            .insertAfter($(this));  
    });  
 
    //Make the editable bodies editable, using single RadEditor, when the user  
    //clicks them and attach mouse-overs to indicate which bodies are editable.  
    $('.SKEditableBody')  
        .one('click', moveEditorToBody)  
        .hover(function(){  
            $(this).addClass('SKEditableBodyHighlight');  
        }, function(){  
            $(this).removeClass('SKEditableBodyHighlight');  
        });  
 
}); 

The problems are:

  1. In IE/Chrome, after an editable body is clicked, the user has to click again before the text insert caret and toolbar will show. Is there a way to make these appear as soon as the user clicks on the editable DIV.
  2. In Firefox, the text insert caret never shows, no matter how many times the user clicks. Sadly, this makes it unusable in Firefox, although if the user enters text it does go into the correct position in the RadEditor. How can I cause the text insert caret to appear in Firefox?

I hope you can help, as this would be a very efficient solution to the problem of having multiple editable areas on a single page.

11 Answers, 1 is accepted

Sort by
0
Dobromir
Telerik team
answered on 29 Mar 2010, 01:01 PM
Hi Debbie,

There is a known issue with RadEditor when moving within the DOM, which applies to the explained scenario. In order to fix this, you need to execute RadEditor's onParentNodeChanged() client method right after appending the RadEditor, e.g.:
......
$editableBody.append($editorPanel);
//need to be executed after moving editor inside the DOM
var editor = $find($radEditor.attr('id'));
editor.onParentNodeChanged();
......

In addition, I suggest to check the following KB article where the functionality that you tried to implement is achieved by using a different approach:
Setting hidden RadEditor in edit mode on click and putting it in non editable mode onblur

Sincerely yours,
Dobromir
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Debbie Roberts
Top achievements
Rank 1
answered on 30 Mar 2010, 12:03 PM

Thank you, Dobromir,

 

Your suggested solution fixes my first problem but it does not solve my second problem. I had already based my jQuery code on your KB article that you mention.

 

Luckily, I have discovered the solution to the missing text insert caret in Firefox, quite by accident.

 

Before the RadEditor is moved in DOM in Firefox, the wrapper containing the RadEditor must be hidden. If the editor is moved without hiding the wrapper, the text insert caret will only appear in the first editable block clicked. It will vanish on all subsequent moves of the editor, making the editor unusable.

The final changes required to make this jQuery code fully cross-browser are as follows:

        //Hide the editor panel. If this is not done here the text insert caret  
        //disappears in Firefox after the 2nd editable body is clicked.  
        $editorPanel.hide();  
 
        //Insert the RadEditor into its new position in the DOM, i.e. in the  
        //editable body the user clicked on.  
        $editableBody.append($editorPanel);  
          
        //Copy the editable body's markup from the textarea into the RadEditor.  
        var editor = $find($radEditor.attr('id'));  
        editor.onParentNodeChanged();  
        var $bodyBlock = $editableBody.find('.SKEditableBodyText');  
        editor.set_html($bodyBlock.val());  
 

Kindest Regards,

Debbie
0
Debbie Roberts
Top achievements
Rank 1
answered on 31 Mar 2010, 11:06 AM
I am still finding a problem that the user needs to click twice on each editable area before the toolbar and text insert caret will appear, although I do now get the text insert caret in Firefox.

The scenario is as follows:

  1. The user clicks on an editable area (at this stage it is a DIV).
  2. The editor is moved in the DOM OK and is shown, after a short delay, WITHOUT the toolbar and text insert caret.
  3. The user then clicks again, on what is now the actual RadEditor, and now the toolbar shows and the text insert caret appears.

Is there any way to simulate the effect of the user having clicked the RadEditor after the editor is moved in the DOM?
Is there a RadEditor method or event that I can fire that will cause the toolbar 'showonfocus' code to execute after moving the RadEditor? I have tried using a timeout and then calling editor.setFocus() but this does not cause the showonfocus code to execute.
Is there a way to cause the text insert caret to appear?

0
Dobromir
Telerik team
answered on 01 Apr 2010, 02:19 PM
Hi Debbie,

RadEditor does not offer such feature / method, nevertheless you can use the following code sample to simulate the click:
.......
editor.onParentNodeChanged();
setTimeout(function()
{
    if ($telerik.isIE)
    {
        editor.fire("Enter");
    }
    else
    {
        editor.pasteHtml("");
    }
    editor.undo(1);
}, 200);

This feature is logged into our ToDo list and we will do our best to implement it in one of our upcoming releases.

Greetings,
Dobromir
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Debbie Roberts
Top achievements
Rank 1
answered on 12 Apr 2010, 02:43 PM
Hi Dobromir,

Many thanks for your reply. A method that we could call to activate the ShowOnFocus toolbar and the re-sizing off the editor when receiving focus would be a really nice feature in a new release of the Telerik controls suite.

You suggested solution works very well in Firefox. However, in IE it erases the existing content of the editable block, so it cannot be used. Firefox was the main browser I was having trouble with, so this is very good for Firefox. In IE, it is useable without this fix, so it is OK.

Debbie
0
Debbie Roberts
Top achievements
Rank 1
answered on 26 Apr 2010, 05:05 PM
Just for further interest of anyone following this thread, I have discovered a very reliable way of making the RadEditor behave correctly in Firefox after the RadEditor is moved in the DOM. This displays the text insert caret and toolbar correctly after a single click on another editable area. The solution is to do the following after the the RadEditor has been moved and made visible again:

        //Move the focus away from the editor onto the first visible form input field.  
        //If we don't do this, the text insert caret disappears in Firefox when a 2nd  
        //editable body is clicked.  
        $('input:visible').eq(0).trigger('focus');  
 
        //Delay a short time and then apply focus to editor to cause text cursor  
        //to be displayed in the RadEditor.  
        setTimeout(function(){  
            editor.setFocus();  
 
            //This forces the formatting toolbar to appear in Firefox when an editable  
            //body is clicked.  
            if ($telerik.isFirefox){  
                setTimeout(function(){  
                    editor.pasteHtml("");  
                    editor.undo(1);  
                }, 200);  
            };  
              
        },200);  
          
 

The trick is to switch the focus to another input field before moving the focus back to the RadEditor. This causes the RadEditor gaining focus events to execute correctly.
0
Misha
Top achievements
Rank 1
answered on 16 Sep 2011, 03:39 PM
It looks wonderful, but if on save method we send ajax request - all pretty behaviour is broken.
0
Rumen
Telerik team
answered on 19 Sep 2011, 11:12 AM
Hi Misha,

Could you please be a bit more specific regarding the exact issue that you experience? Could you please elaborate what do you mean by "all pretty behaviour is broken"?

Please, also provide a sample working project which demonstrates the problem. Thus we will be able to examine your code, test it and provide a solution.

Best regards,
Rumen
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal
0
Misha
Top achievements
Rank 1
answered on 19 Sep 2011, 01:30 PM
http://www.sitefinity.com/devnet/forums/sitefinity-4-x/bugs-issues/radeditor-blur-focus-after-ajax-request.aspx

"pretty behaviour" - I mean, ShowOnFocus - toolbar of radeditor which appears after user clicks on content area of radeditor.
after using radajaxmanger.ajaxrequest("something")  and attaching it to any client event - onblur, onkeyup, selection etc.  - content area becomes disabled, tolbars button also get strange behaviour.
0
Rumen
Telerik team
answered on 21 Sep 2011, 03:37 PM
Hello Misha,

Try to hide the toolbar when the blur event occurs:

var tWnd= editor.get_toolAdapter().get_window();
tWnd.hide();


Best wishes,
Rumen
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now
0
Misha
Top achievements
Rank 1
answered on 26 Sep 2011, 08:43 AM
Hello, please look at
http://www.sitefinity.com/devnet/forums/sitefinity-4-x/bugs-issues/radeditor-blur-focus-after-ajax-request.aspx
I posted example and describe issues and bugs with radeditor.
Tags
Editor
Asked by
Debbie Roberts
Top achievements
Rank 1
Answers by
Dobromir
Telerik team
Debbie Roberts
Top achievements
Rank 1
Misha
Top achievements
Rank 1
Rumen
Telerik team
Share this question
or