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...

Kubectl using SSH tunnel for TKG K8s Clusters

We know SSH'ing and probably many knows about SSH tunnel. The way, in my opinion, these 2 (SSH and SSH tunnel) are different to me (and I am in favor of SSH Tunnel) is how I use it. From tooling perspective I would almost always do tunnel instead of direct ssh.  In this post I will describe how to do SSH tunnel for kubectl to interact with remote kubernetes cluster (Specifically Tanzu Kubernetes Grid aka TKG cluster). Get the project ready to go from my github:  https://github.com/alinahid477/vsphere-with-tanzu-wizard Topics Backstory SSH tunnel for TKG Clusters using Docker container Technical stuff: Tunnel through Bastion for TKG K8s cluster Technical stuff: SSH Tunnel for Kubectl for remote K8s Clusters (same with or without docker) Technical stuff: Explain me this A famous quote from Darth Vader himself: "Feel the power of SSH Tunnel" Backstory Why ssh or ssh tunnel? The below diagram shows in what scenario a SSH or SSH Tunnel almost becomes a necessity. Let's st...

CKA Exam; May 2024: My take on it and cheat sheet

So, I finally got the little green tick of having CKA certification in my certification list. I put off this exam for so long that it seriously became not funny anymore. The internet has quite literally way more than 1000 posts on this topic. But what harm would one more post cause? So here's mine. I will write it from my perspective. I am writing this post just in case if anyone benefits from it, as I predict there could be many on the same boat as me. Background: Kubernetes, modern application architecture, DevSecOps etc are not new territory for me. In fact, I think I am fairly versed in K8s and related tech stack. But due my own imposter syndrome I have been putting off sitting the CKA exam. However, last week I thought about the CKA as "just another approval for my skills" and got the nudge to sit the exam.  Here's what I did till the day I sat for the exam. (Everybody is different but the below worked for me the best) The preparation: As I have been working with...

A CQRS Microservice Architecture - My Way

Microservice Architecture is the new trend in the industry. When I thought of building a decisioning engine to work as my personal assistant I decided to design it as a swarm of Microservices. The most compelling selling point about Microservice Architecture which resonated well for me was its ease of maintainability and that's a big factor for a hobby project like this which has a lot of custom logic programmed into it and requires a lot of frequent changes. In theory, Microservice should fit right in. I tried doing it in the Monolithic way and I failed !!. So, will Microservices solve it for me? Let's find out. In this post I will do it in the "Software Engineering" way. Background: Few weeks ago I created a wifi controlled water system that I can control via my Home Assistant (using my phone even if I am on the other side of the planet, like Batman). And this is working great for me. Read about that here: Smart wifi controlled irrigation system . Bu...