Skip to content

Commit

Permalink
Merge pull request #1583 from ckeditor/t/932-3393b
Browse files Browse the repository at this point in the history
Corrections to Easy Image styles system
  • Loading branch information
Comandeer authored Feb 5, 2018
2 parents c6b5a76 + d356844 commit 721bd11
Show file tree
Hide file tree
Showing 12 changed files with 370 additions and 127 deletions.
229 changes: 142 additions & 87 deletions plugins/easyimage/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@

alignLeft: {
attributes: {
'class': 'easyimage-alignLeft'
'class': 'easyimage-align-left'
},
label: editor.lang.easyimage.commands.alignLeft
},

alignCenter: {
attributes: {
'class': 'easyimage-alignCenter'
'class': 'easyimage-align-center'
},
label: editor.lang.easyimage.commands.alignCenter
},

alignRight: {
attributes: {
'class': 'easyimage-alignRight'
'class': 'easyimage-align-right'
},
label: editor.lang.easyimage.commands.alignRight
}
Expand All @@ -56,60 +56,49 @@

function addCommands( editor, styles ) {
function createCommandRefresh( enableCheck ) {
return function( editor ) {
var widget = editor.widgets.focused;
return function( editor, path ) {
var widget = editor.widgets.focused,
newState = CKEDITOR.TRISTATE_DISABLED;

if ( widget && widget.name === WIDGET_NAME ) {
this.setState( ( enableCheck && enableCheck( widget ) ) ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF );
} else {
this.setState( CKEDITOR.TRISTATE_DISABLED );
}
};
}
var callbackResolution = enableCheck && enableCheck.call( this, widget, editor, path );

function createCommand( options ) {
return {
startDisabled: true,
contextSensitive: true,

exec: function( editor ) {
var widget = editor.widgets.focused;

options.exec( widget );

if ( options.forceSelectionCheck ) {
// We have to manually force refresh commands as refresh seems to be executed prior to exec.
// Without this command states would be outdated.
editor.forceNextSelectionCheck();
editor.selectionChange( true );
}
},
newState = callbackResolution ? CKEDITOR.TRISTATE_ON : CKEDITOR.TRISTATE_OFF;
}

refresh: createCommandRefresh( options.refreshCheck )
this.setState( newState );
};
}

function createStyleCommand( editor, name, styleDefinition ) {
var style;

function createStyleCommand( editor, name, styleDefinition, commandName ) {
styleDefinition.type = 'widget';
styleDefinition.widget = 'easyimage';
styleDefinition.group = 'easyimage';
style = new CKEDITOR.style( styleDefinition );
styleDefinition.group = styleDefinition.group || 'easyimage';
styleDefinition.element = 'figure';
var style = new CKEDITOR.style( styleDefinition );

editor.filter.allow( style );
editor.widgets.registered.easyimage._styles[ name ] = style;

return createCommand( {
exec: function( widget ) {
style.apply( widget.editor );
widget.setData( 'style', name );
},
refreshCheck: function( widget ) {
return widget.data.style === name;
},
forceSelectionCheck: true
// At this point cmd should be treated more as a definition due to #1582.
var cmd = new CKEDITOR.styleCommand( style );
cmd.contextSensitive = true;
cmd.refresh = createCommandRefresh( function( widget, editor, path ) {
return this.style.checkActive( path, editor );
} );

editor.addCommand( commandName, cmd );

// Command needs to be refetched. Calling addCommand will… create a new command.
cmd = editor.getCommand( commandName );

// Enable is called at multiple occasions, especially in editor#mode event listeners.
// Unfortunately it's even called with a timeout there.
cmd.enable = function() {};

// Without this the command is inited with a wrong state.
cmd.refresh( editor, editor.elementPath() );

return cmd;
}

function addDefaultCommands() {
Expand All @@ -121,15 +110,41 @@
}

function addStylesCommands( styles ) {
var style;
// Returns key of style associated with a given command or null if none.
function getStyleNameFromCommand( commandName, styles ) {
var match = commandName.match( /^easyimage(.+)$/ );

if ( match ) {
var lowered = ( match[ 1 ][ 0 ] || '' ).toLowerCase() + match[ 1 ].substr( 1 );
if ( match[ 1 ] in styles ) {
return match[ 1 ];
} else if ( lowered in styles ) {
return lowered;
}
}

if ( !editor.widgets.registered.easyimage._styles ) {
editor.widgets.registered.easyimage._styles = {};
return null;
}

for ( style in styles ) {
editor.addCommand( 'easyimage' + capitalize( style ),
createStyleCommand( editor, style, styles[ style ] ) );
// These commands must trigger refresh.
editor.on( 'afterCommandExec', function( evt ) {
if ( getStyleNameFromCommand( evt.data.name, styles ) ) {
editor.forceNextSelectionCheck();
editor.selectionChange( true );
}
} );

editor.on( 'beforeCommandExec', function( evt ) {
// Style commands should not be toggled.
if ( getStyleNameFromCommand( evt.data.name, styles ) && evt.data.command.style.checkActive( evt.editor.elementPath(), editor ) ) {
evt.cancel();
// Editor needs to be focused, otherwise balloon toolbar will hide.
editor.focus();
}
} );

for ( var style in styles ) {
createStyleCommand( editor, style, styles[ style ], 'easyimage' + capitalize( style ) );
}
}

Expand All @@ -138,32 +153,22 @@
}

function addButtons( editor, styles ) {
function createButton( button ) {
editor.ui.addButton( button.name, {
label: button.label,
command: button.command,
toolbar: 'easyimage,' + ( button.order || 99 )
} );
}

function addDefaultButtons() {
createButton( {
name: 'EasyimageAlt',
editor.ui.addButton( 'EasyimageAlt', {
label: editor.lang.easyimage.commands.altText,
command: 'easyimageAlt',
order: 3
toolbar: 'easyimage,3'
} );
}

function addStylesButtons( styles ) {
var style;

for ( style in styles ) {
createButton( {
name: 'Easyimage' + capitalize( style ),
editor.ui.addButton( 'Easyimage' + capitalize( style ), {
label: styles[ style ].label,
command: 'easyimage' + capitalize( style ),
order: 99
toolbar: 'easyimage,99'
} );
}
}
Expand Down Expand Up @@ -219,20 +224,7 @@
} );
}

function getActiveStyle( widget ) {
var styles = widget.definition._styles,
style;

for ( style in styles ) {
if ( widget.checkStyleActive( styles[ style ] ) ) {
return style;
}
}

return 'full';
}

function registerWidget( editor ) {
function registerWidget( editor, styles ) {
var config = editor.config,
figureClass = config.easyimage_class,
widgetDefinition = {
Expand All @@ -249,6 +241,7 @@
},

requiredContent: 'figure; img[!src]',

styleableElements: 'figure',

supportedTypes: /image\/(jpeg|png|gif|bmp)/,
Expand Down Expand Up @@ -347,15 +340,25 @@
this.on( 'uploadFailed', function() {
alert( this.editor.lang.easyimage.uploadFailed ); // jshint ignore:line
} );

this._loadDefaultStyle();
},

data: function( evt ) {
var data = evt.data;
_loadDefaultStyle: function() {
// Ensures that Easy Image widget uses a default Easy Image style if none other is applied.
var styleMatched = false,
defaultStyleName = editor.config.easyimage_defaultStyle;

if ( !data.style ) {
data.style = getActiveStyle( this );
for ( var styleName in styles ) {
var cmd = editor.getCommand( 'easyimage' + capitalize( styleName ) );

return this.applyStyle( this._styles[ data.style ] );
if ( !styleMatched && cmd && cmd.style && CKEDITOR.tools.array.indexOf( cmd.style.group, 'easyimage' ) !== -1 && this.checkStyleActive( cmd.style ) ) {
styleMatched = true;
}
}

if ( !styleMatched && defaultStyleName && editor.getCommand( 'easyimage' + capitalize( defaultStyleName ) ) ) {
this.applyStyle( editor.getCommand( 'easyimage' + capitalize( defaultStyleName ) ).style );
}
}
};
Expand Down Expand Up @@ -513,7 +516,7 @@
afterInit: function( editor ) {
var styles = getStylesForEditor( editor );

registerWidget( editor );
registerWidget( editor, styles );
addPasteListener( editor );
addCommands( editor, styles );
addButtons( editor, styles );
Expand All @@ -540,24 +543,58 @@
/**
* Custom styles that could be applied to Easy Image widget.
* All styles must be [valid style definitions](#!/guide/dev_howtos_styles-section-how-do-i-customize-the-styles-drop-down-list%3F).
* There are three additional properties for every style definition:
* There are three additional properties for each style definition:
*
* * `label` - string used as a button label in a balloon toolbar for the widget,
* * `icon` - path to the icon used in the balloon toolbar,
* * `iconHiDpi` - path to the high DPI version of the icon.
*
* There are few styles available by default:
*
* * `full` - adding an `easyimage-full` class to the `figure` element.
* * `side` - adding an `easyimage-side` class to the `figure` element.
* * `alignLeft` - adding an `easyimage-align-left` class to the `figure` element.
* * `alignCenter` - adding an `easyimage-align-center` class to the `figure` element.
* * `alignRight` - adding an `easyimage-align-right` class to the `figure` element.
*
* Every style added by this config variable will result in adding `Easyimage<name>` button
* and `easyimage<name>` command, where `<name>` is name of style in pascal case, e.g. `left`
* style would produce `EasyimageLeft` button and `easyimageLeft` command.
*
* // Adds a custom alignment style.
* config.easyimage_styles = {
* left: {
* attributes: {
* 'class': 'left'
* },
* label: 'Align left',
* icon: '/foo/bar/icons/baz.png',
* iconHiDpi: '/foo/bar/icons/hidpi/baz.png'
* icon: '/my/example/icons/left.png',
* iconHiDpi: '/my/example/icons/hidpi/left.png'
* }
* };
*
* Following example changes the class added by full style and adds another border styles:
*
* config.easyimage_styles = {
* full: {
* // Changes just the class name, label icon remains unchanged.
* attributes: {
* 'class': 'my-custom-full-class'
* }
* },
* skipBorder: {
* attributes: {
* 'class': 'skip-border'
* },
* group: 'borders',
* label: 'Skip border'
* },
* thickBorder: {
* attributes: {
* 'class': 'thick-border'
* },
* group: 'borders',
* label: 'Thick border'
* }
* };
*
Expand All @@ -567,11 +604,29 @@
*/
CKEDITOR.config.easyimage_styles = {};


/**
* The default style to be applied to Easy Image widgets, based on keys in {@link #easyimage_styles}.
*
* If set to `null` no default style is applied.
*
* // Make side image a default style.
* config.easyimage_defaultStyle = 'side';
*
* @since 4.9.0
* @cfg {String/null} easyimage_defaultStyle
* @member CKEDITOR.config
*/
CKEDITOR.config.easyimage_defaultStyle = 'full';

/**
* List of buttons to be displayed in a balloon toolbar for Easy Image widget.
*
* If Context Menu plugin is enabled, this config variable will be used also to add
* items to the context menu for Easy Image widget.
*
* You can find list of available styles in {@link #easyimage_styles}.
*
* // Change toolbar to alignment commands.
* config.easyimage_toolbar = [ 'EasyimageAlignLeft', 'EasyimageAlignCenter', 'EasyimageAlignRight' ];
*
Expand Down
6 changes: 3 additions & 3 deletions plugins/easyimage/styles/easyimage.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The outline is not a part of the element's dimensions, we have to use a border a
}

.cke_widget_wrapper_easyimage-side, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-side) > .easyimage-side,
.cke_widget_wrapper_easyimage-alignRight, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-alignRight) > .easyimage-alignRight {
.cke_widget_wrapper_easyimage-align-right, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-align-right) > .easyimage-align-right {
/*
:not() selector will be used for Easy Image content ouside of the editor. E.g. when the editor was destoryed.
See https://github.com/ckeditor/ckeditor-dev/pull/1150#discussion_r150415261 for more details.
Expand All @@ -44,12 +44,12 @@ The outline is not a part of the element's dimensions, we have to use a border a
max-width: 25%;
}

.cke_widget_wrapper_easyimage-alignLeft, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-alignLeft) > .easyimage-alignLeft {
.cke_widget_wrapper_easyimage-align-left, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-align-left) > .easyimage-align-left {
float: left;
max-width: 25%;
}

.cke_widget_wrapper_easyimage-alignCenter, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-alignCenter) > .easyimage-alignCenter {
.cke_widget_wrapper_easyimage-align-center, :not(.cke_widget_wrapper_easyimage):not(.cke_widget_wrapper_easyimage-align-center) > .easyimage-align-center {
margin: 0 auto;
max-width: 90%;
}
Expand Down
Loading

0 comments on commit 721bd11

Please sign in to comment.