forked from nsjcy/frontEnd/nsjcy

xuxj
2020-03-24 ebfd434d26f8269e225efe71ed9c80e2d4cf0ae9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React from 'react';
import './index.less';
 
const stripNbsp = str => str.replace(/ |\u202F|\u00A0/g, ' ');
 
export default class ContentEditable extends React.Component {
  shouldComponentUpdate(nextProps) {
    let {
      props,
      htmlEl
    } = this;
    if (JSON.stringify(this.props.style) === JSON.stringify(nextProps.style)) {
      return false;
    };
    // We need not rerender if the change of props simply reflects the user's edits.
    // Rerendering in this case would make the cursor/caret jump
 
    // Rerender if there is no element yet... (somehow?)
    if (!htmlEl) {
      return true;
    };
    // ...or if html really changed... (programmatically, not by user edit)
    if (
      stripNbsp(nextProps.html) !== stripNbsp(htmlEl.innerHTML) &&
      nextProps.html !== props.html
    ) {
      return true;
    };
    let optional = ['style', 'className', 'disabled', 'tagName'];
    // Handle additional properties
    return optional.some(name => props[name] !== nextProps[name]);
  }
 
  componentDidUpdate() {
    if (this.htmlEl && this.props.html !== this.htmlEl.innerHTML) {
      // Perhaps React (whose VDOM gets outdated because we often prevent
      // rerendering) did not update the DOM. So we update it manually now.
      this.htmlEl.innerHTML = this.props.html;
    };
  }
 
  emitChange = (evt) => {
    if (!this.htmlEl) return;
    var name = evt.target.dataset.name;
    var html = this.htmlEl.innerHTML;
    if (this.props.onChange && html !== this.lastHtml) {
      // Clone event with Object.assign to avoid 
      // "Cannot assign to read only property 'target' of object"
      var evt = Object.assign({}, evt, {
        target: {
          value: html,
          name: name,
        },
      });
      this.props.onChange(evt);
    }
    this.lastHtml = html;
  }
 
  render() {
    var {
      tagName,
      name,
      html,
      style,
      onKeyPress,
      ...otherProps
    } = this.props;
 
    return (
      // React.createElement(
      //   tagName || 'div',
      //   {
      //     ...props,
      //     ref: (e) => this.htmlEl = e,
      //     onInput: this.emitChange,
      //     onBlur: this.props.onBlur || this.emitChange,
      //     contentEditable: !this.props.disabled,
      //     dangerouslySetInnerHTML: {__html: html}
      //   },
      //   this.props.children);
      <div {...otherProps}
        className="contentEditable"
        style={style}
        data-name={name} 
        ref={(e) => this.htmlEl = e}
        onInput={this.emitChange}
        onKeyPress={onKeyPress} 
        //onBlur={this.props.onBlur || this.emitChange}
        contentEditable={!this.props.disabled}
        dangerouslySetInnerHTML={{__html: html}}>
        {this.props.children}
      </div>
    );
  }
}