Modular SPAW Editor v.2 architecture allows for easy extending of core features by plugins. This guide is intended for plugin developers as a documentation of the features available in the core to ease the development process. You can develop plugins that add new features not currently found in the core, you can also make a plugin to incorporate SPAW Editor closely into you CMS (like plugin to browse your internal file management subsystem).
SPAW Editor plugins can be divided into 3 categories:
Note: it is recommended that you read "Integrators Guide" before reading this document
Each plugin has it's own directory under "plugins" subdirectory. That directory can contain any directories and files but there are some directories and filename considerations that have special meaning for SPAW engine:
Name |
Description |
js |
This directory is mandatory. It should also contain at least one of the following subdirectories:
Inside these directories could be any number of JavaScript code files with .js extension. These files will be included into main SPAW Editor's javascript file |
config | This directory could be used to specify some plugin specific configuration parameters in file config.php (see Configuration) |
dialogs | This is a directory where you should put all files that are included into SPAW's special dialog engine (see Dialogs) |
lib |
This directory is where you put subdirectories for various other SPAW Engine related
files. It can contain following subdirectories:
|
You should avoid using above directory names for other purposes of your plugin (even if you don't need them for their intended purpose)
Plugins can add their buttons and dropdown lists to the toolbar. These toolbar items can perform various actions, they can also open plugin specific dialogs.
Plugins can have their own configuration settings. These settings could be set in the main SPAW's config file or in a config.php file inside "config" subdirectory of plugin's directory. In first case it is easier for integrators to maintain configuration parameters in a single place but in the second case your plugin is completely autonomous.
As you may see from the extension config.php is a PHP file. SpawConfig class has some methods to work with configuration settings. You should use SpawConfig::setStaticConfigItem method to set global settings for your plugin. It accepts following arguments:
Name |
Description |
$name | Setting name. There's a naming convention that all plugins should name their settings starting with "PG_<pluginname>_" (like "PG_SPAWFM_DIRECTORIES"). However when you set configurable options for your dropdown you should use setting name constructed like this: "dropdown_data_<pluginname>_<dropdownname> (for example "dropdown_data_zoom_zoom") and specify array as a value. This way array items will be automatically loaded as options in your dropdown list. |
$value | Setting value. This could be of any PHP type however when you use transfer types (see below) SPAW_CFG_TRANSFER_JS or SPAW_CFG_TRANSFER_REQUEST only simple value types could be used. |
$transfer_type |
Specifies how this configuration item should be transferred across various parts
of the script. $transfer_type could be set to one of the following constants (default
is SPAW_CFG_TRANSFER_NONE):
|
To access global static settings you can use one of the following SpawConfig methods
Method signature |
Description |
getStaticConfigValue($name) |
Returns value of config variable with specified name |
getStaticConfigValueElement($name, $index) | Provided specified configuration item value is an array this method returns the value of specified element of the array |
setStaticConfigValue($name, $value) | Sets the value of specified config item. If there's no item with such name, new config item is created |
setStaticConfigValueElement($name, $index, $value) | Provided specified configuration item value is an array this method sets the value of specified element of the array |
Dialogs created using SPAW Engine's dialog techniques (see below) have access to instance specific configuration settings via the following methods of $config object:
Method signature |
Description |
getConfigValue($name) |
Returns value of config variable with specified name |
getConfigValueElement($name, $index) | Provided specified configuration item value is an array this method returns the value of specified element of the array |
setConfigValue($name, $value) | Sets the value of specified config item. If there's no item with such name, new config item is created |
setConfigValueElement($name, $index, $value) | Provided specified configuration item value is an array this method sets the value of specified element of the array |
Configuration settings set with SPAW_CFG_TRANSFER_JS transfer type could be accessed from JavaScript using editor.getConfigValue(name) JavaScript method (see Reference for details)
Plugins can add their own items to toolbars. Unless your plugin adds a feature very closely tied to one of the "standard" SPAW toolbars it is recommended that you add your toolbar items to "plugins" toolbar. In case your plugin adds a lot of toolbar items related to one subject (for example html forms plugin) you may consider creating your own toolbar. Keep in mind that in this case your toolbar wont automatically show up. Integrators will have to manually edit their config files or add your toolbar from code (see Integrators Guide for details).
To add toolbar items you create a file (or files) in "lib/toolbars" subdirectory of your plugin. You name the file like this: <toolbarname>.toolbar.php. Where <toolbarname> is a name of toolbar to which your items should be added (see Integrators Guide for a list of standard toolbars). In this file you create a variable called $items which holds an array of items of type inherited from SpawTbItem. Currently there are 3 such types:
Name |
Description |
SpawTbImage |
Represents static image in the toolbar. Mainly used to represent separator for logical grouping of other toolbar items |
SpawTbButton | Represents toolbar button |
SpawTbDropdown | Represents dropdown list (combobox) |
For example Zoom plugin adds a single dropdown to "plugins" toolbar by creating "lib/toolbars/plugins.toolbar.php" file with the following contents:
<?php
$items = array (
new SpawTbDropdown('zoom', 'zoom', 'isZoomEnabled', 'zoomStatusCheck', 'zoomChange',
'', SPAW_AGENT_IE, false),
);
?>
Toolbar item type constructors accept following arguments:
Name |
Description |
$module |
Module (plugin) name |
$name | Toolbar item name |
$agent |
Optional. Supported user agent (browser). The following constants are defined representing
user agents:
Default value is SPAW_AGENT_ALL. These values could be combined using logical OR
(|) operator. For example to specify that this item should show up in IE and Firefox
but not in Opera you specify |
Name |
Description |
$module |
Module (plugin) name |
$name | Toolbar item name |
$on_enabled_check | Name of the JavaScript method returning true if button is enabled and false if it's not |
$on_pushed_check | Name of the JavaScript method returning true if button should be currently pushed and false otherwise (leave blank if button can't be in pushed state) |
$on_click | Name of the JavaScript method that should be called when button is clicked |
$agent |
Optional. Supported user agent (browser). The following constants are defined representing
user agents:
Default value is SPAW_AGENT_ALL. These values could be combined using logical OR
(|) operator. For example to specify that this item should show up in IE and Firefox
but not in Opera you specify |
$show_in_context_menu | Optional. If set to true specifies that toolbar item should be presented in context menu (when applicable). Default value is false. |
Name |
Description |
$module |
Module (plugin) name |
$name | Toolbar item name |
$on_enabled_check | Name of the JavaScript method returning true if button is enabled and false if it's not |
$on_status_check | Name of the JavaScript method returning the value that should be currently selected in the dropdown (for example font name of the currently selected block) |
$on_change | Name of the JavaScript method that should be called when user selects new value from the list |
$data | Optional. Array with name/value pairs that are used for dropdown items. If not specified (or not an array is specified) data from configuration is used (see Configuration). |
$agent |
Optional. Supported user agent (browser). The following constants are defined representing
user agents:
Default value is SPAW_AGENT_ALL. These values could be combined using logical OR
(|) operator. For example to specify that this item should show up in IE and Firefox
but not in Opera you specify |
Plugins JavaScript code that needs to be loaded together with main SPAW Editor code should be placed in js subdirectory of your plugins directory. Inside js directory it should be placed in one of the subdirectories based on the browser it is intended for. In case your code works in all supported browsers place it in js/common subdirectory. If it works under MSIE only it should go to js/ie, for Gecko - js/gecko and for Opera - js/opera.
In case your code differs in one or just a few lines for various browsers it's better to put it in common directory and then handle differences with "if" operator, but when it differs dramatically it's easier to have several files than maintain complex conditional statements in one file. It also saves download time for users because they are served only the code for their used browser.
Inside these directories you can place any number of JavaScript code files. Inside these files you define a class named SpawPG<pluginname> (for example SpawPGzoom). Then you define methods of the class. These methods are called by the engine when needed (as you have defined in your toolbar item declaration).
Here's a complete listing of the file js/ie/zoom.js for the Zoom plugin:
// zoom plugin
function SpawPGzoom()
{
}
SpawPGzoom.zoomChange = function(editor, tbi, sender)
{
if (tbi.is_enabled)
{
var pdoc = editor.getPageDoc(editor.getActivePage().name);
pdoc.body.style.zoom = sender.options[sender.selectedIndex].value;
sender.selectedIndex = 0;
editor.getPageIframeObject(editor.getActivePage().name).focus();
pdoc.designMode = 'on';
editor.updateToolbar();
}
}
SpawPGzoom.isZoomEnabled = function(editor, tbi)
{
return editor.isInDesignMode();
}
SpawPGzoom.zoomStatusCheck = function(editor, tbi)
{
if (tbi.is_enabled)
{
var pdoc = editor.getPageDoc(editor.getActivePage().name);
return pdoc.body.style.zoom;
}
else
return null;
}
As you may remember from Toolbars section of this guide Zoom plugin has it's toolbar item defined like this:
<?php
$items = array (
new SpawTbDropdown('zoom', 'zoom', 'isZoomEnabled', 'zoomStatusCheck', 'zoomChange',
'', SPAW_AGENT_IE, false),
);
?>
So when SPAW Engine needs to check if Zoom dropdown list should be enabled it calls SpawPGzoom.isZoomEnabled method. To get current zoom value it calls SpawPGzoom.zoomStatusCheck and when users selects a new Zoom value from the list it calls SpawPGzoom.zoomChange method.
Toolbar related methods receive following arguments:
Name |
Description |
editor |
An instance of SpawEditor JavaScript class to which the actions should be applied |
tbi | Toolbar item object (an instance of SpawTbItem descendant class (SpawTbImage, SpawTbButton or SpawTbDropdown)) that initiated this call |
sender | Actual HTML/DOM object that initiated the call (like select object for dropdown or image object for buttons) |
Spaw Editor includes a mechanism to ease dialog development. You can concentrate on functionality directly related to your plugin and SPAW's engine will handle the rest (arguments, themes, localization, etc.).
SpawEngine class includes a method called openDialog which opens SPAW's standard dialog wrapper window. This method accepts following arguments:
Name |
Description |
module |
Plugin name |
dialog | Dialog name |
editor | SpawEditor instance (current editor object) |
arguments | Arguments that should be passed to the dialog (could be of any JavaScript datatype) |
querystring | A string that will be added to the request url of the dialog (for example setting1=value1&setting2=value2) |
callback | Name of the function that should be called when returning from dialog (like 'SpawPGcore.hyperlinkClickCallback') |
tbi | Toolbar item object (an instance of SpawTbItem descendant class (SpawTbImage, SpawTbButton or SpawTbDropdown)) that initiated this call |
sender | Actual HTML/DOM object that initiated the call (like select object for dropdown or image object for buttons) |
To open Hyperlink dialog core plugin calls this method like this:
SpawPGcore.hyperlinkClick = function(editor, tbi, sender)
{
if (tbi.is_enabled)
{
var a = editor.getSelectedElementByTagName("a");
editor.stripAbsoluteUrl(a);
SpawEngine.openDialog('core', 'hyperlink', editor, a, '', 'SpawPGcore.hyperlinkClickCallback', tbi, sender);
}
}
This method opens dialog.php file which in turn includes hyperlink.inc.php file in core plugins dialogs subdirectory (plugins/core/dialogs/hyperlink.inc.php). So you have to name your dialogs body <dialogname>.inc.php and place it in dialogs subdirectory of your plugins directory.
dialog.php loads main Spaw Editor's include files, loads theme specific header and footer and sets up a number of objects and variables you can use in your dialog. Your dialog code is included in the middle (content part) of the dialog. dialog.php uses PHP output buffering so you can modify HTTP headers if you have a need for it.
Here's a list of PHP objects and variables available to your part of the dialog:
Name |
Description |
$lang |
An instance of SpawLang class for handling localized of localized strings (see Localization) |
$config | An instance of SpawConfig class holding global configuration options and instance specific configuration options set with transfer type SPAW_CFG_TRANSFER_SECURE |
In addition to PHP variables there's a number of JavaScript variables that hold useful objects and information:
Name |
Description |
spawEditor |
Holds an instance of SpawEditor object referencing editor instance that initiated this dialog |
spawArguments | Holds whatever arguments you have passed to this dialog via openDialog method |
For your dialogs to look consistently with the current editor's theme you should use predefined CSS class names for your form elements:
Name |
Description |
input |
For general purpose text boxes (input type="text", textarea) |
input3chars | For text boxes that should hold up to 3 characters |
input7chars | For text boxes that should hold up to 7 characters |
bt | For buttons (input type="button") |
To return data to the main window you call SpawDialog.returnValue method before closing dialog window. This methods accepts one argument which is whatever you want to return to the main window. This method calls a function you passed as callback argument to the openDialog method. Callback functions should be defined like this:
SpawPGcore.hyperlinkClickCallback = function(editor, result, tbi, sender)
{
// your code here
}
It accepts 4 parameters:
Name |
Description |
editor |
An instance of SpawEditor class to which actions should be applied |
result | This is what you pass to SpawDialog.returnValue. Your callback function should know what to do with it |
tbi | Toolbar item object (an instance of SpawTbItem descendant class (SpawTbImage, SpawTbButton or SpawTbDropdown)) that initiated this call |
sender | Actual HTML/DOM object that initiated the call (like select object for dropdown or image object for buttons) |
Spaw Editor includes a subsystem handling multilanguage support. You should use it even if you only can make a language file for a single language. If community likes your plugin there will be people who will translate it to their language. In general it is up to you which language files you provide for your plugin, however, we will only list (on our site) plugins that support at least English language.
Each plugin has it's own language files (in case it outputs anything to the client). These files should be located in lib/lang subdirectory of your plugin. Each language has it's own language file named <languagename>.lang.inc.php where <languagename> is 2 character abbreviation of the language name (en - English, fr - French, lt - Lithuanian, etc.). These files have the following structure: there's $spaw_lang_charset variable set to the character set (encoding) of the file. It is highly recommended that you use "utf-8" encoding whenever possible; and $spaw_lang_data array which holds language specific strings. Each item in this array is an array representing one block of language data (usually related to a single logical block like toolbar item, dialog, etc.). The key is the name of the block and the value is an array of strings where key represents string identifier and value represents translation to the language of the file.
$spaw_lang_data = array(
'cut' => array(
'title' => 'Cut'
),
...
);
Each toolbar item should have it's own block named the same way as the item itself (the same applies to dialogs). In the example above you can see a block for "cut" toolbar item. Block item with reserved id "title" is used as alternative text for toolbar items or for the title item in dropdown list or for the header of dialog. Other array can be used by your script as needed.
SpawLang PHP class provides method to retrieve language strings. It's called getMessage(). It accepts following arguments:
Name |
Description |
$message |
Message identifier ("title" in the above example) |
$block | Optional. Block identifier ("cut" in the above example). If no $block is specified current block identifier is used (see below) |
$module | Optional. Module (plugin) identifier representing plugin directory where the language file is located. If no $module is specified current module identifier is used |
Since this function is used a lot in dialogs there's a shortcut for it called m() accepting the same list of arguments.
Methods setModule($module) and setBlock($block) could be used to set current module and block respectively.
So, to output a language specific string in your dialog you use something like this:
echo $lang->m('target','hyperlink','core');
or
$lang->setModule('core');
$lang->setBlock('hyperlink');
echo $lang->m('target');
Both produce the same result but in the second case if you are working with lots of strings for the hyperlink dialog you don't need to specify block and module names over and over.
Spaw Editor's engine tries to help fit your plugins into the overall look of the editor as carefree as possible. If you use classes mentioned in Dialogs section and avoid fancy styling your dialogs should look consistent with the rest of the editor.
However you need to provide graphics for your toolbar buttons. Each theme should include empty button images so you can easily add your image over it to get a fine looking button. You can find these images in plugins/core/lib/theme/<themename>/img/. The files should be named tb__empty*.gif. There could be different variants for each button. For example default "spaw2" theme has 4 variants for each button: tb__empty.gif, tb__empty_down.gif, tb__empty_off.gif, tb__empty_over.gif representing normal, pushed, disabled and hovered buttons respectively. You should create your own buttons from these and save them to files named tb_<youritemname>[_variant].gif in your plugins lib/theme/<themename>/img subdirectory
The engine includes a fallback mechanism displaying special default plugin button in case your plugin doesn't have it's own button for current theme. However you should make an effort to support as many of available themes as possible. We will not list plugins that do not support at least default "spaw2" theme.
Not all plugins should require user interaction. Some plugins sit behind the scene and perform their actions as a reaction to some events
Non-UI plugins can be configured in the same way as UI plugins. However only configuration settings with transfer type SPAW_CFG_TRANSFER_JS make sense for non-UI plugins. For example plugin that removes not allowed tags on form submission can have a configuration setting with allowed tag names. (Note: currently only simple data types can be used for SPAW_CFG_TRANSFER_JS transfer type configuration settings)
You put your code in the same location as for UI plugins. There are no restrictions on what should be inside these files, however, it is recommended that you stick to the same naming conventions as with UI plugins: create a JavaScript class called SpawPG<pluginname> and add your variables and functions as member variables and methods of this class
Non-UI plugins sit silently waiting for some events to occur. Spaw Editor's engine provides means for plugins to hookup to browser and SPAW specific events.
You use SpawEngine.addEventHandler() method to hook-up your event handler functions to specific events. This method accepts 3 parameters:
Name |
Description |
evt_type |
Event identifier. This is either a name of standard browser event (like 'click', 'keypress', etc) or SPAW specific event (see below) |
handler_fn | The name of event handler function (for example "SpawEditor.rightClick") |
evt_target |
Optional. Name of the object to which the event handler should be hooked up. If
not specified the event is attached to all editor page documents (editing areas).
Applicable values:
|
Here's a list of Spaw Editor specific events:
Name |
Description |
spawinit |
Occurs when each editor instance on a page is initialized |
spawallinit | Occurs when all SPAW instances on a page are initialized |
spawbeforepageswitch | Occurs before active page is switched to another page |
spawpageswitch | Occurs when active editor page has changed |
spawgethtml | Occurs before content of the page is rendered to HTML |
spawbeforesubmit | Occurs when page is about to be submitted to the server |
Your script should include a handler for at least one event (unless it's UI plugin or it just provides additional helper functions for other plugins). The best way to attach your events is inside a handler for "spawallinit" event. This means that you should attach a handler to "spawallinit" event right in your script file and then add other handlers inside this handler for "spawallinit". Your handler function should accept 2 arguments: first is SpawEditor instance that initiated the event, the second is JavaScript event object.
Below is the whole code for a sample "stest" plugin. All it does is shows an alert each time you press "s" key inside the editing area.
function SpawPGstest()
{
}
SpawPGstest.init = function(editor, event)
{
SpawEngine.addEventHandler("keydown", "SpawPGstest.keyDown");
}
SpawPGstest.keyDown = function(editor, event)
{
if (event.keyCode == 83)
alert('You\'ve pressed the "s" key');
}
SpawEngine.addEventHandler("spawallinit", "SpawPGstest.init");
Spaw Editor provides a framework for accessing and manipulating editor instances and their content. This section list some of the objects and methods that could be useful while developing plugins.
SpawEngine class provides methods for general Spaw Editor's engine operations. Here's the list of useful "static" class methods
Name |
Description |
getSpawDir() |
Returns virtual directory path where SPAW files are located |
getEditor(name) | Returns SpawEditor object for the editor with specified name |
isInitialized() | Returns true if all editor instances on the page have been initialized |
updateFields() | Updates HTML in all textareas behind all editor pages |
setActiveEditor(editor) | Sets specified editor as currently active editor |
openDialog(module, dialog, editor, arguments, querystring, callback, tbi, sender) | Opens standard dialogs (see Dialogs) |
addEventHandler(evt_type, handler_fn, evt_target) | Attaches event handler function. See Events. |
SpawEditor class represents editor instances on the page. Following is a list of useful editor's instance methods and properties
Name |
Description |
name |
Holds name of the editor |
getConfigValue(name) | Returns the value of configuration item set with SPAW_CFG_TRANSFER_JS transfer type (see Configuration) |
isInitialized() | Returns true if editor is initialized |
getToolbarItem(id) | Returns toolbar item object with specified identifier |
getPage(id) | Returns SpawEditorPage object with specified id |
setActivePage(id) | Sets page with specified id (name) as currently active editor's page |
getActivePage() | Returns currently active editor's page as SpawEditorPage object |
hidePage(page) | Hides specified page (SpawEditorPage object should be passed as parameter) |
showPage(page) | Shows specified page (SpawEditorPage object should be passed as parameter) |
getTheme() | Returns the name of editor's theme (skin) |
getPageInput(page_name) | Returns underlying page's textarea (HTML mode code editing area). Page name (id) should be passed as parameter. |
getPageIframe(page_name) | Returns iframe object representing WYSIWYG editing area. Page name (id) should be passed as parameter. Note: this and getPageIframeObject return the same object under Gecko and Opera but under MSIE getPageIframe returns object as a frame with it's inner document, etc. and getPageIframeObject returns iframe as an object of parent document. |
getPageIframeObject(page_name) | Returns iframe object representing WYSIWYG editing area. Page name (id) should be passed as parameter. |
getPageDoc(page_name) | Returns document object of the WYSIWYG editing area. Page name (id) should be passed as parameter. |
getActivePageDoc() | Returns document object of the WYSIWYG area of currently active editor's page |
updateToolbar() | Updates toolbar items to reflect currently selected editing area state |
updatePageInput(page) | Updates page's HTML editing area's value from WYSIWYG value. SpawEditorPage object should be passed as parameter. |
updatePageDoc(page) | Updates page's WYSIWYG value from HTML editing area's value. SpawEditorPage object should be passed as parameter. |
getPageHtml(page) | Returns HTML code of the current page. SpawEditorPage object should be passed as parameter. |
updateFields() | Updates HTML value of all editor pages |
dom2xml(node) | Returns inner HTML code of the provided DOM node and all it's children |
getCleanCode(node) | Returns inner HTML code of the provided node with formatting and other "garbage" (like MS Word tags) removed |
cleanPageCode() | Cleans active page code using getCleanCode method |
showStatus(message) | Shows specified message in editor's status bar |
getNodeAtSelection() | Returns current selection as DOM node |
insertNodeAtSelection(newNode) | Inserts newNode into current selection on the active page |
getSelectionParent() | Returns closest parent node holding complete selection on the active page |
getSelectedElementByTagName(tagName) | Returns selected HTML element with specified tagName. For example, you have text inside table cell selected and you call this method passing "table" as parameter, this method will return table element inside which selected text is located. Returns null if selection is not inside such element. |
addGlyphs(root) | Adds border outline on tables with border="0" starting with specified DOM node |
removeGlyphs(root) | Removes border outline on tables with border="0" starting with specified DOM node |
isInDesignMode() | Returns true if active page is in Design (WYSIWYG) mode |
getStrippedAbsoluteUrl(url, host_only) | Removes local host and path part from urls. If host_only parameter is set to true removes only the host part. Configuration variable "strip_absolute_urls" should be set to true for this method to work |
stripAbsoluteUrls() | Removes local host and path part from hyperlinks and images on the active page. Configuration variable "strip_absolute_urls" should be set to true for this method to work |
stripAbsoluteUrl(elm) | Removes local host and path part from specified element. Configuration variable "strip_absolute_urls" should be set to true for this method to work. |
selectionWalk(func) added in version 2.0.1 |
Function specified (by reference) will be called on every node in current selection. 3 arguments will be passed to this function: node - the node itself, start_offset - offset where selection starts, if node isn't fully selected, null otherwise, end_offset - offset where selection ends, if not isn't fully selected, null otherwise |
insertHtmlAtSelection(source) added in version 2.0.1 |
Inserts specified string (source) which could either be plain text or HTML into selection |
SpawUtils class provides utility methods that might be useful. Here's a list of "static" class methods
Name |
Description |
rtrim(txt) |
Returns specified string with spacers trimmed from right |
ltrim(txt) | Returns specified string with spacers trimmed from left |
trim(txt) | Returns specified string with spacers trimmed from both sides |