8
0

buttonview.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module ui/button/buttonview
  7. */
  8. import View from '../view';
  9. import Template from '../template';
  10. import IconView from '../icon/iconview';
  11. import TooltipView from '../tooltip/tooltipview';
  12. import { getEnvKeystrokeText } from '@ckeditor/ckeditor5-utils/src/keyboard';
  13. /**
  14. * The button view class.
  15. *
  16. * @extends module:ui/view~View
  17. */
  18. export default class ButtonView extends View {
  19. /**
  20. * @inheritDoc
  21. */
  22. constructor( locale ) {
  23. super( locale );
  24. /**
  25. * The label of the button view visible to the user.
  26. *
  27. * @observable
  28. * @member {String} #label
  29. */
  30. this.set( 'label' );
  31. /**
  32. * (Optional) The keystroke associated with the button, i.e. <kbd>CTRL+B</kbd>,
  33. * in the string format compatible with {@link module:utils/keyboard}.
  34. *
  35. * @observable
  36. * @member {Boolean} #keystroke
  37. */
  38. this.set( 'keystroke' );
  39. /**
  40. * (Optional) Tooltip of the button, i.e. displayed when hovering the button with the mouse cursor.
  41. *
  42. * * If defined as a `Boolean` (e.g. `true`), then combination of `label` and `keystroke` will be set as a tooltip.
  43. * * If defined as a `String`, tooltip will equal the exact text of that `String`.
  44. * * If defined as a `Function`, `label` and `keystroke` will be passed to that function, which is to return
  45. * a string with the tooltip text.
  46. *
  47. * const view = new ButtonView( locale );
  48. * view.tooltip = ( label, keystroke ) => `A tooltip for ${ label } and ${ keystroke }.`
  49. *
  50. * @observable
  51. * @default false
  52. * @member {Boolean|String|Function} #tooltip
  53. */
  54. this.set( 'tooltip' );
  55. /**
  56. * The position of the tooltip. See {@link ui/tooltip/tooltipview~TooltipView#position}
  57. * to learn more about the available position values.
  58. *
  59. * **Note:** It makes sense only when the {@link #tooltip} is active.
  60. *
  61. * @observable
  62. * @default 's'
  63. * @member {'s'|'n'} #position
  64. */
  65. this.set( 'tooltipPosition', 's' );
  66. /**
  67. * The HTML type of the button. Default `button`.
  68. *
  69. * @observable
  70. * @member {'button'|'submit'|'reset'|'menu'} #type
  71. */
  72. this.set( 'type', 'button' );
  73. /**
  74. * Controls whether the button view is "on", e.g. some feature which it represents
  75. * is currently enabled.
  76. *
  77. * @observable
  78. * @member {Boolean} #isOn
  79. */
  80. this.set( 'isOn', false );
  81. /**
  82. * Controls whether the button view is enabled (can be clicked).
  83. *
  84. * @observable
  85. * @member {Boolean} #isEnabled
  86. */
  87. this.set( 'isEnabled', true );
  88. /**
  89. * Controls whether the button view is visible.
  90. *
  91. * @observable
  92. * @member {Boolean} #isVisible
  93. */
  94. this.set( 'isVisible', true );
  95. /**
  96. * (Optional) Whether the label of the button is hidden (e.g. button with icon only).
  97. *
  98. * @observable
  99. * @member {Boolean} #withText
  100. */
  101. this.set( 'withText', false );
  102. /**
  103. * (Optional) Source of the icon. See {@link module:ui/icon/iconview~IconView#content}.
  104. *
  105. * @observable
  106. * @member {String} #icon
  107. */
  108. this.set( 'icon' );
  109. /**
  110. * Controls the `tabindex` attribute of the button.
  111. *
  112. * @observable
  113. * @default -1
  114. * @member {String} #tabindex
  115. */
  116. this.set( 'tabindex', -1 );
  117. /**
  118. * Tooltip of the button bound to the template.
  119. *
  120. * @see #tooltip
  121. * @see #_getTooltipString
  122. * @private
  123. * @observable
  124. * @member {Boolean} #_tooltipString
  125. */
  126. this.bind( '_tooltipString' ).to(
  127. this, 'tooltip',
  128. this, 'label',
  129. this, 'keystroke',
  130. this._getTooltipString.bind( this )
  131. );
  132. /**
  133. * Icon of the button view.
  134. *
  135. * @readonly
  136. * @member {module:ui/icon/iconview~IconView} #iconView
  137. */
  138. /**
  139. * Tooltip of the button view.
  140. *
  141. * @readonly
  142. * @member {module:ui/tooltip/tooltipview~TooltipView} #tooltipView
  143. */
  144. const bind = this.bindTemplate;
  145. this.template = new Template( {
  146. tag: 'button',
  147. attributes: {
  148. class: [
  149. 'ck-button',
  150. bind.to( 'isEnabled', value => value ? 'ck-enabled' : 'ck-disabled' ),
  151. bind.if( 'isVisible', 'ck-hidden', value => !value ),
  152. bind.to( 'isOn', value => value ? 'ck-on' : 'ck-off' ),
  153. bind.if( 'withText', 'ck-button_with-text' )
  154. ],
  155. type: bind.to( 'type', value => value ? value : 'button' ),
  156. tabindex: bind.to( 'tabindex' )
  157. },
  158. children: [
  159. {
  160. tag: 'span',
  161. attributes: {
  162. class: [ 'ck-button__label' ]
  163. },
  164. children: [
  165. {
  166. text: bind.to( 'label' )
  167. }
  168. ]
  169. }
  170. ],
  171. on: {
  172. mousedown: bind.to( evt => {
  173. evt.preventDefault();
  174. } ),
  175. click: bind.to( evt => {
  176. // We can't make the button disabled using the disabled attribute, because it won't be focusable.
  177. // Though, shouldn't this condition be moved to the button controller?
  178. if ( this.isEnabled ) {
  179. this.fire( 'execute' );
  180. } else {
  181. // Prevent the default when button is disabled, to block e.g.
  182. // automatic form submitting. See ckeditor/ckeditor5-link#74.
  183. evt.preventDefault();
  184. }
  185. } )
  186. }
  187. } );
  188. /**
  189. * Fired when the button view is clicked. It won't be fired when the button is disabled.
  190. *
  191. * @event #execute
  192. */
  193. }
  194. /**
  195. * @inheritDoc
  196. */
  197. init() {
  198. if ( this.icon ) {
  199. const iconView = this.iconView = new IconView();
  200. iconView.bind( 'content' ).to( this, 'icon' );
  201. this.element.insertBefore( iconView.element, this.element.firstChild );
  202. // Make sure the icon will be destroyed along with the button.
  203. this.addChildren( iconView );
  204. }
  205. if ( this.tooltip ) {
  206. const tooltipView = this.tooltipView = new TooltipView();
  207. tooltipView.bind( 'text' ).to( this, '_tooltipString' );
  208. tooltipView.bind( 'position' ).to( this, 'tooltipPosition' );
  209. this.element.appendChild( tooltipView.element );
  210. // Make sure the tooltip will be destroyed along with the button.
  211. this.addChildren( tooltipView );
  212. }
  213. super.init();
  214. }
  215. /**
  216. * Focuses the button.
  217. */
  218. focus() {
  219. this.element.focus();
  220. }
  221. /**
  222. * Gets the text for the {@link #tooltipView} from the combination of
  223. * {@link #tooltip}, {@link #label} and {@link #keystroke} attributes.
  224. *
  225. * @private
  226. * @see #tooltip
  227. * @see #_tooltipString
  228. * @param {Boolean|String|Function} tooltip Button tooltip.
  229. * @param {String} label Button label.
  230. * @param {String} keystroke Button keystroke.
  231. * @returns {String}
  232. */
  233. _getTooltipString( tooltip, label, keystroke ) {
  234. if ( tooltip ) {
  235. if ( typeof tooltip == 'string' ) {
  236. return tooltip;
  237. } else {
  238. if ( keystroke ) {
  239. keystroke = getEnvKeystrokeText( keystroke );
  240. }
  241. if ( tooltip instanceof Function ) {
  242. return tooltip( label, keystroke );
  243. } else if ( tooltip === true ) {
  244. return `${ label }${ keystroke ? ` (${ keystroke })` : '' }`;
  245. }
  246. }
  247. }
  248. return false;
  249. }
  250. }