ソースを参照

Extracted ImageBalloonPanel.

Szymon Kupś 9 年 前
コミット
3888aba4d3

+ 30 - 92
packages/ckeditor5-image/src/image.js

@@ -11,42 +11,15 @@ import Plugin from 'ckeditor5-core/src/plugin';
 import ImageEngine from './imageengine';
 import Widget from './widget/widget';
 import ButtonView from 'ckeditor5-ui/src/button/buttonview';
-import BalloonPanelView from 'ckeditor5-ui/src/balloonpanel/balloonpanelview';
-import global from 'ckeditor5-utils/src/dom/global';
 import { isImageWidget } from './utils';
-import throttle from 'ckeditor5-utils/src/lib/lodash/throttle';
 import AlternateTextFormView from 'ckeditor5-image/src/ui/alternatetextformview';
 import clickOutsideHandler from 'ckeditor5-ui/src/bindings/clickoutsidehandler';
 import escPressHandler from 'ckeditor5-ui/src/bindings/escpresshandler';
-import alternateTextIcon from 'ckeditor5-core/theme/icons/source.svg';
+import ImageBalloonPanel from './ui/imageballoonpanel';
 
+import alternateTextIcon from 'ckeditor5-core/theme/icons/source.svg';
 import '../theme/theme.scss';
 
-const arrowVOffset = BalloonPanelView.arrowVerticalOffset;
-const positions = {
-	//	   [text range]
-	//	        ^
-	//	+-----------------+
-	//	|     Balloon     |
-	//	+-----------------+
-	south: ( targetRect, balloonRect ) => ( {
-		top: targetRect.bottom + arrowVOffset,
-		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
-		name: 's'
-	} ),
-
-	//	+-----------------+
-	//	|     Balloon     |
-	//	+-----------------+
-	//	        V
-	//	   [text range]
-	north: ( targetRect, balloonRect ) => ( {
-		top: targetRect.top - balloonRect.height - arrowVOffset,
-		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
-		name: 'n'
-	} )
-};
-
 /**
  * The image plugin.
  *
@@ -100,65 +73,38 @@ export default class Image extends Plugin {
 
 	_createAlternateTextBalloonPanel() {
 		const editor = this.editor;
-		const panel = this._alternateTextBalloonPanel = new BalloonPanelView( this.editor.locale );
-		panel.maxWidth = 300;
-
-		const editingView = editor.editing.view;
-		this._attachBalloonPanel = throttle( attachBalloonPanel, 100 );
-
-		return editor.ui.view.body.add( panel ).then( () => {
-			// Let the focusTracker know about new focusable UI element.
-			editor.ui.focusTracker.add( panel.element );
 
-			// Hide the panel when editor loses focus but no the other way around.
-			panel.listenTo( editor.ui.focusTracker, 'change:isFocused', ( evt, name, is, was ) => {
-				if ( was && !is ) {
-					panel.hide();
-				}
-			} );
-
-			// Hide toolbar when is no longer needed.
-			editor.listenTo( editingView, 'render', () => {
-				const selectedElement = editingView.selection.getSelectedElement();
-
-				if ( !selectedElement || !isImageWidget( selectedElement ) ) {
-					this._hideAlternateTextChangePanel();
-				}
-			}, { priority: 'low' } );
-
-			const form = this._alternateTextForm = new AlternateTextFormView( editor.locale );
-
-			this.listenTo( form, 'submit', () => {
-				editor.execute( 'imageAlternateText', form.alternateTextInput.value );
-				this._hideAlternateTextChangePanel();
-			} );
+		const panel = new ImageBalloonPanel( editor );
+		const form = this._alternateTextForm = new AlternateTextFormView( editor.locale );
 
-			this.listenTo( form, 'cancel', () => this._hideAlternateTextChangePanel() );
+		this.listenTo( form, 'submit', () => {
+			editor.execute( 'imageAlternateText', form.alternateTextInput.value );
+			this._hideAlternateTextChangePanel();
+		} );
 
-			// Close on `ESC` press.
-			escPressHandler( {
-				emitter: panel,
-				activator: () => panel.isVisible,
-				callback: () => this._hideAlternateTextChangePanel()
-			} );
+		this.listenTo( form, 'cancel', () => this._hideAlternateTextChangePanel() );
 
-			// Close on click outside of balloon panel element.
-			clickOutsideHandler( {
-				emitter: panel,
-				activator: () => panel.isVisible,
-				contextElement: panel.element,
-				callback: () => this._hideAlternateTextChangePanel()
-			} );
+		// Close on `ESC` press.
+		escPressHandler( {
+			emitter: panel,
+			activator: () => panel.isVisible,
+			callback: () => this._hideAlternateTextChangePanel()
+		} );
 
-			return panel.content.add( this._alternateTextForm );
+		// Close on click outside of balloon panel element.
+		clickOutsideHandler( {
+			emitter: panel,
+			activator: () => panel.isVisible,
+			contextElement: panel.element,
+			callback: () => this._hideAlternateTextChangePanel()
 		} );
 
-		function attachBalloonPanel() {
-			panel.attachTo( {
-				target: editingView.domConverter.viewRangeToDom( editingView.selection.getFirstRange() ),
-				positions: [ positions.north, positions.south ]
-			} );
-		}
+		this.panel = panel;
+
+		return Promise.all( [
+			panel.content.add( this._alternateTextForm ),
+			editor.ui.view.body.add( panel )
+		] );
 	}
 
 	_showAlternateTextChangePanel() {
@@ -171,21 +117,13 @@ export default class Image extends Plugin {
 
 			this._alternateTextForm.alternateTextInput.value = command.value || '';
 
-			this._attachBalloonPanel();
 			this._alternateTextForm.alternateTextInput.select();
-
-			editor.ui.view.listenTo( global.window, 'scroll', this._attachBalloonPanel );
-			editor.ui.view.listenTo( global.window, 'resize', this._attachBalloonPanel );
+			this.panel.attach();
 		}
 	}
 
 	_hideAlternateTextChangePanel() {
-		const editor = this.editor;
-
-		this._alternateTextBalloonPanel.hide();
-		editor.editing.view.focus();
-
-		editor.ui.view.stopListening( global.window, 'scroll', this._attachBalloonPanel );
-		editor.ui.view.stopListening( global.window, 'resize', this._attachBalloonPanel );
+		this.panel.hide();
+		this.editor.editing.view.focus();
 	}
 }

+ 17 - 85
packages/ckeditor5-image/src/imagetoolbar.js

@@ -9,37 +9,8 @@
 
 import Plugin from 'ckeditor5-core/src/plugin';
 import ToolbarView from 'ckeditor5-ui/src/toolbar/toolbarview';
-import BalloonPanelView from 'ckeditor5-ui/src/balloonpanel/balloonpanelview';
-import Template from 'ckeditor5-ui/src/template';
 import { isImageWidget } from './utils';
-import throttle from 'ckeditor5-utils/src/lib/lodash/throttle';
-import global from 'ckeditor5-utils/src/dom/global';
-
-const arrowVOffset = BalloonPanelView.arrowVerticalOffset;
-const positions = {
-	//	   [text range]
-	//	        ^
-	//	+-----------------+
-	//	|     Balloon     |
-	//	+-----------------+
-	south: ( targetRect, balloonRect ) => ( {
-		top: targetRect.bottom + arrowVOffset,
-		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
-		name: 's'
-	} ),
-
-	//	+-----------------+
-	//	|     Balloon     |
-	//	+-----------------+
-	//	        V
-	//	   [text range]
-	north: ( targetRect, balloonRect ) => ( {
-		top: targetRect.top - balloonRect.height - arrowVOffset,
-		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
-		name: 'n'
-	} )
-};
-
+import ImageBalloonPanel from './ui/imageballoonpanel';
 /**
  * Image toolbar class. Creates image toolbar placed inside balloon panel that is showed when image widget is selected.
  * Toolbar components are created using editor's {@link module:ui/componentfactory~ComponentFactory ComponentFactory}
@@ -60,68 +31,29 @@ export default class ImageToolbar extends Plugin {
 			return;
 		}
 
-		// Create a plain toolbar instance.
+		const panel = new ImageBalloonPanel( editor );
+		const promises = [];
 		const toolbar = new ToolbarView();
-
-		// Create a BalloonPanelView instance.
-		const panel = new BalloonPanelView( editor.locale );
-
-		Template.extend( panel.template, {
-			attributes: {
-				class: [
-					'ck-toolbar__container',
-				]
-			}
-		} );
-
-		// Putting the toolbar inside of the balloon panel.
 		panel.content.add( toolbar );
 
-		return editor.ui.view.body.add( panel ).then( () => {
-			const editingView = editor.editing.view;
-			const promises = [];
-
-			for ( let name of toolbarConfig ) {
-				promises.push( toolbar.items.add( editor.ui.componentFactory.create( name ) ) );
-			}
-
-			// Let the focusTracker know about new focusable UI element.
-			editor.ui.focusTracker.add( panel.element );
-
-			// Hide the panel when editor loses focus but no the other way around.
-			panel.listenTo( editor.ui.focusTracker, 'change:isFocused', ( evt, name, is, was ) => {
-				if ( was && !is ) {
-					panel.hide();
-				}
-			} );
-
-			const attachToolbarCallback = throttle( attachToolbar, 100 );
-
-			// Check if the toolbar should be displayed each time view is rendered.
-			editor.listenTo( editingView, 'render', () => {
-				const selectedElement = editingView.selection.getSelectedElement();
-
-				if ( selectedElement && isImageWidget( selectedElement ) ) {
-					attachToolbar();
+		// Add buttons to the toolbar.
+		for ( let name of toolbarConfig ) {
+			promises.push( toolbar.items.add( editor.ui.componentFactory.create( name ) ) );
+		}
 
-					editor.ui.view.listenTo( global.window, 'scroll', attachToolbarCallback );
-					editor.ui.view.listenTo( global.window, 'resize', attachToolbarCallback );
-				} else {
-					panel.hide();
+		// Add toolbar to editor's UI.
+		promises.push( editor.ui.view.body.add( panel ) );
 
-					editor.ui.view.stopListening( global.window, 'scroll', attachToolbarCallback );
-					editor.ui.view.stopListening( global.window, 'resize', attachToolbarCallback );
-				}
-			}, { priority: 'low' } );
+		// Show toolbar each time image widget is selected.
+		const editingView = editor.editing.view;
+		editor.listenTo( editingView, 'render', () => {
+			const selectedElement = editingView.selection.getSelectedElement();
 
-			function attachToolbar() {
-				panel.attachTo( {
-					target: editingView.domConverter.viewRangeToDom( editingView.selection.getFirstRange() ),
-					positions: [ positions.north, positions.south ]
-				} );
+			if ( selectedElement && isImageWidget( selectedElement ) ) {
+				panel.attach();
 			}
-
-			return Promise.all( promises );
 		} );
+
+		return Promise.all( promises );
 	}
 }

+ 103 - 0
packages/ckeditor5-image/src/ui/imageballoonpanel.js

@@ -0,0 +1,103 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module image/ui/imageballoonpanel
+ */
+
+import Template from 'ckeditor5-ui/src/template';
+import throttle from 'ckeditor5-utils/src/lib/lodash/throttle';
+import global from 'ckeditor5-utils/src/dom/global';
+import BalloonPanelView from 'ckeditor5-ui/src/balloonpanel/balloonpanelview';
+import { isImageWidget } from '../utils';
+
+const arrowVOffset = BalloonPanelView.arrowVerticalOffset;
+const positions = {
+	//	   [text range]
+	//	        ^
+	//	+-----------------+
+	//	|     Balloon     |
+	//	+-----------------+
+	south: ( targetRect, balloonRect ) => ( {
+		top: targetRect.bottom + arrowVOffset,
+		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
+		name: 's'
+	} ),
+
+	//	+-----------------+
+	//	|     Balloon     |
+	//	+-----------------+
+	//	        V
+	//	   [text range]
+	north: ( targetRect, balloonRect ) => ( {
+		top: targetRect.top - balloonRect.height - arrowVOffset,
+		left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
+		name: 'n'
+	} )
+};
+
+export default class ImageBalloonPanel extends BalloonPanelView {
+	constructor( editor ) {
+		super( editor.locale );
+
+		this.editor = editor;
+		const editingView = editor.editing.view;
+
+		Template.extend( this.template, {
+			attributes: {
+				class: [
+					'ck-toolbar__container',
+				]
+			}
+		} );
+
+		// Let the focusTracker know about new focusable UI element.
+		editor.ui.focusTracker.add( this.element );
+
+		// Hide the panel when editor loses focus but no the other way around.
+		this.listenTo( editor.ui.focusTracker, 'change:isFocused', ( evt, name, is, was ) => {
+			if ( was && !is ) {
+				this.hide();
+			}
+		} );
+
+		// Check if the toolbar should be displayed each time view is rendered.
+		editor.listenTo( editingView, 'render', () => {
+			const selectedElement = editingView.selection.getSelectedElement();
+
+			if ( !selectedElement || !isImageWidget( selectedElement ) ) {
+				this.hide();
+			}
+		}, { priority: 'low' } );
+
+		this._throttledAttach = throttle( () => {
+			this._attach();
+		}, 100 );
+	}
+
+	attach() {
+		super.show();
+
+		this._attach();
+		this.editor.ui.view.listenTo( global.window, 'scroll', this._throttledAttach );
+		this.editor.ui.view.listenTo( global.window, 'resize', this._throttledAttach );
+	}
+
+	hide() {
+		super.hide();
+
+		this.editor.ui.view.stopListening( global.window, 'scroll', this._throttledAttach );
+		this.editor.ui.view.stopListening( global.window, 'resize', this._throttledAttach );
+	}
+
+	_attach() {
+		const editingView = this.editor.editing.view;
+
+		this.attachTo( {
+			target: editingView.domConverter.viewRangeToDom( editingView.selection.getFirstRange() ),
+			positions: [ positions.north, positions.south ]
+		} );
+	}
+}