From 0c66afe19deea5af4bf00fb4f712fd3f22abd338 Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Tue, 6 Dec 2016 09:50:39 +0100 Subject: [PATCH 01/15] Contextual toolbar sample. --- .../createcontextualtoolbar.html | 14 +++ .../createcontextualtoolbar.js | 114 ++++++++++++++++++ .../createcontextualtoolbar.md | 6 + theme/components/contextualtoolbar.scss | 30 +++++ theme/theme.scss | 1 + 5 files changed, 165 insertions(+) create mode 100644 tests/manual/createcontextualtoolbar/createcontextualtoolbar.html create mode 100644 tests/manual/createcontextualtoolbar/createcontextualtoolbar.js create mode 100644 tests/manual/createcontextualtoolbar/createcontextualtoolbar.md create mode 100644 theme/components/contextualtoolbar.scss diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html new file mode 100644 index 0000000..a088f2e --- /dev/null +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html @@ -0,0 +1,14 @@ + + + + +
+

This is an editor instance.

+
+ + diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js new file mode 100644 index 0000000..449d6a7 --- /dev/null +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js @@ -0,0 +1,114 @@ +/** + * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* globals window, document, console:false */ + +import ClassicEditor from 'ckeditor5/editor-classic/classic.js'; +import ClickObserver from 'ckeditor5/engine/view/observer/clickobserver.js'; +import Enter from 'ckeditor5/enter/enter.js'; +import Typing from 'ckeditor5/typing/typing.js'; +import Paragraph from 'ckeditor5/paragraph/paragraph.js'; +import Undo from 'ckeditor5/undo/undo.js'; +import Bold from 'ckeditor5/basic-styles/bold.js'; +import Italic from 'ckeditor5/basic-styles/italic.js'; + +import Template from 'ckeditor5/ui/template.js'; +import ToolbarView from 'ckeditor5/ui/toolbar/toolbarview.js'; +import BalloonPanelView from 'ckeditor5/ui/balloonpanel/balloonpanelview.js'; + +// This will become a standard feature of BalloonPanelView. +Object.assign( BalloonPanelView.defaultPositions, { + // [ Target ] + // ^ + // +-----------------+ + // | Balloon | + // +-----------------+ + s: ( targetRect, balloonRect ) => ( { + top: targetRect.bottom + 15, + left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2, + name: 's' + } ), + + // +-----------------+ + // | Balloon | + // +-----------------+ + // V + // [ Target ] + n: ( targetRect, balloonRect ) => ( { + top: targetRect.top - balloonRect.height - 15, + left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2, + name: 'n' + } ), + + // [ Target ] + // ^ + // +-----------------+ + // | Balloon | + // +-----------------+ + forwardSelection: ( targetRect, balloonRect ) => ( { + top: targetRect.bottom + 15, + left: targetRect.right - balloonRect.width / 2, + name: 's' + } ), + + // +-----------------+ + // | Balloon | + // +-----------------+ + // V + // [ Target ] + backwardSelection: ( targetRect, balloonRect ) => ( { + top: targetRect.top - balloonRect.height - 15, + left: targetRect.left - balloonRect.width / 2, + name: 'n' + } ), +} ); + +ClassicEditor.create( document.querySelector( '#editor' ), { + plugins: [ Enter, Typing, Paragraph, Undo, Bold, Italic ], + toolbar: [ 'bold', 'italic', 'undo', 'redo' ] +} ) +.then( editor => { + const viewDocument = editor.editing.view; + const toolbarView = new ToolbarView(); + const balloonPanelView = new BalloonPanelView( editor.locale ); + + balloonPanelView.positions = [ 'se', 'sw' ]; + + Template.extend( balloonPanelView.template, { + attributes: { + class: [ + 'ck-toolbar_contextual', + ] + } + } ); + + balloonPanelView.content.add( toolbarView ); + viewDocument.addObserver( ClickObserver ); + + editor.ui.view.body.add( balloonPanelView ).then( () => { + for ( let name of editor.config.get( 'toolbar' ) ) { + toolbarView.items.add( editor.ui.componentFactory.create( name ) ); + } + + balloonPanelView.bind( 'isVisible' ).to( editor.ui.focusTracker, 'isFocused' ); + + editor.listenTo( viewDocument, 'click', () => { + if ( viewDocument.selection.isCollapsed ) { + balloonPanelView.positions = [ 's' ]; + } else { + balloonPanelView.positions = [ + viewDocument.selection.isBackward ? 'backwardSelection' : 'forwardSelection' + ]; + } + + balloonPanelView.attachTo( viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ) ); + } ); + } ); + + window.editor = editor; +} ) +.catch( err => { + console.error( err.stack ); +} ); diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.md b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.md new file mode 100644 index 0000000..8b0ecb1 --- /dev/null +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.md @@ -0,0 +1,6 @@ +@bender-ui: collapsed +@bender-tags: ui toolbar + +## Foo + +1. Bar diff --git a/theme/components/contextualtoolbar.scss b/theme/components/contextualtoolbar.scss new file mode 100644 index 0000000..5d044f5 --- /dev/null +++ b/theme/components/contextualtoolbar.scss @@ -0,0 +1,30 @@ +// Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. +// For licensing, see LICENSE.md or http://ckeditor.com/license + +.ck-toolbar_contextual { + background: ck-color( 'foreground' ); + + .ck-toolbar { + @include ck-editor-toolbar; + + border: 0; + } + + &.ck-balloon-panel { + &_arrow_s, + &_arrow_se, + &_arrow_sw { + &:after { + border-bottom-color: ck-color( 'foreground' ); + } + } + + &_arrow_n, + &_arrow_ne, + &_arrow_nw { + &:after { + border-top-color: ck-color( 'foreground' ); + } + } + } +} diff --git a/theme/theme.scss b/theme/theme.scss index dcddcb8..808c0bb 100644 --- a/theme/theme.scss +++ b/theme/theme.scss @@ -2,3 +2,4 @@ // For licensing, see LICENSE.md or http://ckeditor.com/license @import 'components/stickytoolbar'; +@import 'components/contextualtoolbar'; From e04d4809d44e902fbbfd56b04e13e52d2247521b Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Tue, 6 Dec 2016 09:52:56 +0100 Subject: [PATCH 02/15] Moved StickyToolbarView manual tests to a dedicated folder. --- tests/manual/{ => stickytoolbarview}/stickytoolbarview.html | 0 tests/manual/{ => stickytoolbarview}/stickytoolbarview.js | 0 tests/manual/{ => stickytoolbarview}/stickytoolbarview.md | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/manual/{ => stickytoolbarview}/stickytoolbarview.html (100%) rename tests/manual/{ => stickytoolbarview}/stickytoolbarview.js (100%) rename tests/manual/{ => stickytoolbarview}/stickytoolbarview.md (100%) diff --git a/tests/manual/stickytoolbarview.html b/tests/manual/stickytoolbarview/stickytoolbarview.html similarity index 100% rename from tests/manual/stickytoolbarview.html rename to tests/manual/stickytoolbarview/stickytoolbarview.html diff --git a/tests/manual/stickytoolbarview.js b/tests/manual/stickytoolbarview/stickytoolbarview.js similarity index 100% rename from tests/manual/stickytoolbarview.js rename to tests/manual/stickytoolbarview/stickytoolbarview.js diff --git a/tests/manual/stickytoolbarview.md b/tests/manual/stickytoolbarview/stickytoolbarview.md similarity index 100% rename from tests/manual/stickytoolbarview.md rename to tests/manual/stickytoolbarview/stickytoolbarview.md From 97b22c7060c1a8e0013f32924f52cc52a53db98c Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Tue, 6 Dec 2016 14:13:46 +0100 Subject: [PATCH 03/15] Updated sample to the latest API. --- .../createcontextualtoolbar.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js index 449d6a7..5180380 100644 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js @@ -18,8 +18,7 @@ import Template from 'ckeditor5/ui/template.js'; import ToolbarView from 'ckeditor5/ui/toolbar/toolbarview.js'; import BalloonPanelView from 'ckeditor5/ui/balloonpanel/balloonpanelview.js'; -// This will become a standard feature of BalloonPanelView. -Object.assign( BalloonPanelView.defaultPositions, { +const positions = { // [ Target ] // ^ // +-----------------+ @@ -62,8 +61,8 @@ Object.assign( BalloonPanelView.defaultPositions, { top: targetRect.top - balloonRect.height - 15, left: targetRect.left - balloonRect.width / 2, name: 'n' - } ), -} ); + } ) +}; ClassicEditor.create( document.querySelector( '#editor' ), { plugins: [ Enter, Typing, Paragraph, Undo, Bold, Italic ], @@ -74,8 +73,6 @@ ClassicEditor.create( document.querySelector( '#editor' ), { const toolbarView = new ToolbarView(); const balloonPanelView = new BalloonPanelView( editor.locale ); - balloonPanelView.positions = [ 'se', 'sw' ]; - Template.extend( balloonPanelView.template, { attributes: { class: [ @@ -95,15 +92,18 @@ ClassicEditor.create( document.querySelector( '#editor' ), { balloonPanelView.bind( 'isVisible' ).to( editor.ui.focusTracker, 'isFocused' ); editor.listenTo( viewDocument, 'click', () => { + let preferredPositions; + if ( viewDocument.selection.isCollapsed ) { - balloonPanelView.positions = [ 's' ]; + preferredPositions = [ positions.s ]; } else { - balloonPanelView.positions = [ - viewDocument.selection.isBackward ? 'backwardSelection' : 'forwardSelection' - ]; + preferredPositions = [ positions[ viewDocument.selection.isBackward ? 'backwardSelection' : 'forwardSelection' ] ]; } - balloonPanelView.attachTo( viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ) ); + balloonPanelView.attachTo( { + target: viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ), + positions: preferredPositions + } ); } ); } ); From fd7f7f1237f2cf1e622f3f4090397f8eee8e695b Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Tue, 6 Dec 2016 16:59:01 +0100 Subject: [PATCH 04/15] Simplified contextual toolbar sample. --- .../createcontextualtoolbar.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js index 5180380..37b60d6 100644 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js @@ -89,21 +89,15 @@ ClassicEditor.create( document.querySelector( '#editor' ), { toolbarView.items.add( editor.ui.componentFactory.create( name ) ); } - balloonPanelView.bind( 'isVisible' ).to( editor.ui.focusTracker, 'isFocused' ); - editor.listenTo( viewDocument, 'click', () => { - let preferredPositions; - - if ( viewDocument.selection.isCollapsed ) { - preferredPositions = [ positions.s ]; + if ( !viewDocument.selection.isCollapsed ) { + balloonPanelView.attachTo( { + target: viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ), + positions: [ positions[ viewDocument.selection.isBackward ? 'backwardSelection' : 'forwardSelection' ] ] + } ); } else { - preferredPositions = [ positions[ viewDocument.selection.isBackward ? 'backwardSelection' : 'forwardSelection' ] ]; + balloonPanelView.hide(); } - - balloonPanelView.attachTo( { - target: viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ), - positions: preferredPositions - } ); } ); } ); From 090a12f843ba8997c36e5c74d1fb45cd1321f0da Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Wed, 7 Dec 2016 13:23:02 +0100 Subject: [PATCH 05/15] Hide contextual toolbar when focusTracker says editor is blurred. --- .../createcontextualtoolbar/createcontextualtoolbar.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js index 37b60d6..dde0302 100644 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js @@ -89,6 +89,14 @@ ClassicEditor.create( document.querySelector( '#editor' ), { toolbarView.items.add( editor.ui.componentFactory.create( name ) ); } + editor.ui.focusTracker.add( balloonPanelView.element ); + + balloonPanelView.listenTo( editor.ui.focusTracker, 'change:isFocused', ( evt, name, is, was ) => { + if ( was && !is ) { + balloonPanelView.hide(); + } + } ); + editor.listenTo( viewDocument, 'click', () => { if ( !viewDocument.selection.isCollapsed ) { balloonPanelView.attachTo( { From dd5ffdd665fb52bc4c9e55a92515bf3b4266614d Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Wed, 7 Dec 2016 13:25:56 +0100 Subject: [PATCH 06/15] Multi-line sample. --- .../manual/createcontextualtoolbar/createcontextualtoolbar.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html index a088f2e..7b46f7c 100644 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html +++ b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html @@ -4,6 +4,8 @@

This is an editor instance.

+

This is an editor instance.

+

This is an editor instance.

diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js b/tests/manual/contextualtoolbar/contextualtoolbar.js similarity index 72% rename from tests/manual/createcontextualtoolbar/createcontextualtoolbar.js rename to tests/manual/contextualtoolbar/contextualtoolbar.js index 1998c90..b0ee1fd 100644 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.js +++ b/tests/manual/contextualtoolbar/contextualtoolbar.js @@ -18,14 +18,15 @@ import Template from 'ckeditor5/ui/template.js'; import ToolbarView from 'ckeditor5/ui/toolbar/toolbarview.js'; import BalloonPanelView from 'ckeditor5/ui/balloonpanel/balloonpanelview.js'; +const arrowVOffset = BalloonPanelView.arrowVerticalOffset; const positions = { - // [ Target ] - // ^ - // +-----------------+ - // | Balloon | - // +-----------------+ + // [text range] + // ^ + // +-----------------+ + // | Balloon | + // +-----------------+ forwardSelection: ( targetRect, balloonRect ) => ( { - top: targetRect.bottom + 15, + top: targetRect.bottom + arrowVOffset, left: targetRect.right - balloonRect.width / 2, name: 's' } ), @@ -34,9 +35,9 @@ const positions = { // | Balloon | // +-----------------+ // V - // [ Target ] + // [text range] backwardSelection: ( targetRect, balloonRect ) => ( { - top: targetRect.top - balloonRect.height - 15, + top: targetRect.top - balloonRect.height - arrowVOffset, left: targetRect.left - balloonRect.width / 2, name: 'n' } ) @@ -47,8 +48,18 @@ ClassicEditor.create( document.querySelector( '#editor' ), { toolbar: [ 'bold', 'italic', 'undo', 'redo' ] } ) .then( editor => { - const viewDocument = editor.editing.view; + createContextualToolbar( editor ); + window.editor = editor; +} ) +.catch( err => { + console.error( err.stack ); +} ); + +function createContextualToolbar( editor ) { + // Create a plain toolbar instance. const toolbar = new ToolbarView(); + + // Create a BalloonPanelView instance. const panel = new BalloonPanelView( editor.locale ); Template.extend( panel.template, { @@ -59,11 +70,13 @@ ClassicEditor.create( document.querySelector( '#editor' ), { } } ); + // Putting the toolbar inside of the balloon panel. panel.content.add( toolbar ); - viewDocument.addObserver( ClickObserver ); editor.ui.view.body.add( panel ).then( () => { - // Fill the toolbar with some buttons. In this case – copy default editor toolbar. + const editingView = editor.editing.view; + + // Fill the toolbar with some buttons. Simply copy default editor toolbar. for ( let name of editor.config.get( 'toolbar' ) ) { toolbar.items.add( editor.ui.componentFactory.create( name ) ); } @@ -78,32 +91,31 @@ ClassicEditor.create( document.querySelector( '#editor' ), { } } ); + editingView.addObserver( ClickObserver ); + // Position the panel each time the user clicked in editable. - editor.listenTo( viewDocument, 'click', () => { + editor.listenTo( editingView, 'click', () => { // This implementation assumes that only non–collapsed selections gets the contextual toolbar. - if ( !viewDocument.selection.isCollapsed ) { - const isBackward = viewDocument.selection.isBackward; + if ( !editingView.selection.isCollapsed ) { + const isBackward = editingView.selection.isBackward; // getBoundingClientRect() makes no sense when the selection spans across number // of lines of text. Using getClientRects() allows us to browse micro–ranges // that would normally make up the bounding client rect. - const rangeRects = viewDocument.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() ).getClientRects(); + const rangeRects = editingView.domConverter.viewRangeToDom( editingView.selection.getFirstRange() ).getClientRects(); // Select the proper range rect depending on the direction of the selection. const rangeRect = isBackward ? rangeRects.item( 0 ) : rangeRects.item( rangeRects.length - 1 ); panel.attachTo( { target: rangeRect, - positions: [ positions[ isBackward ? 'backwardSelection' : 'forwardSelection' ] ] + positions: [ + positions[ isBackward ? 'backwardSelection' : 'forwardSelection' ] + ] } ); } else { panel.hide(); } } ); } ); - - window.editor = editor; -} ) -.catch( err => { - console.error( err.stack ); -} ); +} diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.md b/tests/manual/contextualtoolbar/contextualtoolbar.md similarity index 100% rename from tests/manual/createcontextualtoolbar/createcontextualtoolbar.md rename to tests/manual/contextualtoolbar/contextualtoolbar.md diff --git a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html b/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html deleted file mode 100644 index 7b46f7c..0000000 --- a/tests/manual/createcontextualtoolbar/createcontextualtoolbar.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - -
-

This is an editor instance.

-

This is an editor instance.

-

This is an editor instance.

-
- - From 8464f20562f0dd1b577d643a36be1585219b900a Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Thu, 8 Dec 2016 16:17:50 +0100 Subject: [PATCH 12/15] Code refactoring in the contextual toolbar sample. --- tests/manual/contextualtoolbar/contextualtoolbar.html | 2 +- tests/manual/contextualtoolbar/contextualtoolbar.js | 2 +- tests/manual/contextualtoolbar/contextualtoolbar.md | 1 + theme/components/contextualtoolbar.scss | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/manual/contextualtoolbar/contextualtoolbar.html b/tests/manual/contextualtoolbar/contextualtoolbar.html index 24fafc9..1330cc9 100644 --- a/tests/manual/contextualtoolbar/contextualtoolbar.html +++ b/tests/manual/contextualtoolbar/contextualtoolbar.html @@ -10,7 +10,7 @@ diff --git a/tests/manual/contextualtoolbar/contextualtoolbar.js b/tests/manual/contextualtoolbar/contextualtoolbar.js index b0ee1fd..8e7cec7 100644 --- a/tests/manual/contextualtoolbar/contextualtoolbar.js +++ b/tests/manual/contextualtoolbar/contextualtoolbar.js @@ -65,7 +65,7 @@ function createContextualToolbar( editor ) { Template.extend( panel.template, { attributes: { class: [ - 'ck-toolbar_contextual', + 'ck-toolbar__container', ] } } ); diff --git a/tests/manual/contextualtoolbar/contextualtoolbar.md b/tests/manual/contextualtoolbar/contextualtoolbar.md index 47f2dea..0455530 100644 --- a/tests/manual/contextualtoolbar/contextualtoolbar.md +++ b/tests/manual/contextualtoolbar/contextualtoolbar.md @@ -2,3 +2,4 @@ 1. Create a non–collapsed selection. 2. Create another non–collapsed selection but in another direction. +3. For each selection, a contextual toolbar should appear and the beginning/end of the selection, duplicating main editor toolbar. diff --git a/theme/components/contextualtoolbar.scss b/theme/components/contextualtoolbar.scss index 5d044f5..9585c00 100644 --- a/theme/components/contextualtoolbar.scss +++ b/theme/components/contextualtoolbar.scss @@ -1,7 +1,7 @@ // Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. // For licensing, see LICENSE.md or http://ckeditor.com/license -.ck-toolbar_contextual { +.ck-toolbar__container { background: ck-color( 'foreground' ); .ck-toolbar { From 0af97f05b1c9e3724f683dbf4428a02a7c5c2870 Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Thu, 15 Dec 2016 15:16:51 +0100 Subject: [PATCH 13/15] Fixed: BalloonPanelView.arrow[Horizontal, Vertical]Offset properties are not overwritable. --- src/balloonpanel/balloonpanelview.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/balloonpanel/balloonpanelview.js b/src/balloonpanel/balloonpanelview.js index 74a6947..30a1ab8 100644 --- a/src/balloonpanel/balloonpanelview.js +++ b/src/balloonpanel/balloonpanelview.js @@ -15,8 +15,6 @@ import { getOptimalPosition } from '../../utils/dom/position.js'; import toUnit from '../../utils/dom/tounit.js'; const toPx = toUnit( 'px' ); -const arrowHorizontalOffset = 30; -const arrowVerticalOffset = 15; /** * The balloon panel view class. @@ -174,7 +172,7 @@ export default class BalloonPanelView extends View { * @default 30 * @member {Number} module:ui/balloonpanel/balloonpanelview~BalloonPanelView.arrowHorizontalOffset */ -BalloonPanelView.arrowHorizontalOffset = arrowHorizontalOffset; +BalloonPanelView.arrowHorizontalOffset = 30; /** * A vertical offset of the arrow from the edge of the balloon. Controlled by CSS. @@ -193,7 +191,7 @@ BalloonPanelView.arrowHorizontalOffset = arrowHorizontalOffset; * @default 15 * @member {Number} module:ui/balloonpanel/balloonpanelview~BalloonPanelView.arrowVerticalOffset */ -BalloonPanelView.arrowVerticalOffset = arrowVerticalOffset; +BalloonPanelView.arrowVerticalOffset = 15; /** * A default set of positioning functions used by the balloon panel view @@ -244,26 +242,26 @@ BalloonPanelView.arrowVerticalOffset = arrowVerticalOffset; */ BalloonPanelView.defaultPositions = { se: ( targetRect ) => ( { - top: targetRect.bottom + arrowVerticalOffset, - left: targetRect.left + targetRect.width / 2 - arrowHorizontalOffset, + top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset, + left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset, name: 'se' } ), sw: ( targetRect, balloonRect ) => ( { - top: targetRect.bottom + arrowVerticalOffset, - left: targetRect.left + targetRect.width / 2 - balloonRect.width + arrowHorizontalOffset, + top: targetRect.bottom + BalloonPanelView.arrowVerticalOffset, + left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset, name: 'sw' } ), ne: ( targetRect, balloonRect ) => ( { - top: targetRect.top - balloonRect.height - arrowVerticalOffset, - left: targetRect.left + targetRect.width / 2 - arrowHorizontalOffset, + top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset, + left: targetRect.left + targetRect.width / 2 - BalloonPanelView.arrowHorizontalOffset, name: 'ne' } ), nw: ( targetRect, balloonRect ) => ( { - top: targetRect.top - balloonRect.height - arrowVerticalOffset, - left: targetRect.left + targetRect.width / 2 - balloonRect.width + arrowHorizontalOffset, + top: targetRect.top - balloonRect.height - BalloonPanelView.arrowVerticalOffset, + left: targetRect.left + targetRect.width / 2 - balloonRect.width + BalloonPanelView.arrowHorizontalOffset, name: 'nw' } ) }; From 33df23642745a5ccf6e0c5a6c9e76b3419afb030 Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Thu, 15 Dec 2016 15:29:31 +0100 Subject: [PATCH 14/15] Fixed: Contextual toolbar does not work in Firefox because a mouseup observer is required. --- .../contextualtoolbar/contextualtoolbar.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/manual/contextualtoolbar/contextualtoolbar.js b/tests/manual/contextualtoolbar/contextualtoolbar.js index 8e7cec7..5982ab3 100644 --- a/tests/manual/contextualtoolbar/contextualtoolbar.js +++ b/tests/manual/contextualtoolbar/contextualtoolbar.js @@ -6,7 +6,7 @@ /* globals window, document, console:false */ import ClassicEditor from 'ckeditor5/editor-classic/classic.js'; -import ClickObserver from 'ckeditor5/engine/view/observer/clickobserver.js'; +import DomEventObserver from 'ckeditor5/engine/view/observer/domeventobserver.js'; import Enter from 'ckeditor5/enter/enter.js'; import Typing from 'ckeditor5/typing/typing.js'; import Paragraph from 'ckeditor5/paragraph/paragraph.js'; @@ -91,10 +91,20 @@ function createContextualToolbar( editor ) { } } ); - editingView.addObserver( ClickObserver ); + // Add "mouseup" event observer. It's enought to use ClickObserver in Chrome + // but Firefox requires "mouseup" to work properly. + editingView.addObserver( class extends DomEventObserver { + get domEventType() { + return [ 'mouseup' ]; + } + + onDomEvent( domEvent ) { + this.fire( domEvent.type, domEvent ); + } + } ); // Position the panel each time the user clicked in editable. - editor.listenTo( editingView, 'click', () => { + editor.listenTo( editingView, 'mouseup', () => { // This implementation assumes that only non–collapsed selections gets the contextual toolbar. if ( !editingView.selection.isCollapsed ) { const isBackward = editingView.selection.isBackward; From df261134baff6ea956f66cfe61b10e59bd552f0b Mon Sep 17 00:00:00 2001 From: Aleksander Nowodzinski Date: Fri, 16 Dec 2016 11:23:21 +0100 Subject: [PATCH 15/15] Docs: Clarified docs about balloon positions and their relation with CSS. --- src/balloonpanel/balloonpanelview.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/balloonpanel/balloonpanelview.js b/src/balloonpanel/balloonpanelview.js index 30a1ab8..232e7e4 100644 --- a/src/balloonpanel/balloonpanelview.js +++ b/src/balloonpanel/balloonpanelview.js @@ -49,8 +49,12 @@ export default class BalloonPanelView extends View { this.set( 'left', 0 ); /** - * Balloon panel's current position. Must correspond with - * {@link module:ui/balloonpanel/balloonpanelview~BalloonPanelView.defaultPositions}. + * Balloon panel's current position. The position name is reflected in the CSS class set + * to the balloon, i.e. `.ck-balloon-panel_arrow_se` for "se" position. The class + * controls the minor aspects of the balloon's visual appearance like placement + * of the "arrow". To support a new position, an additional CSS must be created. + * + * Default position names correspond with {@link #defaultPositions}. * * @observable * @default 'se' @@ -238,6 +242,9 @@ BalloonPanelView.arrowVerticalOffset = 15; * * Positioning functions must be compatible with {@link module:utils/dom/position~Position}. * + * The name that position function returns will be reflected in balloon panel's class that + * controls the placement of the "arrow". See {@link #position} to learn more. + * * @member {Object} module:ui/balloonpanel/balloonpanelview~BalloonPanelView.defaultPositions */ BalloonPanelView.defaultPositions = {