I have a RadEditor (EditType="Inline"), inside a RadSplitter/RadPane, and would like to trigger a post back to save to the database, without using a Button click.
Which event is most appropriate to do this?
I've experimented with the OnClientInlineEditCompleted() event. However, it also fires when I click a toolbar button, which is too soon.
The OnClientCommandExecuted() event fires with almost every action, so not good solution.
In the server-side database save method, I compare the existing data to the RadEditor content, if they're different, save it to the database. The problem here is that the changes made to the RadEditor do not show, thus the server-side save method is not fired.
I've attempted to set the focus back to the content of the RadEditor before calling the "__doPostBack()" method, thinking it will accept the changes to the content and save them in the PostBack. It doesn't.
Client code:
function OnClientInlineEditCompleted() {
var editor = $find("<%= NotePad1.ClientID %>");
editor.setFocus();
__doPostBack("", "");
}
PostBack code:
if (NotePad1.Content != MyTable.MyNotePad)
{
UpdateNotePad();
}
Update: I've been able to get this logic to work *almost* as desired by setting a boolean "isUpdated" variable in the OnClientInlineEditCompleted event, then reacting to that value in the OnClientCommandExecuted event.
Where it fails is when there is a dialog involved. For example, when clicking the link button in the toolbar, this causes the events to fire and trigger the postback database save.
It seems I'm close, I just need to figure out how to suppress those dialogs until the user is done editing.
Hi Jeff,
Can you, please, send me the RadEditor setup that you are using? I tested the provided logic and the OnClientInlineEditCompleted event is triggered at my end only when I click outside the Editor and its toolbar. You can see the video from my test here:
http://somup.com/c3VXDHZ2Z1
Below is the code I used with the latest version of the controls:
<div style="margin-top: 100px"> <telerik:RadEditor EditType="Inline" ID="NotePad1" runat="server" OnClientInlineEditCompleted="OnClientInlineEditCompleted"> <Content> <div style="width: 420px"> <h2 class="titleText">RadEditor for ASP.NET AJAX</h2> <p style="text-align: justify;"> <span style="color: #4f6128; font-size: 19px;"><strong>RadEditor</strong></span><span style="color: #4f6128;"> </span>is not simply an HTML <a href="#HTMLDescription"> <sup>1</sup> </a> Editor. It is what Microsoft chose to use in <strong>MSDN</strong>, <strong>CodePlex</strong>, <strong>TechNet</strong>, <strong>MCMS</strong> and even as an alternative to the default editor in <a href="https://www.telerik.com/products/aspnet-ajax/sharepoint.aspx">SharePoint</a>. </p> </div> </Content> </telerik:RadEditor> <asp:Label ID="Label1" runat="server"></asp:Label> </div> <script> function OnClientInlineEditCompleted() { alert("OnClientInlineEditCompleted"); var editor = $find("<%= NotePad1.ClientID %>"); editor.setFocus(); __doPostBack("", ""); } </script>
protected void Page_Load(object sender, EventArgs e) { if (IsPostBack) { if (NotePad1.Content != Label1.Text) { UpdateNotePad(); } } } private void UpdateNotePad() { Label1.Text = NotePad1.Content; }
Vessy,
The video of your test is precisely the behavior I'd like to see. Below is a screenshot of my RadEditor setup. One big difference is I'm using the .axd DialogHandler.
I also made a quick little video of the postback occurring when I click on any tool that fires a dialog. I've cropped it in order to protect proprietary content, so you can't see the dialog window pop-up, as it's off-screen, but you can clearly see the postback. It was blocked from being attached to this message. Please let me know how I can get this to you, if you deem it necessary to view.
Vessy,
I replaced my RadEditor with the example you provided and all accompanying logic to mimic your setup - yielding the same results. The postback occurs with every toolbar button click.
I'm at a loss as to what is causing this behavior. As I mentioned, this RadEditor resides within a Splitter and Pane - could it be that either of those controls are the culprit?
Will test the RadEditor outside of the Splitter to see if the results are different. Outside of using the alternate DialogHandler (.axd), that's the only difference.
Jeff.
Hi Jeff,
Usually a PostBack occurs on every button click when there is a JavaScript error thrown on the page. Can you verify if this is not the case at your end as well?
Vessy,
That is one of the first things I looked at. Just double-checked it and the console does not indicate any JS errors.
Vessy,
Something I've failed to mention, and could be the issue, is that we're using an "external" toolbar. Here's the HTML:
<div> <asp:Panel runat="server" ID="ToolbarHolder"> <div id="toolbarDiv" class="RadEditor reCustomContainer"> </div> </asp:Panel> </div> <telerik:RadEditor ID="reNotePad" runat="server" Width="100%" Height="100%" RenderMode="Lightweight" ForeColor="SteelBlue" Font-Names="Comic Sans MS" BorderStyle="None" EmptyMessage="Enter your notes here ..." OnClientInlineEditCompleted="OnClientInlineEditCompleted" OnClientLoad="OnClientLoad" OnClientCommandExecuted="OnClientCommandExecuted" EditModes="Design" EditType="Inline" Visible="true" DialogHandlerUrl="~/Telerik.Web.UI.DialogHandler.axd" NewLineMode="Br"> <Tools> <telerik:EditorToolGroup dockingzone="toolbarDiv"> <telerik:EditorTool Name="Undo" /> <telerik:EditorTool Name="Redo" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="Bold" /> <telerik:EditorTool Name="Italic" /> <telerik:EditorTool Name="Underline" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="ForeColor" /> <telerik:EditorTool Name="BackColor" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertOrderedList" /> <telerik:EditorTool Name="InsertUnorderedList" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertHorizontalRule" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="Indent" /> <telerik:EditorTool Name="Outdent" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertLink" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="JustifyLeft" /> <telerik:EditorTool Name="JustifyCenter" /> <telerik:EditorTool Name="JustifyRight" /> <telerik:EditorTool Name="JustifyFull" /> </telerik:EditorToolGroup> </Tools> </telerik:RadEditor>
Here is the css used to style this Editor:
/*css to format inline radeditor form My Notepad*/ .RadEditor.RadWindow.reInlineEditor.reToolbarWindow.reWrapper { box-shadow: none !important; border-style: none !important; visibility: hidden !important; } .RadWindow.reInlineEditor .rwContent { /*cannot remove or client change won't fire*/ background-color: transparent !important; color: transparent !important; } .RadEditor.reInlineEditor .reContentArea { font-size: 12px !important; padding: 50px 2px 2px 2px !important; position: center; } .RadEditor.reCustomContainer { border-style: none !important; background-color: #dee3ed; position: fixed; margin-right:51px; z-index: 50000; }
Thanks a lot for the additional details, Jeff.
The faced problem is caused due to the fact the OnInlineEditCompleted event is triggered if you click either outside the editor, either outside the RadWindow holding the floating inline toolbar. The main specific of the inline edit mode of the Editor is that its toolbar is floating, thus it cannot be docked.
As you are docking the toolbar into a separate element outside the RadWindow wrapper, each click over the toolbar is now considered as a click outside the toolbar. That's why the docking zone could be used only when the Normal EditMode of the Editor is used.
Thanks, Vessy. We expected as much. Wanted to get your thoughts on our approach. We're able to catch the active element in the OnClientInlineEditCompleted event - if the active element is the toolbar (which we've designated with a class name), then we do not call the postback, and instead we want to shift focus back to the content area of the editor, so that when the user then clicks away from the editor, the postback will trigger. It seems like we're on the verge of a usable solution, it's just that I've been unable to properly focus/select the content area. Here's the code, would like to get your take on it how to do this:
function OnClientInlineEditCompleted() { let parentClass; try { parentClass = document.activeElement.parentElement.parentElement.parentElement.parentElement.className; } catch (e) { parentClass = ''; } if (parentClass == "panel-editor-toolbar") { var editor = $find("<%=reNotePad.ClientID%>"); // get a reference to RadEditor client object editor.setFocus(); //editor.get_contentArea().focus(); } else { __doPostBack("", ""); } }
Hi Jeff,
Can you elaborate a bit on what behavior do you expect when focusing the Editor? The editor.setFocus() method focusses the Editor's iframe, you can check that by calling document.activeElement in the console of the page.
If you want to position the cursor inside the Editor after the focusing, you can follow the approach explained here:
https://www.telerik.com/forums/set-focus-to-the-end-of-text
Vessy,
We're trying to mimic the user clicking into the content area after a toolbar button click, so that when they then click outside the content area, the postback will get triggered from the OnInlineEditCompleted event.
I actually got this to work yesterday, albeit in a strange way. I added some JavaScript ("editor.hasFocus()") which has an error (the Editor does not have a "hasFocus() method". This error caused the event to delay long enough to be able to produce the desired result.
I don't want to have an error solve my problem, so I thought I'd replace it with a setTimer function, but that didn't work. So, I'm left with the expected outcome but with a javascript error. So strange.
I'm now looking into why the JavaScript error is working this way, and implement some logic that does the same thing without throwing an error.
function OnClientInlineEditCompleted() { let parentClass; // Handle exception thrown when clicking on the body or any other element without four parents try { parentClass = document.activeElement.parentElement.parentElement.parentElement.parentElement.className; } catch (e) { parentClass = ''; } if (parentClass == "panel-editor-toolbar") { var editor = $find("<%=reNotePad.ClientID%>"); //get a reference to RadEditor client object editor.setFocus(); // This if statement throws a javascript error // The byproduct of this is that the postback triggers as desired if (editor.hasFocus()) { alert("Editor has focus"); } //setTimeout(() => { // // Delay processing to ensure Editor regains focus // // in time to trigger postback //}, 1000); } else { __doPostBack("", ""); } }
Vessy,
Adding further clarification, as this issue is quickly becoming fluid: What we noticed is that when you click on a toolbar button, then click outside the content, the OnClientInlineEditCompleted() event does not fire. However, once you click inside the content area again (immediately following a toolbar button click), then click outside the content area, the event/postback is executed properly.
The idea is to automate this step of clicking back into the content area after the toolbar button click. It appears that I've successfully done so.. unfortunately, an unhandled exception is the reason it is succeeding. Interestingly ironic.
Hi Jeff,
When a JavaScript error is thrown on the page it prevents the execution of the remaining part of the client-side logic, hence the postback is not made when you call the unexisting hasFocus() method. Every error on the page prevents the proper functioning of the client-side logic of our controls as well (like the not propered call of the OnClientInlineEditCompleted event), making the usage of this hack strongly not recommended.
Did you have the chance to try the solution suggested in my previous reply? It should be similar to:
<script> function OnClientInlineEditCompleted() { let parentClass; // Handle exception thrown when clicking on the body or any other element without four parents try { parentClass = document.activeElement.parentElement.parentElement.parentElement.parentElement.className; } catch (e) { parentClass = ''; } if (parentClass == "panel-editor-toolbar") { var editor = $find("<%=reNotePad.ClientID%>"); //get a reference to RadEditor client object var doc = editor.get_document(); doc.execCommand("SelectAll", null, false); //Collapse selection to the end editor.getSelection().collapse(); } else { __doPostBack("", ""); } } </script>
Vessy,
Yes, I tried that method, as I discovered it a few days before you mentioned it. It did not produce the desired results. The user still has to manually select inside the content area, then back outside to get the postback to fire.
Just to correct something you mentioned - The exception gets thrown in the TRUE part of the IF statement, and the PostBack gets fired in the FALSE part of the IF statement. The exception does not stop the postback from occurring.
So, the exception allows the RadEditor to appear to be "re-selected" after a toolbar button click. The next time the user clicks outside of the content area, the IF condition will be false, thus firing the postback, and producing the results I need.
The exception is not ideal, and I will continue to look for a better solution.
I've since changed it to just throw an exception, rather than call a non-existent method:
throw 'Force Editor Content area selection';
What do you mean by "not propered call of the OnClientInlineEditCompleted event"?
Hi Jeff,
By saying "not proper call of the OnClientInlineEditCompleted event" I meant that the JavaScript error could be the reason for the a broken cycle of the client-side events, resulting in the OnClientInlineEditCompleted event not triggered in the expected moment.
Of course, if the exception brings the target behavior I encourage you to use it.
I am just pasting below my test setup in case you decide to go in this direction:
<telerik:RadScriptManager ID="RadScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" /> <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" /> <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" /> </Scripts> </telerik:RadScriptManager> <div> <asp:Panel runat="server" ID="ToolbarHolder" CssClass="panel-editor-toolbar"> <div id="toolbarDiv" class="RadEditor reCustomContainer"> </div> </asp:Panel> <telerik:RadEditor ID="reNotePad" runat="server" Width="100%" Height="100%" RenderMode="Lightweight" ForeColor="SteelBlue" Font-Names="Comic Sans MS" BorderStyle="None" EmptyMessage="Enter your notes here ..." OnClientInlineEditCompleted="OnClientInlineEditCompleted" EditModes="Design" EditType="Inline" Visible="true" NewLineMode="Br"> <Content> <div style="width: 420px"> <h2 class="titleText">RadEditor for ASP.NET AJAX</h2> <p style="text-align: justify;"> <span style="color: #4f6128; font-size: 19px;"><strong>RadEditor</strong></span><span style="color: #4f6128;"> </span>is not simply an HTML <a href="#HTMLDescription"> <sup>1</sup> </a> Editor. It is what Microsoft chose to use in <strong>MSDN</strong>, <strong>CodePlex</strong>, <strong>TechNet</strong>, <strong>MCMS</strong> and even as an alternative to the default editor in <a href="https://www.telerik.com/products/aspnet-ajax/sharepoint.aspx">SharePoint</a>. </p> </div> </Content> <Tools> <telerik:EditorToolGroup dockingzone="toolbarDiv"> <telerik:EditorTool Name="Undo" /> <telerik:EditorTool Name="Redo" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="Bold" /> <telerik:EditorTool Name="Italic" /> <telerik:EditorTool Name="Underline" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="ForeColor" /> <telerik:EditorTool Name="BackColor" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertOrderedList" /> <telerik:EditorTool Name="InsertUnorderedList" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertHorizontalRule" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="Indent" /> <telerik:EditorTool Name="Outdent" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="InsertLink" /> <telerik:EditorSeparator /> <telerik:EditorTool Name="JustifyLeft" /> <telerik:EditorTool Name="JustifyCenter" /> <telerik:EditorTool Name="JustifyRight" /> <telerik:EditorTool Name="JustifyFull" /> </telerik:EditorToolGroup> </Tools> </telerik:RadEditor></div> <telerik:RadLabel ID="Label1" runat="server"></telerik:RadLabel> <script> function OnClientInlineEditCompleted() { let parentClass; // Handle exception thrown when clicking on the body or any other element without four parents try { parentClass = document.activeElement.parentElement.parentElement.parentElement.parentElement.className; } catch (e) { parentClass = ''; } console.log(parentClass); if (parentClass == "panel-editor-toolbar") { var editor = $find("<%=reNotePad.ClientID%>"); //get a reference to RadEditor client object var doc = editor.get_document(); doc.execCommand("SelectAll", null, false); //Collapse selection to the end editor.getSelection().collapse(); } else { __doPostBack("", ""); } } </script> <telerik:RadTextBox ID="RadTextBox1" runat="server"></telerik:RadTextBox>
As always, I'm thankful for your assistance. That being said, and as mentioned in the prior reply, I've implemented this exact setup with no success. We would choose to go in this direction if it yielded the desired results.
Hi Jeff,
Allow me to jump into this thread.
Can you please explain in more detail what do you mean by:
"That being said, and as mentioned in the prior reply, I've implemented this exact setup with no success." - what has happened and what is not working with this approach? It might be useful to share two Fiddler Jam captures - one with the code Veselina provided in her last reply, and another one showing your current implementation along with videos and instructions what is happening. This way we will be able to compare them, mock and test them on our side and see the problems/errors you get with each approach.
The Fiddler Jam captures will provide a lot of info easily and allow us to investigate further. Keep in mind that starting from a blank page or at least navigating to your page via the address bar is crucial for capturing all requests and responses:
https://docs.telerik.com/devtools/aspnet-ajax/knowledge-base/common-capture-issues-with-fiddler-jam
Thank you!
Rumen,
Feel free to join in the discussion. I'll summarize what I've posted before:
When the user clicks a toolbar button, I capture that event, and try to force select/re-select the RadEditor content so that when the next time the user clicks anywhere outside of the content, the OnInlineEditCompleted event fires thus triggering the postback to save data if it has been changed.
The forced thrown exception makes this happen. For example, the user will select some text, click the bold button, then click outside the content area, firing the postback, saving the changes back to the database.
Without the forced thrown exception, the user follows the same path above, but when they click outside the content area, after clicking a toolbar button, the OnInlineEditCompleted event doesn't fire - if the user simply clicks inside the content area, then immediately outside the content area, the event and postback fire.
I've used the setup Vessy provided, and the results are the same - The user still has to click inside the content area, then back outside to trigger the postback.
I recently downloaded Fiddler and will try to get comfortable with it to provide the info you requested.
Thanks.
Rumen,
I've recorded the two Fiddler jams and video you requested. I'd rather not post them publicly here in this forum. Which method do you recommend we use to get them to you?
Let me know,
Jeff.
Rumen,
I've opened a support ticket and provided links to the Fiddler Jams there. The ticket number is 1553799.
Thanks,
Jeff.
Hi Jeff,
I have just answered your support ticket on the matter. Please, give the suggested approach a try and let me know how it goes.