Interactive Editor Plugin Guide
Overview
Version 2.0 of the template framework unifies all types of templates into a common, programmable structure that allows developers to create and contribute templates that can be directly embedded in the authoring tool. Currently, the item data are created via the portal the corresponding templates are embedded in the content during authoring.
This doesn't give an author a lot of control over configuring the template, and its behavior. Moreover, it is also limited to the data available as part of an item. The template v2.0 frameworks make it possible for templates to be directly configured from within the authoring tool. Developers can write the custom runtime logic, custom configuration editor, and custom editing experience (WYSIWYG) to make it easier for authors to discover and reuse these templates
These templates can include informational aspects such as a Flashcard that presents the word details or include engaging tasks such as exploring a noun and its related nouns, verbs, etc. Such templates are used for enabling learning tasks - Reading, Writing/Scribbling, Recording, Exploring, Interacting, and so on. The actual templates can range from simple single stage tasks (flashcard, scribble pad, recorder activity) to complex multi-stage tasks that guide the learner through a pre-configured learning activity.
The following aspects of extensions in the authoring tool are described:
Registration and lifecycle
Registering a plugin associates a class (prototype) with a custom plugin object. The element provides callbacks to manage its lifecycle. Uses behaviors to share code.
The plugins core is implemented in its plugin.js file. The file is loaded by the plugin manager and initialized during the load time. The plugins themselves are instantiated when the user creates that object in the editor.
Namespaces: Proposed namespace is editor.* for Editor plugins, renderer.* for Renderer plugins. The community contributed plugins should follow the same convention - org.editor.* and org.renderer.*
var editor.Plugin = Class.extend({
initialize: function(data) {}, // When the plugin is registered, it can set up its dependencies
properties: function(data) {}, // The attributes of the plugin
converter: function(instance) {}, // returns the converter object for this plugin
editor: function(instance) {}, // returns the canvas editor object for the given instance
views: function(instance) {}, // returns the views associated with this plugin
behaviors: function(instance) {}, // returns the behavior mixins for the given instance
create: function(data) {}, // Instantiate an object of the plugin's type (e.g on canvas)
remove: function(data) {} // When the object of the plugin's type is deleted from canvas
// TODO - base class methods
})Properties
For content plugins only, the properties exposed by the plugin are declared. This allows the plugin to inherit the default behaviors related to rendering the properties. Properties are declared by the plugin as follows:
[
{
"propertyName": "", // Name of the property
"title": "", // Display label
"description": "", // Tooltip text
"category": "", // Category of the property for rendring
"dataType": "Text", // Data type (number, text, word, wordlist, color)
"encoding": "", // How the property is saved (attribute, json, cdata)
"required": true,
"displayProperty": "Editable",
"defaultValue": "",
"renderingHints": "{'editor': 'colorpicker'}"
},
... // other properties
]The base plugin declares the default properties for all plugins:
Bounding Box - x, y, w, h
Border - stroke (border color), stroke-width (border size)
Shadow - shadow, offsetX, offsetY, blur
Each custom plugin can extend the properties list and add its own declarable properties. Any other config is generated and handled directly by the plugin and added to its CDATA section config.
Converter & Parser
Converter modifies the content DOM tree and adds the current instance to the DOM. Any cross-plugin modifications (e.g. horizontal concerns) should not be implemented as converters, but as converter behavior that can receive and apply across multiple instances.
var editor.Converter = Class.extend({
// Converts the current object to ECML. Passes the ECML DOM object
toECML: function(instance, dom) {}
// Converts the ECML node into the appropriate plugin object
fromECML: function(node, dom) {}
})Editing
Editor is the base class for all canvas editor plugins. The base class extends the Fabric.js rendering system and provides default functionality to render the editor object on canvas. Default for any editor shows a thumbnail for that object on the canvas.
var editor.Editor = Class.extend({
// Returns the native fabric object to render this plugin's editor
canvasObject: function(instance) {}
})View
View is a visual widget (non-canvas) that is placed in the layout. View is instantiated by the plugin and is manipulated by its behaviors. Any actions within the view are handled by its own handlers. It may or may not fire events for its actions. The view is expected to be bound to its object and update the state internally.
Actions and Events
Actions are executables that are defined by a plugin. Action can be bound to a toolbar, menu bar etc. When the action is clicked, the callback method is called allowing the action to perfom its task. In addition, the action also fires the custom action event to allow any other behaviors to respond to the action. Clicking the action would generally show/hide a view, or add/edit state on the canvas.
Action Data
Note: There may be a need to bind the action to some specific property. E.g. when we put a color selector action, bind it to the color property automatically. Need to think this through.
Behaviors
The basic interfaces are as follows:
Text Provider
Text providers are plugins that expose a textual representation of their content. This allows the authoring tool and other plugins to work with the text and leverage the language platform (e.g. to work with the parser API).
State Listener
Listener for state in the authoring tool. The callback pattern allows the behavior to listen for events while the action is happening (e.g. rotating), or after the action is completed (e.g. rotated). If the action is cancelled, the end event is called with state=CANCELLED. Understandably, the progress events are called on every tick while the end event is called once per action (on finished or cancelled).
Clipboard Listener
Listener for clipboard events - when an object is copied on the clipboard or when it is pasted.
Action Listener
Listener for custom actions. E.g. when read-along editing is completed, it fires the event, that is handled by the appropriate listener.
Note: This mechanism doesn't allow listeners to prevent the action from happening (there is no "beforeXX" event callback and no way defined to cancel an event). This is intentional. If an action has to be disabled based on some condition, the listener should observe the condition and disable the action itself (prevent the user from taking the action rather than trying to cancel it).
Reusable Views/Plugin Artifacts
PropertyConfigFormView - Popup that generates a form based on properties data. For most simple widgets, this form view might be sufficient to configure them
DefaultButtonAction - Default toolbar action (simple button).
WordSelectorView - Uses APIs and provides UI to select a single word from repo
WordlistSelectorView - Uses APIs and provides a UI to select multiple words from repo
Property Observer
Handles the property change notifications for the plugins
Examples/Illustrations
1. Read-Along Widget (Content Plugin)
Plugin.js
ReadAlongConfigView.js
2. Editor Extension - Word Complexity Provider
plugin.js
WordComplexityListener.js
WordComplexityView.js
3. ECML Template
Example of a template that has read-along and recorder widgets on the same page.
plugin.js
DefaultTemplateSelectorView.js
Last updated
Was this helpful?
