suneditor 3.0.0-beta.2 → 3.0.0-beta.20
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/CONTRIBUTING.md +186 -184
- package/LICENSE +21 -21
- package/README.md +157 -180
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +126 -123
- package/src/assets/design/color.css +131 -121
- package/src/assets/design/index.css +3 -3
- package/src/assets/design/size.css +37 -35
- package/src/assets/design/typography.css +37 -37
- package/src/assets/icons/defaultIcons.js +247 -232
- package/src/assets/suneditor-contents.css +779 -778
- package/src/assets/suneditor.css +43 -35
- package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
- package/src/core/base/eventManager.js +1550 -1484
- package/src/core/base/history.js +355 -355
- package/src/core/class/char.js +163 -162
- package/src/core/class/component.js +856 -842
- package/src/core/class/format.js +3433 -3422
- package/src/core/class/html.js +1927 -1890
- package/src/core/class/menu.js +357 -346
- package/src/core/class/nodeTransform.js +424 -424
- package/src/core/class/offset.js +858 -891
- package/src/core/class/selection.js +710 -620
- package/src/core/class/shortcuts.js +98 -98
- package/src/core/class/toolbar.js +438 -430
- package/src/core/class/ui.js +424 -422
- package/src/core/class/viewer.js +750 -750
- package/src/core/editor.js +1810 -1708
- package/src/core/section/actives.js +268 -241
- package/src/core/section/constructor.js +1348 -1661
- package/src/core/section/context.js +102 -102
- package/src/core/section/documentType.js +582 -561
- package/src/core/section/options.js +367 -0
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +36 -36
- package/src/editorInjector/_core.js +92 -92
- package/src/editorInjector/index.js +75 -75
- package/src/events.js +634 -622
- package/src/helper/clipboard.js +59 -59
- package/src/helper/converter.js +586 -564
- package/src/helper/dom/domCheck.js +304 -304
- package/src/helper/dom/domQuery.js +677 -669
- package/src/helper/dom/domUtils.js +618 -557
- package/src/helper/dom/index.js +12 -12
- package/src/helper/env.js +249 -240
- package/src/helper/index.js +25 -25
- package/src/helper/keyCodeMap.js +183 -183
- package/src/helper/numbers.js +72 -72
- package/src/helper/unicode.js +47 -47
- package/src/langs/ckb.js +231 -231
- package/src/langs/cs.js +231 -231
- package/src/langs/da.js +231 -231
- package/src/langs/de.js +231 -231
- package/src/langs/en.js +230 -230
- package/src/langs/es.js +231 -231
- package/src/langs/fa.js +231 -231
- package/src/langs/fr.js +231 -231
- package/src/langs/he.js +231 -231
- package/src/langs/hu.js +230 -230
- package/src/langs/index.js +28 -28
- package/src/langs/it.js +231 -231
- package/src/langs/ja.js +230 -230
- package/src/langs/km.js +230 -230
- package/src/langs/ko.js +230 -230
- package/src/langs/lv.js +231 -231
- package/src/langs/nl.js +231 -231
- package/src/langs/pl.js +231 -231
- package/src/langs/pt_br.js +231 -231
- package/src/langs/ro.js +231 -231
- package/src/langs/ru.js +231 -231
- package/src/langs/se.js +231 -231
- package/src/langs/tr.js +231 -231
- package/src/langs/uk.js +231 -231
- package/src/langs/ur.js +231 -231
- package/src/langs/zh_cn.js +231 -231
- package/src/modules/ApiManager.js +191 -191
- package/src/modules/Browser.js +669 -667
- package/src/modules/ColorPicker.js +364 -362
- package/src/modules/Controller.js +474 -454
- package/src/modules/Figure.js +1620 -1617
- package/src/modules/FileManager.js +359 -359
- package/src/modules/HueSlider.js +577 -565
- package/src/modules/Modal.js +346 -346
- package/src/modules/ModalAnchorEditor.js +643 -643
- package/src/modules/SelectMenu.js +549 -549
- package/src/modules/_DragHandle.js +17 -17
- package/src/modules/index.js +14 -14
- package/src/plugins/browser/audioGallery.js +83 -83
- package/src/plugins/browser/fileBrowser.js +103 -103
- package/src/plugins/browser/fileGallery.js +83 -83
- package/src/plugins/browser/imageGallery.js +81 -81
- package/src/plugins/browser/videoGallery.js +103 -103
- package/src/plugins/command/blockquote.js +61 -60
- package/src/plugins/command/exportPDF.js +134 -134
- package/src/plugins/command/fileUpload.js +456 -456
- package/src/plugins/command/list_bulleted.js +149 -148
- package/src/plugins/command/list_numbered.js +152 -151
- package/src/plugins/dropdown/align.js +157 -155
- package/src/plugins/dropdown/backgroundColor.js +108 -104
- package/src/plugins/dropdown/font.js +141 -137
- package/src/plugins/dropdown/fontColor.js +109 -105
- package/src/plugins/dropdown/formatBlock.js +170 -178
- package/src/plugins/dropdown/hr.js +152 -152
- package/src/plugins/dropdown/layout.js +83 -83
- package/src/plugins/dropdown/lineHeight.js +131 -130
- package/src/plugins/dropdown/list.js +123 -122
- package/src/plugins/dropdown/paragraphStyle.js +138 -138
- package/src/plugins/dropdown/table.js +4110 -4000
- package/src/plugins/dropdown/template.js +83 -83
- package/src/plugins/dropdown/textStyle.js +149 -149
- package/src/plugins/field/mention.js +242 -242
- package/src/plugins/index.js +120 -120
- package/src/plugins/input/fontSize.js +414 -410
- package/src/plugins/input/pageNavigator.js +71 -70
- package/src/plugins/modal/audio.js +677 -677
- package/src/plugins/modal/drawing.js +537 -531
- package/src/plugins/modal/embed.js +886 -886
- package/src/plugins/modal/image.js +1377 -1376
- package/src/plugins/modal/link.js +248 -240
- package/src/plugins/modal/math.js +563 -563
- package/src/plugins/modal/video.js +1226 -1226
- package/src/plugins/popup/anchor.js +224 -222
- package/src/suneditor.js +114 -107
- package/src/themes/dark.css +132 -122
- package/src/typedef.js +132 -130
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/base/eventManager.d.ts +29 -4
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +1 -2
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +6 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +34 -12
- package/types/core/section/constructor.d.ts +5 -638
- package/types/core/section/documentType.d.ts +12 -2
- package/types/core/section/options.d.ts +740 -0
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_core.d.ts +5 -5
- package/types/editorInjector/index.d.ts +2 -2
- package/types/events.d.ts +2 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domQuery.d.ts +5 -5
- package/types/helper/dom/domUtils.d.ts +8 -0
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +4 -1
- package/types/index.d.ts +122 -120
- package/types/langs/_Lang.d.ts +194 -194
- package/types/modules/ColorPicker.d.ts +5 -1
- package/types/modules/Controller.d.ts +8 -4
- package/types/modules/Figure.d.ts +2 -1
- package/types/modules/HueSlider.d.ts +4 -1
- package/types/modules/SelectMenu.d.ts +1 -1
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +1 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
- package/types/plugins/dropdown/font.d.ts +1 -0
- package/types/plugins/dropdown/fontColor.d.ts +1 -0
- package/types/plugins/dropdown/formatBlock.d.ts +3 -2
- package/types/plugins/dropdown/lineHeight.d.ts +1 -0
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/table.d.ts +6 -0
- package/types/plugins/input/fontSize.d.ts +1 -0
- package/types/plugins/modal/drawing.d.ts +4 -0
- package/types/plugins/modal/link.d.ts +32 -15
- package/types/suneditor.d.ts +13 -9
- package/types/typedef.d.ts +8 -0
|
@@ -1,531 +1,537 @@
|
|
|
1
|
-
import EditorInjector from '../../editorInjector';
|
|
2
|
-
import { Modal } from '../../modules';
|
|
3
|
-
import { dom, env } from '../../helper';
|
|
4
|
-
|
|
5
|
-
const { _w,
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {Object} DrawingPluginOptions
|
|
9
|
-
* @property {string} [outputFormat="dataurl"] - The output format of the drawing. Options: "dataurl", "svg".
|
|
10
|
-
* @property {boolean} [useFormatType=false] - Whether to enable format type selection (block vs inline).
|
|
11
|
-
* @property {string} [defaultFormatType="block"] - The default format type, either "block" or "inline".
|
|
12
|
-
* @property {boolean} [keepFormatType=false] - Whether to maintain the chosen format type after drawing.
|
|
13
|
-
* @property {number} [lineWidth=5] - The width of the drawing line.
|
|
14
|
-
* @property {boolean} [lineReconnect=false] - Whether to reconnect lines when drawing.
|
|
15
|
-
* @property {CanvasLineCap} [lineCap="round"] - The style of the line cap ("butt", "round", or "square").
|
|
16
|
-
* @property {string} [lineColor=""] - The color of the drawing line.
|
|
17
|
-
* @property {boolean} [canResize=true] - Whether the modal form can be resized.
|
|
18
|
-
* @property {boolean} [maintainRatio=true] - Whether to maintain the aspect ratio when resizing.
|
|
19
|
-
* @property {Object} [formSize={}] - The size configuration for the drawing modal form.
|
|
20
|
-
* @property {string} [formSize.width="750px"] - The width of the modal form.
|
|
21
|
-
* @property {string} [formSize.height="50vh"] - The height of the modal form.
|
|
22
|
-
* @property {string} [formSize.maxWidth=""] - The maximum width of the modal form.
|
|
23
|
-
* @property {string} [formSize.maxHeight=""] - The maximum height of the modal form.
|
|
24
|
-
* @property {string} [formSize.minWidth="150px"] - The minimum width of the modal form.
|
|
25
|
-
* @property {string} [formSize.minHeight="100px"] - The minimum height of the modal form.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @class
|
|
30
|
-
* @description Drawing modal plugin.
|
|
31
|
-
*/
|
|
32
|
-
class Drawing extends EditorInjector {
|
|
33
|
-
static key = 'drawing';
|
|
34
|
-
static type = 'modal';
|
|
35
|
-
static className = '';
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @constructor
|
|
39
|
-
* @param {__se__EditorCore} editor - The root editor instance
|
|
40
|
-
* @param {DrawingPluginOptions} pluginOptions
|
|
41
|
-
*/
|
|
42
|
-
constructor(editor, pluginOptions) {
|
|
43
|
-
// plugin basic properties
|
|
44
|
-
super(editor);
|
|
45
|
-
this.title = this.lang.drawing;
|
|
46
|
-
this.icon = 'drawing';
|
|
47
|
-
this.pluginOptions = {
|
|
48
|
-
outputFormat: pluginOptions.outputFormat || 'dataurl', // dataurl, svg
|
|
49
|
-
useFormatType: pluginOptions.useFormatType ?? false,
|
|
50
|
-
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block',
|
|
51
|
-
keepFormatType: pluginOptions.keepFormatType ?? false,
|
|
52
|
-
lineWidth: pluginOptions.lineWidth || 5,
|
|
53
|
-
lineReconnect: !!pluginOptions.lineReconnect,
|
|
54
|
-
lineCap: ['butt', 'round', 'square'].includes(pluginOptions.lineCap) ? pluginOptions.lineCap : 'round',
|
|
55
|
-
lineColor: pluginOptions.lineColor || '',
|
|
56
|
-
formSize: {
|
|
57
|
-
width: '750px',
|
|
58
|
-
height: '50vh',
|
|
59
|
-
maxWidth: '',
|
|
60
|
-
maxHeight: '',
|
|
61
|
-
minWidth: '150px',
|
|
62
|
-
minHeight: '100px',
|
|
63
|
-
...pluginOptions.formSize
|
|
64
|
-
},
|
|
65
|
-
canResize: pluginOptions.canResize ?? true,
|
|
66
|
-
maintainRatio: pluginOptions.maintainRatio ?? true
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// exception
|
|
70
|
-
if (!this.plugins.image) {
|
|
71
|
-
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.');
|
|
72
|
-
} else if (this.pluginOptions.outputFormat === 'svg' && !this.plugins.image.pluginOptions.uploadUrl) {
|
|
73
|
-
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// create HTML
|
|
77
|
-
const modalEl = CreateHTML_modal(this);
|
|
78
|
-
|
|
79
|
-
// modules
|
|
80
|
-
this.modal = new Modal(this, modalEl);
|
|
81
|
-
|
|
82
|
-
// members
|
|
83
|
-
this.as = this.pluginOptions.defaultFormatType;
|
|
84
|
-
if (this.pluginOptions.useFormatType) {
|
|
85
|
-
this.asBlock = modalEl.querySelector('[data-command="asBlock"]');
|
|
86
|
-
this.asInline = modalEl.querySelector('[data-command="asInline"]');
|
|
87
|
-
this.eventManager.addEvent([this.asBlock, this.asInline], 'click', this.#OnClickAsButton.bind(this));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @type {HTMLCanvasElement}
|
|
92
|
-
*/
|
|
93
|
-
this.canvas = null;
|
|
94
|
-
this.ctx = null;
|
|
95
|
-
this.isDrawing = false;
|
|
96
|
-
this.points = [];
|
|
97
|
-
this.paths = [];
|
|
98
|
-
this.resizeObserver = null;
|
|
99
|
-
this.__events = {
|
|
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
|
-
this.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
this.
|
|
186
|
-
|
|
187
|
-
this.
|
|
188
|
-
|
|
189
|
-
this.__eventsRegister.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
this.
|
|
227
|
-
this.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
this.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
this.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
this.isDrawing
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
this.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
<div class="se-modal-
|
|
484
|
-
<
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
1
|
+
import EditorInjector from '../../editorInjector';
|
|
2
|
+
import { Modal } from '../../modules';
|
|
3
|
+
import { dom, env } from '../../helper';
|
|
4
|
+
|
|
5
|
+
const { _w, isTouchDevice } = env;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} DrawingPluginOptions
|
|
9
|
+
* @property {string} [outputFormat="dataurl"] - The output format of the drawing. Options: "dataurl", "svg".
|
|
10
|
+
* @property {boolean} [useFormatType=false] - Whether to enable format type selection (block vs inline).
|
|
11
|
+
* @property {string} [defaultFormatType="block"] - The default format type, either "block" or "inline".
|
|
12
|
+
* @property {boolean} [keepFormatType=false] - Whether to maintain the chosen format type after drawing.
|
|
13
|
+
* @property {number} [lineWidth=5] - The width of the drawing line.
|
|
14
|
+
* @property {boolean} [lineReconnect=false] - Whether to reconnect lines when drawing.
|
|
15
|
+
* @property {CanvasLineCap} [lineCap="round"] - The style of the line cap ("butt", "round", or "square").
|
|
16
|
+
* @property {string} [lineColor=""] - The color of the drawing line.
|
|
17
|
+
* @property {boolean} [canResize=true] - Whether the modal form can be resized.
|
|
18
|
+
* @property {boolean} [maintainRatio=true] - Whether to maintain the aspect ratio when resizing.
|
|
19
|
+
* @property {Object} [formSize={}] - The size configuration for the drawing modal form.
|
|
20
|
+
* @property {string} [formSize.width="750px"] - The width of the modal form.
|
|
21
|
+
* @property {string} [formSize.height="50vh"] - The height of the modal form.
|
|
22
|
+
* @property {string} [formSize.maxWidth=""] - The maximum width of the modal form.
|
|
23
|
+
* @property {string} [formSize.maxHeight=""] - The maximum height of the modal form.
|
|
24
|
+
* @property {string} [formSize.minWidth="150px"] - The minimum width of the modal form.
|
|
25
|
+
* @property {string} [formSize.minHeight="100px"] - The minimum height of the modal form.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @class
|
|
30
|
+
* @description Drawing modal plugin.
|
|
31
|
+
*/
|
|
32
|
+
class Drawing extends EditorInjector {
|
|
33
|
+
static key = 'drawing';
|
|
34
|
+
static type = 'modal';
|
|
35
|
+
static className = '';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @constructor
|
|
39
|
+
* @param {__se__EditorCore} editor - The root editor instance
|
|
40
|
+
* @param {DrawingPluginOptions} pluginOptions
|
|
41
|
+
*/
|
|
42
|
+
constructor(editor, pluginOptions) {
|
|
43
|
+
// plugin basic properties
|
|
44
|
+
super(editor);
|
|
45
|
+
this.title = this.lang.drawing;
|
|
46
|
+
this.icon = 'drawing';
|
|
47
|
+
this.pluginOptions = {
|
|
48
|
+
outputFormat: pluginOptions.outputFormat || 'dataurl', // dataurl, svg
|
|
49
|
+
useFormatType: pluginOptions.useFormatType ?? false,
|
|
50
|
+
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block',
|
|
51
|
+
keepFormatType: pluginOptions.keepFormatType ?? false,
|
|
52
|
+
lineWidth: pluginOptions.lineWidth || 5,
|
|
53
|
+
lineReconnect: !!pluginOptions.lineReconnect,
|
|
54
|
+
lineCap: ['butt', 'round', 'square'].includes(pluginOptions.lineCap) ? pluginOptions.lineCap : 'round',
|
|
55
|
+
lineColor: pluginOptions.lineColor || '',
|
|
56
|
+
formSize: {
|
|
57
|
+
width: '750px',
|
|
58
|
+
height: '50vh',
|
|
59
|
+
maxWidth: '',
|
|
60
|
+
maxHeight: '',
|
|
61
|
+
minWidth: '150px',
|
|
62
|
+
minHeight: '100px',
|
|
63
|
+
...pluginOptions.formSize
|
|
64
|
+
},
|
|
65
|
+
canResize: pluginOptions.canResize ?? true,
|
|
66
|
+
maintainRatio: pluginOptions.maintainRatio ?? true
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// exception
|
|
70
|
+
if (!this.plugins.image) {
|
|
71
|
+
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.');
|
|
72
|
+
} else if (this.pluginOptions.outputFormat === 'svg' && !this.plugins.image.pluginOptions.uploadUrl) {
|
|
73
|
+
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// create HTML
|
|
77
|
+
const modalEl = CreateHTML_modal(this);
|
|
78
|
+
|
|
79
|
+
// modules
|
|
80
|
+
this.modal = new Modal(this, modalEl);
|
|
81
|
+
|
|
82
|
+
// members
|
|
83
|
+
this.as = this.pluginOptions.defaultFormatType;
|
|
84
|
+
if (this.pluginOptions.useFormatType) {
|
|
85
|
+
this.asBlock = modalEl.querySelector('[data-command="asBlock"]');
|
|
86
|
+
this.asInline = modalEl.querySelector('[data-command="asInline"]');
|
|
87
|
+
this.eventManager.addEvent([this.asBlock, this.asInline], 'click', this.#OnClickAsButton.bind(this));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @type {HTMLCanvasElement}
|
|
92
|
+
*/
|
|
93
|
+
this.canvas = null;
|
|
94
|
+
this.ctx = null;
|
|
95
|
+
this.isDrawing = false;
|
|
96
|
+
this.points = [];
|
|
97
|
+
this.paths = [];
|
|
98
|
+
this.resizeObserver = null;
|
|
99
|
+
this.__events = {
|
|
100
|
+
touchstart: this.#OnCanvasTouchStart.bind(this),
|
|
101
|
+
touchmove: this.#OnCanvasTouchMove.bind(this),
|
|
102
|
+
mousedown: this.#OnCanvasMouseDown.bind(this),
|
|
103
|
+
mousemove: this.#OnCanvasMouseMove.bind(this),
|
|
104
|
+
mouseup: this.#OnCanvasMouseUp.bind(this),
|
|
105
|
+
mouseleave: this.#OnCanvasMouseLeave.bind(this),
|
|
106
|
+
mouseenter: this.#OnCanvasMouseEnter.bind(this)
|
|
107
|
+
};
|
|
108
|
+
this.__eventsRegister = {
|
|
109
|
+
touchstart: null,
|
|
110
|
+
touchmove: null,
|
|
111
|
+
mousedown: null,
|
|
112
|
+
mousemove: null,
|
|
113
|
+
mouseup: null,
|
|
114
|
+
mouseleave: null,
|
|
115
|
+
mouseenter: null
|
|
116
|
+
};
|
|
117
|
+
this.__eventNameMap = {
|
|
118
|
+
mousedown: isTouchDevice ? 'touchstart' : 'mousedown',
|
|
119
|
+
mousemove: isTouchDevice ? 'touchmove' : 'mousemove',
|
|
120
|
+
mouseup: isTouchDevice ? 'touchend' : 'mouseup',
|
|
121
|
+
mouseleave: 'mouseleave',
|
|
122
|
+
mouseenter: 'mouseenter'
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// init
|
|
126
|
+
this.eventManager.addEvent(modalEl.querySelector('[data-command="remove"]'), 'click', this.#OnRemove.bind(this));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @editorMethod Modules.Modal
|
|
131
|
+
* @description Executes the method that is called when a "Modal" module's is opened.
|
|
132
|
+
*/
|
|
133
|
+
open() {
|
|
134
|
+
if (this.pluginOptions.useFormatType) {
|
|
135
|
+
this._activeAsInline((this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === 'inline');
|
|
136
|
+
}
|
|
137
|
+
this.modal.open();
|
|
138
|
+
this._initDrawing();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @editorMethod Modules.Modal
|
|
143
|
+
* @description Executes the method that is called when a plugin's "modal" is closed.
|
|
144
|
+
*/
|
|
145
|
+
off() {
|
|
146
|
+
this._destroyDrawing();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @editorMethod Modules.Modal
|
|
151
|
+
* @description This function is called when a form within a modal window is "submit".
|
|
152
|
+
* @returns {boolean} Success or failure
|
|
153
|
+
*/
|
|
154
|
+
modalAction() {
|
|
155
|
+
if (this.pluginOptions.outputFormat === 'svg') {
|
|
156
|
+
const files = this._getSVGFileList();
|
|
157
|
+
this.plugins.image.init();
|
|
158
|
+
this.plugins.image.submitFile(files);
|
|
159
|
+
} else {
|
|
160
|
+
// dataurl | svg
|
|
161
|
+
const data = this.canvas.toDataURL();
|
|
162
|
+
const file = { name: 'drawing', size: 0 };
|
|
163
|
+
this.plugins.image.init();
|
|
164
|
+
if (this.as !== 'inline') {
|
|
165
|
+
this.plugins.image.create(data, null, 'auto', '', 'none', file, '');
|
|
166
|
+
} else {
|
|
167
|
+
this.plugins.image.createInline(data, null, 'auto', '', 'none', file, '');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @private
|
|
176
|
+
* @description Initializes the drawing canvas, sets up event listeners, and configures resize handling.
|
|
177
|
+
*/
|
|
178
|
+
_initDrawing() {
|
|
179
|
+
const canvas = (this.canvas = this.modal.form.querySelector('.se-drawing-canvas'));
|
|
180
|
+
this.ctx = canvas.getContext('2d');
|
|
181
|
+
canvas.width = canvas.offsetWidth;
|
|
182
|
+
canvas.height = canvas.offsetHeight;
|
|
183
|
+
|
|
184
|
+
this.points = [];
|
|
185
|
+
this.paths = [];
|
|
186
|
+
|
|
187
|
+
this._setCtx();
|
|
188
|
+
|
|
189
|
+
this.__eventsRegister.touchstart = this.eventManager.addEvent(canvas, 'touchstart', this.__events.touchstart, { passive: false, capture: true });
|
|
190
|
+
this.__eventsRegister.touchmove = this.eventManager.addEvent(canvas, 'touchmove', this.__events.touchmove, true);
|
|
191
|
+
this.__eventsRegister.mousedown = this.eventManager.addEvent(canvas, 'mousedown', this.__events.mousedown, { passive: false, capture: true });
|
|
192
|
+
this.__eventsRegister.mousemove = this.eventManager.addEvent(canvas, 'mousemove', this.__events.mousemove, true);
|
|
193
|
+
this.__eventsRegister.mouseup = this.eventManager.addEvent(canvas, 'mouseup', this.__events.mouseup, true);
|
|
194
|
+
this.__eventsRegister.mouseleave = this.eventManager.addEvent(canvas, 'mouseleave', this.__events.mouseleave);
|
|
195
|
+
this.__eventsRegister.mouseenter = this.eventManager.addEvent(canvas, 'mouseenter', this.__events.mouseenter);
|
|
196
|
+
|
|
197
|
+
if (this.resizeObserver) {
|
|
198
|
+
this.resizeObserver.disconnect();
|
|
199
|
+
this.resizeObserver = null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (env.isResizeObserverSupported) {
|
|
203
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
204
|
+
const prevWidth = canvas.width;
|
|
205
|
+
const prevHeight = canvas.height;
|
|
206
|
+
const newWidth = canvas.offsetWidth;
|
|
207
|
+
const newHeight = canvas.offsetHeight;
|
|
208
|
+
canvas.width = newWidth;
|
|
209
|
+
canvas.height = newHeight;
|
|
210
|
+
if (prevWidth !== canvas.width || prevHeight !== canvas.height) {
|
|
211
|
+
if (this.pluginOptions.maintainRatio) this._adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight);
|
|
212
|
+
this._drawAll();
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
this.resizeObserver.observe(canvas);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* @private
|
|
222
|
+
* @description Destroys the drawing canvas, removes event listeners, and clears stored drawing data.
|
|
223
|
+
*/
|
|
224
|
+
_destroyDrawing() {
|
|
225
|
+
if (this.resizeObserver) {
|
|
226
|
+
this.resizeObserver.disconnect();
|
|
227
|
+
this.resizeObserver = null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (this.canvas) {
|
|
231
|
+
this.eventManager.removeEvent(this.__eventsRegister.mousedown);
|
|
232
|
+
this.eventManager.removeEvent(this.__eventsRegister.mousemove);
|
|
233
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseup);
|
|
234
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseleave);
|
|
235
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseenter);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
this.canvas = null;
|
|
239
|
+
this.ctx = null;
|
|
240
|
+
this.points = [];
|
|
241
|
+
this.paths = [];
|
|
242
|
+
this.isDrawing = false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @private
|
|
247
|
+
* @description Configures the drawing context (canvas settings like line width, color, etc.).
|
|
248
|
+
*/
|
|
249
|
+
_setCtx() {
|
|
250
|
+
this.ctx.lineWidth = this.pluginOptions.lineWidth;
|
|
251
|
+
this.ctx.lineCap = this.pluginOptions.lineCap;
|
|
252
|
+
this.ctx.strokeStyle = this.pluginOptions.lineColor || _w.getComputedStyle(this.carrierWrapper).color;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* @private
|
|
257
|
+
* @description Draws the current stroke based on collected points.
|
|
258
|
+
*/
|
|
259
|
+
_draw() {
|
|
260
|
+
this._setCtx();
|
|
261
|
+
this.ctx.beginPath();
|
|
262
|
+
this.points.forEach(([x, y], i) => {
|
|
263
|
+
if (i === 0) {
|
|
264
|
+
this.ctx.moveTo(x, y);
|
|
265
|
+
} else {
|
|
266
|
+
this.ctx.lineTo(x, y);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
this.ctx.stroke();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @private
|
|
274
|
+
* @description Redraws all stored paths onto the canvas.
|
|
275
|
+
*/
|
|
276
|
+
_drawAll() {
|
|
277
|
+
this._setCtx();
|
|
278
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
279
|
+
this.paths.forEach((path) => {
|
|
280
|
+
this.points = path;
|
|
281
|
+
this._draw();
|
|
282
|
+
});
|
|
283
|
+
this.points = [];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @private
|
|
288
|
+
* @description Adjusts all stored paths to fit new canvas dimensions after a resize event.
|
|
289
|
+
* @param {number} prevWidth - The previous width of the canvas.
|
|
290
|
+
* @param {number} prevHeight - The previous height of the canvas.
|
|
291
|
+
* @param {number} newWidth - The new width of the canvas.
|
|
292
|
+
* @param {number} newHeight - The new height of the canvas.
|
|
293
|
+
*/
|
|
294
|
+
_adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight) {
|
|
295
|
+
const xRatio = newWidth / prevWidth;
|
|
296
|
+
const yRatio = newHeight / prevHeight;
|
|
297
|
+
|
|
298
|
+
this.paths = this.paths.map((path) => path.map(([x, y]) => [x * xRatio, y * yRatio]));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* @private
|
|
303
|
+
* @description Clears the canvas and resets stored drawing paths.
|
|
304
|
+
*/
|
|
305
|
+
_clearCanvas() {
|
|
306
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
307
|
+
this.points = [];
|
|
308
|
+
this.paths = [];
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @private
|
|
313
|
+
* @description Generates an SVG representation of the drawn content.
|
|
314
|
+
* @returns {*} The generated SVG element.
|
|
315
|
+
*/
|
|
316
|
+
_getSVG() {
|
|
317
|
+
const svgNS = 'http://www.w3.org/2000/svg';
|
|
318
|
+
const svg = document.createElementNS(svgNS, 'svg');
|
|
319
|
+
svg.setAttribute('width', this.canvas.width + '');
|
|
320
|
+
svg.setAttribute('height', this.canvas.height + '');
|
|
321
|
+
svg.setAttribute('viewBox', `0 0 ${this.canvas.width} ${this.canvas.height}`);
|
|
322
|
+
svg.setAttribute('xmlns', svgNS);
|
|
323
|
+
|
|
324
|
+
this.paths.forEach((path) => {
|
|
325
|
+
const pathData = path.reduce((acc, [x, y], i) => {
|
|
326
|
+
return acc + (i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`);
|
|
327
|
+
}, '');
|
|
328
|
+
const svgPath = document.createElementNS(svgNS, 'path');
|
|
329
|
+
svgPath.setAttribute('d', pathData);
|
|
330
|
+
svgPath.setAttribute('fill', 'none');
|
|
331
|
+
svgPath.setAttribute('stroke', String(this.ctx.strokeStyle));
|
|
332
|
+
svgPath.setAttribute('stroke-width', this.ctx.lineWidth + '');
|
|
333
|
+
svg.appendChild(svgPath);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return svg;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @private
|
|
341
|
+
* @description Converts the SVG element into a downloadable file.
|
|
342
|
+
* @returns {FileList} A FileList containing the generated SVG file.
|
|
343
|
+
*/
|
|
344
|
+
_getSVGFileList() {
|
|
345
|
+
const svgElement = this._getSVG();
|
|
346
|
+
const serializer = new XMLSerializer();
|
|
347
|
+
const svgString = serializer.serializeToString(svgElement);
|
|
348
|
+
const blob = new Blob([svgString], { type: 'image/svg+xml' });
|
|
349
|
+
const file = new File([blob], 'drawing.svg', { type: 'image/svg+xml' });
|
|
350
|
+
|
|
351
|
+
// Creating a FileList
|
|
352
|
+
const dataTransfer = new DataTransfer();
|
|
353
|
+
dataTransfer.items.add(file);
|
|
354
|
+
|
|
355
|
+
return dataTransfer.files;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @private
|
|
360
|
+
* @description Retrieves touch coordinates relative to the canvas.
|
|
361
|
+
* @param {TouchEvent} e - The touch event.
|
|
362
|
+
* @returns {{x: number, y: number}} An object containing the x and y coordinates.
|
|
363
|
+
*/
|
|
364
|
+
_getCanvasTouchPointer(e) {
|
|
365
|
+
const { touches } = e;
|
|
366
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
367
|
+
const x = touches[0].clientX - rect.left;
|
|
368
|
+
const y = touches[0].clientY - rect.top;
|
|
369
|
+
return { x, y };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* @private
|
|
374
|
+
* @description Activates either block or inline format mode for inserted drawings.
|
|
375
|
+
* @param {boolean} isInline - Whether the drawing should be inserted as an inline element.
|
|
376
|
+
*/
|
|
377
|
+
_activeAsInline(isInline) {
|
|
378
|
+
if (isInline) {
|
|
379
|
+
dom.utils.addClass(this.asInline, 'on');
|
|
380
|
+
dom.utils.removeClass(this.asBlock, 'on');
|
|
381
|
+
this.as = 'inline';
|
|
382
|
+
} else {
|
|
383
|
+
dom.utils.addClass(this.asBlock, 'on');
|
|
384
|
+
dom.utils.removeClass(this.asInline, 'on');
|
|
385
|
+
this.as = 'block';
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @param {MouseEvent} e - Event object
|
|
391
|
+
*/
|
|
392
|
+
#OnCanvasMouseDown(e) {
|
|
393
|
+
e.preventDefault();
|
|
394
|
+
this.isDrawing = true;
|
|
395
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
396
|
+
this._draw();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* @param {MouseEvent} e - Event object
|
|
401
|
+
*/
|
|
402
|
+
#OnCanvasMouseMove(e) {
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
if (!this.isDrawing) return;
|
|
405
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
406
|
+
this._draw();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @param {TouchEvent} e - Event object
|
|
411
|
+
*/
|
|
412
|
+
#OnCanvasTouchStart(e) {
|
|
413
|
+
e.preventDefault();
|
|
414
|
+
const { x, y } = this._getCanvasTouchPointer(e);
|
|
415
|
+
this.isDrawing = true;
|
|
416
|
+
this.points.push([x, y]);
|
|
417
|
+
this._draw();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @param {TouchEvent} e - Event object
|
|
422
|
+
*/
|
|
423
|
+
#OnCanvasTouchMove(e) {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
const { x, y } = this._getCanvasTouchPointer(e);
|
|
426
|
+
if (!this.isDrawing) return;
|
|
427
|
+
this.points.push([x, y]);
|
|
428
|
+
this._draw();
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
#OnCanvasMouseUp() {
|
|
432
|
+
this.isDrawing = false;
|
|
433
|
+
if (this.points.length > 0) {
|
|
434
|
+
this.paths.push([...this.points]);
|
|
435
|
+
this.points = [];
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
#OnCanvasMouseLeave() {
|
|
440
|
+
if (this.isDrawing) {
|
|
441
|
+
this.paths.push([...this.points]);
|
|
442
|
+
if (!this.pluginOptions.lineReconnect) {
|
|
443
|
+
this.points = [];
|
|
444
|
+
this.isDrawing = false;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* @param {MouseEvent} e - Event object
|
|
451
|
+
*/
|
|
452
|
+
#OnCanvasMouseEnter(e) {
|
|
453
|
+
if (e.buttons === 1) {
|
|
454
|
+
this.isDrawing = true;
|
|
455
|
+
if (!this.pluginOptions.lineReconnect) {
|
|
456
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
457
|
+
} else {
|
|
458
|
+
const lastPath = this.paths[this.paths.length - 1];
|
|
459
|
+
const lastPoint = lastPath[lastPath.length - 1];
|
|
460
|
+
this.points.push([lastPoint[0], lastPoint[1]]);
|
|
461
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
462
|
+
}
|
|
463
|
+
this._draw();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
#OnRemove() {
|
|
468
|
+
this._clearCanvas();
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* @param {MouseEvent} e - Event object
|
|
473
|
+
*/
|
|
474
|
+
#OnClickAsButton(e) {
|
|
475
|
+
this._activeAsInline(dom.query.getEventTarget(e).getAttribute('data-command') === 'asInline');
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function CreateHTML_modal({ lang, icons, pluginOptions }) {
|
|
480
|
+
const { width, height, maxWidth, maxHeight, minWidth, minHeight } = pluginOptions.formSize;
|
|
481
|
+
const html = /*html*/ `
|
|
482
|
+
<form>
|
|
483
|
+
<div class="se-modal-header">
|
|
484
|
+
<button type="button" data-command="close" class="se-btn se-close-btn" title="${lang.close}" aria-label="${lang.close}">
|
|
485
|
+
${icons.cancel}
|
|
486
|
+
</button>
|
|
487
|
+
<span class="se-modal-title">${lang.drawing_modal_title}</span>
|
|
488
|
+
</div>
|
|
489
|
+
<div class="se-modal-body" style="width: ${width}; height: ${height}; min-width: ${minWidth}; min-height: ${minHeight};">
|
|
490
|
+
<canvas class="se-drawing-canvas" style="width: 100%; height: 100%;"></canvas>
|
|
491
|
+
${pluginOptions.canResize ? '<div class="se-modal-resize-handle-w"></div><div class="se-modal-resize-handle-h"></div><div class="se-modal-resize-handle-c"></div>' : ''}
|
|
492
|
+
</div>
|
|
493
|
+
<div class="se-modal-body-bottom">
|
|
494
|
+
<div class="se-modal-form">
|
|
495
|
+
<div class="se-modal-flex-form">
|
|
496
|
+
${
|
|
497
|
+
pluginOptions.useFormatType
|
|
498
|
+
? /*html*/ `
|
|
499
|
+
<div class="se-modal-flex-group">
|
|
500
|
+
<button type="button" class="se-btn se-tooltip" data-command="asBlock" aria-label="${lang.blockStyle}">
|
|
501
|
+
${icons.as_block}
|
|
502
|
+
${dom.utils.createTooltipInner(lang.blockStyle)}
|
|
503
|
+
</button>
|
|
504
|
+
<button type="button" class="se-btn se-tooltip" data-command="asInline" aria-label="${lang.inlineStyle}">
|
|
505
|
+
${icons.as_inline}
|
|
506
|
+
${dom.utils.createTooltipInner(lang.inlineStyle)}
|
|
507
|
+
</button>
|
|
508
|
+
</div>`
|
|
509
|
+
: ''
|
|
510
|
+
}
|
|
511
|
+
<div class="se-modal-flex-group">
|
|
512
|
+
<button type="button" class="se-btn se-tooltip" data-command="remove" aria-label="${lang.remove}">
|
|
513
|
+
${icons.eraser}
|
|
514
|
+
${dom.utils.createTooltipInner(lang.remove)}
|
|
515
|
+
</button>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
<div class="se-modal-footer">
|
|
521
|
+
<button type="submit" class="se-btn-primary" title="${lang.submitButton}" aria-label="${lang.submitButton}">
|
|
522
|
+
<span>${lang.submitButton}</span>
|
|
523
|
+
</button>
|
|
524
|
+
</div>
|
|
525
|
+
</form>`;
|
|
526
|
+
|
|
527
|
+
return dom.utils.createElement(
|
|
528
|
+
'DIV',
|
|
529
|
+
{
|
|
530
|
+
class: 'se-modal-content se-modal-responsive',
|
|
531
|
+
style: `max-width: ${maxWidth}; max-height: ${maxHeight};`
|
|
532
|
+
},
|
|
533
|
+
html
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export default Drawing;
|