Create.js
Create.js Integration Guide
Welcome to the Create.js integration guide. This guide aims to provide all the needed information for CMS developers to integrate Create.js as their front-end editing interface.
This guide is still in early stages, and so if you notice any errors or omissions, pull requests are more than welcome into the gh-pages branch of the Create.js repository.
Introduction
Create.js was originally written in 2010 as the next-generation content editing interface of Midgard CMS. Henri Bergius presented it in the Aloha Editor developer conference in Vienna last year, and the TYPO3 developers expressed interest in reusing the codebase.
Because of this we started extracting the various parts of the Create UI into their own, reusable components. The first one was VIE, which provides the underlaying management of editable objects. In basic use scenario, it loads content annotated with RDFa from the web page, populates it into Backbone.js Models and Collections, and then creates Backbone Views for the original RDFa-annotated parts of DOM.
This way the DOM will automatically stay in sync when data changes, whether that happens by user interaction like editing, or through some server communications (we’ve done collaborative editing demos over WebSockets, for instance).
Backbone.js is used there for two reasons:
- It handles the management of data in Models and Collections, and the connection of those to Views in an elegant way
- Backbone.Sync is a very good abstraction when we need to be able to persist/retrieve content from various different CMS back-ends
Later in 2011 the German AI Research Institute (DFKI) and Salzburg Research joined the VIE effort through the EU-funded IKS Project. This enabled us to make the library a lot more capable, adding type information, proper namespace handling, and connections with other semantic tools like Apache Stanbol and DBpedia.
The Create.js interface was then rebuilt on top of this new VIE library by writing a bunch of jQuery UI widgets. This way we have an overall default UX that we can ship, but still provide a bunch of different widgets for CMS vendors to pick-and-choose.
Create.js widgets

- Editable: makes an RDFa entities (as identified by
about) editable with some editing widget (now plain contentEditable, Aloha, and Hallo supported, more to come). Provides the events like “modified” of those widgets in a uniform way. Editable also deals with Collections, allowing user to add/remove items from them - Storage: provides localStorage save/restore capability, and keeps track of what entities ought to be saved to the back-end
- Workflows: retrieves workflows that user can activate for a given entity from the back-end, and handles running them. These could be simply things like publish/unpublish and delete, or more complex workflows
- Notifications: notification bubbles/dialogs that can be used for telling user what has happened (“X has been saved successfully”), or query them for what they want to do (“You have X local modifications for this page. Restore/Ignore”)
- Tags: content tagging widget
- Toolbar: holder widget for a toolbar overlay where widgets like Editable, Storage, and Workflows can place buttons
- Create: ties all of these together to the default UX
Some CMSs use the full Create UX, and some use just parts to provide the UX they want to have. Examples of custom UXs include Symfony CMF and OpenCms.
Create.js integration in nutshell
In nutshell, you have to do the following:
- Annotate your content with RDFa
- Include the Create dependencies (jQuery, jQuery UI, Underscore, Backbone, VIE, the editor of your choice)
- Include the Create JavaScript file (see
examples/create.jsandexamples/create-min.js) - Implement Backbone.sync for your back-end
Blogsiple is a Node.js based CMS integration testbed for Create. It may provide useful examples on how the connection between Create and a REST-capable web tool works.
RDFa: Making content editable
RDFa is a way of making regular HTML pages also understandable by machines. It is often used for communicating the information on your website to search engines in a more structured way, but it is also used by Create.js to make content editable.
The RDFa capabilities in Create.js are provided by VIE, a library that connects RDFa content and Backbone.js models together.
Making a content object editable
The base use case of editing content with RDFa in Create.js is to mark-up an individual content object as such.
If you’re for example displaying an article with:
<div class="article">
<h1>Some title</h1>
<div>
Some content
</div>
</div>
Then all RDFa needed to make it editable would be:
<div class="article" about="/my/article">
<h1 property="title">Some title</h1>
<div property="content">
Some content
</div>
</div>
This way VIE understands that the information contained in the outer DIV is an editable object identified by URI /my/article. It also understands that is has two editable properties, title and content.
This information comes from the newly-added attributes:
aboutgives the identifier of an object. The identifiers should be URIs, but basically anything that your back-end will understand is finepropertytells that the h1 contains the title of the post, and the div contains the contents. These become attributes of our Backbone model instance
In addition to about and property, you can also tell VIE the type of the content object using the typeof attribute:
<div class="article" about="/my/article" typeof="sioc:Post">
<h1 property="title">Some title</h1>
<div property="content">
Some content
</div>
</div>
This would tell us that the editable entity is a blog post.
Collections
Relationships between entities allow you to communicate structured content to Create.js, which will turn them into Backbone collections. For example, to annotate a list of blog posts:
<div about="http://example.net/blog/" rel="dcTerms:hasPart">
<div about="http://example.net/my-post">...</div>
<div about="http://example.net/second-post">...</div>
</div>
This tells Create that there is a blog entity, which contains a collection of two posts. The important things here are:
- The first
aboutidentifies also the blog post container as an entity reltells that there is a relation between the blog container, and the blog posts under it
Create will use the first entity inside a collection as a “template”, and knows how to add or remove entities from the collection. In Edit mode the user would see an Add button next to the collection.
Vocabularies
You’re free to use any vocabulary to describe your content for Create.js. However, there are some existing vocabulary definitions that are useful, especially if you’d like your RDFa data to be usable by other tools beside Create, like search engines:
Create widget
The Midgard.midgardCreate widget is what ties everything together in the Create.js user interface.
Starting Create:
jQuery(document).ready(function() {
jQuery('body').midgardCreate({
url: function() { return '/some/backend/url'; }
});
});
You can pass Create configuration options when calling the midgardCreate widget. For example, to use Aloha Editor instead of Hallo, do:
jQuery('body').midgardCreate({
url: function() { return '/some/backend/url'; },
editor: 'aloha',
workflows: {
url: function(model) {
return '/some/backend/workflows/fetch/url/' + model.id;
}
}
});
Configuration
The behavior of Create.js can be modified by passing various configuration keys to the midgardCreate widget:
toolbar: Initial toolbar rendering style, eitherfullorminimizedstate: Initial usage state, eitherbrowseoredithighlight: Whether to highlight editable elements when entering edit modehighlightColor: Color to use for the highlights. By default#67cc08(light green)editorWidgets: widgets for editing different types of content. By default Hallo is usededitorOptions: additional editor optionscollectionWidgets: widgets for managing different types of collections. By defaultmidgardCollectionAddis usedurl: callback function used for determining the URL where to save content itemsvie: an instance of VIE. If this is not provided, Create will instantiate onestanbolUrl: URL for the Stanbol instance used for content enhancementsdbPediaUrl: URL for the DBpedia instance used for fetching additional information on linked entitiestags: Whether to enable the tag widgetbuttonContainer: CSS selector for where the Edit and Save buttons should be placedtemplates: HTML templates used for widget output
Events
Create is an event-based user interface. Normally integrators shouldn’t need to deal with these events, but they’re explained here in case of some customization needs.
midgardcreatestatechange: when user switches between browse and edit modes. Event data contains an object with keystatetelling the state being changed to
Using a custom VIE instance
There are many reasons for using your own configuration of VIE with Create.js. You may for instance want to enable different services, or Stanbol access points there.
The VIE instance should at least have the RDFaService loaded to it. For example:
// Prepare VIE
var v = new VIE();
v.use(new v.RdfaService());
// Load Create.js with your VIE instance
jQuery('body').midgardCreate({
vie: v
});
Defining custom editors
Managing of different content editors is handled by the Editable widget in Create.js. For convenience, the editor setup can however be provided using a configuration API in the Create widget.
The editors themselves are provided by a Create.js compatible editingWidget. The system comes with some pre-built editing widgets, including plain contentEditable, Hallo, and Aloha Editor, but you can also build your own.
Editor configuration starts by defining a new named editor configuration, in this example an editor called title that uses Hallo:
jQuery('body').midgardCreate('configureEditor', 'title', 'halloWidget', {
plugins: {
halloformat: {}
}
});
Once an editor has been defined, Create can be configured to use it for various editable properties. This can be done by property name, for example:
jQuery('body').midgardCreate('setEditorForProperty', 'dcterms:title', 'title');
The same editor configuration can be reused in as many properties as you like. If you’re using the VIE type system, then editors can also be configured for property types:
jQuery('body').midgardCreate('setEditorForType', 'Text', 'title');
If you want to use a particular editor configuration as the default, you can also do:
jQuery('body').midgardCreate('setEditorForProperty', 'default', 'title');
Making a property non-editable
The editor configuration system can also be used to make properties non-editable by setting their editor to null:
jQuery('body').midgardCreate('setEditorForProperty', 'dcterms:author', null);
Editable widget
The Midgard.midgardEditable widget (or: editable entity widget) is responsible for loading property editor widgets (for example, the Hallo rich text editor) for editing various content elements, and synchronizing those with the underlying VIE entity instances.
Create.js will load the EditableEntity widget automatically for all RDFa annotated entities on the page, but you can also do it manually:
jQuery('[about]').midgardEditable({
vie: new VIE()
});
Let’s clarify the nomenclature to take away any possible confusion:
- a
subjectis the identifier of an entity - a
predicateis the identifier of a property of an entity - an
entityis an instance of asubjectthat contains thepropertiesidentified for it by(subject, predicate)pairs - a
propertyis an instance of apredicatefor a givenentity(and thus contains the value for thatpredicate)
So, Create.js will instantiate an editable entity widget for each entity on the page, which in turn will then instantiate a property editor widget for each property within that entity. Note that it is possible to have multiple EditableEntity widgets for the same entity — you may need to do this because your entity may be spread all over the page, for example.
Configuration
propertyEditorWidgets: object telling which property editor widget to load for which content typepropertyEditorWidgetsConfiguration: object telling how each property editor widget should be configuredcollectionWidgets: object telling which collection handling widget to load for which content type
States
The EditableEntity widget carries an editable entity through various different states and controls the behavior of the particular property editor widgets as needed. There are various events signaling transitions between different states.
Note: state handling of the EditableEntity widget and the PredicateEditor widgets it may contain still needs to be refined.
- Inactive - editable has been loaded but editor is not active. Entered via the
midgardeditabledisableevent - Candidate - editor has been enabled for the editable. Entered via the
midgardeditableenableandmidgardeditablenablepropertyevents - Highlighted - user’s mouse is over an editor but the editor hasn’t been focused yet. Entered via the
midgardeditablehighlightevent - Active - editor is focused. Entered via
midgardeditableactivatedand exited viamidgardeditabledeactivated - Modified - contents of the editor have been modified. Entered via
midgardeditablechangedevent - Invalid - contents of the editor have validation error(s)
Events
All events below always contain the following event data:
entity: the Backbone model instance for the entityeditableEntity: the EditableEntity widget object for the entityentityElement: the DOM element for the entity
If an event is specific to a property of the entity, then it will also contain the following event data:
predicate: the identifying predicate for the property of the entitypropertyEditor: the PredicateEditor widget object for the predicate of the entitypropertyElement: the DOM element for the property of the entity
Events:
midgardeditableenable: when an entity has been made editable.midgardeditabledisable: when an entity has been made non-editable.midgardeditableactivated: when a particular property of an entity has been activated in a property editor.midgardeditabledeactivated: when a particular property of an entity has been deactivated in a property editor.midgardeditablechanged: when a particular property of an entity has been changed in a property editor.midgardeditableenableproperty: when a particular property of an entity has been made editable.
Because of a limitation of jQuery UI, please note that this event can be triggered by the EntityEditable widget only. So, with this HTML structure:
<article about="/my/article" typeof="sioc:Post">
<header>
<h1 property="title">A title</h1>
</header>
<div class="content" property="content">
Some content
</div>
</article>
// this works (event triggered on the entity)
jQuery('body article').bind('midgardeditableenableproperty',
function(event, data) {
console.log('i am called')
}
);
// this doesn't work (event triggered on a property of the entity)
jQuery('body article .content').bind('midgardeditableenableproperty',
function(event, data) {
console.log('i am called');
}
);
Workflows widget
The Midgard.midgardWorkflows widget provides a way to see current workflow status of the currently activated content item, and initiate new workflows for it.
The Workflows widget will be automatically initiated by Create.js. You can also run it standalone:
jQuery('body').midgardWorkflows({
url: function (item) { return '/some/item/workflows.json'; }
});
Configuration
url: The URL callback function used for retrieving workflows for an item
Events
midgardworkflowschanged: triggered whenever workflows have been retrieved for an item. Event data contains the content item and the available workflows
Toolbar widget
The Midgard.midgardToolbar widget provides the floating toolbar where various Create.js widgets place their buttons.
The toolbar can rendered full, or in a minimized mode where only the logo is shown. The minimized mode also triggers Create’s focus mode where the other UI elements are also shown in a minimalistic fashion, allowing authors to focus on the content they’re writing.
When the Create widget is used the toolbar will be instantiated automatically. If you want to use it standalone, then call it in the following way:
jQuery('body').midgardToolbar({
display: 'full'
});
Tool areas
The toolbar provides several different areas where buttons can be placed.
- Session status: Used for actions that affect the current usage session, like Edit and Save. This area is identified by the CSS selector
.create-ui-toolbar-wrapper .create-ui-statustools
Configuration
display: The display status of the toolbar, eitherfullorminimized
Events
midgardtoolbarstatechange: when user opens or minimizes the toolbar. Event data contains an object with keydisplaytelling the new state
Storage widget
The Midgard.midgardStorage widget keeps track of content items edited using the Editable widget, and provides saving and loading functionality via both localStorage (for unsaved drafts) and the CMS back-end.
The Storage widget will be automatically instatiated by Create.js, but if you want to use it standalone, you can also:
jQuery('body').midgardStorage({
vie: new VIE(),
url: function (item) { return '/some/url'; }
});
Communications with the CMS back-end
Create communicates with your server-side system using Backbone.sync. By default this means that we send and retrieve content encoded in JSON-LD over XmlHttpRequest calls.
If you’re using this default approach, it is important to provide the URL of the endpoint on your server that you want Backbone and Create to talk with. This can be done by passing a string when initializing midgardCreate:
jQuery('body').midgardCreate({
url: function() { return '/some/backend/url'; }
});
When implemented this way, all communications from Create will happen using normal RESTful HTTP calls to that URL.
- Creating a new object makes a
HTTP POSTto the URL - Updating or fetching an object makes a
HTTP PUTorHTTP GETto that URL with theidof the object appended (for example/some/backend/url/objectId)
If you need to use different URIs for different entities, you can accomplish this by modifying the URL callback function. In the function the this context will refer to the entity being saved. For example:
jQuery('body').midgardCreate({
url: function () {
if (this.isNew() && this.collection) {
return this.collection.url;
}
return this.getSubjectUri();
}
});
You can override this default communications layer by implementing your own Backbone.sync method. Some examples:
Configuration
localStorage: Whether to enable localStorage. The Storage widget will automatically probe whether browser has support for it and enable it accordinglyvie: VIE instance to be used for content itemsurl: The URL callback function used with Backbone.syncautoSave: Whether autosaving is enabled.falseby defaultautoSaveInterval: autosaving interval, in millisecondseditableNs: jQuery UI event namespace used for Editable widgets. By defaultmidgardeditabletemplates: HTMl templates for user interface message contents of this widget
Methods
The Storage widget provides some public methods you can call:
-
saveRemote: save a single entity to the remote server. Takes an options object withsuccessanderrorcallbacks -
saveRemoteAll: save all pending changes to the remote server. Takes an options object withsuccessanderrorcallbacks. Example:jQuery('body').midgardStorage('saveRemoteAll', { success: function () { console.log("All saved!"); }, error: function () { console.log("Failed"); } }); -
hasLocal: check whether an entity has values in localStorage -
readLocal: update an entity with the values from localStorage -
checkRestore: if there are local modifications to editable entities, show a notification dialog asking whether to restore them. Example:jQuery('body').midgardStorage('checkRestore'); -
disableSave: temporarily prevent autosaving -
enableSave: re-enable autosaving
Events
midgardstorageloaded: when an item has been restored from localStoragemidgardstoragesave: when save to back-end has been initiated. Event data contains models key with all the changed entitiesmidgardstoragesaved: when save has completed succesfullymidgardstorageerror: when saving an entity failes. Event data contains the failed entity instance
Notifications widget
The Midgard.midgardNotifications widget provides a way to display notifications on various events to the user. These notifications may optionally provide buttons that the user can act on.
When initialized, the notifications widget will instantiate a div element for containing any notifications being displayed.
The notifications widget will be instantiated by the Create widget automatically. If you want to use it standalone, simply call:
jQuery('body').midgardNotifications();
Displaying notifications
When the notifications widget is instantiated to an element, it will set a data attribute midgardNotifications pointing to itself.
This allows new notifications to be shown using the following call:
jQuery('body').data('midgardNotifications').create({
body: 'Hello, world!'
});
The create method accepts various properties to affect the behavior of a notification pop-up. These include:
body: Textual contents of the notificationclass_prefix: Prefix for the CSS classes of the notification elementauto_show: whether the notification should be displayed automaticallybindTo: a CSS selector to bind the notification into a particular DOM element instead of the notifications areagravity: the direction from the notification to the bound element. For exampleTRfor top-righttimeout: how many milliseconds the notification should be shown, or0for foreveractions: array of action buttons to be added to the notification