Browse Source

add renderMathJaxInRealtime option for preview

Yuki Takei 8 years ago
parent
commit
9669e0d775

+ 1 - 1
resource/css/_form.scss

@@ -214,7 +214,7 @@
       margin-right: 0.5em;
     }
 
-    .btn.btn-style-active-line {
+    .btn-style-active-line, .btn-render-mathjax-in-realtime {
       &:hover:not(.active), &:focus:not(.active) {
         background-color: inherit;
       }

+ 10 - 5
resource/js/app.js

@@ -119,28 +119,33 @@ if (elem) {
  * PageEditor
  */
 let pageEditor = null;
+const editorOptions = new EditorOptions(crowi.editorOptions);
+const previewOptions = new PreviewOptions(crowi.previewOptions);
 // render PageEditor
 const pageEditorElem = document.getElementById('page-editor');
 if (pageEditorElem) {
-  const editorOptions = new EditorOptions(crowi.editorOptions);
   pageEditor = ReactDOM.render(
     <PageEditor crowi={crowi} pageId={pageId} revisionId={pageRevisionId} pagePath={pagePath}
-        markdown={entities.decodeHTML(pageContent)} editorOptions={editorOptions}
+        markdown={entities.decodeHTML(pageContent)}
+        editorOptions={editorOptions} previewOptions={previewOptions}
         onSaveSuccess={onSaveSuccess} />,
     pageEditorElem
   );
   // set refs for pageEditor
   crowi.setPageEditor(pageEditor);
 }
-// render EditorOptionsSelector
+// render OptionsSelector
 const pageEditorOptionsSelectorElem = document.getElementById('page-editor-options-selector');
 if (pageEditorOptionsSelectorElem) {
-  const editorOptions = new EditorOptions(crowi.editorOptions);
   ReactDOM.render(
-    <OptionsSelector editorOptions={editorOptions}
+    <OptionsSelector editorOptions={editorOptions} previewOptions={previewOptions}
         onChange={(newEditorOptions, newPreviewOptions) => { // set onChange event handler
+          // set options
           pageEditor.setEditorOptions(newEditorOptions);
+          pageEditor.setPreviewOptions(newPreviewOptions);
+          // save
           crowi.saveEditorOptions(newEditorOptions);
+          crowi.savePreviewOptions(newPreviewOptions);
         }} />,
     pageEditorOptionsSelectorElem
   );

+ 17 - 2
resource/js/components/PageEditor.js

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 import * as toastr from 'toastr';
 import { throttle, debounce } from 'throttle-debounce';
 
-import { EditorOptions } from './PageEditor/OptionsSelector';
+import { EditorOptions, PreviewOptions } from './PageEditor/OptionsSelector';
 import Editor from './PageEditor/Editor';
 import Preview from './PageEditor/Preview';
 
@@ -25,6 +25,7 @@ export default class PageEditor extends React.Component {
       isUploadableFile,
       isMathJaxEnabled,
       editorOptions: this.props.editorOptions,
+      previewOptions: this.props.previewOptions,
     };
 
     this.setCaretLine = this.setCaretLine.bind(this);
@@ -72,6 +73,14 @@ export default class PageEditor extends React.Component {
     this.setState({ editorOptions });
   }
 
+  /**
+   * set options (used from the outside)
+   * @param {object} previewOptions
+   */
+  setPreviewOptions(previewOptions) {
+    this.setState({ previewOptions });
+  }
+
   /**
    * the change event handler for `markdown` state
    * @param {string} value
@@ -292,7 +301,12 @@ export default class PageEditor extends React.Component {
           />
         </div>
         <div className="col-md-6 hidden-sm hidden-xs page-editor-preview-container">
-          <Preview html={this.state.html} inputRef={el => this.previewElement = el} isMathJaxEnabled={this.state.isMathJaxEnabled} />
+          <Preview html={this.state.html}
+              inputRef={el => this.previewElement = el}
+              isMathJaxEnabled={this.state.isMathJaxEnabled}
+              renderMathJaxOnInit={false}
+              previewOptions={this.state.previewOptions}
+          />
         </div>
       </div>
     )
@@ -307,4 +321,5 @@ PageEditor.propTypes = {
   pagePath: PropTypes.string,
   onSaveSuccess: PropTypes.func,
   editorOptions: PropTypes.instanceOf(EditorOptions),
+  previewOptions: PropTypes.instanceOf(PreviewOptions),
 };

+ 44 - 21
resource/js/components/PageEditor/OptionsSelector.js

@@ -5,23 +5,8 @@ import FormGroup from 'react-bootstrap/es/FormGroup';
 import FormControl from 'react-bootstrap/es/FormControl';
 import ControlLabel from 'react-bootstrap/es/ControlLabel';
 import Button from 'react-bootstrap/es/Button';
-
-export class EditorOptions {
-  constructor(props) {
-    this.theme = 'elegant';
-    this.styleActiveLine = false;
-
-    Object.assign(this, props);
-  }
-}
-
-export class PreviewOptions {
-  constructor(props) {
-    this.renderMathJaxInRealtime = false;
-
-    Object.assign(this, props);
-  }
-}
+import DropdownButton from 'react-bootstrap/es/DropdownButton';
+import MenuItem from 'react-bootstrap/es/MenuItem';
 
 export default class OptionsSelector extends React.Component {
 
@@ -39,6 +24,7 @@ export default class OptionsSelector extends React.Component {
 
     this.onChangeTheme = this.onChangeTheme.bind(this);
     this.onClickStyleActiveLine = this.onClickStyleActiveLine.bind(this);
+    this.onClickRenderMathJaxInRealtime = this.onClickRenderMathJaxInRealtime.bind(this);
   }
 
   componentDidMount() {
@@ -67,6 +53,15 @@ export default class OptionsSelector extends React.Component {
     this.dispatchOnChange();
   }
 
+  onClickRenderMathJaxInRealtime(event) {
+    const newValue = !this.state.previewOptions.renderMathJaxInRealtime;
+    const newOpts = Object.assign(this.state.previewOptions, {renderMathJaxInRealtime: newValue});
+    this.setState({previewOptions: newOpts});
+
+    // dispatch event
+    this.dispatchOnChange();
+  }
+
   dispatchOnChange() {
     if (this.props.onChange != null) {
       this.props.onChange(this.state.editorOptions, this.state.previewOptions);
@@ -93,20 +88,48 @@ export default class OptionsSelector extends React.Component {
   }
 
   renderStyleActiveLineSelector() {
-    const bool = this.state.editorOptions.styleActiveLine || false;
+    const bool = this.state.editorOptions.styleActiveLine;
     return (
       <FormGroup controlId="formControlsSelect">
         <Button active={bool} className="btn-style-active-line"
-            onClick={this.onClickStyleActiveLine}
-            ref="styleActiveLineButton">
+            onClick={this.onClickStyleActiveLine}>
           Active Line
         </Button>
       </FormGroup>
     )
   }
 
+  renderRealtimeMathJaxSelector() {
+    const bool = this.state.previewOptions.renderMathJaxInRealtime;
+    return (
+      <FormGroup controlId="formControlsSelect">
+        <Button active={bool} className="btn-render-mathjax-in-realtime"
+            onClick={this.onClickRenderMathJaxInRealtime}>
+          <i className="fa fa-superscript" aria-hidden="true"></i>
+        </Button>
+      </FormGroup>
+    )
+  }
+
   render() {
-    return <span>{this.renderThemeSelector()} {this.renderStyleActiveLineSelector()}</span>
+    return <span>{this.renderThemeSelector()} {this.renderStyleActiveLineSelector()} {this.renderRealtimeMathJaxSelector()}</span>
+  }
+}
+
+export class EditorOptions {
+  constructor(props) {
+    this.theme = 'elegant';
+    this.styleActiveLine = false;
+
+    Object.assign(this, props);
+  }
+}
+
+export class PreviewOptions {
+  constructor(props) {
+    this.renderMathJaxInRealtime = false;
+
+    Object.assign(this, props);
   }
 }
 

+ 11 - 1
resource/js/components/PageEditor/Preview.js

@@ -1,5 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
+import { PreviewOptions } from './OptionsSelector';
 
 export default class Preview extends React.Component {
 
@@ -7,8 +8,15 @@ export default class Preview extends React.Component {
     super(props);
   }
 
+  componentDidMount() {
+    if (this.props.isMathJaxEnabled && this.props.renderMathJaxOnInit) {
+      this.renderMathJax();
+    }
+  }
+
   componentDidUpdate() {
-    if (this.props.isMathJaxEnabled) {
+    const opts = this.props.previewOptions;
+    if (this.props.isMathJaxEnabled && opts != null && opts.renderMathJaxInRealtime) {
       this.renderMathJax();
     }
   }
@@ -41,4 +49,6 @@ Preview.propTypes = {
   html: PropTypes.string,
   inputRef: PropTypes.func.isRequired,  // for getting div element
   isMathJaxEnabled: PropTypes.bool,
+  renderMathJaxOnInit: PropTypes.bool,
+  previewOptions: PropTypes.instanceOf(PreviewOptions),
 };

+ 5 - 0
resource/js/util/Crowi.js

@@ -74,6 +74,7 @@ export default class Crowi {
       'users',
       'draft',
       'editorOptions',
+      'previewOptions',
     ];
 
     keys.forEach(key => {
@@ -153,6 +154,10 @@ export default class Crowi {
     this.localStorage.setItem('editorOptions', JSON.stringify(options));
   }
 
+  savePreviewOptions(options) {
+    this.localStorage.setItem('previewOptions', JSON.stringify(options));
+  }
+
   findUserById(userId) {
     if (this.userById && this.userById[userId]) {
       return this.userById[userId];