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

Commit

Permalink
Merge pull request #165 from ckeditor/t/ckeditor5/645
Browse files Browse the repository at this point in the history
Feature: Implemented a 2–step link UI with a refreshed look&feel (see ckeditor/ckeditor5#645). Closes #31.

BREAKING CHANGE: The structure of the link UI has changed dramatically. Some pieces of the `LinkFormView` belong now to the `LinkActionsView` class. The CSS classes have also changed along with component templates.
  • Loading branch information
Reinmar authored Feb 2, 2018
2 parents 4cbb524 + 70a55ef commit 6baee95
Show file tree
Hide file tree
Showing 10 changed files with 989 additions and 389 deletions.
328 changes: 248 additions & 80 deletions src/link.js

Large diffs are not rendered by default.

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

/**
* @module link/ui/linkactionsview
*/

import View from '@ckeditor/ckeditor5-ui/src/view';
import ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';

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

import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';

import unlinkIcon from '../../theme/icons/unlink.svg';
import pencilIcon from '@ckeditor/ckeditor5-core/theme/icons/pencil.svg';
import '../../theme/linkactions.css';

/**
* The link actions view class. This view displays link preview, allows
* unlinking or editing the link.
*
* @extends module:ui/view~View
*/
export default class LinkActionsView extends View {
/**
* @inheritDoc
*/
constructor( locale ) {
super( locale );

const t = locale.t;

/**
* Tracks information about DOM focus in the actions.
*
* @readonly
* @member {module:utils/focustracker~FocusTracker}
*/
this.focusTracker = new FocusTracker();

/**
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
*
* @readonly
* @member {module:utils/keystrokehandler~KeystrokeHandler}
*/
this.keystrokes = new KeystrokeHandler();

/**
* The href preview view.
*
* @member {module:ui/view~View}
*/
this.previewButtonView = this._createPreviewButton();

/**
* The unlink button view.
*
* @member {module:ui/button/buttonview~ButtonView}
*/
this.unlinkButtonView = this._createButton( t( 'Unlink' ), unlinkIcon, 'unlink' );

/**
* The edit link button view.
*
* @member {module:ui/button/buttonview~ButtonView}
*/
this.editButtonView = this._createButton( t( 'Edit link' ), pencilIcon, 'edit' );

/**
* Value of the "href" attribute of the link to use in the {@link #previewButtonView}.
*
* @observable
* @member {String}
*/
this.set( 'href' );

/**
* A collection of views which can be focused in the view.
*
* @readonly
* @protected
* @member {module:ui/viewcollection~ViewCollection}
*/
this._focusables = new ViewCollection();

/**
* Helps cycling over {@link #_focusables} in the view.
*
* @readonly
* @protected
* @member {module:ui/focuscycler~FocusCycler}
*/
this._focusCycler = new FocusCycler( {
focusables: this._focusables,
focusTracker: this.focusTracker,
keystrokeHandler: this.keystrokes,
actions: {
// Navigate fields backwards using the Shift + Tab keystroke.
focusPrevious: 'shift + tab',

// Navigate fields forwards using the Tab key.
focusNext: 'tab'
}
} );

this.setTemplate( {
tag: 'div',

attributes: {
class: [
'ck-link-actions',
],

// https://github.com/ckeditor/ckeditor5-link/issues/90
tabindex: '-1'
},

children: [
this.previewButtonView,
this.editButtonView,
this.unlinkButtonView
]
} );
}

/**
* @inheritDoc
*/
render() {
super.render();

const childViews = [
this.previewButtonView,
this.editButtonView,
this.unlinkButtonView
];

childViews.forEach( v => {
// Register the view as focusable.
this._focusables.add( v );

// Register the view in the focus tracker.
this.focusTracker.add( v.element );
} );

// Start listening for the keystrokes coming from #element.
this.keystrokes.listenTo( this.element );
}

/**
* Focuses the fist {@link #_focusables} in the actions.
*/
focus() {
this._focusCycler.focusFirst();
}

/**
* Creates a button view.
*
* @private
* @param {String} label The button label.
* @param {String} icon The button's icon.
* @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.
* @returns {module:ui/button/buttonview~ButtonView} The button view instance.
*/
_createButton( label, icon, eventName ) {
const button = new ButtonView( this.locale );

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

button.delegate( 'execute' ).to( this, eventName );

return button;
}

/**
* Creates a link href preview button.
*
* @private
* @returns {module:ui/button/buttonview~ButtonView} The button view instance.
*/
_createPreviewButton() {
const button = new ButtonView( this.locale );
const bind = this.bindTemplate;
const t = this.t;

button.set( {
withText: true,
tooltip: t( 'Open link in new tab' )
} );

button.extendTemplate( {
attributes: {
class: [
'ck-link-actions__preview'
],
href: bind.to( 'href' ),
target: '_blank'
}
} );

button.bind( 'label' ).to( this, 'href', href => {
return href || t( 'This link has no URL' );
} );

button.bind( 'isEnabled' ).to( this, 'href', href => !!href );

button.template.tag = 'a';
button.template.eventListeners = {};

return button;
}
}

/**
* Fired when the {@link #editButtonView} is clicked.
*
* @event edit
*/

/**
* Fired when the {@link #unlinkButtonView} is clicked.
*
* @event unlink
*/
51 changes: 15 additions & 36 deletions src/ui/linkformview.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';

import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';
import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
import '../../theme/linkform.css';

/**
Expand Down Expand Up @@ -65,22 +67,15 @@ export default class LinkFormView extends View {
*
* @member {module:ui/button/buttonview~ButtonView}
*/
this.saveButtonView = this._createButton( t( 'Save' ) );
this.saveButtonView = this._createButton( t( 'Save' ), checkIcon );
this.saveButtonView.type = 'submit';

/**
* The Cancel button view.
*
* @member {module:ui/button/buttonview~ButtonView}
*/
this.cancelButtonView = this._createButton( t( 'Cancel' ), 'cancel' );

/**
* The Unlink button view.
*
* @member {module:ui/button/buttonview~ButtonView}
*/
this.unlinkButtonView = this._createButton( t( 'Unlink' ), 'unlink' );
this.cancelButtonView = this._createButton( t( 'Cancel' ), cancelIcon, 'cancel' );

/**
* A collection of views which can be focused in the form.
Expand Down Expand Up @@ -133,21 +128,8 @@ export default class LinkFormView extends View {

children: [
this.urlInputView,
{
tag: 'div',

attributes: {
class: [
'ck-link-form__actions'
]
},

children: [
this.saveButtonView,
this.cancelButtonView,
this.unlinkButtonView
]
}
this.saveButtonView,
this.cancelButtonView
]
} );
}
Expand All @@ -165,8 +147,7 @@ export default class LinkFormView extends View {
const childViews = [
this.urlInputView,
this.saveButtonView,
this.cancelButtonView,
this.unlinkButtonView
this.cancelButtonView
];

childViews.forEach( v => {
Expand Down Expand Up @@ -209,15 +190,19 @@ export default class LinkFormView extends View {
* Creates a button view.
*
* @private
* @param {String} label The button label
* @param {String} label The button label.
* @param {String} icon The button's icon.
* @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.
* @returns {module:ui/button/buttonview~ButtonView} The button view instance.
*/
_createButton( label, eventName ) {
_createButton( label, icon, eventName ) {
const button = new ButtonView( this.locale );

button.label = label;
button.withText = true;
button.set( {
label,
icon,
tooltip: true
} );

if ( eventName ) {
button.delegate( 'execute' ).to( this, eventName );
Expand All @@ -239,9 +224,3 @@ export default class LinkFormView extends View {
*
* @event cancel
*/

/**
* Fired when the {@link #unlinkButtonView} is clicked.
*
* @event unlink
*/
Loading

0 comments on commit 6baee95

Please sign in to comment.