Aloha Editor

These guides help you to make your content editable and to develop Aloha Editor.

Writing Plugins

After reading this guide, you will be able to:

  • Create plugins to adjust Aloha Editor to your needs.
  • Load and define dependencies with RequireJS.
  • Include other resources from your plugins

1 RequireJS modules explained

We use RequireJS to manage JavaScript dependencies, that’s why some basic understanding is very helpful. By using RequireJS, we gain some nice benefits: First, we the dependency management between JavaScript files is done for us, meaning they are included in the correct order.

The basic element of RequireJS is a so called module which is one file that defines and exports a JavaScript object. This reference can be used in other modules by requiring that module.

A module does not need to define its own name, it is simply named by its location on the file system.

Modules are created using define(dependencies, callback), where the first parameter dependencies is an array of other RequireJS modules this plugin needs in order to function properly. The second parameter is callback is a function which is executed as soon as all dependencies are loaded. The first dependency is passed to the callback as first parameter, the second dependency as the second, and so on.

Circular dependencies need some special treatment. It is most often a sign of bad code, but if you need to do this, follow the guide at the RequireJS website.

You may use modules by requireing them if you specified the dependency you may use:


	var module = require( 'module' );

If you want to load a module dynamically without defining a dependency you may use:


	// note the array!
	require( ['module'], function( module ) {
		// module available here
	});

2 Using require

You may user require to define modules as well as requiring dynamically other modules.

To define a module you need to define it with its dependencies and a callback function. The callback function gets the defined modules as parameters in order you defined them.

myplugin/lib/module.js

define(
[ 'dependendmodule1', 'dependendmodule2' ],
function( dependendmodule1, dependendmodule2 ) {
	"use strict";

	// you can use  dependendmodule1, dependendmodule2 here. 
	// both are loaded.

	return {};

});

You do not need to define all parameter of the callback function but require the module as needed. In order to not interfere with other modules we require all Aloha Editor modules in the aloha context. The configuration is available in Aloha.settings.requireConf. The method Aloha.require() is a shorthand to require with the Aloha Editor configuration and additionally gives you the Aloha object an argument if you pass only a callback function or as return if you pass no argument at all.

myplugin/lib/module.js

define(
[ 'dependendmodule1', 'dependendmodule2' ],
function() {
	"use strict";

	var 
		Aloha = Aloha.require(),
		dependendmodule1 = require( Aloha.settings.requireConf, 'dependendmodule1' ),
		dependendmodule2 = Aloha.require( 'dependendmodule2' ); // shorthand to the above
		
	Aloha.require( function( localAloha ) {
		// localAloha is available here  
	};
	
	return {};

});

You may also require module or Aloha itself on demand

someJS.js

( function() {
	"use strict";

	Aloha.require( function( Aloha ) {
		// localAloha is available here
		// but not neccessarily fully initialized
		Aloha.jQuery('body').bind('aloha', function() {
			// Aloha is initialized here
		});  
	});
	
	Aloha.require( ['dependendmodule1'], function( dependendmodule1 ) {
		// dependendmodule1 is available here  
	};
	
	return {};

});

3 Aloha plugins and their dependencies

In the following example, we define a components plugin with two modules. The first module componenttype defines two classes. The second module component has a dependency to componenttype, and RequireJS injects what has been returned by componenttype.

The plugin requires the module aloha/plugin which gives you the plugin factory method create()

plugin1/lib/plugin1-plugin.js

define(
[ 'aloha/plugin' ],
function( plugin ) {
    "use strict";
	// we do nothing but provide component modules...
    return plugin.create( 'plugin1', {});
});

The componenttye has no dependency thus the dependency array is empty.

plugin1/lib/abstractmodule.js

define(
[], // no dependency
function() {
	"use strict";

	var abstractModule = Class.extend({
    	doOther: function() {
    		return 'didOther';
    	}
    });

	return abstractModule;

});

The component depends on the local module componenttype and defines its dependency.

plugin1/lib/module.js

define(
['./abstractmodule'], // dependency in the same path
function( abstractModule ) {
    "use strict";

    var module = abstractModule.extend({
		doSome: function() {
			return 'didSome';
		}
    });
    return new module();

});

3.1 Cross plugin dependencies

If we want to use cross plugin modules you should not define a dependency on plugin1/module from plugin1 because that would hinder your plugin from working, because of the unfullfilled dependency. Instead require the module in your code with a Aloha.require() and extend the module with our own function when plugin2 is loaded. If another plugin would require plugin1/module it would have our extended functionality.

plugin2/lib/plugin2-plugin.js

define(
[ 'aloha/plugin' ],
function( plugin, module ) {
    "use strict";
    
    // now we require the the modue of plugin1
    Aloha.require( [ 'plugin1/module' ], function( module ) }
 	   // module is available here
    	module.doThis = function() {
    		return 'didThis';
    	};
    });
    
	// we do nothing but provide component modules...
    return plugin.create( 'plugin2', {});
});

4 Aloha require path mapping for plugins

So, at which place does Aloha look up modules? We’ll explain this with a few examples:

Definition in RequireJS File Name
myplugin/foo path_to_bundle/myplugin/lib/foo.js
Including other RequireJS modules is the most common case
myplugin/vendor/legacy_lib path_to_bundle/myplugin/vendor/legacy_lib.js
Include a legacy library
css!myplugin/css/cssfile.css path_to_bundle/myplugin/css/cssfile.css
Includes the CSS file in the document <head>.
i18n!myplugin/nls/i18n.js uses Aloha.settings.locale or tries to detect the language from the browser.
text!myplugin/res/template.html Load the content of a text file (e.g. templates).

The bundle name is not part of the RequireJS definition, as this is installation-specific. You as plugin developer should not care about where other plugins are located on disk.

5 Changelog