June 2008

SELF OverLib - eZ Publish JavaScript overLIB library integration

Tuesday, 24 June 2008, 11:44
Categories: Extensions
Tags: OverLib, JavaScript, integration, template operator

This extension integrates a popular OverLib JavaScript library with eZ Publish. Beside providing a simple template operator for automated generation of OverLib instances, it introduces a fallback configuration architecture for even easier and flexible use. It is possible to use pre-configurable presets, ad-hoc configurated calls as well as any combination of the two approaches.

Description

For each OverLib instance, a JavaScript code must be generated within HTML document that requires a number of paramter variables to be passed. Those variables control what text/content will be displayed, how the window will behave, what it will look like, will it be sticky, and so on. There are several problems with literally defining this JavaScript code in the templates:
- It is not easy to deal with special characters and escape strings, especially in the eZ template language,
- Static JavaScript code is not flexible in case of any future changes, especially across big projects.

To cope with those problems, a simple template operator is introduced. The operator automatically deals with any special chars that could destroy JavaScript code. It is also configurable by means of presets. Any number of presets can be defined and each preset can define any combination of OverLib settings.

To ensure that overlib gets always generated properly and the JavaScript has every variable required, a setting fallback system is introduced. The following priority is used to determine the values of OverLib parameters:
1) Ad-hoc declarations (within the template itself, when using the operator),
2) Preset declarations (if a preset was declared and used)
3) Default system values.
Any combination and order of parameters can be used.

Note: Please read the selfoverlib.ini configuration file for further details.
Note: Find out more about OverLib library at http://www.bosrup.com/web/overlib/

Examples

{* This is an adhoc declaration, it has no pre-configured settings, *}
{* all the paramters that are not declared will have default OverLib values. *}
{selfoverlib_display(
hash(
'content', 'THIS IS MY OVERLIB TEXT',
'caption', 'THIS IS MY OVERLIB CAPTION',
'html_value', 'THIS IS THE ANCHOR',
'width', '225',
)
)}
{* This is a preset-based declaration. You do not have to define anything *}
{* except for the preset and the content. *}
{selfoverlib_display(
hash(
'preset', 'admindefault',
'caption', 'Help: how to use it?',
'content', 'It order to use this functionality, you must...',
)
)}

Read doc/readme.txt for further details.

This extension is available at:
http://ez.no/developer/contribs/template_plugins/self_overlib

Comments (4)

Class-attribute-based button sets in new MCE Online Editor

Tuesday, 24 June 2008, 02:58
Categories: Lab
Tags: eZ MCE Online Editor, class attribute, eZOE, XML editor, hack

One of my primary postulates towards the new MCE Online Editor is that it supports different button sets, depending on explicit call or preset settings. Actually, presets would stand a much better approach, so let's forget about template declaration for a while. I decided to find out how much work it would require to make the preset approach run.

Ini structure modification

First of all, we have to store the settings we will be using later on. Current button declaration in ezoe.ini looks as follows:

[EditorSettings]
Buttons[]
Buttons[]=formatselect
Buttons[]=bold
Buttons[]=italic
Buttons[]=underline
...

We would need multi-dimentional array with multiple preset-like named blocks instead:

[EditorSettings]
ButtonPresets[]
ButtonPresets[]=full
ButtonPresets[]=mini
#...
[ButtonPreset-full]
Buttons[]
Buttons[]=formatselect
Buttons[]=bold
Buttons[]=italic
Buttons[]=underline
Buttons[]=|
Buttons[]=bullist
Buttons[]=numlist
Buttons[]=indent
Buttons[]=outdent
Buttons[]=|
Buttons[]=undo
Buttons[]=redo
#...
[ButtonPreset-mini]
Buttons[]
Buttons[]=formatselect
Buttons[]=bold
Buttons[]=italic
Buttons[]=underline
Buttons[]=|
Buttons[]=bullist
Buttons[]=numlist
Buttons[]=indent
Buttons[]=outdent

XMLBlock datatype modification

Once we're done with our preset configuration, we have to make the XML Block datatype actually display and store the preset values. First of all, we need to modify the datatype itself (kernel/classes/datatypes/ezxmltext/ezxmltexttype.php):

// Class constants declaration
const BUTTONS_FIELD = 'data_text2';
const BUTTONS_VARIABLE = '_ezxmltext_buttons_';
// Fetch and store post data - method modification
function fetchClassAttributeHTTPInput( $http, $base, $classAttribute )
{
$column = $base . self::COLS_VARIABLE . $classAttribute->attribute( 'id' );
$buttons = $base . self::BUTTONS_VARIABLE . $classAttribute->attribute( 'id' );
if ( $http->hasPostVariable( $column ) )
{
$columnValue = $http->postVariable( $column );
$classAttribute->setAttribute( self::COLS_FIELD, $columnValue );
$buttonsValue = $http->postVariable( $buttons );
$classAttribute->setAttribute( self::BUTTONS_FIELD, $buttonsValue );
return true;
}
return false;
}

The example above is not complete, there are other methods to modify, like initialization or (un)serialization ones. This should be enough to run the test, though.

We still have to modify the datatype templates. Again, we'll do the minimum: modify the datatype's class attribute template (design/standard/templates/class/datatype/edit/ezxmltext.tpl) by adding the following code:

<div class="block">
<label>{'Button preset'|i18n( 'design/standard/class/datatype' )}:</label>
<select name="ContentClass_ezxmltext_buttons_{$class_attribute.id}">
{def $preset_list=ezini( 'EditorSettings', 'ButtonPresets', 'ezoe.ini' )}
{foreach $preset_list as $preset}
<option value="{$preset|wash()}"{if eq( $preset, $class_attribute.data_text2 )} selected="selected"{/if}>{$preset|wash()}</option>
{/foreach}
</select>
</div>

Now, all pieces are in their place for the final cuts.

MCE Online Editor modification

First of all, we have to modify the method responsible for collecting the button settings from the configuration files. We locate the eZOEXMLInput handler class and extend the proper method:

function getEditorButtonList()
{
if ( $this->editorButtonList === null )
{
$contentClassAttributeID = $this->ContentObjectAttribute->ContentClassAttributeID;
$contentClassAttribute = eZContentClassAttribute::fetch( $contentClassAttributeID );
$buttonPreset = $contentClassAttribute->DataText2;

$oeini = eZINI::instance( 'ezoe.ini' );
$buttonPresets = $oeini->variable( 'EditorSettings', 'ButtonPresets' );

if( !in_array( $buttonPreset, $buttonPresets ) )
{
$buttonPreset = $buttonPresets[0];
}
$buttonList = $oeini->variable( 'ButtonPreset-' . $buttonPreset , 'Buttons' );

$contentini = eZINI::instance( 'content.ini' );
$tags = $contentini->variable('CustomTagSettings', 'AvailableCustomTags' );
$hideButtons = array();
$showButtons = array();

// filter out underline if custom underline tag is not enabled
if ( !in_array('underline', $tags ) )
$hideButtons[] = 'underline';

// filter out pagebreak if custom pagebreak tag is not enabled
if ( !in_array('pagebreak', $tags ) )
$hideButtons[] = 'pagebreak';

// filter out relations buttons if user dosn't have access to relations
if ( !eZOEXMLInput::currentUserHasAccess( 'relations' ) )
{
$hideButtons[] = 'image';
$hideButtons[] = 'objects';
}
foreach( $buttonList as $button )
{
if ( !in_array( $button, $hideButtons ) )
$showButtons[] = $button;
}
$this->editorButtonList = $showButtons;
}
return $this->editorButtonList;
}

All this modification does is choose a proper button preset instead of a general one. It could be more warning-secured, this is the minimum.

This seems to be all, but it is not. The main MCE init template uses run-once operator to make sure that OE init is only run once. This is going to be a problem since OE button configuration is part of the init. We have to remove the run-once operator and allow multiple initializations. Now, I'm not sure at the moment if this is JavaScript-safe, but seems to work fine at first glance. Edit ezxmltext_ezoe.tpl template file and comment out run-once operators:

{*run-once*}
...
{*/run-once*}

This should be it.

Summary

As this example shows, a number of kernel-located files have to be modified in order to achieve this functionality. This takes just a couple of minutes once you know what you're doing, but kernel modification won't likely be accepted for premium support, for example. This is why I really hope this modification makes it to the eZ Publish 4.1.0 release, with some 4.0.x backward compatibility mode.

Also, note that this is hardly a substitute for server-side validation of what user is allowed to do within the OE (which ideally should automatically control what a user can do and I hope for that in eZ 4.2+), but stands a great transitional presentation-layer functionality that can be backed up with proper access control. Many projects will suffer if this is not in place...

Comments (2)