easy-richtextarea 4.0.1 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -8
- package/example.js +1012 -595
- package/lib/browser.js +9 -9
- package/lib/constants.js +13 -4
- package/lib/contentCompare.js +34 -0
- package/lib/example/richTextarea.js +2 -2
- package/lib/example/view.js +18 -9
- package/lib/keyCodes.js +13 -0
- package/lib/main.js +1 -1
- package/lib/operation/delete.js +101 -52
- package/lib/operation/empty.js +21 -6
- package/lib/operation/insert.js +78 -31
- package/lib/operations/fromJSON.js +4 -4
- package/lib/operations/generate.js +11 -11
- package/lib/operations/transform.js +3 -7
- package/lib/richTextarea.js +244 -156
- package/lib/selection.js +55 -13
- package/lib/types.js +13 -13
- package/lib/undoBuffer.js +105 -0
- package/package.json +3 -2
- package/src/browser.js +3 -3
- package/src/constants.js +1 -0
- package/src/contentCompare.js +34 -0
- package/src/example/richTextarea.js +11 -9
- package/src/example/view.js +28 -10
- package/src/keyCodes.js +3 -0
- package/src/main.js +1 -0
- package/src/operation/delete.js +135 -58
- package/src/operation/empty.js +19 -14
- package/src/operation/insert.js +97 -39
- package/src/operations/fromJSON.js +4 -4
- package/src/operations/generate.js +17 -13
- package/src/operations/transform.js +3 -3
- package/src/richTextarea.js +316 -185
- package/src/selection.js +53 -9
- package/src/types.js +6 -6
- package/src/undoBuffer.js +73 -0
- package/test/content/transform.js +15 -17
- package/test/helpers.js +27 -21
- package/test/operation/delete.js +187 -147
- package/test/operation/empty.js +3 -5
- package/test/operation/insert.js +134 -118
- package/test/operations/generate.js +25 -29
- package/test/operations/transform.js +37 -98
- package/lib/stringCompare.js +0 -33
- package/src/stringCompare.js +0 -33
package/src/richTextarea.js
CHANGED
|
@@ -1,86 +1,136 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { Element, document, eventTypes } from "easy";
|
|
4
4
|
|
|
5
5
|
import Selection from "./selection"
|
|
6
|
+
import UndoBuffer from "./undoBuffer";
|
|
7
|
+
import InsertOperation from "./operation/insert";
|
|
8
|
+
import DeleteOperation from "./operation/delete";
|
|
9
|
+
import generateOperations from "./operations/generate";
|
|
10
|
+
|
|
11
|
+
import { Z_KEY_CODE } from "./keyCodes";
|
|
12
|
+
import { TEXT, EMPTY_STRING } from "./constants";
|
|
13
|
+
|
|
14
|
+
const { CUT_EVENT_TYPE,
|
|
15
|
+
COPY_EVENT_TYPE,
|
|
16
|
+
BLUR_EVENT_TYPE,
|
|
17
|
+
PASTE_EVENT_TYPE,
|
|
18
|
+
INPUT_EVENT_TYPE,
|
|
19
|
+
FOCUS_EVENT_TYPE,
|
|
20
|
+
CHANGE_EVENT_TYPE,
|
|
21
|
+
SCROLL_EVENT_TYPE,
|
|
22
|
+
KEYDOWN_EVENT_TYPE,
|
|
23
|
+
CONTEXTMENU_EVENT_TYPE,
|
|
24
|
+
SELECTIONCHANGE_EVENT_TYPE } = eventTypes;
|
|
6
25
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
CHANGE_EVENT_TYPE,
|
|
11
|
-
SCROLL_EVENT_TYPE,
|
|
12
|
-
KEYDOWN_EVENT_TYPE,
|
|
13
|
-
MOUSEUP_EVENT_TYPE,
|
|
14
|
-
MOUSEDOWN_EVENT_TYPE,
|
|
15
|
-
MOUSEMOVE_EVENT_TYPE,
|
|
16
|
-
CONTEXTMENU_EVENT_TYPE } = eventTypes;
|
|
26
|
+
export default class RichTextarea extends Element {
|
|
27
|
+
constructor(selector, focused, readOnly, undoBuffer, previousContent, previousSelection) {
|
|
28
|
+
super(selector);
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
this.focused = focused;
|
|
31
|
+
this.readOnly = readOnly;
|
|
32
|
+
this.undoBuffer = undoBuffer;
|
|
33
|
+
this.previousContent = previousContent;
|
|
34
|
+
this.previousSelection = previousSelection;
|
|
35
|
+
}
|
|
19
36
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
isFocused() {
|
|
38
|
+
return this.focused;
|
|
39
|
+
}
|
|
23
40
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
isReadOnly() {
|
|
42
|
+
return this.readOnly;
|
|
43
|
+
}
|
|
27
44
|
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
getUndoBuffer() {
|
|
46
|
+
return this.undoBuffer;
|
|
47
|
+
}
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
getPreviousContent() {
|
|
50
|
+
return this.prevousContent;
|
|
51
|
+
}
|
|
32
52
|
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
getPreviousSelection() {
|
|
54
|
+
return this.previousSelection;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setFocused(focused) {
|
|
58
|
+
this.focused = focused;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setReadOnly(readOnly) {
|
|
62
|
+
this.readOnly = readOnly;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setPreviousContent(previousContent) {
|
|
66
|
+
this.previousContent = previousContent;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setPreviousSelection(previousSelection) {
|
|
70
|
+
this.previousSelection = previousSelection;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
intermediateHandler = (event, element, undoable = true, eventType = CHANGE_EVENT_TYPE, selectionChanged = this.hasSelectionChanged()) => {
|
|
74
|
+
if (this.readOnly) {
|
|
75
|
+
const content = this.previousContent; ///
|
|
76
|
+
|
|
77
|
+
this.setContent(content);
|
|
35
78
|
}
|
|
36
79
|
|
|
37
80
|
const content = this.getContent(),
|
|
38
81
|
selection = this.getSelection(),
|
|
39
|
-
|
|
40
|
-
|
|
82
|
+
contentChanged = this.hasContentChanged(),
|
|
83
|
+
changed = (contentChanged || selectionChanged);
|
|
41
84
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
85
|
+
if (changed) {
|
|
86
|
+
this.callHandlers(eventType, event, element);
|
|
87
|
+
}
|
|
45
88
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
eventType = CHANGE_EVENT_TYPE;
|
|
89
|
+
if (undoable) {
|
|
90
|
+
if (contentChanged) {
|
|
91
|
+
const operations = generateOperations(this.previousContent, content);
|
|
50
92
|
|
|
51
|
-
|
|
93
|
+
this.undoBuffer.addOperations(operations);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
52
96
|
|
|
53
|
-
|
|
54
|
-
}
|
|
97
|
+
this.previousContent = content; ///
|
|
55
98
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
mouseDown = this.isMouseDown(),
|
|
59
|
-
eventTYpe = CHANGE_EVENT_TYPE;
|
|
99
|
+
this.previousSelection = selection; ///
|
|
100
|
+
}
|
|
60
101
|
|
|
61
|
-
|
|
62
|
-
|
|
102
|
+
selectChangeHandler = (event, element) => {
|
|
103
|
+
if (this.focused) {
|
|
104
|
+
this.intermediateHandler(event, element);
|
|
63
105
|
}
|
|
64
106
|
}
|
|
65
107
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.setMouseDown(mouseDown);
|
|
70
|
-
};
|
|
108
|
+
contextmenuHandler = (event, element) => {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
}
|
|
71
111
|
|
|
72
112
|
keyDownHandler = (event, element) => {
|
|
73
|
-
const
|
|
74
|
-
eventType = CHANGE_EVENT_TYPE;
|
|
113
|
+
const { keyCode } = event;
|
|
75
114
|
|
|
76
|
-
|
|
77
|
-
|
|
115
|
+
if (keyCode === Z_KEY_CODE) {
|
|
116
|
+
const { ctrlKey, metaKey } = event;
|
|
78
117
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
118
|
+
if (ctrlKey || metaKey) {
|
|
119
|
+
const { shiftKey } = event;
|
|
120
|
+
|
|
121
|
+
shiftKey ?
|
|
122
|
+
this.redo(event, element) :
|
|
123
|
+
this.undo(event, element);
|
|
124
|
+
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
82
130
|
|
|
83
|
-
|
|
131
|
+
defer(() => {
|
|
132
|
+
this.intermediateHandler(event, element);
|
|
133
|
+
});
|
|
84
134
|
}
|
|
85
135
|
|
|
86
136
|
scrollHandler = (event, element) => {
|
|
@@ -90,17 +140,97 @@ export default class RichTextarea extends Element {
|
|
|
90
140
|
}
|
|
91
141
|
|
|
92
142
|
focusHandler = (event, element) => {
|
|
93
|
-
|
|
94
|
-
|
|
143
|
+
this.focused = true;
|
|
144
|
+
|
|
145
|
+
defer(() => {
|
|
146
|
+
const undoable = true,
|
|
147
|
+
eventType = FOCUS_EVENT_TYPE,
|
|
148
|
+
selectionChanged = true;
|
|
95
149
|
|
|
96
|
-
|
|
150
|
+
this.intermediateHandler(event, element, undoable, eventType, selectionChanged);
|
|
151
|
+
});
|
|
97
152
|
}
|
|
98
153
|
|
|
99
154
|
blurHandler = (event, element) => {
|
|
100
|
-
|
|
101
|
-
|
|
155
|
+
this.focused = false;
|
|
156
|
+
|
|
157
|
+
const undoable = true,
|
|
158
|
+
eventType = BLUR_EVENT_TYPE,
|
|
159
|
+
selectionChanged = true;
|
|
160
|
+
|
|
161
|
+
this.intermediateHandler(event, element, undoable, eventType, selectionChanged);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
inputHandler = (event, element) => {
|
|
165
|
+
this.intermediateHandler(event, element);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
pasteHandler = (event, element) => {
|
|
169
|
+
const { clipboardData } = event,
|
|
170
|
+
textData = clipboardData.getData(TEXT);
|
|
171
|
+
|
|
172
|
+
if (textData === EMPTY_STRING) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const selection = this.getSelection(),
|
|
177
|
+
selectionEmpty = selection.isEmpty();
|
|
178
|
+
|
|
179
|
+
if (!selectionEmpty) {
|
|
180
|
+
const content = this.getContent(),
|
|
181
|
+
deleteOperation = DeleteOperation.fromContentAndSelection(content, selection),
|
|
182
|
+
operation = deleteOperation;
|
|
183
|
+
|
|
184
|
+
this.applyOperation(operation);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const content = textData, ///
|
|
188
|
+
insertOperation = InsertOperation.fromContentAndSelection(content, selection),
|
|
189
|
+
operation = insertOperation; ///
|
|
102
190
|
|
|
103
|
-
this.
|
|
191
|
+
this.applyOperation(operation);
|
|
192
|
+
|
|
193
|
+
this.intermediateHandler(event, element);
|
|
194
|
+
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
copyHandler = (event, element) => {
|
|
199
|
+
const selection = this.getSelection(),
|
|
200
|
+
selectionEmpty = selection.isEmpty();
|
|
201
|
+
|
|
202
|
+
if (selectionEmpty) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const selectedContent = this.getSelectedContent();
|
|
207
|
+
|
|
208
|
+
navigator.clipboard.writeText(selectedContent);
|
|
209
|
+
|
|
210
|
+
event.preventDefault();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
cutHandler = (event, element) => {
|
|
214
|
+
const selection = this.getSelection(),
|
|
215
|
+
selectionEmpty = selection.isEmpty();
|
|
216
|
+
|
|
217
|
+
if (selectionEmpty) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const selectedContent = this.getSelectedContent();
|
|
222
|
+
|
|
223
|
+
navigator.clipboard.writeText(selectedContent);
|
|
224
|
+
|
|
225
|
+
const content = this.getContent(),
|
|
226
|
+
deleteOperation = DeleteOperation.fromContentAndSelection(content, selection),
|
|
227
|
+
operation = deleteOperation; ///
|
|
228
|
+
|
|
229
|
+
this.applyOperation(operation);
|
|
230
|
+
|
|
231
|
+
this.intermediateHandler(event, element);
|
|
232
|
+
|
|
233
|
+
event.preventDefault();
|
|
104
234
|
}
|
|
105
235
|
|
|
106
236
|
isActive() {
|
|
@@ -109,6 +239,30 @@ export default class RichTextarea extends Element {
|
|
|
109
239
|
return active;
|
|
110
240
|
}
|
|
111
241
|
|
|
242
|
+
undo(event, element) {
|
|
243
|
+
const operation = this.undoBuffer.undo();
|
|
244
|
+
|
|
245
|
+
if (operation !== null) {
|
|
246
|
+
const undoable = false;
|
|
247
|
+
|
|
248
|
+
this.applyOperation(operation);
|
|
249
|
+
|
|
250
|
+
this.intermediateHandler(event, element, undoable);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
redo(event, element) {
|
|
255
|
+
const operation = this.undoBuffer.redo();
|
|
256
|
+
|
|
257
|
+
if (operation !== null) {
|
|
258
|
+
const undoable = false;
|
|
259
|
+
|
|
260
|
+
this.applyOperation(operation);
|
|
261
|
+
|
|
262
|
+
this.intermediateHandler(event, element, undoable);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
112
266
|
getContent() {
|
|
113
267
|
const domElement = this.getDOMElement(),
|
|
114
268
|
{ value } = domElement,
|
|
@@ -124,71 +278,81 @@ export default class RichTextarea extends Element {
|
|
|
124
278
|
return selection;
|
|
125
279
|
}
|
|
126
280
|
|
|
127
|
-
|
|
281
|
+
getSelectedContent() {
|
|
282
|
+
const content = this.getContent(),
|
|
283
|
+
selection = this.getSelection(),
|
|
284
|
+
endPosition = selection.getEndPosition(),
|
|
285
|
+
startPosition = selection.getStartPosition(),
|
|
286
|
+
start = startPosition, ///
|
|
287
|
+
end = endPosition, ///
|
|
288
|
+
selectedContent = content.slice(start, end);
|
|
289
|
+
|
|
290
|
+
return selectedContent;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
hasContentChanged() {
|
|
294
|
+
const content = this.getContent(),
|
|
295
|
+
contentPreviousContent = (content === this.previousContent),
|
|
296
|
+
contentChanged = !contentPreviousContent;
|
|
297
|
+
|
|
298
|
+
return contentChanged;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
hasSelectionChanged() {
|
|
302
|
+
const selection = this.getSelection(),
|
|
303
|
+
selectionPreviousSelection = selection.isEqualTo(this.previousSelection),
|
|
304
|
+
selectionChanged = !selectionPreviousSelection; ///
|
|
305
|
+
|
|
306
|
+
return selectionChanged;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
setContent(content, setPreviousContent = true) {
|
|
128
310
|
const value = content, ///
|
|
129
|
-
previousContent = content, ///
|
|
130
311
|
domElement = this.getDOMElement();
|
|
131
312
|
|
|
132
313
|
Object.assign(domElement, {
|
|
133
314
|
value
|
|
134
315
|
});
|
|
135
316
|
|
|
136
|
-
|
|
317
|
+
if (setPreviousContent) {
|
|
318
|
+
this.previousContent = content; ///
|
|
319
|
+
}
|
|
137
320
|
}
|
|
138
321
|
|
|
139
|
-
setSelection(selection) {
|
|
322
|
+
setSelection(selection, setPreviousSelection = true) {
|
|
140
323
|
const selectionStartPosition = selection.getStartPosition(),
|
|
141
324
|
selectionEndPosition = selection.getEndPosition(),
|
|
142
325
|
selectionStart = selectionStartPosition, ///
|
|
143
326
|
selectionEnd = selectionEndPosition, ///
|
|
144
|
-
previousSelection = selection, ///
|
|
145
327
|
domElement = this.getDOMElement();
|
|
146
328
|
|
|
147
|
-
|
|
148
|
-
selectionStart,
|
|
149
|
-
selectionEnd
|
|
150
|
-
});
|
|
329
|
+
domElement.setSelectionRange(selectionStart, selectionEnd);
|
|
151
330
|
|
|
152
|
-
|
|
331
|
+
if (setPreviousSelection) {
|
|
332
|
+
this.previousSelection = selection; ///
|
|
333
|
+
}
|
|
153
334
|
}
|
|
154
335
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
changed = (contentChanged || selectionChanged);
|
|
336
|
+
applyOperation(operation) {
|
|
337
|
+
let content = this.getContent(),
|
|
338
|
+
selection = this.getSelection();
|
|
159
339
|
|
|
160
|
-
|
|
161
|
-
|
|
340
|
+
const transformedContent = operation.transformContent(content),
|
|
341
|
+
transformedSelection = operation.transformSelection(selection);
|
|
162
342
|
|
|
163
|
-
|
|
164
|
-
const content = this.getContent(),
|
|
165
|
-
previousContent = this.getPreviousContent(),
|
|
166
|
-
contentDifferentToPreviousContent = (content !== previousContent),
|
|
167
|
-
contentChanged = contentDifferentToPreviousContent; ///
|
|
343
|
+
content = transformedContent; ///
|
|
168
344
|
|
|
169
|
-
|
|
170
|
-
}
|
|
345
|
+
selection = transformedSelection; ///
|
|
171
346
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
previousSelection = this.getPreviousSelection(),
|
|
175
|
-
selectionDifferentToPreviousSelection = selection.isDifferentTo(previousSelection),
|
|
176
|
-
selectionChanged = selectionDifferentToPreviousSelection; ///
|
|
347
|
+
const setPreviousContent = false,
|
|
348
|
+
setPreviousSelection = false;
|
|
177
349
|
|
|
178
|
-
|
|
350
|
+
this.setContent(content, setPreviousContent);
|
|
351
|
+
|
|
352
|
+
this.setSelection(selection, setPreviousSelection);
|
|
179
353
|
}
|
|
180
354
|
|
|
181
355
|
activate() {
|
|
182
|
-
const mouseDown = false;
|
|
183
|
-
|
|
184
|
-
this.setMouseDown(mouseDown);
|
|
185
|
-
|
|
186
|
-
window.on(`${BLUR_EVENT_TYPE} ${MOUSEUP_EVENT_TYPE} ${CONTEXTMENU_EVENT_TYPE}`, this.mouseUpHandler, this); ///
|
|
187
|
-
|
|
188
|
-
this.on(MOUSEDOWN_EVENT_TYPE, this.mouseDownHandler, this);
|
|
189
|
-
|
|
190
|
-
this.on(MOUSEMOVE_EVENT_TYPE, this.mouseMoveHandler, this);
|
|
191
|
-
|
|
192
356
|
this.on(KEYDOWN_EVENT_TYPE, this.keyDownHandler, this);
|
|
193
357
|
|
|
194
358
|
this.on(INPUT_EVENT_TYPE, this.inputHandler, this);
|
|
@@ -203,16 +367,6 @@ export default class RichTextarea extends Element {
|
|
|
203
367
|
}
|
|
204
368
|
|
|
205
369
|
deactivate() {
|
|
206
|
-
const mouseDown = false;
|
|
207
|
-
|
|
208
|
-
this.setMouseDown(mouseDown);
|
|
209
|
-
|
|
210
|
-
window.off(`${BLUR_EVENT_TYPE} ${MOUSEUP_EVENT_TYPE} ${CONTEXTMENU_EVENT_TYPE}`, this.mouseUpHandler, this); ///
|
|
211
|
-
|
|
212
|
-
this.off(MOUSEDOWN_EVENT_TYPE, this.mouseDownHandler, this);
|
|
213
|
-
|
|
214
|
-
this.off(MOUSEMOVE_EVENT_TYPE, this.mouseMoveHandler, this);
|
|
215
|
-
|
|
216
370
|
this.off(KEYDOWN_EVENT_TYPE, this.keyDownHandler, this);
|
|
217
371
|
|
|
218
372
|
this.off(INPUT_EVENT_TYPE, this.inputHandler, this);
|
|
@@ -286,8 +440,12 @@ export default class RichTextarea extends Element {
|
|
|
286
440
|
const eventListeners = this.findEventListeners(eventType);
|
|
287
441
|
|
|
288
442
|
eventListeners.forEach((eventListener) => {
|
|
289
|
-
|
|
290
|
-
|
|
443
|
+
let { element } = eventListener;
|
|
444
|
+
|
|
445
|
+
const { handler } = eventListener,
|
|
446
|
+
handlerElement = element; ///
|
|
447
|
+
|
|
448
|
+
element = this; ///
|
|
291
449
|
|
|
292
450
|
if ((handler !== this.blurHandler) && (handler !== this.focusHandler) && (handler !== this.scrollHandler)) {
|
|
293
451
|
handler.call(handlerElement, ...remainingArguments, element);
|
|
@@ -295,88 +453,37 @@ export default class RichTextarea extends Element {
|
|
|
295
453
|
});
|
|
296
454
|
}
|
|
297
455
|
|
|
298
|
-
|
|
299
|
-
const {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
isMouseDown() {
|
|
305
|
-
const { mouseDown } = this.getState();
|
|
306
|
-
|
|
307
|
-
return mouseDown;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
getPreviousContent() {
|
|
311
|
-
const { previousContent } = this.getState();
|
|
312
|
-
|
|
313
|
-
return previousContent;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
getPreviousSelection() {
|
|
317
|
-
const { previousSelection } = this.getState();
|
|
456
|
+
didMount() {
|
|
457
|
+
const { onChange, onScroll, onFocus, onBlur } = this.properties,
|
|
458
|
+
changeHandler = onChange, ///
|
|
459
|
+
scrollHandler = onScroll, ///
|
|
460
|
+
focusHandler = onFocus, ///
|
|
461
|
+
blurHandler = onBlur; ///
|
|
318
462
|
|
|
319
|
-
|
|
320
|
-
|
|
463
|
+
const content = this.getContent(),
|
|
464
|
+
selection = this.getSelection();
|
|
321
465
|
|
|
322
|
-
|
|
323
|
-
this.updateState({
|
|
324
|
-
readOnly
|
|
325
|
-
});
|
|
326
|
-
}
|
|
466
|
+
this.previousContent = content; ///
|
|
327
467
|
|
|
328
|
-
|
|
329
|
-
this.updateState({
|
|
330
|
-
mouseDown
|
|
331
|
-
});
|
|
332
|
-
}
|
|
468
|
+
this.previousSelection = selection; ///
|
|
333
469
|
|
|
334
|
-
|
|
335
|
-
this.updateState({
|
|
336
|
-
previousContent
|
|
337
|
-
});
|
|
338
|
-
}
|
|
470
|
+
changeHandler && this.onChange(changeHandler, this);
|
|
339
471
|
|
|
340
|
-
|
|
341
|
-
this.updateState({
|
|
342
|
-
previousSelection
|
|
343
|
-
});
|
|
344
|
-
}
|
|
472
|
+
scrollHandler && this.onScroll(scrollHandler, this);
|
|
345
473
|
|
|
346
|
-
|
|
347
|
-
const readOnly = false,
|
|
348
|
-
mouseDown = false,
|
|
349
|
-
previousContent = null,
|
|
350
|
-
previousSelection = null;
|
|
474
|
+
focusHandler && this.onFocus(focusHandler, this);
|
|
351
475
|
|
|
352
|
-
this.
|
|
353
|
-
readOnly,
|
|
354
|
-
mouseDown,
|
|
355
|
-
previousContent,
|
|
356
|
-
previousSelection
|
|
357
|
-
});
|
|
358
|
-
}
|
|
476
|
+
blurHandler && this.onBlur(blurHandler, this);
|
|
359
477
|
|
|
360
|
-
|
|
361
|
-
const { onChange, onScroll, onFocus, onBlur } = this.properties,
|
|
362
|
-
changeHandler = onChange, ///
|
|
363
|
-
scrollHandler = onScroll, ///
|
|
364
|
-
focusHandler = onFocus, ///
|
|
365
|
-
blurHandler = onBlur; ///
|
|
478
|
+
this.on(CUT_EVENT_TYPE, this.cutHandler);
|
|
366
479
|
|
|
367
|
-
|
|
368
|
-
scrollHandler && this.onScroll(scrollHandler, this);
|
|
369
|
-
focusHandler && this.onFocus(focusHandler, this);
|
|
370
|
-
blurHandler && this.onBlur(blurHandler, this);
|
|
480
|
+
this.on(COPY_EVENT_TYPE, this.copyHandler);
|
|
371
481
|
|
|
372
|
-
|
|
373
|
-
selection = this.getSelection(),
|
|
374
|
-
previousContent = content, ///
|
|
375
|
-
previousSelection = selection; ///
|
|
482
|
+
this.on(PASTE_EVENT_TYPE, this.pasteHandler);
|
|
376
483
|
|
|
377
|
-
this.
|
|
484
|
+
this.on(CONTEXTMENU_EVENT_TYPE, this.contextmenuHandler);
|
|
378
485
|
|
|
379
|
-
this.
|
|
486
|
+
document.on(SELECTIONCHANGE_EVENT_TYPE, this.selectChangeHandler);
|
|
380
487
|
}
|
|
381
488
|
|
|
382
489
|
willUnmount() {
|
|
@@ -387,10 +494,23 @@ export default class RichTextarea extends Element {
|
|
|
387
494
|
blurHandler = onBlur; ///
|
|
388
495
|
|
|
389
496
|
changeHandler && this.offChange(changeHandler, this);
|
|
497
|
+
|
|
390
498
|
scrollHandler && this.offScroll(scrollHandler, this);
|
|
499
|
+
|
|
391
500
|
focusHandler && this.offFocus(focusHandler, this);
|
|
501
|
+
|
|
392
502
|
blurHandler && this.offBlur(blurHandler, this);
|
|
393
503
|
|
|
504
|
+
this.off(CUT_EVENT_TYPE, this.cutHandler);
|
|
505
|
+
|
|
506
|
+
this.off(COPY_EVENT_TYPE, this.copyHandler);
|
|
507
|
+
|
|
508
|
+
this.off(PASTE_EVENT_TYPE, this.pasteHandler);
|
|
509
|
+
|
|
510
|
+
this.off(CONTEXTMENU_EVENT_TYPE, this.contextmenuHandler);
|
|
511
|
+
|
|
512
|
+
document.off(SELECTIONCHANGE_EVENT_TYPE, this.selectChangeHandler);
|
|
513
|
+
|
|
394
514
|
const active = this.isActive();
|
|
395
515
|
|
|
396
516
|
if (active) {
|
|
@@ -398,10 +518,6 @@ export default class RichTextarea extends Element {
|
|
|
398
518
|
}
|
|
399
519
|
}
|
|
400
520
|
|
|
401
|
-
initialise() {
|
|
402
|
-
this.setInitialState();
|
|
403
|
-
}
|
|
404
|
-
|
|
405
521
|
static tagName = "textarea";
|
|
406
522
|
|
|
407
523
|
static ignoredProperties = [
|
|
@@ -414,4 +530,19 @@ export default class RichTextarea extends Element {
|
|
|
414
530
|
static defaultProperties = {
|
|
415
531
|
className: "rich"
|
|
416
532
|
};
|
|
533
|
+
|
|
534
|
+
static fromClass(Class, properties, ...remainingArguments) {
|
|
535
|
+
const focused = false,
|
|
536
|
+
readOnly = false,
|
|
537
|
+
undoBuffer = UndoBuffer.fromNothing(),
|
|
538
|
+
previousContent = null,
|
|
539
|
+
previousSelection = null,
|
|
540
|
+
richTextarea = Element.fromClass(Class, properties, focused, readOnly, undoBuffer, previousContent, previousSelection, ...remainingArguments);
|
|
541
|
+
|
|
542
|
+
return richTextarea;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function defer(func) {
|
|
547
|
+
setTimeout(func, 0);
|
|
417
548
|
}
|