Front-End Development

8.1 Experience Editor JavaScript APIs

Javascript Abstract@1x.jpg

[su_note note_color=”#fafafa”]There are parts of Sitecore APIs that are well understood, widely used, and probably won’t change without a really good reason. And then there are relatively new APIs – some introduced along with new product features (e.g. xDB in 7.5, Content Testing in 8.0) and others added to support the shift in the underlying technologies (e.g. SPEAK-ification of the Experience Editor ribbon) . These APIs are young and as they grow and mature they also tend to change their shape and form. This is good news for the APIs – they are getting better indeed – but may surprise a developer maintaining a module for various Sitecore versions.[/su_note]

Sitecore.ExperienceEditor.js

Sitecore 8.0 introduced SPEAK-ified version of the Experience Editor ribbon. If you built or ported your own Page Editor extensions you have probably followed in Sitecore footsteps and used SPEAK pipelines along with Sitecore.ExperienceEditor.js APIs (I know I did). Your code might look like this:

define(["sitecore"], function (Sitecore) {
Sitecore.Commands.MyNewCommand = {
canExecute: function (context) {
return Sitecore.ExperienceEditor.isInMode("edit");
},

execute: function (context) {
context.app.disableButtonClickEvents();

Sitecore.ExperienceEditor.PipelinesUtil.executePipeline(context.app.MyNewPipeline, function () {
Sitecore.ExperienceEditor.PipelinesUtil.executeProcessors(Sitecore.Pipelines.MyNewPipeline, context);
});

context.app.enableButtonClickEvents();
}
};
});

you might also be leaning on a few other helpers:

Sitecore.ExperienceEditor.Dialogs.showModalDialog(...);
...
Sitecore.ExperienceEditor.TranslationsUtils.translateText(...);

These have moved in 8.1. Partly because it had to change (the original Sitecore.ExperienceEditor.js looked as if it was very quickly put together), and partly – I believe – because it’s easier to change a JavaScript API than it is a C# API. Plus, if you don’t document your APIs or otherwise expose implementation teams to its existence you may not feel that you are breaking anything when you’re changing it.

Covid 19
COVID-19: Digital Insights For Enterprise Action

Access Perficient’s latest insights into how you can leverage digital technologies to not only respond to the pandemic, but drive your operations forward and deliver experiences your customers need.

Get Informed

You will see that refactored commands in 8.1 all look similar to this:

define(
[
"sitecore",
"/-/speak/v1/ExperienceEditor/ExperienceEditor.js",
"/-/speak/v1/ExperienceEditor/TranslationUtil.js"
],
function (Sitecore, ExperienceEditor, TranslationUtil) {
Sitecore.Commands.Lock =
{
...
ExperienceEditor.PipelinesUtil.executePipeline(...);
...
TranslationUtil.translateText(...);
...
}
});

Sitecore API Wrapper

The refactoring in 8.1 didn’t change the signatures of the methods that I have used – only changed where I would find them. Still, it is a breaking change – my code stopped working. Now I need to fix it and ideally do it and maintain backwards compatibility with 8.0. Here’s what I have quickly come up with. In SitecoreApiWrapper.js:

define(["sitecore"], function (Sitecore) {
var resolve = function (attr) {
// ***** Sitecore 8.0 *****
var result = Sitecore.ExperienceEditor[attr];

// ***** Sitecore 8.1 *****
if (!result) {
result = require("/-/speak/v1/ExperienceEditor/ExperienceEditor.js")[attr];
}

return result;
};

return {
PipelinesUtil: function () {
return resolve("PipelinesUtil");
},

Web: function () {
return resolve("Web");
},

Dialogs: function() {
return resolve("Dialogs");
},

TranslationsUtils: function () {
return Sitecore.ExperienceEditor.TranslationsUtils ||
require("/-/speak/v1/ExperienceEditor/TranslationUtil.js");
}
};
});

It will basically first try the original namespace and then fall back to requiring a 8.1 module where the things live now. Reflection is very natural with JavaScript where object.property is equivalent to object["property"] and it saved me quite a few keystrokes. I still wish JavaScript had method_missing though.

Here’s how my code looks now:

require.config({
paths: {
sitecoreApiWrapper: "/-/speak/v1/mymodule/SitecoreApiWrapper"
}
});

define(["sitecore", "sitecoreApiWrapper"], function (Sitecore, SitecoreApiWrapper) {
Sitecore.Commands.MyNewCommand = {
canExecute: function (context) {
return context.currentContext.webEditMode === "edit";
},

execute: function (context) {
context.app.disableButtonClickEvents();

SitecoreApiWrapper.PipelinesUtil().executePipeline(context.app.MyNewPipeline, function () {
SitecoreApiWrapper.PipelinesUtil().executeProcessors(Sitecore.Pipelines.MyNewPipeline, context);
});

context.app.enableButtonClickEvents();
}
};
});

The Sitecore.ExperienceEditor.isInMode() was replaced with going after the raw value on the context – this is what both 8.0 and 8.1 do anyway.

[su_divider][divider top=”1″][/su_divider]

I did smile at one change though. TranslationsUtils became TranslationUtil – both words lost the plural vs. singular battle. PipelinesUtil stood its ground.

About the Author

As a Sitecore MVP, Brian spends most of his time consulting and architecting software solutions for enterprise-level Sitecore projects.

More from this Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up