Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into t/ckeditor5-engine/738
Browse files Browse the repository at this point in the history
  • Loading branch information
Kamil Piechaczek committed Feb 28, 2018
2 parents 70e6a4f + d677fb6 commit 7192ba3
Show file tree
Hide file tree
Showing 6 changed files with 475 additions and 432 deletions.
124 changes: 6 additions & 118 deletions src/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,16 @@
* @module list/list
*/

import ListEngine from './listengine';

import numberedListIcon from '../theme/icons/numberedlist.svg';
import bulletedListIcon from '../theme/icons/bulletedlist.svg';
import ListEditing from './listediting';
import ListUI from './listui';

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';

/**
* The list feature. It introduces the `numberedList` and `bulletedList` buttons that
* allow to convert paragraphs to and from list items and indent or outdent them.
* The list feature.
*
* See also {@link module:list/listengine~ListEngine}.
* It loads the {@link module:list/listediting~ListEditing list editing feature}
* and {@link module:list/listui~ListUI list UI feature}.
*
* @extends module:core/plugin~Plugin
*/
Expand All @@ -28,7 +25,7 @@ export default class List extends Plugin {
* @inheritDoc
*/
static get requires() {
return [ ListEngine ];
return [ ListEditing, ListUI ];
}

/**
Expand All @@ -37,113 +34,4 @@ export default class List extends Plugin {
static get pluginName() {
return 'List';
}

/**
* @inheritDoc
*/
init() {
// Create two buttons and link them with numberedList and bulletedList commands.
const t = this.editor.t;
this._addButton( 'numberedList', t( 'Numbered List' ), numberedListIcon );
this._addButton( 'bulletedList', t( 'Bulleted List' ), bulletedListIcon );

const viewDocument = this.editor.editing.view.document;

// Overwrite default Enter key behavior.
// If Enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it.
this.listenTo( viewDocument, 'enter', ( evt, data ) => {
const doc = this.editor.model.document;
const positionParent = doc.selection.getLastPosition().parent;

if ( doc.selection.isCollapsed && positionParent.name == 'listItem' && positionParent.isEmpty ) {
this.editor.execute( 'outdentList' );

data.preventDefault();
evt.stop();
}
} );

// Overwrite default Backspace key behavior.
// If Backspace key is pressed with selection collapsed on first position in first list item, outdent it. #83
this.listenTo( viewDocument, 'delete', ( evt, data ) => {
// Check conditions from those that require less computations like those immediately available.
if ( data.direction !== 'backward' ) {
return;
}

const selection = this.editor.model.document.selection;

if ( !selection.isCollapsed ) {
return;
}

const firstPosition = selection.getFirstPosition();

if ( !firstPosition.isAtStart ) {
return;
}

const positionParent = firstPosition.parent;

if ( positionParent.name !== 'listItem' ) {
return;
}

const previousIsAListItem = positionParent.previousSibling && positionParent.previousSibling.name === 'listItem';

if ( previousIsAListItem ) {
return;
}

this.editor.execute( 'outdentList' );

data.preventDefault();
evt.stop();
}, { priority: 'high' } );

const getCommandExecuter = commandName => {
return ( data, cancel ) => {
const command = this.editor.commands.get( commandName );

if ( command.isEnabled ) {
this.editor.execute( commandName );
cancel();
}
};
};

this.editor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) );
this.editor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) );
}

/**
* Helper method for initializing a button and linking it with an appropriate command.
*
* @private
* @param {String} commandName The name of the command.
* @param {Object} label The button label.
* @param {String} icon The source of the icon.
*/
_addButton( commandName, label, icon ) {
const editor = this.editor;
const command = editor.commands.get( commandName );

editor.ui.componentFactory.add( commandName, locale => {
const buttonView = new ButtonView( locale );

buttonView.set( {
label,
icon,
tooltip: true
} );

// Bind button model to command.
buttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );

// Execute command.
this.listenTo( buttonView, 'execute', () => editor.execute( commandName ) );

return buttonView;
} );
}
}
72 changes: 70 additions & 2 deletions src/listengine.js → src/listediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

/**
* @module list/listengine
* @module list/listediting
*/

import ListCommand from './listcommand';
Expand Down Expand Up @@ -35,7 +35,7 @@ import {
*
* @extends module:core/plugin~Plugin
*/
export default class ListEngine extends Plugin {
export default class ListEditing extends Plugin {
/**
* @inheritDoc
*/
Expand Down Expand Up @@ -101,6 +101,74 @@ export default class ListEngine extends Plugin {
// Register commands for indenting.
editor.commands.add( 'indentList', new IndentCommand( editor, 'forward' ) );
editor.commands.add( 'outdentList', new IndentCommand( editor, 'backward' ) );

const viewDocument = this.editor.editing.view.document;

// Overwrite default Enter key behavior.
// If Enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it.
this.listenTo( viewDocument, 'enter', ( evt, data ) => {
const doc = this.editor.model.document;
const positionParent = doc.selection.getLastPosition().parent;

if ( doc.selection.isCollapsed && positionParent.name == 'listItem' && positionParent.isEmpty ) {
this.editor.execute( 'outdentList' );

data.preventDefault();
evt.stop();
}
} );

// Overwrite default Backspace key behavior.
// If Backspace key is pressed with selection collapsed on first position in first list item, outdent it. #83
this.listenTo( viewDocument, 'delete', ( evt, data ) => {
// Check conditions from those that require less computations like those immediately available.
if ( data.direction !== 'backward' ) {
return;
}

const selection = this.editor.model.document.selection;

if ( !selection.isCollapsed ) {
return;
}

const firstPosition = selection.getFirstPosition();

if ( !firstPosition.isAtStart ) {
return;
}

const positionParent = firstPosition.parent;

if ( positionParent.name !== 'listItem' ) {
return;
}

const previousIsAListItem = positionParent.previousSibling && positionParent.previousSibling.name === 'listItem';

if ( previousIsAListItem ) {
return;
}

this.editor.execute( 'outdentList' );

data.preventDefault();
evt.stop();
}, { priority: 'high' } );

const getCommandExecuter = commandName => {
return ( data, cancel ) => {
const command = this.editor.commands.get( commandName );

if ( command.isEnabled ) {
this.editor.execute( commandName );
cancel();
}
};
};

this.editor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) );
this.editor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) );
}
}

Expand Down
64 changes: 64 additions & 0 deletions src/listui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module list/listui
*/

import numberedListIcon from '../theme/icons/numberedlist.svg';
import bulletedListIcon from '../theme/icons/bulletedlist.svg';

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';

/**
* The list UI feature. It introduces the `numberedList` and `bulletedList` buttons that
* allow to convert paragraphs to and from list items and indent or outdent them.
*
* @extends module:core/plugin~Plugin
*/
export default class ListUI extends Plugin {
/**
* @inheritDoc
*/
init() {
// Create two buttons and link them with numberedList and bulletedList commands.
const t = this.editor.t;
this._addButton( 'numberedList', t( 'Numbered List' ), numberedListIcon );
this._addButton( 'bulletedList', t( 'Bulleted List' ), bulletedListIcon );
}

/**
* Helper method for initializing a button and linking it with an appropriate command.
*
* @private
* @param {String} commandName The name of the command.
* @param {Object} label The button label.
* @param {String} icon The source of the icon.
*/
_addButton( commandName, label, icon ) {
const editor = this.editor;

editor.ui.componentFactory.add( commandName, locale => {
const command = editor.commands.get( commandName );

const buttonView = new ButtonView( locale );

buttonView.set( {
label,
icon,
tooltip: true
} );

// Bind button model to command.
buttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );

// Execute command.
this.listenTo( buttonView, 'execute', () => editor.execute( commandName ) );

return buttonView;
} );
}
}
Loading

0 comments on commit 7192ba3

Please sign in to comment.