UNPKG

rich-react-editor

Version:

react editor with support of image and multi languages

244 lines (204 loc) 7.59 kB
import $ from "jquery"; import React, { Component } from "react"; import PropTypes from "prop-types"; import CustomHintPopover from "./CustomHintPopover"; import "summernote/dist/summernote"; import "summernote/dist/summernote.css"; import "codemirror/lib/codemirror.css"; import '../public/ReactEditor.css'; class ReactEditor extends Component { constructor(props) { super(props); this.uid = `${this.props.name}-rich-react-editor`; this.editor = {}; this.noteEditable = null; this.notePlaceholder = null; this.onInit = this.onInit.bind(this); this.onImageUpload = this.onImageUpload.bind(this); this.focus = this.focus.bind(this); this.isEmpty = this.isEmpty.bind(this); this.reset = this.reset.bind(this); this.replace = this.replace.bind(this); this.disable = this.disable.bind(this); this.enable = this.enable.bind(this); this.toggleState = this.toggleState.bind(this); this.insertImage = this.insertImage.bind(this); this.insertNode = this.insertNode.bind(this); this.insertText = this.insertText.bind(this); this.onPaste = this.onPaste.bind(this); ReactEditor.focus = this.focus.bind(this); ReactEditor.onPaste = this.onPaste.bind(this); ReactEditor.isEmpty = this.isEmpty.bind(this); ReactEditor.reset = this.reset.bind(this); ReactEditor.replace = this.replace.bind(this); ReactEditor.disable = this.disable.bind(this); ReactEditor.enable = this.enable.bind(this); ReactEditor.toggleState = this.toggleState.bind(this); ReactEditor.insertImage = this.insertImage.bind(this); ReactEditor.insertNode = this.insertNode.bind(this); ReactEditor.insertText = this.insertText.bind(this); } componentDidMount() { const options = this.props.options || {}; window.$ = $; const codeview = this.props.codeview; // const codeviewCommand = codeview ? 'codeview.activate' : 'codeview.deactivate'; options.callbacks = this.callbacks; this.editor = $(`#${this.uid}`); $.extend(true, $.summernote.options.modules, { 'hintPopover': CustomHintPopover }); this.editor.summernote(options); if (codeview) { this.editor.summernote("codeview.activate"); } } componentWillReceiveProps(nextProps) { const { props } = this; const codeview = nextProps.codeview; const codeviewCommand = codeview ? "codeview.activate" : "codeview.deactivate"; if (typeof nextProps.value === "string" && props.value !== nextProps.value) { this.replace(nextProps.value); } if (typeof nextProps.disabled === "boolean" && props.disabled !== nextProps.disabled) { this.toggleState(nextProps.disabled); } if (codeview !== props.codeview) { this.editor.summernote(codeviewCommand); } } shouldComponentUpdate() { return false; } componentWillUnmount() { if (this.editor.summernote) { this.editor.summernote("destroy"); } } onInit() { const { disabled, onInit } = this.props; const $container = this.editor.parent(); this.noteEditable = $container.find(".note-editable"); this.notePlaceholder = $container.find(".note-placeholder"); if (typeof disabled === "boolean") { this.toggleState(disabled); } if (typeof onInit === "function") { onInit({ summernote: this.editor.summernote.bind(this.editor), focus: this.focus, isEmpty: this.isEmpty, reset: this.reset, replace: this.replace, disable: this.disable, enable: this.enable, insertImage: this.insertImage, onPaste: this.onPaste, insertNode: this.insertNode, insertText: this.insertText }); } } onImageUpload(images) { const { onImageUpload } = this.props; if (typeof onImageUpload === "function") { onImageUpload(images, this.insertImage); } } focus() { this.editor.summernote("focus"); } onPaste(e) { // taking html from clipboard var bufferText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('text/html'); // proceeding html string for removing style var divElement = document.createElement('div'); divElement.innerHTML = bufferText; // loop through ALL DOM elements inside the divElement var elements = divElement.getElementsByTagName("*"); for (var i = 0; i < elements.length; i++) { var element = elements[i]; $(element).removeAttr('style'); } e.preventDefault(); // inserting html into summernote item this.editor.summernote('pasteHTML', $(divElement).html()); // this.editor.summernote("focus") } isEmpty() { return this.editor.summernote("isEmpty"); } reset() { this.editor.summernote("reset"); } replace(content) { const { noteEditable, notePlaceholder } = this; const prevContent = noteEditable.html(); const contentLength = content.length; if (prevContent !== content) { if (this.isEmpty() && contentLength > 0) { notePlaceholder.hide(); } else if (contentLength === 0) { notePlaceholder.show(); } noteEditable.html(content); } } disable() { this.editor.summernote("disable"); } enable() { this.editor.summernote("enable"); } toggleState(disabled) { if (disabled) { this.disable(); } else { this.enable(); } } insertImage(url, filenameOrCallback) { this.editor.summernote("insertImage", url, filenameOrCallback); } insertNode(node) { this.editor.summernote("insertNode", node); } insertText(text) { this.editor.summernote("insertText", text); } get callbacks() { const props = this.props; return { onInit: this.onInit, onEnter: props.onEnter, onFocus: props.onFocus, onBlur: props.onBlur, onKeyup: props.onKeyUp, onKeydown: props.onKeyDown, onPaste: this.onPaste, onChange: props.onChange, onImageUpload: this.onImageUpload }; } render() { const { value, defaultValue, showLoading } = this.props; const html = value || defaultValue; return React.createElement("div", { id: this.uid, dangerouslySetInnerHTML: { __html: html === null && showLoading ? "<div class='justify-to-center' contenteditable='false'>loading..</div>" : html } }); } } ReactEditor.propTypes = { value: PropTypes.string, placeholder: PropTypes.string, defaultValue: PropTypes.string, codeview: PropTypes.bool, options: PropTypes.object, disabled: PropTypes.bool, onInit: PropTypes.func, onEnter: PropTypes.func, onFocus: PropTypes.func, onBlur: PropTypes.func, onKeyUp: PropTypes.func, onKeyDown: PropTypes.func, onPaste: PropTypes.func, onChange: PropTypes.func, onImageUpload: PropTypes.func }; export default ReactEditor;