Procházet zdrojové kódy

Removed #title from ButtonView. Replaced by #tooltip with possible
Boolean, String or Function data type.

Bound tooltip–specific ButtonView class to the presence of

Enabled new ButtonView tooltip API in createDropdown helper.

Aleksander Nowodzinski před 9 roky
rodič
revize
ab7f18ea0a

+ 39 - 20
packages/ckeditor5-ui/src/button/buttonview.js

@@ -43,14 +43,21 @@ export default class ButtonView extends View {
 		this.set( 'keystroke' );
 
 		/**
-		 * (Optional) Title of the button displayed in the tooltip, i.e. when
-		 * hovering the button with the mouse cursor. When `title` property is not defined
-		 * then combination of `label` and `keystroke` will be set as title.
+		 * (Optional) Tooltip of the button, i.e. displayed when hovering the button with the mouse cursor.
+		 *
+		 *   * If defined as a `Boolean` (e.g. `true`), then combination of `label` and `keystroke` will be set as tooltip.
+		 *   * If defined as a `String`, tooltip will equal the exact text of that `String`.
+		 *   * If defined as a `Function`, `label` and `keystroke` will be passed to that function, which is to return
+		 *     a string with the tooltip text.
+		 *
+		 *		const view = new ButtonView( locale );
+		 *		view.tooltip = ( label, keystroke ) => `A tooltip for ${ label } and ${ keystroke }.`
 		 *
 		 * @observable
-		 * @member {Boolean} #title
+		 * @see #_tooltipString
+		 * @member {Boolean|String|Function} #tooltip
 		 */
-		this.set( 'title' );
+		this.set( 'tooltip' );
 
 		/**
 		 * The HTML type of the button. Default `button`.
@@ -94,14 +101,15 @@ export default class ButtonView extends View {
 		this.set( 'icon' );
 
 		/**
-		 * Title of the button bound to the template.
+		 * Tooltip of the button bound to the template.
 		 *
-		 * @see #title
+		 * @see #tooltip
+		 * @see #_getTooltipString
 		 * @private
 		 * @observable
-		 * @member {Boolean} #_tooltip
+		 * @member {Boolean} #_tooltipString
 		 */
-		this.bind( '_tooltip' ).to( this, 'title', this, 'label', this, 'keystroke', this._getTooltip.bind( this ) );
+		this.bind( '_tooltipString' ).to( this, 'tooltip', this, 'label', this, 'keystroke', this._getTooltipString.bind( this ) );
 
 		/**
 		 * Icon of the button view.
@@ -118,14 +126,14 @@ export default class ButtonView extends View {
 			attributes: {
 				class: [
 					'ck-button',
-					'ck-tooltip_s',
+					bind.if( '_tooltipString', 'ck-tooltip_s' ),
 					bind.to( 'isEnabled', value => value ? 'ck-enabled' : 'ck-disabled' ),
 					bind.to( 'isOn', value => value ? 'ck-on' : 'ck-off' ),
 					bind.if( 'withText', 'ck-button_with-text' )
 				],
 				type: bind.to( 'type', value => value ? value : 'button' ),
 				'data-ck-tooltip': [
-					bind.to( '_tooltip' )
+					bind.to( '_tooltipString' )
 				]
 			},
 
@@ -192,23 +200,34 @@ export default class ButtonView extends View {
 	}
 
 	/**
-	 * Gets value for the `data-ck-tooltip` attribute from title, label and keystroke properties.
+	 * Gets value for the `data-ck-tooltip` attribute from the combination of
+	 * {@link #tooltip}, {@link #label} and {@link #keystroke} attributes.
 	 *
 	 * @private
-	 * @param {String} title Button title.
+	 * @see #tooltip
+	 * @see #_tooltipString
+	 * @param {Boolean|String|Function} tooltip Button tooltip.
 	 * @param {String} label Button label.
 	 * @param {String} keystroke Button keystroke.
 	 * @returns {String}
 	 */
-	_getTooltip( title, label, keystroke ) {
-		if ( title ) {
-			return title;
-		}
+	_getTooltipString( tooltip, label, keystroke ) {
+		if ( tooltip ) {
+			if ( typeof tooltip === 'string' ) {
+				return tooltip;
+			} else {
+				if ( keystroke ) {
+					keystroke = getEnvKeystrokeText( keystroke );
+				}
 
-		if ( keystroke ) {
-			label += ` (${ getEnvKeystrokeText( keystroke ) })`;
+				if ( tooltip instanceof Function ) {
+					return tooltip( label, keystroke );
+				} else if ( tooltip === true ) {
+					return `${ label }${ keystroke ? ` (${ keystroke })` : '' }`;
+				}
+			}
 		}
 
-		return label;
+		return false;
 	}
 }

+ 1 - 1
packages/ckeditor5-ui/src/dropdown/createdropdown.js

@@ -21,7 +21,7 @@ import DropdownPanelView from './dropdownpanelview';
  */
 export default function createDropdown( model, locale ) {
 	const buttonView = new ButtonView( locale );
-	buttonView.bind( 'label', 'isOn', 'isEnabled', 'withText', 'keystroke' ).to( model );
+	buttonView.bind( 'label', 'isOn', 'isEnabled', 'withText', 'keystroke', 'tooltip' ).to( model );
 
 	const panelView = new DropdownPanelView( locale );
 

+ 76 - 13
packages/ckeditor5-ui/tests/button/buttonview.js

@@ -23,10 +23,9 @@ describe( 'ButtonView', () => {
 	describe( '<button> bindings', () => {
 		describe( 'class', () => {
 			it( 'is set initially', () => {
-				expect( view.element.classList ).to.have.length( 4 );
+				expect( view.element.classList ).to.have.length( 3 );
 				expect( view.element.classList.contains( 'ck-button' ) ).to.true;
 				expect( view.element.classList.contains( 'ck-off' ) ).to.true;
-				expect( view.element.classList.contains( 'ck-tooltip_s' ) ).to.true;
 			} );
 
 			it( 'reacts on view#isEnabled', () => {
@@ -67,29 +66,93 @@ describe( 'ButtonView', () => {
 		} );
 
 		describe( 'tooltip', () => {
-			it( 'is not initially set ', () => {
+			it( 'is not initially set', () => {
 				expect( view.element.dataset.ckTooltip ).to.undefined;
 			} );
 
-			it( 'is always equal to view#title if is defined', () => {
-				view.title = 'bar';
+			it( 'is not initially set (despite #label and #keystroke)', () => {
 				view.label = 'foo';
 				view.keystroke = 'A';
 
-				expect( view.element.dataset.ckTooltip ).to.equal( 'bar' );
+				expect( view.element.dataset.ckTooltip ).to.undefined;
 			} );
 
-			it( 'is equal to view#label when view#title is not defined', () => {
-				view.label = 'bar';
+			it( 'is not set if neither `true`, String or Function', () => {
+				view.label = 'foo';
+				view.keystroke = 'A';
+				view.tooltip = false;
+
+				expect( view.element.dataset.ckTooltip ).to.undefined;
+
+				view.tooltip = 3;
+				expect( view.element.dataset.ckTooltip ).to.undefined;
 
-				expect( view.element.dataset.ckTooltip ).to.equal( 'bar' );
+				view.tooltip = new Date();
+				expect( view.element.dataset.ckTooltip ).to.undefined;
 			} );
 
-			it( 'contains keystroke when view#label and view#keystroke is defined', () => {
-				view.label = 'bar';
-				view.keystroke = 'A';
+			describe( 'defined as a Boolean', () => {
+				it( 'renders tooltip text out of #label and #keystroke', () => {
+					view.tooltip = true;
+					view.label = 'bar';
+					view.keystroke = 'A';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'bar (A)' );
+				} );
+
+				it( 'reacts to changes in #label and #keystroke', () => {
+					view.tooltip = true;
+					view.label = 'foo';
+					view.keystroke = 'B';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'foo (B)' );
+
+					view.label = 'baz';
+					view.keystroke = false;
 
-				expect( view.element.dataset.ckTooltip ).to.equal( 'bar (A)' );
+					expect( view.element.dataset.ckTooltip ).to.equal( 'baz' );
+				} );
+			} );
+
+			describe( 'defined as a String', () => {
+				it( 'renders as a plain text', () => {
+					view.tooltip = 'bar';
+					view.label = 'foo';
+					view.keystroke = 'A';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'bar' );
+				} );
+
+				it( 'reacts to changes of #tooltip', () => {
+					view.tooltip = 'bar';
+					expect( view.element.dataset.ckTooltip ).to.equal( 'bar' );
+
+					view.tooltip = 'foo';
+					expect( view.element.dataset.ckTooltip ).to.equal( 'foo' );
+				} );
+			} );
+
+			describe( 'defined as a Function', () => {
+				it( 'generates a tooltip text when passed #label and #keystroke', () => {
+					view.tooltip = ( l, k ) => `${ l } - ${ k }`;
+					view.label = 'foo';
+					view.keystroke = 'A';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'foo - A' );
+				} );
+
+				it( 'reacts to changes of #label and #keystroke', () => {
+					view.tooltip = ( l, k ) => `${ l } - ${ k }`;
+					view.label = 'foo';
+					view.keystroke = 'A';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'foo - A' );
+
+					view.label = 'bar';
+					view.keystroke = 'B';
+
+					expect( view.element.dataset.ckTooltip ).to.equal( 'bar - B' );
+				} );
 			} );
 		} );
 

+ 4 - 3
packages/ckeditor5-ui/tests/dropdown/createdropdown.js

@@ -18,7 +18,8 @@ describe( 'createDropdown', () => {
 			label: 'foo',
 			isOn: false,
 			isEnabled: true,
-			withText: false
+			withText: false,
+			tooltip: false
 		};
 
 		const model = new Model( modelDef );
@@ -27,9 +28,9 @@ describe( 'createDropdown', () => {
 		assertBinding( view.buttonView,
 			modelDef,
 			[
-				[ model, { label: 'bar', isOn: true, isEnabled: false, withText: true } ]
+				[ model, { label: 'bar', isOn: true, isEnabled: false, withText: true, tooltip: true } ]
 			],
-			{ label: 'bar', isOn: true, isEnabled: false, withText: true }
+			{ label: 'bar', isOn: true, isEnabled: false, withText: true, tooltip: true }
 		);
 	} );