-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
Copy pathComponentTextView.js
146 lines (127 loc) · 3.71 KB
/
ComponentTextView.js
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import { on, off } from 'utils/mixins';
const ComponentView = require('./ComponentView');
module.exports = ComponentView.extend({
events: {
dblclick: 'onActive',
input: 'onInput'
},
initialize(o) {
ComponentView.prototype.initialize.apply(this, arguments);
this.disableEditing = this.disableEditing.bind(this);
const model = this.model;
const em = this.em;
this.listenTo(model, 'focus', this.onActive);
this.listenTo(model, 'change:content', this.updateContentText);
this.rte = em && em.get('RichTextEditor');
},
updateContentText(m, v, opts = {}) {
!opts.fromDisable && this.disableEditing();
},
/**
* Enable element content editing
* @private
* */
onActive(e) {
// We place this before stopPropagation in case of nested
// text components will not block the editing (#1394)
if (this.rteEnabled || !this.model.get('editable')) {
return;
}
e && e.stopPropagation && e.stopPropagation();
const rte = this.rte;
if (rte) {
try {
this.activeRte = rte.enable(this, this.activeRte);
} catch (err) {
console.error(err);
}
}
this.rteEnabled = 1;
this.toggleEvents(1);
},
/**
* Disable element content editing
* @private
* */
disableEditing() {
const model = this.model;
const editable = model.get('editable');
const rte = this.rte;
const contentOpt = { fromDisable: 1 };
if (rte && editable) {
try {
rte.disable(this, this.activeRte);
} catch (err) {
console.error(err);
}
const content = this.getChildrenContainer().innerHTML;
const comps = model.get('components');
comps.length && comps.reset();
model.set('content', '', contentOpt);
// If there is a custom RTE the content is just baked staticly
// inside 'content'
if (rte.customRte) {
// Avoid double content by removing its children components
// and force to trigger change
model.set('content', content, contentOpt);
} else {
const clean = model => {
const selectable = !['text', 'default', ''].some(type =>
model.is(type)
);
model.set({
editable: selectable && model.get('editable'),
highlightable: 0,
removable: 0,
draggable: 0,
copyable: 0,
selectable: selectable,
hoverable: selectable,
toolbar: ''
});
model.get('components').each(model => clean(model));
};
// Avoid re-render on reset with silent option
model.trigger('change:content', model, '', contentOpt);
comps.add(content);
comps.each(model => clean(model));
comps.trigger('resetNavigator');
}
}
this.rteEnabled = 0;
this.toggleEvents();
},
/**
* Callback on input event
* @param {Event} e
*/
onInput(e) {
const { em } = this;
// Update toolbars
em && em.trigger('change:canvasOffset');
},
/**
* Isolate disable propagation method
* @param {Event}
* @private
* */
disablePropagation(e) {
e.stopPropagation();
},
/**
* Enable/Disable events
* @param {Boolean} enable
*/
toggleEvents(enable) {
var method = enable ? 'on' : 'off';
const mixins = { on, off };
this.em.setEditing(enable);
// The ownerDocument is from the frame
var elDocs = [this.el.ownerDocument, document];
mixins.off(elDocs, 'mousedown', this.disableEditing);
mixins[method](elDocs, 'mousedown', this.disableEditing);
// Avoid closing edit mode on component click
this.$el.off('mousedown', this.disablePropagation);
this.$el[method]('mousedown', this.disablePropagation);
}
});