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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. * Indicates the position of the tooltip.
  43. */
  44. tooltipPosition:
  45. React.PropTypes.oneOf([ 'bottom', 'left', 'right', 'top' ])
  46. };
  47. /**
  48. * Initializes new ToolbarButton instance.
  49. *
  50. * @param {Object} props - The read-only properties with which the new
  51. * instance is to be initialized.
  52. */
  53. constructor(props: Object) {
  54. super(props);
  55. // Bind methods to save the context
  56. this._createRefToButton = this._createRefToButton.bind(this);
  57. this._onClick = this._onClick.bind(this);
  58. }
  59. /**
  60. * Sets shortcut/tooltip
  61. * after mounting of the component.
  62. *
  63. * @inheritdoc
  64. * @returns {void}
  65. */
  66. componentDidMount(): void {
  67. this._setShortcutAndTooltip();
  68. if (this.props.onMount) {
  69. this.props.onMount();
  70. }
  71. }
  72. /**
  73. * Invokes on unmount handler if it was passed to the props.
  74. *
  75. * @inheritdoc
  76. * @returns {void}
  77. */
  78. componentWillUnmount(): void {
  79. if (this.props.onUnmount) {
  80. this.props.onUnmount();
  81. }
  82. }
  83. /**
  84. * Implements React's {@link Component#render()}.
  85. *
  86. * @inheritdoc
  87. * @returns {ReactElement}
  88. */
  89. render(): ReactElement<*> {
  90. const { button } = this.props;
  91. const attributes = getButtonAttributesByProps(button);
  92. const popups = button.popups || [];
  93. return (
  94. <a
  95. { ...attributes }
  96. onClick = { this._onClick }
  97. ref = { this._createRefToButton }>
  98. { this._renderInnerElementsIfRequired() }
  99. { this._renderPopups(popups) }
  100. </a>
  101. );
  102. }
  103. /**
  104. * Creates reference to current toolbar button.
  105. *
  106. * @param {HTMLElement} element - HTMLElement representing the toolbar
  107. * button.
  108. * @returns {void}
  109. * @private
  110. */
  111. _createRefToButton(element: HTMLElement): void {
  112. this.button = element;
  113. }
  114. /**
  115. * Wrapper on on click handler props for current button.
  116. *
  117. * @param {Event} event - Click event object.
  118. * @returns {void}
  119. * @private
  120. */
  121. _onClick(event: Event): void {
  122. const {
  123. button,
  124. onClick
  125. } = this.props;
  126. const {
  127. enabled,
  128. unclickable
  129. } = button;
  130. if (enabled && !unclickable && onClick) {
  131. onClick(event);
  132. }
  133. }
  134. /**
  135. * If toolbar button should contain children elements
  136. * renders them.
  137. *
  138. * @returns {ReactElement|null}
  139. * @private
  140. */
  141. _renderInnerElementsIfRequired(): ReactElement<*> | null {
  142. if (this.props.button.html) {
  143. return this.props.button.html;
  144. }
  145. return null;
  146. }
  147. /**
  148. * Renders popup element for toolbar button.
  149. *
  150. * @param {Array} popups - Array of popup objects.
  151. * @returns {Array}
  152. * @private
  153. */
  154. _renderPopups(popups: Array<*> = []): Array<*> {
  155. return popups.map(popup => {
  156. let gravity = 'n';
  157. if (popup.dataAttrPosition) {
  158. gravity = popup.dataAttrPosition;
  159. }
  160. const title = this.props.t(popup.dataAttr, popup.dataInterpolate);
  161. return (
  162. <div
  163. className = { popup.className }
  164. data-popup = { gravity }
  165. id = { popup.id }
  166. key = { popup.id }
  167. title = { title } />
  168. );
  169. });
  170. }
  171. /**
  172. * Sets shortcut and tooltip for current toolbar button.
  173. *
  174. * @private
  175. * @returns {void}
  176. */
  177. _setShortcutAndTooltip(): void {
  178. const { button, tooltipPosition } = this.props;
  179. const name = button.buttonName;
  180. if (UIUtil.isButtonEnabled(name)) {
  181. if (!button.unclickable) {
  182. UIUtil.setTooltip(this.button,
  183. button.tooltipKey,
  184. tooltipPosition);
  185. }
  186. if (button.shortcut) {
  187. APP.keyboardshortcut.registerShortcut(
  188. button.shortcut,
  189. button.shortcutAttr,
  190. button.shortcutFunc,
  191. button.shortcutDescription
  192. );
  193. }
  194. }
  195. }
  196. }
  197. export default translate(ToolbarButton);