diff --git a/options.js b/options.js index f5d3f5f..36df08c 100644 --- a/options.js +++ b/options.js @@ -74,6 +74,12 @@ function defaults() default: 0, label: "Popup requires key" }); + settings.push({ + id: "ignore_linebreaks", + kind: "checkbox", + default: false, + label: "Ignore hard line breaks" + }); // display settings.push({ @@ -115,7 +121,15 @@ function defaults() max: 10000, step: 1, default: 600, - label: "Lookup popup width (before scaling)" + label: "Lookup popup width (before scaling) (limited to half the browser window width)" + }); + settings.push({ + id: "sticky_maxheight", + kind: "number", + min: 0, + max: 10000, + default: 0, + label: "Maximum height of Sticky and Mining UI modes - 0 is full screen" }); settings.push({ id: "fixedwidth", @@ -134,7 +148,21 @@ function defaults() kind: "combobox", options: ["Top left", "Top right", "Bottom left", "Bottom right"], default: 0, - label: "Popup positioning corner" + label: "Which corner of the popup follows the mouse" + }); + settings.push({ + id: "x_dodge", + kind: "combobox", + options: ["Flip", "Push"], + default: 1, + label: "How to keep the popup on the screen horizontally" + }); + settings.push({ + id: "y_dodge", + kind: "combobox", + options: ["Flip", "Push"], + default: 0, + label: "How to keep the popup on the screen vertically (at least one of these two options should be \"Push\")" }); // theme @@ -185,12 +213,6 @@ function defaults() default: "", label: "Font override (highlighted text only) (without trailing comma)" }); - settings.push({ - id: "ignore_linebreaks", - kind: "checkbox", - default: false, - label: "Ignore hard line breaks" - }); settings.push({ id: "sticky", kind: "checkbox", @@ -423,6 +445,7 @@ This format can be extended in the future if it becomes desirable to include mor optionsection.appendChild(document.createElement("hr")); let backup_save = document.createElement("button"); + backup_save.type = "button"; backup_save.innerText = "Save Backup"; backup_save.addEventListener("click", (async function () { diff --git a/texthook.js b/texthook.js index 7dd3637..f4b93e7 100644 --- a/texthook.js +++ b/texthook.js @@ -44,7 +44,10 @@ yoffset: 22, ignore_linebreaks: false, sticky: false, popup_follows_mouse: true, -popup_requires_key: 0 // 0: none; 1: ctrl; 2: shift +popup_requires_key: 0, // 0: none; 1: ctrl; 2: shift +x_dodge: 1, +y_dodge: 0, +sticky_maxheight: 0, }; let platform = "win"; @@ -102,7 +105,10 @@ function set_sticky_styles(mydiv) else mydiv.style.left = "10px"; mydiv.style.marginRight = "unset"; - mydiv.style.maxHeight = "calc(100vh - 20px)"; + if(settings.sticky_maxheight == 0) + mydiv.style.maxHeight = "calc(100vh - 20px)"; + else + mydiv.style.maxHeight = Math.round(Number(settings.sticky_maxheight))+"px"; mydiv.style.overflowY = "scroll"; mydiv.style.marginLeft = "unset"; mydiv.style.marginTop = "unset"; @@ -162,6 +168,7 @@ function display_div(middle, x, y) mydoc = find_root.document; } catch(err) {} } + // compensate for body being relative if it is, because our popup is absolute let relative_body = getComputedStyle(mydoc.body).position == "relative"; if(relative_body) @@ -174,15 +181,19 @@ function display_div(middle, x, y) newy -= mydoc.scrollingElement.scrollTop; } + let basewidth = Math.round(Number(settings.width)); + if(settings.x_dodge != 1 && basewidth > mydoc.documentElement.getBoundingClientRect().width/2 - settings.xoffset - 5) + basewidth = Math.max(150, Math.round(mydoc.documentElement.getBoundingClientRect().width/2 - settings.xoffset - 5)); + let styletext = ""; if(settings.fixedwidth) { - styletext += "max-width: " + Math.round(Number(settings.width)) + "px; " - styletext += "min-width: " + Math.round(Number(settings.width)) + "px; " + styletext += "max-width: " + basewidth + "px; " + styletext += "min-width: " + basewidth + "px; " } else { - styletext += "max-width: " + Math.round(Number(settings.width)) + "px; " + styletext += "max-width: " + basewidth + "px; " styletext += "min-width: 150px; " } styletext += "position: absolute; top: 0; left: 0; transition: unset; "; @@ -221,7 +232,7 @@ function display_div(middle, x, y) outer.style = styletext; - let mywidth = settings.width*settings.scale; + let mywidth = basewidth*settings.scale; if(!settings.fixedwidthpositioning) mywidth = outer.offsetWidth*settings.scale; @@ -231,27 +242,6 @@ function display_div(middle, x, y) set_sticky_styles(outer); else { - - let buffer = settings.xoffset+5; - - if(mywidth+buffer*2 < mydoc.documentElement.getBoundingClientRect().width) - { - if((corner == 0 || corner == 2) && newx+mywidth+buffer > mydoc.documentElement.getBoundingClientRect().right) - { - if(corner == 0) - corner = 1; - else if(corner == 2) - corner = 3; - } - if((corner == 1 || corner == 3) && newx-mywidth-buffer < mydoc.documentElement.getBoundingClientRect().left) - { - if(corner == 1) - corner = 0; - else if(corner == 3) - corner = 2; - } - } - if(corner == 1 || corner == 3) { newx -= mywidth; @@ -261,7 +251,9 @@ function display_div(middle, x, y) newx += settings.xoffset; if(corner == 2 || corner == 3) - newy = newy - outer.getBoundingClientRect().height; + newy = newy - outer.getBoundingClientRect().height - settings.yoffset; + else + newy = newy + settings.yoffset; // fixes an absolute positioning """feature""" that doesn't work properly with very wide pages (e.g. pages of left-to-right vertical text) outer.style.top = "0px"; @@ -269,10 +261,7 @@ function display_div(middle, x, y) let width = outer.offsetWidth; // - if(corner == 3 || corner == 2) - outer.style.top = (newy-settings.yoffset)+"px"; - else - outer.style.top = (newy+settings.yoffset)+"px"; + outer.style.top = (newy)+"px"; outer.style.bottom = "unset"; outer.style.right = "unset"; outer.style.left = (newx)+"px"; @@ -284,20 +273,49 @@ function display_div(middle, x, y) // } - let localrect = outer.getBoundingClientRect(); + let localrect; - if(localrect.bottom-5 > window.innerHeight) + let dodged_vertically = false; + + // dodge top/bottom + localrect = outer.getBoundingClientRect(); + if(localrect.bottom+5 > mydoc.body.clientHeight) { - newy -= localrect.bottom-5 - window.innerHeight; + if(settings.y_dodge == 1) // slide + newy -= localrect.bottom+5 - mydoc.body.clientHeight; + else // flip + newy -= localrect.height + settings.yoffset*2; + outer.style.top = (newy)+"px"; + dodged_vertically = true; + } + localrect = outer.getBoundingClientRect(); + if(localrect.top-5 < 0 && (!dodged_vertically || corner == 0 || corner == 1)) // (prefer running off the top when using "bottom" alignments) + { + if(settings.y_dodge == 1) + newy -= localrect.top-5; + else + newy += localrect.height + settings.yoffset*2; outer.style.top = (newy)+"px"; } + // dodge left/right localrect = outer.getBoundingClientRect(); - - if(localrect.top-5 < 0) + if(localrect.right+5 > mydoc.body.clientWidth) { - newy -= localrect.top-5; - outer.style.top = (newy)+"px"; + if(settings.x_dodge == 1) + newx -= localrect.right+5 - mydoc.body.clientWidth; + else + newx -= localrect.width + settings.xoffset*2; + outer.style.left = (newx)+"px"; + } + localrect = outer.getBoundingClientRect(); + if(localrect.left-5 < 0) + { + if(settings.x_dodge == 1) + newx -= localrect.left-5; + else + newx += localrect.width + settings.xoffset*2; + outer.style.left = (newx)+"px"; } } @@ -940,6 +958,10 @@ async function settings_init() getvar("popup_follows_mouse", true); getvar("popup_requires_key", 0); + getvar("x_dodge", 1); + getvar("y_dodge", 0); + getvar("sticky_maxheight", 0); + if(!settings.enabled && exists_div()) delete_div(); if(!settings.enabled)