-
Notifications
You must be signed in to change notification settings - Fork 18
Added keepAttachedTo
method to the BalloonPanelView.
#172
Changes from 7 commits
2d9f309
3a6b741
9233160
a5c1dab
4d1443f
e078d48
30904a7
a3f0934
fc6ec1a
724a590
f3840ae
8692e48
3941c56
af93584
4a31312
dd62d00
5fbbe27
b7d759e
e369e41
3c55902
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,14 @@ | |
* @module ui/panel/balloon/balloonpanelview | ||
*/ | ||
|
||
/* globals document */ | ||
|
||
import View from '../../view'; | ||
import Template from '../../template'; | ||
import { getOptimalPosition } from '@ckeditor/ckeditor5-utils/src/dom/position'; | ||
import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit'; | ||
import global from '@ckeditor/ckeditor5-utils/src/dom/global'; | ||
|
||
const toPx = toUnit( 'px' ); | ||
const defaultLimiterElement = global.document.body; | ||
|
||
/** | ||
* The balloon panel view class. | ||
|
@@ -151,14 +151,48 @@ export default class BalloonPanelView extends View { | |
defaultPositions.ne, | ||
defaultPositions.nw | ||
], | ||
limiter: document.body, | ||
limiter: defaultLimiterElement, | ||
fitInViewport: true | ||
}, options ); | ||
|
||
const { top, left, name: position } = getOptimalPosition( positionOptions ); | ||
|
||
Object.assign( this, { top, left, position } ); | ||
} | ||
|
||
/** | ||
* Works exactly the same as {module:ui/panel/balloon/balloonpanelview~BalloonPanelView.attachTo} with one exception. | ||
* Position of attached panel is constantly updated when any of parents of the target or limiter elements are scrolled | ||
* or when browser window is resized. Thanks to this panel always sticks to the target element. See #170. | ||
* | ||
* @param {module:utils/dom/position~Options} options Positioning options compatible with | ||
* {@link module:utils/dom/position~getOptimalPosition}. Default `positions` array is | ||
* {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions}. | ||
*/ | ||
keepAttachedTo( options ) { | ||
// First we need to attach the balloon panel to the target element. | ||
this.attachTo( options ); | ||
|
||
const target = options.target; | ||
const limiter = options.limiter || defaultLimiterElement; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line lacks test coverage. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
// Then we need to listen on scroll event of eny element in the document. | ||
this.listenTo( global.document, 'scroll', ( evt, domEvt ) => { | ||
// And update position if scrolled element contains related to the balloon elements. | ||
if ( domEvt.target.contains( target ) || domEvt.target.contains( limiter ) ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would happen if For the DOM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
this.attachTo( options ); | ||
} | ||
}, { useCapture: true } ); | ||
|
||
// We need to listen on window resize event and update position. | ||
this.listenTo( global.window, 'resize', () => this.attachTo( options ) ); | ||
|
||
// After all we need to clean up the listener. | ||
this.once( 'change:isVisible', () => { | ||
this.stopListening( global.document, 'scroll' ); | ||
this.stopListening( global.window, 'resize' ); | ||
} ); | ||
} | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<div class="container-a"> | ||
<div class="container-b"> | ||
<div> | ||
<div id="editor-attach"> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p>Balloon is attached to the <strong>TARGET</strong> element.</p> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<div id="editor-stick"> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p>Balloon sticks to the <strong>TARGET</strong> element.</p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
<p></p> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<style> | ||
body { | ||
height: 100%; | ||
} | ||
|
||
.balloon-content { | ||
padding: 10px; | ||
font-size: 16px; | ||
} | ||
|
||
.ck-editor__editable { | ||
max-height: 300px; | ||
} | ||
|
||
.container-a { | ||
height: 500px; | ||
width: 750px; | ||
overflow: scroll; | ||
} | ||
|
||
.container-b { | ||
padding: 500px 30px 30px; | ||
display: flex; | ||
width: 1000px; | ||
height: 2000px; | ||
background: #e1e1e1; | ||
} | ||
|
||
.container-b > div { | ||
margin: 0 20px; | ||
} | ||
</style> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/** | ||
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
/* globals window, document, console:false */ | ||
|
||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classic'; | ||
import ArticlePresets from '@ckeditor/ckeditor5-presets/src/article'; | ||
import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview'; | ||
import View from '@ckeditor/ckeditor5-ui/src/view'; | ||
import Template from '@ckeditor/ckeditor5-ui/src/template'; | ||
|
||
// Content of the balloon panel. | ||
class BalloonContentView extends View { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. KISS. Add simple styles .ck-balloon-panel {
padding: 2em;
} and then There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
constructor() { | ||
super(); | ||
|
||
this.template = new Template( { | ||
tag: 'div', | ||
attributes: { | ||
class: 'balloon-content' | ||
}, | ||
children: [ | ||
{ | ||
text: 'Balloon' | ||
} | ||
] | ||
} ); | ||
} | ||
} | ||
|
||
// Set initial scroll of one of the container element. | ||
document.querySelector( '.container-a' ).scrollTop = 450; | ||
|
||
// Init editor with balloon attached to the target element. | ||
ClassicEditor.create( document.querySelector( '#editor-attach' ), { | ||
plugins: [ ArticlePresets ], | ||
toolbar: [ 'bold', 'italic', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
const panel = new BalloonPanelView(); | ||
|
||
panel.content.add( new BalloonContentView() ); | ||
editor.ui.view.body.add( panel ); | ||
|
||
editor.ui.view.element.querySelector( '.ck-editor__editable' ).scrollTop = 360; | ||
|
||
panel.init().then( () => { | ||
panel.attachTo( { | ||
target: editor.ui.view.element.querySelector( '.ck-editor__editable p strong' ), | ||
limiter: editor.ui.view.editableElement | ||
} ); | ||
} ); | ||
|
||
window.attachEditor = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); | ||
|
||
// Init editor with balloon sticked to the target element. | ||
ClassicEditor.create( document.querySelector( '#editor-stick' ), { | ||
plugins: [ ArticlePresets ], | ||
toolbar: [ 'bold', 'italic', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
const panel = new BalloonPanelView(); | ||
|
||
panel.content.add( new BalloonContentView() ); | ||
editor.ui.view.body.add( panel ); | ||
|
||
editor.ui.view.element.querySelector( '.ck-editor__editable' ).scrollTop = 360; | ||
|
||
panel.init().then( () => { | ||
panel.keepAttachedTo( { | ||
target: editor.ui.view.element.querySelector( '.ck-editor__editable p strong' ), | ||
limiter: editor.ui.view.editableElement | ||
} ); | ||
} ); | ||
|
||
window.stickEditor = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## BalloonPanelView `attachTo` vs `keepAttachedTo` | ||
|
||
Scroll editable elements and container (horizontally as well). Balloon in the left editor should float but balloon in the | ||
right editor should stick to the target element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full link to the issue would be safer. We had code moving between repos and such hashes became outdated more than once already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.