Adding custom Javascript and Stylesheets in the Content Editor

tl;dr Add custom resources in the Sitecore Content Editor from config setting

I recently created some custom fields in which I needed to add some custom JavaScript. I looked at a couple of other implementations of custom fields but they all worked on the individual control, not at an Item level or adding snippets of Javascript by inlining it adding if from code-behind declarations. I also wanted to avoid modifying any standard Sitecore files if at all possible, which some of the other custom field implementation had done and makes installing multiple packages tricky since each would overwrite the changes of the others. Aside from which, I wanted to avoid it from an upgrade point of view. I also needed to update the UI when the content had been loaded so would need to listen for that event.

I needed to add my own Javascript file into the Content Editor in which I would be able to write standard Javascript.

If we hook into the renderContentEditor pipeline it is possible to add our own controls into the head section of the Content Editor (/sitecore/shell/Applications/Content Manager/Default.aspx).

public class InjectScripts
{
    private const string JavascriptTag = "<script src=\"{0}\"></script>";
    private const string StylesheetLinkTag = "<link href=\"{0}\" rel=\"stylesheet\" />";

    public void Process(PipelineArgs args)
    {
        AddControls(JavascriptTag, "CustomContentEditorJavascript");
        AddControls(StylesheetLinkTag, "CustomContentEditorStylesheets");
    }

    private void AddControls(string resourceTag, string configKey)
    {
        Assert.IsNotNullOrEmpty(configKey, "Content Editor resource config key cannot be null");

        string resources = Sitecore.Configuration.Settings.GetSetting(configKey);

        if (String.IsNullOrEmpty(resources))
            return;

        foreach (var resource in resources.Split('|'))
        {
            Sitecore.Context.Page.Page.Header.Controls.Add((Control)new LiteralControl(resourceTag.FormatWith(resource)));
        }
    }
}

We then patch the Sitecore config with our new pipeline processor and our new config keys which contain a pipe separated list of resources to include:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
     <pipelines>
       <renderContentEditor>
         <processor patch:before="*[1]" type="HideDependentFields.SC.Pipelines.RenderContentEditor.InjectScripts, HideDependentFields.Types" />
       </renderContentEditor>
     </pipelines>
     <settings>
       <setting name="CustomContentEditorJavascript" value="/path-to/script1.js|/path-to/script2.js|/path-to/script3.js"/>
       <setting name="CustomContentEditorStylesheets" value="/path-to/style1.js|/path-to/style2.js|/path-to/style3.js"/>
     </settings>
   </sitecore>
</configuration>

Super clean with no direct amendments to any standard Sitecore files. It turns out we also have an additional benefit. While I was looking around code of custom fields I noticed Ruud Van Falier’s Limited Text Control used jQuery, which was added in Sitecore back in version 6.5 and a reference to which is included in the Content Editor (jQuery v1.10.2 in Sitecore 7.2).

That means we could use PrototypeJS/Scriptalicious:

document.observe("dom:loaded", function(event) {
    $$('.element-selector').each( function(element, index) {
        DoCustomPrototypeLoadStuff(element);
    });
});
 

Or jQuery/jQuery UI:

$sc(document).ready(function(event) {
    $sc('.element-selector').each( function(index) {
        DoCustomJQueryLoadStuff(this);
    });
})

This is just an example, you should be scoping your jQuery code to avoid conflicts and make your code looks a little nicer 🙂