@@ -17,6 +17,7 @@ const PARENT_TAGS_TO_EXCLUDE = ["STYLE", "SCRIPT", "TITLE"];
17
17
var setting = { } ;
18
18
var mouseTarget = null ;
19
19
const nodeLengthCache = new WeakMap ( ) ;
20
+ var prevWordSegIndex = 0 ;
20
21
21
22
export function enableMouseoverTextEvent ( _window = window , settingPointer ) {
22
23
var textDetectTime = setting ?. [ "tooltipEventInterval" ] || 0.7 ;
@@ -110,22 +111,16 @@ export async function getMouseoverText(x, y) {
110
111
if (
111
112
! isFirefox ( ) &&
112
113
( mouseoverType === "word" || mouseoverType === "sentence" ) &&
113
- ! mouseoverText [ "mouseoverText" ]
114
+ ! mouseoverText [ "mouseoverText" ] &&
115
+ checkContainerDetectText ( range , x , y ) // check if container detect text
114
116
) {
115
- return getTextFromRange ( range , x , y , true , mouseoverType ) ;
117
+ return getTextFromRange ( range , x , y , true , mouseoverType ) ;
116
118
}
117
119
118
-
119
120
return mouseoverText ;
120
121
}
121
122
122
- function getTextFromRange (
123
- range ,
124
- x ,
125
- y ,
126
- useSegmentation = false ,
127
- mouseoverType
128
- ) {
123
+ function getTextFromRange ( range , x , y , useSegmentation , mouseoverType ) {
129
124
var output = { mouseoverText : "" , mouseoverRange : range } ;
130
125
var wordRange = expandRange ( range , mouseoverType , useSegmentation , x , y ) ;
131
126
if ( checkXYInElement ( wordRange , clientX , clientY ) ) {
@@ -146,14 +141,11 @@ function expandRange(range, type, useSegmentation, x, y) {
146
141
range = getContainerRange ( range ) ;
147
142
} else if ( isFirefox ( ) || useSegmentation ) {
148
143
// for firefox, use segmentation to extract word
149
-
150
-
151
-
152
- // console.time("expandRangeWithSeg");
153
- range = expandRangeWithSeg ( range , type , x , y ) ;
154
144
155
- // console.timeEnd("expandRangeWithSeg");
145
+ // console.time("expandRangeWithSeg");
146
+ range = expandRangeWithSeg ( range , type , x , y ) ;
156
147
148
+ // console.timeEnd("expandRangeWithSeg");
157
149
} else {
158
150
// for chrome, use range expand
159
151
range = getExpandRange ( range , type ) ;
@@ -331,20 +323,14 @@ export function checkXYInElement(ele, x, y) {
331
323
}
332
324
}
333
325
334
-
326
+ function checkContainerDetectText ( rangeOri , x , y ) {
327
+ var mouseoverText = getTextFromRange ( rangeOri , x , y , false , "container" ) ;
328
+ return mouseoverText [ "mouseoverText" ] ? mouseoverText : null ;
329
+ }
335
330
336
331
//firefox word break ====================================
337
332
function expandRangeWithSeg ( rangeOri , type = "word" , x , y ) {
338
333
//check text exist over container for fast checking
339
- // var mouseoverText = getTextFromRange(rangeOri, x, y, false, "container");
340
- // if(!mouseoverText["mouseoverText"]){
341
- // return null;
342
- // }
343
-
344
-
345
-
346
-
347
- // console.time("expandRangeWithSeginit");
348
334
var range = rangeOri . cloneRange ( ) ;
349
335
var rangeContainer = expandRange ( range , "container" ) ;
350
336
const textNode = rangeContainer . commonAncestorContainer ;
@@ -356,8 +342,6 @@ function expandRangeWithSeg(rangeOri, type = "word", x, y) {
356
342
// console.timeEnd("getWordSegmentInfo");
357
343
// console.log("Word Segment Info:", wordSliceInfo);
358
344
359
-
360
-
361
345
// console.log('==========================================================');
362
346
// var wholeText = textNode.innerText;
363
347
// var wordSliceInfo = getWordSegmentInfo(wholeText, type);
@@ -370,7 +354,7 @@ function expandRangeWithSeg(rangeOri, type = "word", x, y) {
370
354
// console.log("New Line Count:", newLineCount);
371
355
372
356
// console.log("wordSliceInfo:", wordSliceInfo);
373
-
357
+
374
358
// console.log('==========================================================2');
375
359
var wholeText = getNodeText ( textNode ) ;
376
360
@@ -379,18 +363,38 @@ function expandRangeWithSeg(rangeOri, type = "word", x, y) {
379
363
// var textLength = wholeText.length;
380
364
// var newLineCount = (wholeText.match(/\n/g) || []).length;
381
365
382
- // console.log("Text Length:", textLength);
383
- // console.log("New Line Count:", newLineCount);
384
- // console.log("wordSliceInfo:", wordSliceInfo);
385
-
386
-
366
+ var char = getCurrentMousePointedChar ( rangeOri , x , y ) ;
367
+ var wordSegInfoFiltered = filterWordSegInfo ( wordSliceInfo , char ) ;
387
368
// get all word range by segment
388
369
// console.time("findWordRange");
389
- const currentWordNode = findWordRange ( wordSliceInfo , textNode , x , y ) ;
370
+ const currentWordNode = findWordRange (
371
+ wordSegInfoFiltered ,
372
+ textNode ,
373
+ x ,
374
+ y ,
375
+ char
376
+ ) ;
390
377
// console.timeEnd("findWordRange");
391
- // console.log("Current Word Node:", currentWordNode);
392
378
return currentWordNode ;
393
379
}
380
+ function getCurrentMousePointedChar ( range , x , y ) {
381
+ if ( ! range || range . startContainer . nodeType !== Node . TEXT_NODE ) return null ;
382
+
383
+ const textContent = range . startContainer . textContent ;
384
+ if ( ! textContent ) return null ;
385
+
386
+ const clonedRange = range . cloneRange ( ) ;
387
+ for ( let i = 0 ; i < textContent . length ; i ++ ) {
388
+ clonedRange . setStart ( range . startContainer , i ) ;
389
+ clonedRange . setEnd ( range . startContainer , i + 1 ) ;
390
+
391
+ if ( isPointInRange ( clonedRange , x , y ) ) {
392
+ return textContent [ i ] ;
393
+ }
394
+ }
395
+
396
+ return null ;
397
+ }
394
398
395
399
function isPointInRange ( range , x , y ) {
396
400
const rects = range . getClientRects ( ) ;
@@ -413,18 +417,16 @@ function getWordSegmentInfo(text, type) {
413
417
return wordsMeta ;
414
418
}
415
419
416
- function findWordRange ( wordSegInfo , textNode , x , y ) {
420
+ function filterWordSegInfo ( wordSegInfo , char ) {
421
+ if ( ! char ) {
422
+ return [ ] ;
423
+ }
417
424
var newLineCount = 0 ;
418
-
419
- // console.log(wordSegInfo)
420
- // console.log(textNode)
421
-
422
- // console.time("wordSegInfoExtract");
423
425
var wordSegInfoExtract = wordSegInfo
424
- . map ( ( wordMeta ) => {
426
+ . map ( ( wordMeta , itemIndex ) => {
425
427
var word = wordMeta . segment ;
426
428
var index = wordMeta . index ;
427
- var newLine = 0
429
+ var newLine = 0 ;
428
430
// if (word.includes("\n")) {
429
431
// var newLine = (word.match(/\n/g) || []).length; // count new line
430
432
// word = word.replace(/\n/g, "");
@@ -435,43 +437,45 @@ function findWordRange(wordSegInfo, textNode, x, y) {
435
437
// index -= newLineCount; // Adjust index only once
436
438
// }
437
439
return {
438
- ...wordMeta ,
439
440
segment : word ,
440
441
index : index , // Use the updated index
441
442
newLine : newLine ,
443
+ itemIndex : itemIndex , // Add item index key
442
444
} ;
443
445
} )
444
- . filter ( ( wordMeta ) => wordMeta . segment . length > 0 ) ;
445
- // console.timeEnd("wordSegInfoExtract");
446
-
446
+ . filter ( ( wordMeta ) => wordMeta . segment . length > 0 )
447
+ . filter ( ( wordMeta ) => wordMeta . segment . includes ( char ) ) ; // filter out current mouse pointed char
448
+
449
+ return wordSegInfoExtract ;
450
+ }
447
451
448
- // console.time("wordSegInfoExtractLoop");
449
- for ( const wordMeta of wordSegInfoExtract ) {
452
+ function findWordRange ( wordSegInfo , textNode , x , y ) {
453
+ // Sort wordSegInfo by previous word segment index
454
+ wordSegInfo . sort ( ( a , b ) => {
455
+ const distanceA = Math . abs ( a . itemIndex - prevWordSegIndex ) ;
456
+ const distanceB = Math . abs ( b . itemIndex - prevWordSegIndex ) ;
457
+ return distanceA - distanceB ;
458
+ } ) ;
459
+
460
+ for ( const wordMeta of wordSegInfo ) {
450
461
try {
451
- var wordRange = document . createRange ( ) ;
452
462
var index = wordMeta . index + wordMeta . newLine ;
453
463
var word = wordMeta . segment ;
454
464
var wordLen = word . length ;
455
- // console.time("selectNode1" );
465
+ var wordRange = document . createRange ( ) ;
456
466
const selectedNode1 = selectNode ( textNode , index ) ;
457
- // console.timeEnd("selectNode1");
458
-
459
- // console.time("selectNode2");
460
467
const selectedNode2 = selectNode ( textNode , index + wordLen ) ;
461
- // console.timeEnd("selectNode2");
462
-
463
468
wordRange . setStart ( selectedNode1 . node , selectedNode1 . index ) ;
464
469
wordRange . setEnd ( selectedNode2 . node , selectedNode2 . index ) ;
465
470
466
471
if ( isPointInRange ( wordRange , x , y ) ) {
467
- // console.timeEnd("wordSegInfoExtractLoop") ;
472
+ prevWordSegIndex = wordMeta . itemIndex ;
468
473
return wordRange ;
469
474
}
470
475
} catch ( error ) {
471
476
console . log ( error ) ;
472
477
}
473
478
}
474
- // console.timeEnd("wordSegInfoExtractLoop");
475
479
return null ;
476
480
}
477
481
@@ -511,7 +515,6 @@ function getNodeLength(ele) {
511
515
return length ;
512
516
}
513
517
514
-
515
518
function getNodeText ( ele ) {
516
519
if ( ele . nodeType === Node . TEXT_NODE ) {
517
520
return ele . textContent || "" ;
0 commit comments