Home Reference Source

application/components/common/rich-editor2/plugins/styler.js

  1. import React from 'react';
  2. import Dialog from 'material-ui/Dialog';
  3. import TextField from 'material-ui/TextField';
  4. import FlatButton from 'material-ui/FlatButton';
  5. import RaisedButton from 'material-ui/RaisedButton';
  6. import toStyle from 'css-to-style';
  7. import ToolbarButton from '../common/toolbar-button';
  8.  
  9. export const SERIALIZER_RULES = [
  10. {
  11. serialize(obj, children) {
  12. if (obj.object == 'inline' && obj.type == 'styler') {
  13. return <span style={obj.data.get('style').length ? toStyle(obj.data.get('style')) : {}} className={obj.data.get('klass')}>{children}</span>;
  14. }
  15. }
  16. }
  17. ];
  18.  
  19. class StylerButton extends ToolbarButton
  20. {
  21. handleOnClick(e) {
  22. return stylerClickHandler.call(this.props.editor, e);
  23. }
  24.  
  25. getLabel() {
  26. return <i className='fa fa-paint-brush'></i>;
  27. }
  28. }
  29.  
  30. class StylerNode extends React.Component
  31. {
  32. constructor(props) {
  33. super(props);
  34.  
  35. this.parentEditor = this.props.editor;
  36. }
  37.  
  38. render() {
  39. const {data} = this.props.node;
  40.  
  41. const handleClick = e => {
  42. e.preventDefault();
  43.  
  44. // open the modal and store the styler data
  45. this.props.editor.setState({
  46. 'myStylerModalOpen': true,
  47. 'myStylerData': data
  48. });
  49.  
  50. }
  51. return (
  52. <span {...this.props.attributes} className='styler-panted' onClick={handleClick}>
  53. {this.props.children}
  54. </span>
  55. )
  56. }
  57. }
  58.  
  59. function stylerClickHandler(e, defaultUrl = '') {
  60. const {editor} = this;
  61. const {editorContent} = this.state;
  62. const hasStyler = this.hasInline('styler');
  63.  
  64. if (hasStyler) {
  65. // user highlighted a link and clicked the button, so remove the link
  66. editor.unwrapInline('styler');
  67. } else if (editorContent.selection.isExpanded) {
  68. // open the modal
  69. editor.setState({'myStylerModalOpen': true});
  70. return;
  71. }
  72. }
  73.  
  74. class StylerModal extends React.Component {
  75.  
  76. constructor(props) {
  77. super(props);
  78.  
  79. this.state = {
  80. style: '',
  81. klass: '',
  82. };
  83. }
  84.  
  85. closeModal() {
  86. this.props.editor.setState({
  87. 'myStylerModalOpen': false,
  88. 'myStylerData': null,
  89. });
  90. this.setState({
  91. style: '',
  92. klass: '',
  93. });
  94. }
  95.  
  96. handleCancel(e) {
  97. this.closeModal.call(this);
  98. }
  99.  
  100. componentWillReceiveProps(newProps) {
  101. if (newProps.editor && newProps.editor.state.myStylerData) {
  102. this.setState({
  103. 'style': newProps.editor.state.myStylerData.get('style'),
  104. 'klass': newProps.editor.state.myStylerData.get('klass')
  105. });
  106. }
  107. }
  108.  
  109. handleSave(e) {
  110.  
  111. // remove any existing links, expand the selection then replace the URL
  112. // if it's set
  113. this.props.editor
  114. .focus()
  115. .moveAnchorToStartOfInline()
  116. .moveFocusToEndOfInline()
  117. .unwrapInline('styler')
  118. .wrapInline({
  119. type: 'styler',
  120. data: {
  121. 'style': this.state.style,
  122. 'klass': this.state.klass
  123. }
  124. });
  125. this.props.editor.moveToEnd();
  126.  
  127. setTimeout(() => {
  128. this.closeModal.call(this);
  129. }, 250);
  130. }
  131.  
  132. updateStyle(e) {
  133. this.setState({
  134. style: e.target.value
  135. });
  136. }
  137.  
  138. updateKlass(e) {
  139. this.setState({
  140. klass: e.target.value
  141. });
  142. }
  143.  
  144. handleKeyPress(e) {
  145. if (e.key == 'Enter') {
  146. this.handleSave.call(this, e);
  147. }
  148. }
  149.  
  150. render() {
  151. const buttons = [
  152. <FlatButton
  153. label='Cancel'
  154. onClick={this.handleCancel.bind(this)}
  155. />,
  156. <RaisedButton
  157. label='Save'
  158. onClick={this.handleSave.bind(this)}
  159. primary={true}
  160. />
  161. ]
  162.  
  163. return (
  164. <Dialog
  165. modal={true}
  166. actions={buttons}
  167. title='Edit Styles'
  168. open={this.props.editor.state.myStylerModalOpen ? true : false}
  169. >
  170. <TextField
  171. floatingLabelText="Style"
  172. value={this.state.style}
  173. onChange={this.updateStyle.bind(this)}
  174. onKeyPress={this.handleKeyPress.bind(this)}
  175. fullWidth={true}
  176. />
  177. <TextField
  178. floatingLabelText="Class"
  179. value={this.state.klass}
  180. onChange={this.updateKlass.bind(this)}
  181. onKeyPress={this.handleKeyPress.bind(this)}
  182. fullWidth={true}
  183. />
  184. </Dialog>
  185. );
  186. }
  187. };
  188.  
  189. function StylerPlugin(options) {
  190. return {
  191. renderEditor(props, editor, next) {
  192. const children = next();
  193. return (
  194. <React.Fragment>
  195. {children}
  196. <StylerModal editor={editor} />
  197. </React.Fragment>
  198. );
  199. },
  200. renderNode(props, editor, next) {
  201. const {attributes, children} = props;
  202.  
  203. switch(props.node.type) {
  204. case 'styler':
  205. return <StylerNode {...props} editor={editor}/>;
  206. default:
  207. return next();
  208. }
  209.  
  210. }
  211. };
  212. };
  213. export {StylerPlugin, StylerButton, stylerClickHandler};