Implementation Guide

From AlohaWiki

Jump to: navigation, search
Warning
Warning

Some or all information on this page is out of date starting with Aloha Editor Version 0.10 and needs to be updated.


Contents

Configure Aloha for local development

If the autobase detection does not work you will get the following error:

 Can’t find object GENTICS.

Add the following code before loading the aloha script.

<script>
GENTICS_Aloha_base = "file:///Users/haymo/Documents/workspace/Aloha-Editor/WebContent/";
</script>

Aloha Objects

All objects necessary for Aloha are located in the "Gentics.Aloha" Namespace.

GENTICS.Aloha

The GENTICS.Aloha object represents Aloha itself to provide basic functionality.

API Methods

General Aloha settings

All Aloha settings are defined in the GENTICS.Aloha.settings object:

 GENTICS.Aloha.settings = {
   'i18n' : {
     'current' : 'de'
   },
   'base' : 'http://my.domain/aloha/',
   'readonly' : true,
   'ribbon' : false
 };

Available general settings:

GENTICS.Aloha.Log

The GENTICS.Aloha.Log object represents the Aloha log, which can be used to log special events (for example, when errors occur in Plugins, etc.) It also provides access to the log history e.g. for sending the collected log entries to a backend for permanently storing.

API Methods

Keep these articles coming as they've opneed many new doors for me.

Example: Fetch the log history

/*
 * This function serves as handler for the 'logFull' event
 */
function handleLogFull() {
  // get the log history
  var logHistory = GENTICS.Aloha.Log.getLogHistory();

  // TODO: do something with the log history, e.g. send to a backend server for storing

  // flush the log history
  GENTICS.Aloha.Log.flushLogHistory();
}

// subscribe for the 'logFull' event
GENTICS.Aloha.EventRegistry.subscribe(GENTICS.Aloha.Log, 'logFull', handleLogFull);

Handling of Javascript Errors

Aloha automatically handles javascript runtime errors (not parsing errors), that occur after Aloha has been initialized (which occurs when the DOM is ready). Javascript errors are logged in log level 'error'.

It is a known issue that Google Chrome does not support handling of javascript runtime errors!

GENTICS.Aloha.Editable

The GENTICS.Aloha.Editable object represents content which can be edited inline on a page. To enable an object for editing, use the Aloha jQuery Plugin function:

<div id="editme">This is my editable content</div>
<script type="text/javascript">
$(function () {
	$('#editme').aloha();
});
</script>

Another example, which turns all of a pages h2 elements into editables:

<script type="text/javascript">
$(function () {
	$('h2').aloha();
});
</script>

To remove the Aloha Editor for all h2 elements use:

<script type="text/javascript">
$(function () {
	$('h2').mahalo();
});
</script>

For compatibility reasons you might want to use our fallback method, if another jQuery plugin has been created, which also registers the aloha()-function with jQuery:

<script type="text/javascript">
$(function () {
	$('h2').GENTICS_aloha();
});
</script>

Methods:

GENTICS.Aloha.Event

The Event object is used to encapsulate the data attached to an event. It contains the event's name, it's source and additional properties.

Currently the following Events are available

In Aloha it is also possible to create custom events which can be fired and subscribed.

When creating a new Event, it must be given a name. Optionally the source object can be passed to the event, if it is relevant. If no source object is given, GENTICS.Aloha is used as source object.

// trigger the event "MyPluginEvent" with a reference to the plugin
GENTICS.Aloha.EventRegistry.trigger(
  new GENTICS.Aloha.Event("MyPluginEvent", this)
);

// trigger the event "MyPluginEvent" without source object
GENTICS.Aloha.EventRegistry.trigger(
  new GENTICS.Aloha.Event("MyPluginEvent")
);

API Methods

1

GENTICS.Aloha.Selection

The Aloha Selection component will automatically take care of user selections and create selection trees out of them. Selection trees are the main construct to modify the DOM. Additionally the Selection component can change markup of the current selection.

API Methods

 markupObj = jQuery('<b></b>');
 // or: 
 markupObj = jQuery('<span class="hyperimportant"></span>');
 // or:
 markupObj = jQuery('<h1></h1>');

Example: add an italic (<i>) markup around the selected text

This is our source Text, where the markup should be applied:

<p>The selection goes from |here to somewhere else here| and the text continues</p>

When the user selects the text above between the to "|", and then calls:

GENTICS.Aloha.Selection.changeMarkupOnSelection(jQuery('<i></i>'));

The DOM will be modified so that the resultig HTML is:

<p>The selection goes from |<i>here to somewhere else here</i>| and the text continues</p>

If the method is called again, the markup will be removed. If the selection changes and the method is called again, the markup will be adapted accordingly.

GENTICS.Aloha.FloatingMenu

The Floating Menu provides the user with buttons to interact with the currently edited content. The buttons are added by plugins, can be organized into Tabs and Groups. The visibility of buttons can be managed in two ways:

* by defining the visibility scope of the button (while adding it), see #Scopes
* by individually hiding or showing buttons, see #Showing or Hiding Buttons

Floating

Unless pinned by the user, the floating menu will automatically float to the nearest wrapping block level element of the current selection.

Scopes

Every button is added to the floating menu with a scope. A button will only be visible in the floating menu, if its scope is currently set.

Predefined scopes

There are some predefined scopes, which cover common cases:

* GENTICS.Aloha.empty is the empty scope, which is active if no other scope is active. Normally no plugin should add buttons with that scope.
* GENTICS.Aloha.global is the global scope, which serves as base for all other scopes
* GENTICS.Aloha.continuoustext is the scope for continuous text and is automatically set by aloha whenever an editable is activated and no other scope is set by plugins

Inheritance of Scopes

Every scope can extend other scopes, so that it inherits all buttons from other scopes.

The predefined scopes have the following inheritance hierarchy:

* GENTICS.Aloha.empty extends no other scope
* GENTICS.Aloha.global extends GENTICS.Aloha.empty
* GENTICS.Aloha.continuoustext extends GENTICS.Aloha.global

Defining new scopes

It is possible to define new scopes:

  GENTICS.Aloha.FloatingMenu.createScope('com.example.aloha.plugins.Strong.myscope', 'GENTICS.Aloha.global');

Defines a new scope with com.example.aloha.plugins.Strong.myscope as name, which extends GENTICS.Aloha.global.

By calling:

  GENTICS.Aloha.FloatingMenu.createScope('com.example.aloha.plugins.Strong.myotherscope', ['com.example.aloha.plugins.Strong.myscope', 'GENTICS.Aloha.continuoustext']);

it is possible to define a scope which extends two other scopes (com.example.aloha.plugins.Strong.myscope and GENTICS.Aloha.continuoustext).

It is absolutely necessary to have the names of defined scopes unique, so it is our strong recommendation to use the plugin namespace as prefix for scope names as well.

Setting the current Scope

When a plugin defines its own scopes, it also has to set those scopes when necessary:

GENTICS.Aloha.FloatingMenu.setScope('com.example.aloha.plugins.Strong.myscope');

Tabs and Button Groups

Buttons in the floating menu can be organized in Tabs and Button Groups within the Tabs. Tabs are identified by their label and the Button Groups by their index (counting from left).

The plugins shipped with Aloha define the following tabs:

* Format holds the buttons for formatting text (making it bold, italic, etc. and adding headlines, lists, ...)
* Insert holds buttons for inserting new elements like tables, images, ...

If a plugin wants to add a button to the Format tab, it must use GENTICS.Aloha.i18n(GENTICS.Aloha, 'floatingmenu.tab.format') as tab label, and for the Insert tab, it must use GENTICS.Aloha.i18n(GENTICS.Aloha, 'floatingmenu.tab.insert'). Of course, every plugin may create its own tabs, but implementors should be aware that too many different tabs may overcrowd the floating menu!

Adding Buttons

Adding buttons to the floating menu should definitely be done during the plugin initialization in the init method of the plugin with a call like this:

GENTICS.Aloha.FloatingMenu.addButton(scope, button, tab, group);

Where

* scope is the scope of the button, which must be either a predefined one or defined by the plugin before
* button is the button itself (an instance of #GENTICS.Aloha.ui.Button
* tab is the label of the tab
* group is the index of the group

Showing or Hiding Buttons

Besides using scopes, there is another possibility to individually show or hide buttons:

button.show();

will show the button and

button.hide();

will hide the button. It is important to known that buttons are only visible if it is not hidden (by calling button.hide()) AND if its scope is the current one or extends the current one.

GENTICS.Aloha.Plugin

To use Gentics Aloha with your own plugins, you have to extend the GENTICS.Aloha.Plugin object. Specify a fully qualified name to the plugin constructor. As soon as Gentics Aloha finishes loading, the init-method of your Plugin will be called, where various initialization tasks may be handled.

Namespaces

You are urged to use Java-like namespaces for your plugins, to ensure that there are no naming conflicts.

Example: the Austrian Company "Colorful" should use the following namespace for their color plugin:

at.colorful.aloha.ColorPlugin

Example: Loading & initializing your plugin

// specify your plugin using a full namespace
Example.HelloWorldPlugin = new GENTICS.Aloha.Plugin("com.example.HelloWorld");
Example.HelloWorldPlugin.init = function () {
  // all the init stuff is done here...
  alert("The HelloWorld Plugin has been initialized!");
};

Defining plugin settings

Plugin settings are defined under GENTICS.Aloha.settings.plugins like the following example:

GENTICS.Aloha.settings = {
	"plugins" : {
		"com.example.HelloWorld" : {
			"freakShow" : true
		}
	}
};

Every plugin has following standard setting properties:

enabled

The default value of it is "true". If you set it to false the plugin is disabled and its initialization method will not be invoked.

config

“config” is an hash array which provides a default configuration for this plugin for all editables, as well as a css selector based individual configuration. The default value must be defined in the plugin. Example configuration:

GENTICS.Aloha.settings = {
	"plugins": {
	 	"com.gentics.aloha.plugins.Format": {
		 	// all elements with no specific configuration get this configuration
			config : [ 'b', 'i','sub','sup'],
		  	editables : {
				// no formatting allowed for title
				'#title'	: [ ], 
				// formatting for all editable DIVs
				'div'		: [ 'b', 'i', 'del', 'sub', 'sup'  ], 
				// content is a DIV and has class .article so it gets both buttons
				'.article'	: [ 'b', 'i', 'p', 'title', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'removeFormat']
		  	}
		}
	}
}

Accessing plugin settings

Plugin settings can be accessed in two ways:

GENTICS.Aloha.settings.plugins["com.example.HelloWorld"].freakShow

or using the "settings" shortcut:

Example.HelloWorldPlugin.init = function () {
  // access the plugin settings here
  alert(this.settings.freakShow);
};

API Methods

GENTICS.Aloha.Repository

Implements a repository to organise and expose data from any source to Aloha.

API Methods

GENTICS.Aloha.ui.Button

Instances of GENTICS.Aloha.ui.Button define buttons which can be added to the #GENTICS.Aloha.FloatingMenu.

Buttons can be created like:

new GENTICS.Aloha.ui.Button({
	'iconClass' : 'GENTICS_button GENTICS_button_ul',
	'size' : 'small',
	'tooltip' : this.i18n('button.createulist.tooltip'),
	'toggle' : true,
	'onclick' : function (element, event) {
		that.transformList(false);
	}
});

with the following properties:

Dependencies

Aloha currently depends on


Using jQuery with Aloha

Gentics Aloha heavily relies on jQuery. If you want to use jQuery in your web application along with Gentics Aloha, you have to use the jQuery version provided by Aloha (currently 1.4.2).

You may override the jQuery version provided with an Aloha compatible one by including your own, before the Aloha script tag (refering aloha-nodeps-[version].js) has been included.

Aloha and continuous text

How can you turn DOM elements into continuous text editable by Aloha? Luckily there is a jQuery Plugin, which keeps this task very simple for you to handle. If you know how to use jQuery, you can do it:

<script type="text/javascript">

// initialize aloha continuous text when the dom is ready
$(function() {
  // the DOM object identified by id="main" will be
  // made available as aloha continuous text
  $('#main').aloha();
});
  
</script>

Of course you can also turn multiple DOM elements into continuous text to be edited with Aloha. Always keep in mind that DOM initialization has to be finished before turning objects into continous text. Also notice, that only block elements such as div and h[1-6] may be turned into continous text.

You may also apply Aloha to other DOM elements such as p's or single table cells, but these do not allow for any part of content, thus resulting in invalid html code.

Logging in Aloha

Use the following methods to log, whereever necessary:

GENTICS.Aloha.Log.log(level, component, message);
GENTICS.Aloha.Log.error(component, message);
GENTICS.Aloha.Log.warn(component, message);
GENTICS.Aloha.Log.info(component, message);
GENTICS.Aloha.Log.debug(component, message);

The following methods allow to check whether a specific log level is enabled:

GENTICS.Aloha.Log.isLogLevelEnabled(level);
GENTICS.Aloha.Log.isErrorEnabled();
GENTICS.Aloha.Log.isWarnEnabled();
GENTICS.Aloha.Log.isInfoEnabled();
GENTICS.Aloha.Log.isDebugEnabled();

The method

GENTICS.Aloha.Log.getLogHistory();

returns the log history. Every Entry has the following properties:

* level - log level (lowercase)
* component - String representation of the component that created the log
* message - log message as String
* date - Date object of the log time

With

GENTICS.Aloha.Log.flushLogHistory();

the log history can be flushed (emptied).

When the highWaterMark (default 90% of the maximum allowed entries) is reached, the event

* logFull

is fired from the object GENTICS.Aloha.Log.

Setting the log levels:

  GENTICS.Aloha.settings =  {
   logLevels: {'error': true, 'warn': true, 'info': true, 'debug': true}
  };

I18n in Aloha

Aloha supports full internationalization of core components and Plugins.

Supported languages of Aloha core

Currently, Aloha comes with support for:

Setting the current Aloha language

Defined language

The Aloha Editor UI language can be set like this

GENTICS.Aloha.settings = {
   'i18n' : {
     'current' : 'en'
   }
 }

If implemented in a backend system this is the preferred method. You can ensure that the Aloha Editor is in sync with the language of the backend system.

Language autodetection

If the current language is not set, Aloha tries to identify the browsers language and use this. If passed the ACCEPT-LANGUAGE string from the server Aloha Editor can detect the users language even more accurate. This is the best method to detect user preferred language.

 GENTICS.Aloha.settings = {
	"i18n": {
		// you can either let the system detect the users language (set acceptLanguage on server)
		// In PHP this would would be '<?=$_SERVER['HTTP_ACCEPT_LANGUAGE']?>' resulting in 
		"acceptLanguage": 'de-de,de;q=0.8,it;q=0.6,en-us;q=0.7,en;q=0.2’
	}
}

If acceptLanguage is not passed, the navigator object is used to detect language. Usually this works and the language in most cases is the OS language of the user. If all methods fail, the language is set to English ('en').

File structure of Plugin Dictionaries

The dictionary files provided by a Plugin must be located in the following file structure:

/plugins/
/plugins/table/
/plugins/table/plugin.js
/plugins/table/i18n/
/plugins/table/i18n/de.dict
/plugins/table/i18n/en.dict

The files must be located in the i18n folder and must be named like [language-code].dict.

Aloha must be able to find and load the dictionary files on demand, which requires two additional settings:

Base directory of the plugin

The base directory of the plugin (under the /plugins/ folder of aloha) must be known to Aloha for loading dictionary files. This must either be the unique namespace of the plugin, or can be set in the constructor:

Example.HelloWorldPlugin = new GENTICS.Aloha.Plugin("com.example.HelloWorld");
- would require the path structure to look like this: -
/plugins/
/plugins/com.example.HelloWorld/
/plugins/com.example.HelloWorld/plugin.js
/plugins/com.example.HelloWorld/i18n/
/plugins/com.example.HelloWorld/i18n/de.dict
/plugins/com.example.HelloWorld/i18n/en.dict

Format of Dictionary Files

The following snipplet of a dictionary file contains examples for special translations:

 key.to.translate = Here comes the Translation text
 something.with.replacement = Hello, {0} {1}!
 special.characters = If we like to use special characters like \{, \}, \\, we need to escape them!
 multiline.translation = This is a multiline translation!\nHere comes the next line.

The i18n Methods

There are two i18n Methods:

 GENTICS.Aloha.i18n(component, key, replacements); // for translations from the component's dictionary
 GENTICS.Aloha.Plugin.i18n(key, replacements); // for translations from the Plugin's dictionary

For example:

 GENTICS.Aloha.i18n(GENTICS.Aloha, 'welcome.message'); // search for the translation to 'welcome.message' in the core dictionary

The other i18n method exists for every plugin:

 Example.HelloWorldPlugin = new GENTICS.Aloha.Plugin("com.example.HelloWorld");
 Example.HelloWorldPlugin.i18n('welcome.message'); // searches for the translation to
  // 'welcome.message' in the plugin dictionary, and would fall back to the core
  // dictionary, if not found in the plugin dictionary.

Replacements in Translations

In translations, replacement placeholders are defined by {0}, {1}, ...

See the following example:

 Example.HelloWorldPlugin = new GENTICS.Aloha.Plugin("com.example.HelloWorld");
 Example.HelloWorldPlugin.i18n('welcome.message', ['John', 'Doe']);

When the welcome.message is defined like

 welcome.message = Welcome, {0} {1}!

The translation of the call above would be:

 Welcome, John Doe!

Define available Plugin Languages

The available languages of the dictionary files of a Plugin can be defined by setting the languages property of the Plugin object:

 Example.HelloWorldPlugin = new GENTICS.Aloha.Plugin("com.example.HelloWorld");
 Example.HelloWorldPlugin.languages = ['en', 'de'];

The order of the language definition is relevant for fallback: When Aloha is configured to use a language (e.g. 'fr'), which is not available in a Plugin, the first available Plugin language (in this case 'en') is used as fallback.

General Knowledge

Useful CSS Classes

 .x-combo-list-item .x-combo-selected {
     background-color: #...... !important;
 }
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox