Skip to main content

Customising Sitecore's Rich Text Editor. R u Kidding me?

theProblem:
The front end ( html and css ) is set up such a way that for the description text form a sitecore content needs to have a <p> tag wrapped around it. 
Now, I'm sure just by reading the above 2 lines you are thinking "WOW that's really simple and every RTE does that by default. So, continuing to reading this is useless and this guy is clearly dumb enough."

"sayth whath" - said thor
Well Yes and No.
This is what I found:
So by default the RTE wraps texts in a <p> tag = TRUE. BUT the catch is you will need to hit a enter or copy paste multiple paragraph. Then the RTE will clean the HTML and in the process it will wrap each para in a <p> tag. NICE. Of course there's a setting for it that you can modify and instead of <p> you can have <br/> and so.
<setting name="HtmlEditor.LineBreak" value="p" />
And no you can't have anything that you want there.. there's a limited list of tags that you can put in the settings.
Either way that VERY COOL OF YOU, SITECORE.
But this doesn't solve my problem. Cause I want ( or the client wants or the requirement is) to add a <p> tag regardless of hitting the enter button.
So when someone types in one line in there and hit the "accept" button the text will be wrapped in a <p> tag.
This has been stuck in the head and I had dreams about it.
theResearch:
This is where I start cursing sitecore because of it's lack of documentation and particularly how the RTE is baked into it.
Basically SITECORE uses RADEditor from Telerik ( which is 'probably' not TinyMCE )  as its RTE. In terms of how rad editor is made is flexible enough to customise its behaviour according to the needs BUT the way sitecore has included it makes it somewhat not so much customisable.
AND OFCOURSE THERE IS NO OR VERY LESS DOCUMENTATION ABOUT IT.
I eventually ended up seeing it internal code from Sitecore.client.dll and figure out how they're incorporating the RadEditor.
What I Tried:
"sitecore\shell\Controls\Rich Text Editor\EditorWindow.aspx" is the file that displays the UI of the editor. And one of the JS functions in there is my injection point for my custom snippet to add <p> tag.
BUT obviously I cannot change this file because it won't be in the sourcecontrol and as part of standard practice I should not modify SITECORE's core file as it will lead to inconsistency in different environment and will become difficult to manage (should the need arises to re-install sitecore).
Also, because how RadEditor is baked into SITECORE I could not implement my own custom EditorFilter because according to the RadEditor documentation that would require modifying its declaration in <telerik:RadEditor ID="Editor" Runat="server"> which also is in EditorWindow.aspx. So there goes my golden egg. :( ( I did say F*** Y** SITECORE at this point, ofcourse)
theSolution:
Fortunately, From the dll, one particular function caught my eye: 
protected virtual void SetupScripts()
{
foreach (XmlNode node in Factory.GetConfigNodes("clientscripts/htmleditor/script"))
this.Result.Scripts.AppendFormat("<script src=\"{0}\" language=\"{1}\"></script>\n", (object) XmlUtil.GetAttribute("src", node), (object) XmlUtil.GetAttribute("language", node));
}
NICE, eh ? The developers of SITECORE are clever after all.
So I did this in the webconfig,
<!-- CLIENT SCRIPTS
These script files are included in the client, e.g. '<script src="/myscript.js" language="JavaScript"/>'
-->
<clientscripts>
<everypage />
<htmleditor>
<script src="/assets/js/CustomRTE.js" language="javascript"/>
</htmleditor>
</clientscripts>

And overrode "scSendRequest" function from EditorWindow.aspx.
window.scSendRequest = function(evt, command){
var editor = scRichText.getEditor();
if (editor.get_mode() == 2){//If in HTML edit mode
editor.set_mode(1); //Set mode to Design
}
var htmls = editor.get_html(true);
var regex = /<p[^>]*>.*?<\/p>/i;
var match = regex.exec(htmls);
if(match == null && htmls != null) {
htmls = "<p>" + htmls + "</p>";
}
//$("EditorValue").value = editor.get_html(true);
$("EditorValue").value = htmls;
scForm.browser.clearEvent(evt);

scForm.postRequest("", "", "", command);
return false;
}

AND YAY .. double rainbow and unicorn.

Obviously the JS stuffs didn't come out my head right away. I must confess the struggle.
So with this approach nothing from SITECORE's core has been modified and all the custom code sits out side of sitecore shell making them source controllable too and achieve's what I wanted.

The important thing I learned here is overriding a JS function. Didn't even know that was possible. Weird.
However the question remains, where the F*** is the documentation ?

theEnd:
There might be more straight forward and better way of doing it ( for which what I have done is dumb enough ) .. but until then this will do. 
Either way, this opens few other doors for customising Sitecore's RTE. ( if it helps anyone )

Thank you for reading a lot of texts.

Comments

Popular posts from this blog

The story of a Hack Job

"So, you have hacked it" -- Few days ago one of the guys at work passed me this comment on a random discussion about something I built. I paused for a moment and pondered: Do I reply defending how that's not a hack. OR Do I just not bother I picked the second option for 2 reasons: It was late. It probably isn't worth defending the "hack vs" topic as the comment passed was out of context. So I chose the next best action and replied "Yep, sure did and it is working great.". I felt like Batman in the moment. In this post I will rant about the knowledge gap around hacking and then describe about one of the components of my home automation project (really, this is the main reason for this post) and use that as an example how hacking is cool and does not always mean bad. But first lets align on my definition of hacking: People use this term in good and bad, both ways. For example: "He/she did a hack job" -- Yeah, that probably

Smart wifi controlled irrigation system using Sonoff and Home Assistant on Raspberry Pi - Part 1

If you have a backyard just for the sake of having one or it came with the house and you hate watering your garden or lawn/backyard then you have come to the right place. I genuinely believe that it is a waste of my valuable time. I would rather watch bachelorette on TV than go outside, turn on tap, hold garden hose in hand to water. Too much work!! Luckily, we have things like sprinkler system, soaker etc which makes things a bit easy. But you still have to get off that comfy couch and turn on tap (then turn off if there's no tap timer in place). ** Skip to the youtube video part if reading is not your thing   When I first moved into my house at first it was exciting to get a backyard (decent size), but soon that turned on annoyance when it came down maintaining it, specially the watering part. I laid bunch sprinklers and soaker through out the yard and bought tap timer but I still needed to routinely turn on the tap timer. Eventually few days ago I had enough of this rub

Exception Handling With Exception Policy

This is how I would think of an application at the very basic level: Now this works great. But one thing that is missing in this picture is Exception Handling . In many cases we pay very less attention to it and take it as "we'll cross that bridge when it'll come to that". We can get away with this as in many application as exceptions does not stop it from being in the state "is the application working" as long as we code it carefully and at the very least handling the exceptions in code blocks. This works. But we end up having try catch and if else everywhere and often with messy or no direction to what type of exception is to be handled where and how. Nonetheless, when it comes down an enhancement that depends upon different types exceptions, we will end up writing/modifying code every where, resulting in even messier code. I'm sure no one wants that. Even, in scenarios, a custom handler is not the answer either. Cause this way we will s