@svgedit/svgcanvas 7.2.6 → 7.4.1

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.
@@ -28,68 +28,69 @@ export const init = canvas => {
28
28
  /**
29
29
  * Group: Text edit functions
30
30
  * Functions relating to editing text elements.
31
- * @namespace {PlainObject} textActions
31
+ * @class TextActions
32
32
  * @memberof module:svgcanvas.SvgCanvas#
33
33
  */
34
- export const textActionsMethod = (function () {
35
- let curtext
36
- let textinput
37
- let cursor
38
- let selblock
39
- let blinker
40
- let chardata = []
41
- let textbb // , transbb;
42
- let matrix
43
- let lastX
44
- let lastY
45
- let allowDbl
34
+ class TextActions {
35
+ #curtext = null
36
+ #textinput = null
37
+ #cursor = null
38
+ #selblock = null
39
+ #blinker = null
40
+ #chardata = []
41
+ #textbb = null // , transbb;
42
+ #matrix = null
43
+ #lastX = null
44
+ #lastY = null
45
+ #allowDbl = false
46
46
 
47
47
  /**
48
48
  *
49
49
  * @param {Integer} index
50
50
  * @returns {void}
51
+ * @private
51
52
  */
52
- function setCursor (index) {
53
- const empty = textinput.value === ''
54
- textinput.focus()
53
+ #setCursor = (index = undefined) => {
54
+ const empty = this.#textinput.value === ''
55
+ this.#textinput.focus()
55
56
 
56
- if (!arguments.length) {
57
+ if (index === undefined) {
57
58
  if (empty) {
58
59
  index = 0
59
60
  } else {
60
- if (textinput.selectionEnd !== textinput.selectionStart) {
61
+ if (this.#textinput.selectionEnd !== this.#textinput.selectionStart) {
61
62
  return
62
63
  }
63
- index = textinput.selectionEnd
64
+ index = this.#textinput.selectionEnd
64
65
  }
65
66
  }
66
67
 
67
- const charbb = chardata[index]
68
+ const charbb = this.#chardata[index]
68
69
  if (!empty) {
69
- textinput.setSelectionRange(index, index)
70
+ this.#textinput.setSelectionRange(index, index)
70
71
  }
71
- cursor = getElement('text_cursor')
72
- if (!cursor) {
73
- cursor = document.createElementNS(NS.SVG, 'line')
74
- assignAttributes(cursor, {
72
+ this.#cursor = getElement('text_cursor')
73
+ if (!this.#cursor) {
74
+ this.#cursor = document.createElementNS(NS.SVG, 'line')
75
+ assignAttributes(this.#cursor, {
75
76
  id: 'text_cursor',
76
77
  stroke: '#333',
77
78
  'stroke-width': 1
78
79
  })
79
- getElement('selectorParentGroup').append(cursor)
80
+ getElement('selectorParentGroup').append(this.#cursor)
80
81
  }
81
82
 
82
- if (!blinker) {
83
- blinker = setInterval(function () {
84
- const show = cursor.getAttribute('display') === 'none'
85
- cursor.setAttribute('display', show ? 'inline' : 'none')
83
+ if (!this.#blinker) {
84
+ this.#blinker = setInterval(() => {
85
+ const show = this.#cursor.getAttribute('display') === 'none'
86
+ this.#cursor.setAttribute('display', show ? 'inline' : 'none')
86
87
  }, 600)
87
88
  }
88
89
 
89
- const startPt = ptToScreen(charbb.x, textbb.y)
90
- const endPt = ptToScreen(charbb.x, textbb.y + textbb.height)
90
+ const startPt = this.#ptToScreen(charbb.x, this.#textbb.y)
91
+ const endPt = this.#ptToScreen(charbb.x, this.#textbb.y + this.#textbb.height)
91
92
 
92
- assignAttributes(cursor, {
93
+ assignAttributes(this.#cursor, {
93
94
  x1: startPt.x,
94
95
  y1: startPt.y,
95
96
  x2: endPt.x,
@@ -98,8 +99,8 @@ export const textActionsMethod = (function () {
98
99
  display: 'inline'
99
100
  })
100
101
 
101
- if (selblock) {
102
- selblock.setAttribute('d', '')
102
+ if (this.#selblock) {
103
+ this.#selblock.setAttribute('d', '')
103
104
  }
104
105
  }
105
106
 
@@ -109,40 +110,41 @@ export const textActionsMethod = (function () {
109
110
  * @param {Integer} end
110
111
  * @param {boolean} skipInput
111
112
  * @returns {void}
113
+ * @private
112
114
  */
113
- function setSelection (start, end, skipInput) {
115
+ #setSelection = (start, end, skipInput) => {
114
116
  if (start === end) {
115
- setCursor(end)
117
+ this.#setCursor(end)
116
118
  return
117
119
  }
118
120
 
119
121
  if (!skipInput) {
120
- textinput.setSelectionRange(start, end)
122
+ this.#textinput.setSelectionRange(start, end)
121
123
  }
122
124
 
123
- selblock = getElement('text_selectblock')
124
- if (!selblock) {
125
- selblock = document.createElementNS(NS.SVG, 'path')
126
- assignAttributes(selblock, {
125
+ this.#selblock = getElement('text_selectblock')
126
+ if (!this.#selblock) {
127
+ this.#selblock = document.createElementNS(NS.SVG, 'path')
128
+ assignAttributes(this.#selblock, {
127
129
  id: 'text_selectblock',
128
130
  fill: 'green',
129
131
  opacity: 0.5,
130
132
  style: 'pointer-events:none'
131
133
  })
132
- getElement('selectorParentGroup').append(selblock)
134
+ getElement('selectorParentGroup').append(this.#selblock)
133
135
  }
134
136
 
135
- const startbb = chardata[start]
136
- const endbb = chardata[end]
137
+ const startbb = this.#chardata[start]
138
+ const endbb = this.#chardata[end]
137
139
 
138
- cursor.setAttribute('visibility', 'hidden')
140
+ this.#cursor.setAttribute('visibility', 'hidden')
139
141
 
140
- const tl = ptToScreen(startbb.x, textbb.y)
141
- const tr = ptToScreen(startbb.x + (endbb.x - startbb.x), textbb.y)
142
- const bl = ptToScreen(startbb.x, textbb.y + textbb.height)
143
- const br = ptToScreen(
142
+ const tl = this.#ptToScreen(startbb.x, this.#textbb.y)
143
+ const tr = this.#ptToScreen(startbb.x + (endbb.x - startbb.x), this.#textbb.y)
144
+ const bl = this.#ptToScreen(startbb.x, this.#textbb.y + this.#textbb.height)
145
+ const br = this.#ptToScreen(
144
146
  startbb.x + (endbb.x - startbb.x),
145
- textbb.y + textbb.height
147
+ this.#textbb.y + this.#textbb.height
146
148
  )
147
149
 
148
150
  const dstr =
@@ -164,7 +166,7 @@ export const textActionsMethod = (function () {
164
166
  bl.y +
165
167
  'z'
166
168
 
167
- assignAttributes(selblock, {
169
+ assignAttributes(this.#selblock, {
168
170
  d: dstr,
169
171
  display: 'inline'
170
172
  })
@@ -175,29 +177,30 @@ export const textActionsMethod = (function () {
175
177
  * @param {Float} mouseX
176
178
  * @param {Float} mouseY
177
179
  * @returns {Integer}
180
+ * @private
178
181
  */
179
- function getIndexFromPoint (mouseX, mouseY) {
182
+ #getIndexFromPoint = (mouseX, mouseY) => {
180
183
  // Position cursor here
181
184
  const pt = svgCanvas.getSvgRoot().createSVGPoint()
182
185
  pt.x = mouseX
183
186
  pt.y = mouseY
184
187
 
185
188
  // No content, so return 0
186
- if (chardata.length === 1) {
189
+ if (this.#chardata.length === 1) {
187
190
  return 0
188
191
  }
189
192
  // Determine if cursor should be on left or right of character
190
- let charpos = curtext.getCharNumAtPosition(pt)
193
+ let charpos = this.#curtext.getCharNumAtPosition(pt)
191
194
  if (charpos < 0) {
192
195
  // Out of text range, look at mouse coords
193
- charpos = chardata.length - 2
194
- if (mouseX <= chardata[0].x) {
196
+ charpos = this.#chardata.length - 2
197
+ if (mouseX <= this.#chardata[0].x) {
195
198
  charpos = 0
196
199
  }
197
- } else if (charpos >= chardata.length - 2) {
198
- charpos = chardata.length - 2
200
+ } else if (charpos >= this.#chardata.length - 2) {
201
+ charpos = this.#chardata.length - 2
199
202
  }
200
- const charbb = chardata[charpos]
203
+ const charbb = this.#chardata[charpos]
201
204
  const mid = charbb.x + charbb.width / 2
202
205
  if (mouseX > mid) {
203
206
  charpos++
@@ -210,9 +213,10 @@ export const textActionsMethod = (function () {
210
213
  * @param {Float} mouseX
211
214
  * @param {Float} mouseY
212
215
  * @returns {void}
216
+ * @private
213
217
  */
214
- function setCursorFromPoint (mouseX, mouseY) {
215
- setCursor(getIndexFromPoint(mouseX, mouseY))
218
+ #setCursorFromPoint = (mouseX, mouseY) => {
219
+ this.#setCursor(this.#getIndexFromPoint(mouseX, mouseY))
216
220
  }
217
221
 
218
222
  /**
@@ -221,14 +225,15 @@ export const textActionsMethod = (function () {
221
225
  * @param {Float} y
222
226
  * @param {boolean} apply
223
227
  * @returns {void}
228
+ * @private
224
229
  */
225
- function setEndSelectionFromPoint (x, y, apply) {
226
- const i1 = textinput.selectionStart
227
- const i2 = getIndexFromPoint(x, y)
230
+ #setEndSelectionFromPoint = (x, y, apply) => {
231
+ const i1 = this.#textinput.selectionStart
232
+ const i2 = this.#getIndexFromPoint(x, y)
228
233
 
229
234
  const start = Math.min(i1, i2)
230
235
  const end = Math.max(i1, i2)
231
- setSelection(start, end, !apply)
236
+ this.#setSelection(start, end, !apply)
232
237
  }
233
238
 
234
239
  /**
@@ -236,8 +241,9 @@ export const textActionsMethod = (function () {
236
241
  * @param {Float} xIn
237
242
  * @param {Float} yIn
238
243
  * @returns {module:math.XYObject}
244
+ * @private
239
245
  */
240
- function screenToPt (xIn, yIn) {
246
+ #screenToPt = (xIn, yIn) => {
241
247
  const out = {
242
248
  x: xIn,
243
249
  y: yIn
@@ -246,8 +252,8 @@ export const textActionsMethod = (function () {
246
252
  out.x /= zoom
247
253
  out.y /= zoom
248
254
 
249
- if (matrix) {
250
- const pt = transformPoint(out.x, out.y, matrix.inverse())
255
+ if (this.#matrix) {
256
+ const pt = transformPoint(out.x, out.y, this.#matrix.inverse())
251
257
  out.x = pt.x
252
258
  out.y = pt.y
253
259
  }
@@ -260,15 +266,16 @@ export const textActionsMethod = (function () {
260
266
  * @param {Float} xIn
261
267
  * @param {Float} yIn
262
268
  * @returns {module:math.XYObject}
269
+ * @private
263
270
  */
264
- function ptToScreen (xIn, yIn) {
271
+ #ptToScreen = (xIn, yIn) => {
265
272
  const out = {
266
273
  x: xIn,
267
274
  y: yIn
268
275
  }
269
276
 
270
- if (matrix) {
271
- const pt = transformPoint(out.x, out.y, matrix)
277
+ if (this.#matrix) {
278
+ const pt = transformPoint(out.x, out.y, this.#matrix)
272
279
  out.x = pt.x
273
280
  out.y = pt.y
274
281
  }
@@ -283,279 +290,293 @@ export const textActionsMethod = (function () {
283
290
  *
284
291
  * @param {Event} evt
285
292
  * @returns {void}
293
+ * @private
286
294
  */
287
- function selectAll (evt) {
288
- setSelection(0, curtext.textContent.length)
289
- evt.target.removeEventListener('click', selectAll)
295
+ #selectAll = (evt) => {
296
+ this.#setSelection(0, this.#curtext.textContent.length)
297
+ evt.target.removeEventListener('click', this.#selectAll)
290
298
  }
291
299
 
292
300
  /**
293
301
  *
294
302
  * @param {Event} evt
295
303
  * @returns {void}
304
+ * @private
296
305
  */
297
- function selectWord (evt) {
298
- if (!allowDbl || !curtext) {
306
+ #selectWord = (evt) => {
307
+ if (!this.#allowDbl || !this.#curtext) {
299
308
  return
300
309
  }
301
310
  const zoom = svgCanvas.getZoom()
302
311
  const ept = transformPoint(evt.pageX, evt.pageY, svgCanvas.getrootSctm())
303
312
  const mouseX = ept.x * zoom
304
313
  const mouseY = ept.y * zoom
305
- const pt = screenToPt(mouseX, mouseY)
314
+ const pt = this.#screenToPt(mouseX, mouseY)
306
315
 
307
- const index = getIndexFromPoint(pt.x, pt.y)
308
- const str = curtext.textContent
309
- const first = str.substr(0, index).replace(/[a-z\d]+$/i, '').length
310
- const m = str.substr(index).match(/^[a-z\d]+/i)
316
+ const index = this.#getIndexFromPoint(pt.x, pt.y)
317
+ const str = this.#curtext.textContent
318
+ const first = str.slice(0, index).replace(/[a-z\d]+$/i, '').length
319
+ const m = str.slice(index).match(/^[a-z\d]+/i)
311
320
  const last = (m ? m[0].length : 0) + index
312
- setSelection(first, last)
321
+ this.#setSelection(first, last)
313
322
 
314
323
  // Set tripleclick
315
- svgCanvas.$click(evt.target, selectAll)
324
+ svgCanvas.$click(evt.target, this.#selectAll)
316
325
 
317
- setTimeout(function () {
318
- evt.target.removeEventListener('click', selectAll)
326
+ setTimeout(() => {
327
+ evt.target.removeEventListener('click', this.#selectAll)
319
328
  }, 300)
320
329
  }
321
330
 
322
- return /** @lends module:svgcanvas.SvgCanvas#textActions */ {
323
- /**
324
- * @param {Element} target
325
- * @param {Float} x
326
- * @param {Float} y
327
- * @returns {void}
328
- */
329
- select (target, x, y) {
330
- curtext = target
331
- svgCanvas.textActions.toEditMode(x, y)
332
- },
333
- /**
334
- * @param {Element} elem
335
- * @returns {void}
336
- */
337
- start (elem) {
338
- curtext = elem
339
- svgCanvas.textActions.toEditMode()
340
- },
341
- /**
342
- * @param {external:MouseEvent} evt
343
- * @param {Element} mouseTarget
344
- * @param {Float} startX
345
- * @param {Float} startY
346
- * @returns {void}
347
- */
348
- mouseDown (evt, mouseTarget, startX, startY) {
349
- const pt = screenToPt(startX, startY)
350
-
351
- textinput.focus()
352
- setCursorFromPoint(pt.x, pt.y)
353
- lastX = startX
354
- lastY = startY
355
-
356
- // TODO: Find way to block native selection
357
- },
358
- /**
359
- * @param {Float} mouseX
360
- * @param {Float} mouseY
361
- * @returns {void}
362
- */
363
- mouseMove (mouseX, mouseY) {
364
- const pt = screenToPt(mouseX, mouseY)
365
- setEndSelectionFromPoint(pt.x, pt.y)
366
- },
367
- /**
368
- * @param {external:MouseEvent} evt
369
- * @param {Float} mouseX
370
- * @param {Float} mouseY
371
- * @returns {void}
372
- */
373
- mouseUp (evt, mouseX, mouseY) {
374
- const pt = screenToPt(mouseX, mouseY)
375
-
376
- setEndSelectionFromPoint(pt.x, pt.y, true)
377
-
378
- // TODO: Find a way to make this work: Use transformed BBox instead of evt.target
379
- // if (lastX === mouseX && lastY === mouseY
380
- // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) {
381
- // svgCanvas.textActions.toSelectMode(true);
382
- // }
383
-
384
- if (
385
- evt.target !== curtext &&
386
- mouseX < lastX + 2 &&
387
- mouseX > lastX - 2 &&
388
- mouseY < lastY + 2 &&
389
- mouseY > lastY - 2
390
- ) {
391
- svgCanvas.textActions.toSelectMode(true)
392
- }
393
- },
394
- /**
395
- * @function
396
- * @param {Integer} index
397
- * @returns {void}
398
- */
399
- setCursor,
400
- /**
401
- * @param {Float} x
402
- * @param {Float} y
403
- * @returns {void}
404
- */
405
- toEditMode (x, y) {
406
- allowDbl = false
407
- svgCanvas.setCurrentMode('textedit')
408
- svgCanvas.selectorManager.requestSelector(curtext).showGrips(false)
409
- // Make selector group accept clicks
410
- /* const selector = */ svgCanvas.selectorManager.requestSelector(curtext) // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used
411
- // const sel = selector.selectorRect;
412
-
413
- svgCanvas.textActions.init()
414
-
415
- curtext.style.cursor = 'text'
416
-
417
- // if (supportsEditableText()) {
418
- // curtext.setAttribute('editable', 'simple');
419
- // return;
420
- // }
421
-
422
- if (!arguments.length) {
423
- setCursor()
424
- } else {
425
- const pt = screenToPt(x, y)
426
- setCursorFromPoint(pt.x, pt.y)
427
- }
331
+ /**
332
+ * @param {Element} target
333
+ * @param {Float} x
334
+ * @param {Float} y
335
+ * @returns {void}
336
+ */
337
+ select (target, x, y) {
338
+ this.#curtext = target
339
+ svgCanvas.textActions.toEditMode(x, y)
340
+ }
428
341
 
429
- setTimeout(function () {
430
- allowDbl = true
431
- }, 300)
432
- },
433
- /**
434
- * @param {boolean|Element} selectElem
435
- * @fires module:svgcanvas.SvgCanvas#event:selected
436
- * @returns {void}
437
- */
438
- toSelectMode (selectElem) {
439
- svgCanvas.setCurrentMode('select')
440
- clearInterval(blinker)
441
- blinker = null
442
- if (selblock) {
443
- selblock.setAttribute('display', 'none')
444
- }
445
- if (cursor) {
446
- cursor.setAttribute('visibility', 'hidden')
447
- }
448
- curtext.style.cursor = 'move'
342
+ /**
343
+ * @param {Element} elem
344
+ * @returns {void}
345
+ */
346
+ start (elem) {
347
+ this.#curtext = elem
348
+ svgCanvas.textActions.toEditMode()
349
+ }
449
350
 
450
- if (selectElem) {
451
- svgCanvas.clearSelection()
452
- curtext.style.cursor = 'move'
351
+ /**
352
+ * @param {external:MouseEvent} evt
353
+ * @param {Element} mouseTarget
354
+ * @param {Float} startX
355
+ * @param {Float} startY
356
+ * @returns {void}
357
+ */
358
+ mouseDown (evt, mouseTarget, startX, startY) {
359
+ const pt = this.#screenToPt(startX, startY)
453
360
 
454
- svgCanvas.call('selected', [curtext])
455
- svgCanvas.addToSelection([curtext], true)
456
- }
457
- if (!curtext?.textContent.length) {
458
- // No content, so delete
459
- svgCanvas.deleteSelectedElements()
460
- }
361
+ this.#textinput.focus()
362
+ this.#setCursorFromPoint(pt.x, pt.y)
363
+ this.#lastX = startX
364
+ this.#lastY = startY
461
365
 
462
- textinput.blur()
463
-
464
- curtext = false
465
-
466
- // if (supportsEditableText()) {
467
- // curtext.removeAttribute('editable');
468
- // }
469
- },
470
- /**
471
- * @param {Element} elem
472
- * @returns {void}
473
- */
474
- setInputElem (elem) {
475
- textinput = elem
476
- },
477
- /**
478
- * @returns {void}
479
- */
480
- clear () {
481
- if (svgCanvas.getCurrentMode() === 'textedit') {
482
- svgCanvas.textActions.toSelectMode()
483
- }
484
- },
485
- /**
486
- * @param {Element} _inputElem Not in use
487
- * @returns {void}
488
- */
489
- init (_inputElem) {
490
- if (!curtext) {
491
- return
492
- }
493
- let i
494
- let end
495
- // if (supportsEditableText()) {
496
- // curtext.select();
497
- // return;
498
- // }
499
-
500
- if (!curtext.parentNode) {
501
- // Result of the ffClone, need to get correct element
502
- const selectedElements = svgCanvas.getSelectedElements()
503
- curtext = selectedElements[0]
504
- svgCanvas.selectorManager.requestSelector(curtext).showGrips(false)
505
- }
366
+ // TODO: Find way to block native selection
367
+ }
368
+
369
+ /**
370
+ * @param {Float} mouseX
371
+ * @param {Float} mouseY
372
+ * @returns {void}
373
+ */
374
+ mouseMove (mouseX, mouseY) {
375
+ const pt = this.#screenToPt(mouseX, mouseY)
376
+ this.#setEndSelectionFromPoint(pt.x, pt.y)
377
+ }
378
+
379
+ /**
380
+ * @param {external:MouseEvent} evt
381
+ * @param {Float} mouseX
382
+ * @param {Float} mouseY
383
+ * @returns {void}
384
+ */
385
+ mouseUp (evt, mouseX, mouseY) {
386
+ const pt = this.#screenToPt(mouseX, mouseY)
387
+
388
+ this.#setEndSelectionFromPoint(pt.x, pt.y, true)
389
+
390
+ // TODO: Find a way to make this work: Use transformed BBox instead of evt.target
391
+ // if (lastX === mouseX && lastY === mouseY
392
+ // && !rectsIntersect(transbb, {x: pt.x, y: pt.y, width: 0, height: 0})) {
393
+ // svgCanvas.textActions.toSelectMode(true);
394
+ // }
395
+
396
+ if (
397
+ evt.target !== this.#curtext &&
398
+ mouseX < this.#lastX + 2 &&
399
+ mouseX > this.#lastX - 2 &&
400
+ mouseY < this.#lastY + 2 &&
401
+ mouseY > this.#lastY - 2
402
+ ) {
403
+ svgCanvas.textActions.toSelectMode(true)
404
+ }
405
+ }
406
+
407
+ /**
408
+ * @param {Integer} index
409
+ * @returns {void}
410
+ */
411
+ setCursor (index) {
412
+ this.#setCursor(index)
413
+ }
414
+
415
+ /**
416
+ * @param {Float} x
417
+ * @param {Float} y
418
+ * @returns {void}
419
+ */
420
+ toEditMode (x, y) {
421
+ this.#allowDbl = false
422
+ svgCanvas.setCurrentMode('textedit')
423
+ svgCanvas.selectorManager.requestSelector(this.#curtext).showGrips(false)
424
+ // Make selector group accept clicks
425
+ /* const selector = */ svgCanvas.selectorManager.requestSelector(this.#curtext) // Do we need this? Has side effect of setting lock, so keeping for now, but next line wasn't being used
426
+ // const sel = selector.selectorRect;
427
+
428
+ svgCanvas.textActions.init()
429
+
430
+ this.#curtext.style.cursor = 'text'
431
+
432
+ // if (supportsEditableText()) {
433
+ // curtext.setAttribute('editable', 'simple');
434
+ // return;
435
+ // }
436
+
437
+ if (arguments.length === 0) {
438
+ this.#setCursor()
439
+ } else {
440
+ const pt = this.#screenToPt(x, y)
441
+ this.#setCursorFromPoint(pt.x, pt.y)
442
+ }
443
+
444
+ setTimeout(() => {
445
+ this.#allowDbl = true
446
+ }, 300)
447
+ }
448
+
449
+ /**
450
+ * @param {boolean|Element} selectElem
451
+ * @fires module:svgcanvas.SvgCanvas#event:selected
452
+ * @returns {void}
453
+ */
454
+ toSelectMode (selectElem) {
455
+ svgCanvas.setCurrentMode('select')
456
+ clearInterval(this.#blinker)
457
+ this.#blinker = null
458
+ if (this.#selblock) {
459
+ this.#selblock.setAttribute('display', 'none')
460
+ }
461
+ if (this.#cursor) {
462
+ this.#cursor.setAttribute('visibility', 'hidden')
463
+ }
464
+ this.#curtext.style.cursor = 'move'
506
465
 
507
- const str = curtext.textContent
508
- const len = str.length
466
+ if (selectElem) {
467
+ svgCanvas.clearSelection()
468
+ this.#curtext.style.cursor = 'move'
509
469
 
510
- const xform = curtext.getAttribute('transform')
470
+ svgCanvas.call('selected', [this.#curtext])
471
+ svgCanvas.addToSelection([this.#curtext], true)
472
+ }
473
+ if (!this.#curtext?.textContent.length) {
474
+ // No content, so delete
475
+ svgCanvas.deleteSelectedElements()
476
+ }
511
477
 
512
- textbb = utilsGetBBox(curtext)
478
+ this.#textinput.blur()
513
479
 
514
- matrix = xform ? getMatrix(curtext) : null
480
+ this.#curtext = false
515
481
 
516
- chardata = []
517
- chardata.length = len
518
- textinput.focus()
482
+ // if (supportsEditableText()) {
483
+ // curtext.removeAttribute('editable');
484
+ // }
485
+ }
519
486
 
520
- curtext.removeEventListener('dblclick', selectWord)
521
- curtext.addEventListener('dblclick', selectWord)
487
+ /**
488
+ * @param {Element} elem
489
+ * @returns {void}
490
+ */
491
+ setInputElem (elem) {
492
+ this.#textinput = elem
493
+ }
522
494
 
523
- if (!len) {
524
- end = { x: textbb.x + textbb.width / 2, width: 0 }
525
- }
495
+ /**
496
+ * @returns {void}
497
+ */
498
+ clear () {
499
+ if (svgCanvas.getCurrentMode() === 'textedit') {
500
+ svgCanvas.textActions.toSelectMode()
501
+ }
502
+ }
503
+
504
+ /**
505
+ * @param {Element} _inputElem Not in use
506
+ * @returns {void}
507
+ */
508
+ init (_inputElem) {
509
+ if (!this.#curtext) {
510
+ return
511
+ }
512
+ let i
513
+ let end
514
+ // if (supportsEditableText()) {
515
+ // curtext.select();
516
+ // return;
517
+ // }
518
+
519
+ if (!this.#curtext.parentNode) {
520
+ // Result of the ffClone, need to get correct element
521
+ const selectedElements = svgCanvas.getSelectedElements()
522
+ this.#curtext = selectedElements[0]
523
+ svgCanvas.selectorManager.requestSelector(this.#curtext).showGrips(false)
524
+ }
526
525
 
527
- for (i = 0; i < len; i++) {
528
- const start = curtext.getStartPositionOfChar(i)
529
- end = curtext.getEndPositionOfChar(i)
526
+ const str = this.#curtext.textContent
527
+ const len = str.length
530
528
 
531
- if (!supportsGoodTextCharPos()) {
532
- const zoom = svgCanvas.getZoom()
533
- const offset = svgCanvas.contentW * zoom
534
- start.x -= offset
535
- end.x -= offset
529
+ const xform = this.#curtext.getAttribute('transform')
536
530
 
537
- start.x /= zoom
538
- end.x /= zoom
539
- }
531
+ this.#textbb = utilsGetBBox(this.#curtext)
540
532
 
541
- // Get a "bbox" equivalent for each character. Uses the
542
- // bbox data of the actual text for y, height purposes
533
+ this.#matrix = xform ? getMatrix(this.#curtext) : null
543
534
 
544
- // TODO: Decide if y, width and height are actually necessary
545
- chardata[i] = {
546
- x: start.x,
547
- y: textbb.y, // start.y?
548
- width: end.x - start.x,
549
- height: textbb.height
550
- }
535
+ this.#chardata = []
536
+ this.#chardata.length = len
537
+ this.#textinput.focus()
538
+
539
+ this.#curtext.removeEventListener('dblclick', this.#selectWord)
540
+ this.#curtext.addEventListener('dblclick', this.#selectWord)
541
+
542
+ if (!len) {
543
+ end = { x: this.#textbb.x + this.#textbb.width / 2, width: 0 }
544
+ }
545
+
546
+ for (i = 0; i < len; i++) {
547
+ const start = this.#curtext.getStartPositionOfChar(i)
548
+ end = this.#curtext.getEndPositionOfChar(i)
549
+
550
+ if (!supportsGoodTextCharPos()) {
551
+ const zoom = svgCanvas.getZoom()
552
+ const offset = svgCanvas.contentW * zoom
553
+ start.x -= offset
554
+ end.x -= offset
555
+
556
+ start.x /= zoom
557
+ end.x /= zoom
551
558
  }
552
559
 
553
- // Add a last bbox for cursor at end of text
554
- chardata.push({
555
- x: end.x,
556
- width: 0
557
- })
558
- setSelection(textinput.selectionStart, textinput.selectionEnd, true)
560
+ // Get a "bbox" equivalent for each character. Uses the
561
+ // bbox data of the actual text for y, height purposes
562
+
563
+ // TODO: Decide if y, width and height are actually necessary
564
+ this.#chardata[i] = {
565
+ x: start.x,
566
+ y: this.#textbb.y, // start.y?
567
+ width: end.x - start.x,
568
+ height: this.#textbb.height
569
+ }
559
570
  }
571
+
572
+ // Add a last bbox for cursor at end of text
573
+ this.#chardata.push({
574
+ x: end.x,
575
+ width: 0
576
+ })
577
+ this.#setSelection(this.#textinput.selectionStart, this.#textinput.selectionEnd, true)
560
578
  }
561
- })()
579
+ }
580
+
581
+ // Export singleton instance for backward compatibility
582
+ export const textActionsMethod = new TextActions()