Description
WYSIWYG text field editor programming in Plone.
Plone supports TinyMCE (default), Kupu and CKEditor.
TinyMCE and Plone integration is distributed in Products.TinyMCE package.
Plone offers many kind of support and enhancements in site internal content linking
The recommended method for linking the content is Linking by UID since Products.TinyMCE version 1.3.
This solves issues with earlier Plone versions where the link targets become invalid when a HTML textfield with relative links where shown on the other page as the original context.
Note
You might need to turn on Linking by UID setting on in the site setup if you are migrating from older Plone sites.
Plone supports user text changeable editor. The active editor is stored in the user preferences.
The user can fallback to hand-edited HTML by setting active editor to none.
The rich text widget can also support optional input formats besides HTML: structured text and so on.
The format selector itself is rendered by wysiwyg_support.pt macros which is Plone core
You can use TinyMCE body selector make your CSS class have different styles in view and edit modes (inside TinyMCE)
/* Break columns in two column layout
*
* https://developer.mozilla.org/en/css3_columns
*
*/
.column-breaker {
column-break-before: always;
display: block;
}
.mceContentBody .column-breaker {
color: red;
border: 1px dashed red;
display: block;
}
Note
Firefox does not actually support column breaks, so this was useful headaching experience.
In your add-on code, all TinyMCE options in the control panel can be exported and imported using GenericSetup, portal_setup and tinymce.xml.
Plone ships with pre-compressed TinyMCE source code enabled by default.
If you want to toy around with TinyMCE source code itself, you might want to first enable the usage of debug version of TinyMCE source.
In Products.TinyMCE.skins open tiny_mce_src.js and copy-paste its content into tiny_mce.js.
Note
Replacing tiny_mce.js with tiny_mce_src.js in portal_javascripts doesn't seem to work as it breaks TinyMCE plug-in loading.
TinyMCE consists of plug-ins. Existing plug-ins can be overlaid with your custom version by loading Javascript after core TinyMCE load.
Here are instructions how to add new buttons to TinyMCE
Some rules
So in the end you'll have a file:
yourcompany.app./yourcompany/app/skins/tinymce_plugin_flowplayer/flowplayer/editor_plugin.js
Why all this? I don't know. And honestly, in this point, I don't care.
Register your specially named skin layer in skins.xml:
<?xml version="1.0"?>
<object name="portal_skins" meta_type="Plone Skins Tool">
<object name="tinymce_plugin_flowplayer"
meta_type="Filesystem Directory View"
directory="your.app:skins/tinymce_plugin_flowplayer"/>
<skin-path name="*">
<layer name="tinymce_plugin_flowplayer"
insert-after="custom"/>
</skin-path>
</object>
Register your plugin in tinymce.xml GenericSetup install profile
<?xml version="1.0"?>
<object>
<toolbar>
<customtoolbarbuttons purge="False">
<element value="flowplayer"/>
</customtoolbarbuttons>
</toolbar>
<resourcetypes>
<customplugins purge="False">
<element value="flowplayer"/>
</customplugins>
Then finally drop a editor_plugin.js to your plug-in folder
/**
* a TinyMCE plug-in for opening a dialog asking a video link and creating Flowplayer code out of it
*
*/
(function() {
tinymce.create('tinymce.plugins.FlowplayerPlugin', {
init : function (ed, url) {
var t = this;
t.url = url;
t.editor = ed;
t.docs = false;
ed.addButton('flowplayer', {
title : 'Video',
cmd : 'flowplayer',
image : url + '/img/flowplayer.gif'
});
ed.addCommand('flowplayer', function (val, page) {
var url = prompt("Copy-paste URL to MP4 video file", "");
// note: flowplayer link must not have text inside
html = '<a class="flow-player tinymce-flow-player" href="' + url + '" />';
ed.execCommand('mceInsertContent', false, html);
});
//ed.onPostRender.add(t._setupTOC, t);
},
getInfo : function () {
return {
longname : 'collective.flowplayer video insert plug-in ',
author : 'Mikko Ohtamaa',
authorurl : 'http://webandmobile.mfabrik.com',
infourl : 'http://webandmobile.mfabrik.com',
version : "1.0"
};
}
});
tinymce.PluginManager.add('flowplayer', tinymce.plugins.FlowplayerPlugin);
})();
TinyMCE exposes URL to your plug-in base folder, where editor_plugin.js is, as plug-in init() parameter.
You can construct relative URLs to set media resources in init().
ed.addButton('flowplayer', {
title : 'Video',
cmd : 'video',
image : url + '/img/placegallery.gif'
});
TinyMCE does not directly accept strings as labels, but uses its own internal translation mechanism which is not gettext.
Sample content
tinyMCE.addI18n('en.placegallery',{
desc : 'Placegallery button'
});
More info
The recommended way is to customize TinyMCE
Create a duplicate of plug-in JS file (table.js), register it as a custom Javascript from your add-on resource folder.
TinyMCE overrides previous plug-in registrations with new ones and you can just re-register your own plug-in version to override the existing version.
<!-- TinyMCE customizations -->
<javascript
id="++resource++your.app/tiny_mce_special.js"
authenticated="True"
cacheable="True" compression="safe" cookable="True" insert-after="tinymce.js"
enabled="True" expression=""
inline="False"
/>
Yoiu can also override CSS, HTML (.htm.pt templates) with z3c.jbot as instructed above.
Example:
jbot/Products.TinyMCE.skins.tinymce.plugins.table.js.table.js
Warning
Since there resources are loaded in <iframe> the normal browser refresh does not trigger reload for them. Right click <iframe>, choose Refresh from context menu.
The source code of this file is hosted on GitHub. Everyone can update and fix errors in this document with few clicks - no downloads needed.
For basic information about updating this manual and Sphinx format please see Writing and updating the manual guide.