application/components/common/rich-editor2/plugins/styler.js
import React from 'react';
import Dialog from 'material-ui/Dialog';
import TextField from 'material-ui/TextField';
import FlatButton from 'material-ui/FlatButton';
import RaisedButton from 'material-ui/RaisedButton';
import toStyle from 'css-to-style';
import ToolbarButton from '../common/toolbar-button';
export const SERIALIZER_RULES = [
{
serialize(obj, children) {
if (obj.object == 'inline' && obj.type == 'styler') {
return <span style={obj.data.get('style').length ? toStyle(obj.data.get('style')) : {}} className={obj.data.get('klass')}>{children}</span>;
}
}
}
];
class StylerButton extends ToolbarButton
{
handleOnClick(e) {
return stylerClickHandler.call(this.props.editor, e);
}
getLabel() {
return <i className='fa fa-paint-brush'></i>;
}
}
class StylerNode extends React.Component
{
constructor(props) {
super(props);
this.parentEditor = this.props.editor;
}
render() {
const {data} = this.props.node;
const handleClick = e => {
e.preventDefault();
// open the modal and store the styler data
this.props.editor.setState({
'myStylerModalOpen': true,
'myStylerData': data
});
}
return (
<span {...this.props.attributes} className='styler-panted' onClick={handleClick}>
{this.props.children}
</span>
)
}
}
function stylerClickHandler(e, defaultUrl = '') {
const {editor} = this;
const {editorContent} = this.state;
const hasStyler = this.hasInline('styler');
if (hasStyler) {
// user highlighted a link and clicked the button, so remove the link
editor.unwrapInline('styler');
} else if (editorContent.selection.isExpanded) {
// open the modal
editor.setState({'myStylerModalOpen': true});
return;
}
}
class StylerModal extends React.Component {
constructor(props) {
super(props);
this.state = {
style: '',
klass: '',
};
}
closeModal() {
this.props.editor.setState({
'myStylerModalOpen': false,
'myStylerData': null,
});
this.setState({
style: '',
klass: '',
});
}
handleCancel(e) {
this.closeModal.call(this);
}
componentWillReceiveProps(newProps) {
if (newProps.editor && newProps.editor.state.myStylerData) {
this.setState({
'style': newProps.editor.state.myStylerData.get('style'),
'klass': newProps.editor.state.myStylerData.get('klass')
});
}
}
handleSave(e) {
// remove any existing links, expand the selection then replace the URL
// if it's set
this.props.editor
.focus()
.moveAnchorToStartOfInline()
.moveFocusToEndOfInline()
.unwrapInline('styler')
.wrapInline({
type: 'styler',
data: {
'style': this.state.style,
'klass': this.state.klass
}
});
this.props.editor.moveToEnd();
setTimeout(() => {
this.closeModal.call(this);
}, 250);
}
updateStyle(e) {
this.setState({
style: e.target.value
});
}
updateKlass(e) {
this.setState({
klass: e.target.value
});
}
handleKeyPress(e) {
if (e.key == 'Enter') {
this.handleSave.call(this, e);
}
}
render() {
const buttons = [
<FlatButton
label='Cancel'
onClick={this.handleCancel.bind(this)}
/>,
<RaisedButton
label='Save'
onClick={this.handleSave.bind(this)}
primary={true}
/>
]
return (
<Dialog
modal={true}
actions={buttons}
title='Edit Styles'
open={this.props.editor.state.myStylerModalOpen ? true : false}
>
<TextField
floatingLabelText="Style"
value={this.state.style}
onChange={this.updateStyle.bind(this)}
onKeyPress={this.handleKeyPress.bind(this)}
fullWidth={true}
/>
<TextField
floatingLabelText="Class"
value={this.state.klass}
onChange={this.updateKlass.bind(this)}
onKeyPress={this.handleKeyPress.bind(this)}
fullWidth={true}
/>
</Dialog>
);
}
};
function StylerPlugin(options) {
return {
renderEditor(props, editor, next) {
const children = next();
return (
<React.Fragment>
{children}
<StylerModal editor={editor} />
</React.Fragment>
);
},
renderNode(props, editor, next) {
const {attributes, children} = props;
switch(props.node.type) {
case 'styler':
return <StylerNode {...props} editor={editor}/>;
default:
return next();
}
}
};
};
export {StylerPlugin, StylerButton, stylerClickHandler};