@cocreate/selection 1.15.2 → 1.16.0
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/package.json +4 -4
- package/src/index.js +32 -30
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/selection",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "A simple selection component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"selection",
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
},
|
|
37
37
|
"main": "./src/index.js",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cocreate/utils": "^1.44.
|
|
39
|
+
"@cocreate/utils": "^1.44.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@cocreate/webpack": "^1.6.
|
|
42
|
+
"@cocreate/webpack": "^1.6.2"
|
|
43
43
|
},
|
|
44
44
|
"allowScripts": {
|
|
45
45
|
"@cocreate/utils@1.42.2": true,
|
|
46
46
|
"@cocreate/webpack@1.4.3": true
|
|
47
47
|
}
|
|
48
|
-
}
|
|
48
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { cssPath, domParser } from '@cocreate/utils';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Safely splices a string into another string without polluting the global String prototype.
|
|
5
|
+
*/
|
|
6
|
+
export function customSplice(sourceStr, index, absIndex, stringToAdd) {
|
|
7
|
+
return sourceStr.slice(0, index) + stringToAdd + sourceStr.slice(index + Math.abs(absIndex));
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
export function getSelection(element) {
|
|
8
11
|
try {
|
|
@@ -34,7 +37,6 @@ export function getSelection(element) {
|
|
|
34
37
|
domTextEditor = domTextEditor.closest('[contenteditable]');
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
38
40
|
let start = getNodePosition(range.startContainer, domTextEditor, range.startOffset)
|
|
39
41
|
let end = start
|
|
40
42
|
if (range.startContainer !== range.endContainer) {
|
|
@@ -79,10 +81,11 @@ export function getSelection(element) {
|
|
|
79
81
|
}
|
|
80
82
|
} catch (error) {
|
|
81
83
|
console.error("Error fetching selection from element:", error);
|
|
84
|
+
// Safe fallback to prevent cascading undefined errors
|
|
85
|
+
return { start: 0, end: 0, value: "", range: null };
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
|
|
86
89
|
function getNodePosition(container, domTextEditor, position) {
|
|
87
90
|
try {
|
|
88
91
|
let string = domTextEditor.htmlString
|
|
@@ -108,13 +111,15 @@ function getNodePosition(container, domTextEditor, position) {
|
|
|
108
111
|
|
|
109
112
|
} catch (error) {
|
|
110
113
|
console.error("Error getting node position:", error);
|
|
114
|
+
// Fallback to preserve execution
|
|
115
|
+
return position || 0;
|
|
111
116
|
}
|
|
112
|
-
|
|
113
117
|
}
|
|
114
118
|
|
|
115
119
|
export function processSelection(element, value = "", prev_start, prev_end, start, end, range) {
|
|
116
120
|
let prevStart = prev_start;
|
|
117
121
|
let prevEnd = prev_end;
|
|
122
|
+
|
|
118
123
|
if (prev_start >= start) {
|
|
119
124
|
if (value == "") {
|
|
120
125
|
prev_start -= end - start;
|
|
@@ -124,11 +129,13 @@ export function processSelection(element, value = "", prev_start, prev_end, star
|
|
|
124
129
|
prev_start += value.length;
|
|
125
130
|
prev_end += value.length;
|
|
126
131
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Fixed dangling block: Now a proper sequential conditional
|
|
135
|
+
if (value == "" && prev_end >= start) {
|
|
136
|
+
prev_end = (prev_end >= end) ? prev_end - (end - start) : start;
|
|
131
137
|
}
|
|
138
|
+
|
|
132
139
|
if (range) {
|
|
133
140
|
if (prevStart > prev_start) {
|
|
134
141
|
let length = prevStart - prev_start;
|
|
@@ -140,6 +147,7 @@ export function processSelection(element, value = "", prev_start, prev_end, star
|
|
|
140
147
|
if (range.startOffset == 0 || range.startOffset >= length)
|
|
141
148
|
range.startOffset += length;
|
|
142
149
|
}
|
|
150
|
+
|
|
143
151
|
if (prevEnd > prev_end) {
|
|
144
152
|
let length = prevEnd - prev_end;
|
|
145
153
|
if (Math.sign(length) === 1 && range.endOffset >= length)
|
|
@@ -165,20 +173,8 @@ export function setSelection(element, start, end, range) {
|
|
|
165
173
|
let Document = element.ownerDocument;
|
|
166
174
|
|
|
167
175
|
let startContainer, endContainer
|
|
168
|
-
// if (range.startContainer.htmlString)
|
|
169
176
|
startContainer = getContainer(range.startContainer, range.textStart - range.startOffset);
|
|
170
|
-
// else
|
|
171
|
-
// startContainer = getContainer(range.startContainer, range.startOffset);
|
|
172
|
-
|
|
173
|
-
// if (range.endContainer.htmlString)
|
|
174
177
|
endContainer = getContainer(range.endContainer, range.textEnd - range.endOffset);
|
|
175
|
-
// else
|
|
176
|
-
// endContainer = getContainer(range.endContainer, range.endOffset);
|
|
177
|
-
|
|
178
|
-
// let startContainer = getContainer(range.startContainer, range.elementStart);
|
|
179
|
-
// let endContainer = getContainer(range.endContainer, range.elementEnd);
|
|
180
|
-
// let startContainer = getContainer(range.startContainer, range.startOffset);
|
|
181
|
-
// let endContainer = getContainer(range.endContainer, range.endOffset);
|
|
182
178
|
|
|
183
179
|
if (!startContainer || !endContainer)
|
|
184
180
|
return;
|
|
@@ -220,11 +216,13 @@ export function getElementPosition(str, start, end) {
|
|
|
220
216
|
let angleEnd = startString.lastIndexOf(">");
|
|
221
217
|
let endStringAngleEnd = endString.indexOf(">");
|
|
222
218
|
let element, path, position, nodeStart, nodeEnd, startNode, type;
|
|
219
|
+
|
|
223
220
|
if (angleEnd > angleStart) {
|
|
224
221
|
let length = 0;
|
|
225
222
|
if (start != end)
|
|
226
223
|
length = end - start;
|
|
227
|
-
|
|
224
|
+
// Refactored to use the standalone customSplice function
|
|
225
|
+
let string = customSplice(str, start, length, '<findelement></findelement>');
|
|
228
226
|
let newDom = domParser(string);
|
|
229
227
|
let findEl = newDom.querySelector('findelement');
|
|
230
228
|
if (findEl) {
|
|
@@ -269,7 +267,8 @@ export function getElementPosition(str, start, end) {
|
|
|
269
267
|
}
|
|
270
268
|
|
|
271
269
|
if (nodeEnd > 0) {
|
|
272
|
-
|
|
270
|
+
// Refactored to use the standalone customSplice function
|
|
271
|
+
let string = customSplice(str, nodeEnd - 1, 0, ' findelement');
|
|
273
272
|
let newDom = domParser(string);
|
|
274
273
|
element = newDom.querySelector('[findelement]');
|
|
275
274
|
if (!element && newDom.tagName == 'HTML')
|
|
@@ -278,7 +277,8 @@ export function getElementPosition(str, start, end) {
|
|
|
278
277
|
element = element.parentElement;
|
|
279
278
|
element.removeAttribute('findelement');
|
|
280
279
|
} else {
|
|
281
|
-
|
|
280
|
+
// Refactored to use the standalone customSplice function
|
|
281
|
+
let string = customSplice(str, angleStart, 0, '<findelement></findelement>');
|
|
282
282
|
let newDom = domParser(string);
|
|
283
283
|
element = newDom.querySelector('findelement');
|
|
284
284
|
if (element) {
|
|
@@ -346,8 +346,8 @@ export function getStringPosition({ string, target, position, attribute, propert
|
|
|
346
346
|
}
|
|
347
347
|
else
|
|
348
348
|
element = dom.querySelector(selector);
|
|
349
|
+
|
|
349
350
|
if (!element) {
|
|
350
|
-
// console.log('element could not be found using selector:', selector);
|
|
351
351
|
return;
|
|
352
352
|
}
|
|
353
353
|
let start = 0, end = 0;
|
|
@@ -368,6 +368,7 @@ export function getStringPosition({ string, target, position, attribute, propert
|
|
|
368
368
|
let attrValue = element.getAttribute(attribute);
|
|
369
369
|
let attrStart = elString.indexOf(` ${attribute}=`);
|
|
370
370
|
start = start + attrStart;
|
|
371
|
+
|
|
371
372
|
if (attribute == 'style') {
|
|
372
373
|
if (remove)
|
|
373
374
|
element.style.removeProperty(property);
|
|
@@ -408,12 +409,15 @@ export function getStringPosition({ string, target, position, attribute, propert
|
|
|
408
409
|
}
|
|
409
410
|
catch (e) {
|
|
410
411
|
console.log(e);
|
|
412
|
+
// Return safe fallback instead of throwing implicit undefined
|
|
413
|
+
return { start: 0, end: 0, newValue: value };
|
|
411
414
|
}
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
function getElFromString(dom, string, element, position, isAttribute) {
|
|
415
418
|
let findEl = document.createElement('findelement');
|
|
416
419
|
let start, angle, documentTypeAngles;
|
|
420
|
+
|
|
417
421
|
if (position == 'afterbegin') {
|
|
418
422
|
element.insertAdjacentElement('afterbegin', findEl);
|
|
419
423
|
angle = '>';
|
|
@@ -445,7 +449,6 @@ function getElFromString(dom, string, element, position, isAttribute) {
|
|
|
445
449
|
findEl.remove();
|
|
446
450
|
|
|
447
451
|
let domString = dom.innerHTML.substring(0, start);
|
|
448
|
-
// let domString = dom.outerHTML.substring(0, start);
|
|
449
452
|
|
|
450
453
|
if (dom.tagName == "HTML") {
|
|
451
454
|
domString = dom.outerHTML.substring(0, start);
|
|
@@ -453,10 +456,10 @@ function getElFromString(dom, string, element, position, isAttribute) {
|
|
|
453
456
|
let documentType = string.substring(0, htmlIndex);
|
|
454
457
|
documentTypeAngles = documentType.split(angle).length - 1;
|
|
455
458
|
}
|
|
459
|
+
|
|
456
460
|
let angles = domString.split(angle);
|
|
457
461
|
let angleLength = angles.length - 1;
|
|
458
|
-
|
|
459
|
-
// angleLength += 1;
|
|
462
|
+
|
|
460
463
|
if (documentTypeAngles)
|
|
461
464
|
angleLength += documentTypeAngles;
|
|
462
465
|
let elStart = getPosition(string, angle, angleLength);
|
|
@@ -482,7 +485,6 @@ function getPosition(string, subString, index) {
|
|
|
482
485
|
let startstring = angleArray.join(subString);
|
|
483
486
|
let start = startstring.length;
|
|
484
487
|
return start;
|
|
485
|
-
// return string.split(subString, index).join(subString).length;
|
|
486
488
|
}
|
|
487
489
|
|
|
488
490
|
export default { getSelection, setSelection, hasSelection, processSelection, getStringPosition, getElementPosition };
|