Как разместить всплывающее окно на основе щелчка курсора (без использования JQuery)? - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь создать расширение для Firefox, где я хочу, чтобы всплывающее окно появлялось рядом с текстом, который дважды щелкнул. Поскольку я размещаю этот код в качестве скрипта содержимого моего расширения, который будет загружен на ЛЮБОЙ веб-сайт, я пытался не использовать jQuery для этой задачи.

Я видел и реализовывал ответы, приведенные в ссылках:
Как разместить popover над выделенной частью текста?
Как разместить всплывающий элемент div в зависимости от положения, в котором курсор щелкает
Использование координат мыши / курсора для позиционирования всплывающего окна

К сожалению, большинство из этих ответов были в jQuery. Я попытался заменить их на чистую реализацию DOM и придумал следующий код:

function doSomethingWithSelectedText(obj) {
    var textObj = getSelectedTextObj();
    if (textObj.toString() && textObj.toString().trim().split(" ").length <= 2) {
        var NewPara = document.createElement("div");
        NewPara.setAttribute("id", "infoDiv");
        NewPara.setAttribute("class", "tooltipDiv");
        NewPara.appendChild(document.createTextNode(textObj.toString().trim()));

        if (document.getElementsByClassName("tooltipDiv").length) {
            var OldPara = document.getElementById("infoDiv");
            document.body.replaceChild(NewPara, OldPara);
        }

        else {
            document.body.appendChild(NewPara);
        }

        document.getElementById("infoDiv").style.display = "block";
        document.getElementById("infoDiv").style.width = "250px";
        document.getElementById("infoDiv").style.zIndex = "101";
        document.getElementById("infoDiv").style.backgroundColor = "#F5DEB3";
        document.getElementById("infoDiv").style.border = "3px solid #666";
        document.getElementById("infoDiv").style.padding = "12px 12px 12px 12px";
        document.getElementById("infoDiv").style.borderRadius = "0px 0px 25px 0px";
        document.getElementById("infoDiv").style.position = "absolute";

        var oRect = textObj.getRangeAt(0).getBoundingClientRect();
        var leftOffset, topOffset;
        var pageWidth, pageHeight;
        var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0],

        pageWidth = w.innerWidth || e.clientWidth || g.clientWidth,
        pageHeight = w.innerHeight|| e.clientHeight|| g.clientHeight;

        leftOffset = oRect.left + oRect.width + 1 + 12;
        if (300 + leftOffset > pageWidth - 12) {
            leftOffset = pageWidth - 350 - 12;
        }

        topOffset = oRect.top;
        if (topOffset + 12 > pageHeight) {
            topOffset -= 12;
        }

        leftOffset += window.scrollX;
        topOffset += window.scrollY;
        document.getElementById("infoDiv").style.left = leftOffset;
        document.getElementById("infoDiv").style.top = topOffset;
    }

    else {
        document.getElementById("infoDiv").style.display = "none";
    };
};

Проблема с приведенным выше кодом заключается в том, что всплывающее окно не отображается рядом с текстом, по которому дважды щелкают мышью, вместо этого оно иногда отображается ниже, а иногда и над экраном. Я пытался расположить div в разных местах и ​​заменить clientX, clientY на pageX, pageY, но, похоже, ничего не работает. Я твердо верю, что проблема с узлом NewPara и его положением, но я не могу его определить.

ОБНОВЛЕНИЕ: Изменен код, но первоначальная проблема все еще сохраняется.

1 Ответ

0 голосов
/ 25 мая 2019

Есть две основные проблемы, которые исправят положение отображения всплывающего окна.Во-первых, document.body следует заменить на document.documentElement, чтобы поместить область за пределы тега body и в тег html.Следующая и главная проблема связана с leftOffset и topOffset.Оба они никогда не конвертируются в px, поэтому они никогда не отображаются браузером.Чтобы предотвратить это, используйте String(leftOffset) + "px" и String(topOffset) + "px".Вот модифицированный код:

function doSomethingWithSelectedText(obj) {
    var textObj = getSelectedTextObj();
    if (textObj.toString() && textObj.toString().trim().split(" ").length <= 2) {
        var NewPara = document.createElement("div");
        NewPara.setAttribute("id", "infoDiv");
        NewPara.setAttribute("class", "tooltipDiv");
        NewPara.appendChild(document.createTextNode(textObj.toString().trim()));

        if (document.getElementsByClassName("tooltipDiv").length) {
            var OldPara = document.getElementById("infoDiv");
            document.documentElement.replaceChild(NewPara, OldPara);
        }

        else {
            document.documentElement.appendChild(NewPara);
        }

        var oRect = textObj.getRangeAt(0).getBoundingClientRect();
        var leftOffset, topOffset;
        var pageWidth, pageHeight;
        var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0],

        pageWidth = w.innerWidth || e.clientWidth || g.clientWidth,
        pageHeight = w.innerHeight|| e.clientHeight|| g.clientHeight;

        leftOffset = oRect.left + oRect.width + 1 + 12;
        if (300 + leftOffset > pageWidth - 12) {
            leftOffset = pageWidth - 350 - 12;
        }

        topOffset = oRect.top;
        if (topOffset + 12 > pageHeight) {
            topOffset -= 12;
        }

        leftOffset += window.scrollX;
        topOffset += window.scrollY;

        document.getElementById("infoDiv").style.display = "block";
        document.getElementById("infoDiv").style.width = "250px";
        document.getElementById("infoDiv").style.zIndex = "101";
        document.getElementById("infoDiv").style.backgroundColor = "#F5DEB3";
        document.getElementById("infoDiv").style.border = "3px solid #666";
        document.getElementById("infoDiv").style.padding = "12px 12px 12px 12px";
        document.getElementById("infoDiv").style.borderRadius = "0px 0px 25px 0px";
        document.getElementById("infoDiv").style.position = "absolute";

        document.getElementById("infoDiv").style.left = String(leftOffset) + "px";
        document.getElementById("infoDiv").style.top = String(topOffset) + "px";
    }

    else {
        document.getElementById("infoDiv").style.display = "none";
    };
};

Это исправляет проблему с позицией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...