jakub holý

building the right thing, building it right, fast

CKEditor: Scroll dialogs with the page, i.e. not fixed to the middle

2011-03-31 09:06:31General

Dialogs in the popular rich-text wysiwyg JavaScript editor CKEditor 3.5.2 are fixed-positioned and thus when you scroll the editor's page they always stay in the middle as you can see in its demo. That is a problem if the dialog is longer then the height of the page because you will be never able to scroll to its end (where the Ok/Cancle buttons are located).

It could be perhaps solved by adding a scrollbar to the dialog but I solved it by overriding the dialog's position: fixed with position: absolute. Here is how to do it.

Add the following to the CKEditor's configuration (either directly when you instantiate it or into a custom config, if you have one):


CKEDITOR.on('dialogDefinition', function(e) {
    var dialogName = e.data.name;
    var dialogDefinition = e.data.definition;
    dialogDefinition.dialog.parts.dialog.setStyles(
        {
            position : 'absolute'
        });
});


(I've copied the idea of using the on dialogDefinition event from a source I don't remember.)

Explanation

The div and table, which constitute the two top-level elements of a dialog, are created in themes/default/theme.js in the method buildDialog(editor). This method is called from dialog/plugin.js where these elements are further modified, including the following:


var themeBuilt = editor.theme.buildDialog( editor );
...
this.parts = themeBuilt.parts;
...
// Set the startup styles for the dialog, avoiding it enlarging the
// page size on the dialog creation.
this.parts.dialog.setStyles(
	{
		position : CKEDITOR.env.ie6Compat ? 'absolute' : 'fixed',
		top : 0,
		left: 0,
		visibility : 'hidden'
	});
...
this.definition = definition = CKEDITOR.fire( 'dialogDefinition', ...).definition;


We make use of the fired event to modify the dialog's definition to our liking, overriding the position to be always absolute.

Why CKEditor uses position: fixed is explained in its ticket #2127.