Clean up docRangeFromPoint

Use a cached value for checking if the browser is Firefox.
Only validate and set up document.caretRangeFromPoint once.
Use switch for multiple comparisons on the same value.
This commit is contained in:
toasted-nutbread 2019-08-10 13:33:00 -04:00
parent e23d4b9a82
commit 2edd4183a0

View File

@ -17,6 +17,8 @@
*/ */
const IS_FIREFOX = /Firefox/.test(navigator.userAgent);
function docOffsetCalc(element) { function docOffsetCalc(element) {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
@ -69,43 +71,23 @@ function docRangeFromPoint(point) {
const element = document.elementFromPoint(point.x, point.y); const element = document.elementFromPoint(point.x, point.y);
let imposter = null; let imposter = null;
if (element) { if (element) {
if (element.nodeName === 'IMG' || element.nodeName === 'BUTTON') { switch (element.nodeName) {
case 'IMG':
case 'BUTTON':
return new TextSourceElement(element); return new TextSourceElement(element);
} else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { case 'INPUT':
case 'TEXTAREA':
imposter = docImposterCreate(element); imposter = docImposterCreate(element);
break;
} }
} }
if (!document.caretRangeFromPoint) {
document.caretRangeFromPoint = (x, y) => {
const position = document.caretPositionFromPoint(x,y);
if (position && position.offsetNode && position.offsetNode.nodeType === Node.TEXT_NODE) {
const range = document.createRange();
range.setStart(position.offsetNode, position.offset);
range.setEnd(position.offsetNode, position.offset);
return range;
}
return null;
};
}
const range = document.caretRangeFromPoint(point.x, point.y); const range = document.caretRangeFromPoint(point.x, point.y);
if (range === null) { if (imposter !== null) {
return; imposter.style.zIndex = -2147483646;
} }
if(imposter !== null) imposter.style.zIndex = -2147483646; return range !== null && isPointInRange(point, range) ? new TextSourceRange(range) : null;
const rects = range.getClientRects();
for (const rect of rects) {
if (point.y <= rect.bottom + 2) {
return new TextSourceRange(range);
}
}
if (navigator.userAgent.match(/Firefox/)) {
return new TextSourceRange(range);
}
} }
function docSentenceExtract(source, extent) { function docSentenceExtract(source, extent) {
@ -178,3 +160,33 @@ function docSentenceExtract(source, extent) {
offset: position - startPos - padding offset: position - startPos - padding
}; };
} }
function isPointInRange(point, range) {
if (IS_FIREFOX) {
// Always return true on Firefox due to an issue where range.getClientRects()
// does not return a correct set of rects for characters at the beginning of a line.
return true;
}
const y = point.y - 2;
for (const rect of range.getClientRects()) {
if (y <= rect.bottom) {
return true;
}
}
return false;
}
if (typeof document.caretRangeFromPoint !== 'function') {
document.caretRangeFromPoint = (x, y) => {
const position = document.caretPositionFromPoint(x, y);
if (position && position.offsetNode && position.offsetNode.nodeType === Node.TEXT_NODE) {
const range = document.createRange();
range.setStart(position.offsetNode, position.offset);
range.setEnd(position.offsetNode, position.offset);
return range;
}
return null;
};
}