Home Reference Source

application/components/common/rich-editor/media-resize.js

  1. import React from 'react';
  2. import LoadingIndicator from './../loading-indicator';
  3. import {ResizableBox} from 'react-resizable';
  4. import RaisedButton from 'material-ui/RaisedButton';
  5. import BaseView from './../../base-view';
  6.  
  7. /**
  8. * MediaResize component handles the draggable
  9. * resizing of media blocks. This does not update media
  10. * block meta, but sends the data to a callback.
  11. */
  12. class MediaResize extends BaseView {
  13.  
  14. constructor(props) {
  15. super(props);
  16. this.displayName = 'MediaResize';
  17.  
  18. this.handleResize = this.handleResize.bind(this);
  19. this.handleFinish = this.handleFinish.bind(this);
  20.  
  21. this.state = {
  22. initialHeight: 0,
  23. initialWidth: 0,
  24. height: 0,
  25. width: 0
  26. };
  27. }
  28.  
  29. /**
  30. * Set initial width and height if provided by properties
  31. */
  32. componentWillMount() {
  33. this.setState({
  34. 'initialWidth': this.props.width ? this.props.width : 0,
  35. 'initialHeight': this.props.height ? this.props.height : 0,
  36. 'width': this.props.width ? this.props.width : 0,
  37. 'height': this.props.height ? this.props.height : 0
  38. });
  39. }
  40.  
  41. /**
  42. * Callback to set initial size if not set.
  43. *
  44. * @see render()
  45. */
  46. setSize() {
  47. const {height, width} = this.refs.container.getBoundingClientRect();
  48.  
  49. this.setState({
  50. initialHeight: height,
  51. initialWidth: width,
  52. height: height,
  53. width: width
  54. });
  55. }
  56.  
  57. /**
  58. * Handle resize event. Updates the height and width.
  59. *
  60. * Also calls onResize prop if provided
  61. */
  62. handleResize(e, data) {
  63. const editorBox = this.refs.editorBox.getBoundingClientRect();
  64. const ratio = editorBox.width / data.size.width;
  65.  
  66. this.setState({
  67. height: data.size.height,
  68. width: data.size.width,
  69. editorWidth: editorBox.width,
  70. editorHeight: data.size.height * ratio
  71. });
  72.  
  73. if (this.props.onResize) {
  74. this.props.onResize(data);
  75. }
  76. }
  77. handleFinish() {
  78. if (this.props.onFinish) {
  79. this.props.onFinish(this.state);
  80. }
  81. }
  82.  
  83. render() {
  84. if (!this.props.content.size) {
  85. return <LoadingIndicator size="small" />
  86. }
  87.  
  88. // If there is no initial width (i.e. it's null or 0) we inject the image into the component, get the size
  89. // THEN initialize the resizer. This is necessary because the resizer requires an initial height and width.
  90. if (!this.state.initialWidth) {
  91. return (
  92. <div ref='editorBox' style={{width:'95%'}}>
  93. <LoadingIndicator size="small" />
  94. <img ref='container' src={this.props.content.get('attachment').get('public_url')} style={{maxWidth: '100%'}} onLoad={this.setSize.bind(this)} />
  95. </div>
  96. );
  97. }
  98.  
  99. const className = 'alignment-container ' + (this.props.align ? this.props.align : 'center');
  100.  
  101. let maxResizeWidth = this.state.initialWidth + 5;
  102. let maxResizeHeight = this.state.initialHeight + 5;
  103. let minResizeWidth = 175;
  104. let minResizeHeight = this.state.initialHeight * (175/this.state.initialWidth);
  105.  
  106. if (this.state.editorWidth) {
  107. maxResizeWidth = this.state.editorWidth;
  108. }
  109. if (this.state.editorHeight) {
  110. maxResizeHeight = this.state.editorHeight;
  111. }
  112.  
  113. return (
  114. <div ref='editorBox' style={{width:'95%', margin:'0 auto'}}>
  115. <div className={className} style={{height: this.state.height, width: this.state.width}}>
  116. <div className='alignment-inner' style={{height: this.state.height}}>
  117. <div className='alignment-content' style={{height: this.state.height}}>
  118. <div className='center-toolbar' style={{top: this.state.height/2}}>
  119. <RaisedButton secondary={true} label='Done' onClick={this.handleFinish} />
  120. </div>
  121. <ResizableBox
  122. width={this.state.initialWidth}
  123. height={this.state.initialHeight}
  124. lockAspectRatio={true}
  125. onResize={this.handleResize}
  126. minConstraints={[minResizeWidth, minResizeHeight]}
  127. maxConstraints={[maxResizeWidth, maxResizeHeight]}
  128. >
  129. <img src={this.props.content.get('attachment').get('public_url')} style={{width: '100%'}} />
  130. </ResizableBox>
  131. </div>
  132. </div>
  133. </div>
  134. </div>
  135. );
  136. }
  137. }
  138.  
  139. export default MediaResize;