diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 751c6acc..a9e27f49 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -31,10 +31,10 @@ class Popup { } showAt(rect) { - this.container.style.left = rect.x + 'px'; - this.container.style.top = rect.y + 'px'; - this.container.style.height = rect.height + 'px'; - this.container.style.width = rect.width + 'px'; + this.container.style.left = `${rect.x}px`; + this.container.style.top = `${rect.y}px`; + this.container.style.height = `${rect.height}px`; + this.container.style.width = `${rect.width}px`; this.container.style.visibility = 'visible'; } diff --git a/ext/fg/js/util.js b/ext/fg/js/util.js index 99da6381..01df01d7 100644 --- a/ext/fg/js/util.js +++ b/ext/fg/js/util.js @@ -66,19 +66,41 @@ function addDefinition(definition, mode) { return invokeBgApi('addDefinition', {definition, mode}); } -function createImposter(element) { - const imposter = document.createElement('div'); - const elementRect = element.getBoundingClientRect(); +function getElementOffset(element) { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; + const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; + const clientTop = document.documentElement.clientTop || document.body.clientTop || 0; + const clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0; + + const rect = element.getBoundingClientRect(); + const top = Math.round(rect.top + scrollTop - clientTop); + const left = Math.round(rect.left + scrollLeft - clientLeft); + + return {top, left}; +} + +function createImposter(element) { + const styleProps = window.getComputedStyle(element); + const stylePairs = []; + for (const key of styleProps) { + stylePairs.push(`${key}: ${styleProps[key]};`); + } + + const offset = getElementOffset(element); + const imposter = document.createElement('div'); imposter.className = 'yomichan-imposter'; imposter.innerText = element.value; - imposter.style.cssText = window.getComputedStyle(element).cssText; + imposter.style.cssText = stylePairs.join('\n'); imposter.style.position = 'absolute'; - imposter.style.top = elementRect.top + 'px'; - imposter.style.left = elementRect.left + 'px'; + imposter.style.top = `${offset.top}px`; + imposter.style.left = `${offset.left}px`; imposter.style.zIndex = 2147483646; - document.body.appendChild(imposter); + if (element.nodeName === 'TEXTAREA' && styleProps.overflow === 'visible') { + imposter.style.overflow = 'auto'; + } + document.body.appendChild(imposter); imposter.scrollTop = element.scrollTop; imposter.scrollLeft = element.scrollLeft; } @@ -89,6 +111,12 @@ function destroyImposters() { } } +function hideImposters() { + for (const element of document.getElementsByClassName('yomichan-imposter')) { + element.style.visibility = 'hidden'; + } +} + function textSourceFromPoint(point, imposter) { const element = document.elementFromPoint(point.x, point.y); if (element !== null) { @@ -101,6 +129,7 @@ function textSourceFromPoint(point, imposter) { const range = document.caretRangeFromPoint(point.x, point.y); if (range !== null) { + hideImposters(); return new TextSourceRange(range); } diff --git a/ext/manifest.json b/ext/manifest.json index 2d820c7d..3edc8fa6 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Yomichan", - "version": "1.0.16", + "version": "1.0.17", "description": "Japanese dictionary with Anki integration", "icons": {"16": "img/icon16.png", "48": "img/icon48.png", "128": "img/icon128.png"}, @@ -10,7 +10,7 @@ "author": "Alex Yatskov", "background": {"page": "bg/background.html"}, "content_scripts": [{ - "matches": ["*://*/*", "file://*/*"], + "matches": ["http://*/*", "https://*/*", "file://*/*"], "js": [ "fg/js/gecko.js", "fg/js/source-range.js",