You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ToolbarButton.web.js 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* @flow */
  2. import React from 'react';
  3. import { translate } from '../../base/i18n';
  4. import UIUtil from '../../../../modules/UI/util/UIUtil';
  5. import AbstractToolbarButton from './AbstractToolbarButton';
  6. import { getButtonAttributesByProps } from '../functions';
  7. declare var APP: Object;
  8. declare var interfaceConfig: Object;
  9. /**
  10. * Represents a button in Toolbar on React.
  11. *
  12. * @class ToolbarButton
  13. * @extends AbstractToolbarButton
  14. */
  15. class ToolbarButton extends AbstractToolbarButton {
  16. _createRefToButton: Function;
  17. _onClick: Function;
  18. /**
  19. * Toolbar button component's property types.
  20. *
  21. * @static
  22. */
  23. static propTypes = {
  24. ...AbstractToolbarButton.propTypes,
  25. /**
  26. * Object describing button.
  27. */
  28. button: React.PropTypes.object.isRequired,
  29. /**
  30. * Handler for component mount.
  31. */
  32. onMount: React.PropTypes.func,
  33. /**
  34. * Handler for component unmount.
  35. */
  36. onUnmount: React.PropTypes.func,
  37. /**
  38. * Translation helper function.
  39. */
  40. t: React.PropTypes.func
  41. };
  42. /**
  43. * Initializes new ToolbarButton instance.
  44. *
  45. * @param {Object} props - The read-only properties with which the new
  46. * instance is to be initialized.
  47. */
  48. constructor(props: Object) {
  49. super(props);
  50. // Bind methods to save the context
  51. this._createRefToButton = this._createRefToButton.bind(this);
  52. this._onClick = this._onClick.bind(this);
  53. }
  54. /**
  55. * Sets shortcut/tooltip
  56. * after mounting of the component.
  57. *
  58. * @inheritdoc
  59. * @returns {void}
  60. */
  61. componentDidMount(): void {
  62. this._setShortcutAndTooltip();
  63. if (this.props.onMount) {
  64. this.props.onMount();
  65. }
  66. }
  67. /**
  68. * Invokes on unmount handler if it was passed to the props.
  69. *
  70. * @inheritdoc
  71. * @returns {void}
  72. */
  73. componentWillUnmount(): void {
  74. if (this.props.onUnmount) {
  75. this.props.onUnmount();
  76. }
  77. }
  78. /**
  79. * Implements React's {@link Component#render()}.
  80. *
  81. * @inheritdoc
  82. * @returns {ReactElement}
  83. */
  84. render(): ReactElement<*> {
  85. const { button } = this.props;
  86. const attributes = getButtonAttributesByProps(button);
  87. const popups = button.popups || [];
  88. return (
  89. <a
  90. { ...attributes }
  91. onClick = { this._onClick }
  92. ref = { this._createRefToButton }>
  93. { this._renderInnerElementsIfRequired() }
  94. { this._renderPopups(popups) }
  95. </a>
  96. );
  97. }
  98. /**
  99. * Creates reference to current toolbar button.
  100. *
  101. * @param {HTMLElement} element - HTMLElement representing the toolbar
  102. * button.
  103. * @returns {void}
  104. * @private
  105. */
  106. _createRefToButton(element: HTMLElement): void {
  107. this.button = element;
  108. }
  109. /**
  110. * Wrapper on on click handler props for current button.
  111. *
  112. * @param {Event} event - Click event object.
  113. * @returns {void}
  114. * @private
  115. */
  116. _onClick(event: Event): void {
  117. const {
  118. button,
  119. onClick
  120. } = this.props;
  121. const {
  122. enabled,
  123. unclickable
  124. } = button;
  125. if (enabled && !unclickable && onClick) {
  126. onClick(event);
  127. }
  128. }
  129. /**
  130. * If toolbar button should contain children elements
  131. * renders them.
  132. *
  133. * @returns {ReactElement|null}
  134. * @private
  135. */
  136. _renderInnerElementsIfRequired(): ReactElement<*> | null {
  137. if (this.props.button.html) {
  138. return this.props.button.html;
  139. }
  140. return null;
  141. }
  142. /**
  143. * Renders popup element for toolbar button.
  144. *
  145. * @param {Array} popups - Array of popup objects.
  146. * @returns {Array}
  147. * @private
  148. */
  149. _renderPopups(popups: Array<*> = []): Array<*> {
  150. return popups.map(popup => {
  151. let gravity = 'n';
  152. if (popup.dataAttrPosition) {
  153. gravity = popup.dataAttrPosition;
  154. }
  155. const title = this.props.t(popup.dataAttr);
  156. return (
  157. <div
  158. className = { popup.className }
  159. data-popup = { gravity }
  160. id = { popup.id }
  161. key = { popup.id }
  162. title = { title } />
  163. );
  164. });
  165. }
  166. /**
  167. * Sets shortcut and tooltip for current toolbar button.
  168. *
  169. * @private
  170. * @returns {void}
  171. */
  172. _setShortcutAndTooltip(): void {
  173. const { button } = this.props;
  174. const name = button.buttonName;
  175. if (UIUtil.isButtonEnabled(name)) {
  176. const tooltipPosition
  177. = interfaceConfig.MAIN_TOOLBAR_BUTTONS.indexOf(name) > -1
  178. ? 'bottom' : 'right';
  179. if (!button.unclickable) {
  180. UIUtil.setTooltip(this.button,
  181. button.tooltipKey,
  182. tooltipPosition);
  183. }
  184. if (button.shortcut) {
  185. APP.keyboardshortcut.registerShortcut(
  186. button.shortcut,
  187. button.shortcutAttr,
  188. button.shortcutFunc,
  189. button.shortcutDescription
  190. );
  191. }
  192. }
  193. }
  194. }
  195. export default translate(ToolbarButton);