Recently all the browsers that are implementing the latest and greatest elements of CSS 3 have added support for CSS Transforms, and so I decided to have a little fun while creating a little example about how to create a custom dropdown element in the CKEditor toolbar.
The idea is to provide a new dropdown that allows the user to set the zoom level for the editor, this example is gonna be a little rough and it can be greatly improved, but this is mostly a proof of concept about how to do it.
The first step is to create the skeleton for the plugin:
CKEDITOR.plugins.add( 'zoom',
{
requires : [ 'richcombo' ],
init : function( editor )
{
} //Init
} );
That code should be placed in a "plugin.js" file located in the plugins/zoom folder of your CKEditor installation. If you want to create another plugin, you'll use another folder name and put that name as the first parameter in the call to CKEDITOR.plugins.add()
For this plugin we need to be sure that the code from the "richcombo" plugin is loaded, as that's the real code that will create the dropdown element, so we specify it in the requires field of the plugin.
Finally this plugin must be added to the CKEditor instance, so in your config.js (or whatever other place you want to specify it) add it to the plugins that must be loaded:
config.extraPlugins = 'zoom';
You can place an alert() inside the init function to verify that the plugin is being loaded when you refresh the page with CKEditor. If it doesn't work, verify the error console and try to clear your cache.
Now we need to fill up the code in the init function to create the dropdown:
init : function( editor )
{
var config = editor.config;
editor.ui.addRichCombo( 'Zoom',
{
label : "100 %",
title : 'Zoom',
multiSelect : false,
panel :
{
css : [ CKEDITOR.getUrl( editor.skinPath + 'editor.css' ) ].concat( config.contentsCss )
},
init : function()
{
var zoomOptions = [50, 75, 100, 125, 150, 200, 400],
zoom;
this.startGroup( 'Zoom level' );
// Loop over the Array, adding all items to the
// combo.
for ( i = 0 ; i < zoomOptions.length ; i++ )
{
zoom = zoomOptions[ i ];
// value, html, text
this.add( zoom, zoom + " %", zoom + " %" );
}
// Default value on first click
this.setValue(100, "100 %");
}
});
// End of richCombo element
} //Init
In this function we are creating the dropdown as a "RichCombo" element with editor.ui.addRichCombo() The function takes as parameters the name of the RichCombo and the object that contains the definition. Inside this object there's an init() function that will be called to initialize the dropdown on first click, here we specify the options available in the RichCombo and add them with this.add()
So now we can add to the toolbar of our CKEditor this 'Zoom' RichCombo element:
...
['Maximize', 'ShowBlocks', 'Zoom'],
...
Refreshing the page will show now the dropdown and clicking on it will show the panel, although we still haven't specified what must be done when an option is selected. Doing it in a simple way and not trying to optimize how it works we can add this function to the RichCombo definition:
...
// Default value on first click
this.setValue(100, "100 %");
},
onClick : function( value )
{
var body = editor.document.getBody().$;
body.style.MozTransformOrigin = "top left";
body.style.MozTransform = "scale(" + (value/100) + ")";
body.style.WebkitTransformOrigin = "top left";
body.style.WebkitTransform = "scale(" + (value/100) + ")";
body.style.OTransformOrigin = "top left";
body.style.OTransform = "scale(" + (value/100) + ")";
body.style.TransformOrigin = "top left";
body.style.Transform = "scale(" + (value/100) + ")";
// IE
body.style.zoom = value/100;
}
});
// End of richCombo element
...
This code blindly tries to set the property for each browser, without bothering about which one is being used of if it supports CSS Transforms at all. We know that IE doesn't support them, but it has supported since long ago the style.zoom so in this case we can use just that.
A correct implementation of the plugin should verify that the browser does support CSS Transforms (or is IE and can use .zoom) before adding the RichCombo, and in the onClick event handler should use just the correct property instead of trying all of them.
This plugin also lacks internationalization, because that wasn't the point of this test, but it should be easy to add and to fix other little things.
But there are two problems that can be seen with just this code:
The first one is that the width of the combo in the toolbar is a little too big to specify some little text like "100%". This is being tracked in ticket 4559 but as you can see by reading all the comments there's no easy solution that can be applied to automatically fix it. So the solution is to add some rules in the stylesheet, although that makes deploying the plugin a little harder. Maybe the RichCombo should be allowed to specify a width in its definition?
The second problem appears only in Webkit browsers (Safari and Chrome), when you open up the panel it will take full height, and it's a little ugly. Other combos have their size specified in the skins css but that doesn't seems like a good solution if you want to publish a plugin that will be used for other people, as well as making upgrading a little harder.
Browser support: The zoom feature should work in IE6+, Firefox 3.5+, current Safari and Chrome (I don't have old versions to test) and Opera 10.5+ (still in alpha)
Happy 2010
Edit may-2013:
A new version of the plugin compatible with CKEditor 4 is available at the plugins repository. Zoom plugin.