application/components/common/rich-editor/media-resize.js
import React from 'react';
import LoadingIndicator from './../loading-indicator';
import {ResizableBox} from 'react-resizable';
import RaisedButton from 'material-ui/RaisedButton';
import BaseView from './../../base-view';
/**
* MediaResize component handles the draggable
* resizing of media blocks. This does not update media
* block meta, but sends the data to a callback.
*/
class MediaResize extends BaseView {
constructor(props) {
super(props);
this.displayName = 'MediaResize';
this.handleResize = this.handleResize.bind(this);
this.handleFinish = this.handleFinish.bind(this);
this.state = {
initialHeight: 0,
initialWidth: 0,
height: 0,
width: 0
};
}
/**
* Set initial width and height if provided by properties
*/
componentWillMount() {
this.setState({
'initialWidth': this.props.width ? this.props.width : 0,
'initialHeight': this.props.height ? this.props.height : 0,
'width': this.props.width ? this.props.width : 0,
'height': this.props.height ? this.props.height : 0
});
}
/**
* Callback to set initial size if not set.
*
* @see render()
*/
setSize() {
const {height, width} = this.refs.container.getBoundingClientRect();
this.setState({
initialHeight: height,
initialWidth: width,
height: height,
width: width
});
}
/**
* Handle resize event. Updates the height and width.
*
* Also calls onResize prop if provided
*/
handleResize(e, data) {
const editorBox = this.refs.editorBox.getBoundingClientRect();
const ratio = editorBox.width / data.size.width;
this.setState({
height: data.size.height,
width: data.size.width,
editorWidth: editorBox.width,
editorHeight: data.size.height * ratio
});
if (this.props.onResize) {
this.props.onResize(data);
}
}
handleFinish() {
if (this.props.onFinish) {
this.props.onFinish(this.state);
}
}
render() {
if (!this.props.content.size) {
return <LoadingIndicator size="small" />
}
// If there is no initial width (i.e. it's null or 0) we inject the image into the component, get the size
// THEN initialize the resizer. This is necessary because the resizer requires an initial height and width.
if (!this.state.initialWidth) {
return (
<div ref='editorBox' style={{width:'95%'}}>
<LoadingIndicator size="small" />
<img ref='container' src={this.props.content.get('attachment').get('public_url')} style={{maxWidth: '100%'}} onLoad={this.setSize.bind(this)} />
</div>
);
}
const className = 'alignment-container ' + (this.props.align ? this.props.align : 'center');
let maxResizeWidth = this.state.initialWidth + 5;
let maxResizeHeight = this.state.initialHeight + 5;
let minResizeWidth = 175;
let minResizeHeight = this.state.initialHeight * (175/this.state.initialWidth);
if (this.state.editorWidth) {
maxResizeWidth = this.state.editorWidth;
}
if (this.state.editorHeight) {
maxResizeHeight = this.state.editorHeight;
}
return (
<div ref='editorBox' style={{width:'95%', margin:'0 auto'}}>
<div className={className} style={{height: this.state.height, width: this.state.width}}>
<div className='alignment-inner' style={{height: this.state.height}}>
<div className='alignment-content' style={{height: this.state.height}}>
<div className='center-toolbar' style={{top: this.state.height/2}}>
<RaisedButton secondary={true} label='Done' onClick={this.handleFinish} />
</div>
<ResizableBox
width={this.state.initialWidth}
height={this.state.initialHeight}
lockAspectRatio={true}
onResize={this.handleResize}
minConstraints={[minResizeWidth, minResizeHeight]}
maxConstraints={[maxResizeWidth, maxResizeHeight]}
>
<img src={this.props.content.get('attachment').get('public_url')} style={{width: '100%'}} />
</ResizableBox>
</div>
</div>
</div>
</div>
);
}
}
export default MediaResize;