如何基于光标单击(不使用jQuery)放置弹出窗口?

时间:2019-05-24 16:53:42

标签: javascript dom firefox-addon

我正在尝试创建Firefox扩展,我希望在该扩展名上双击一些文本。在将这段代码作为扩展程序的内容脚本(将在任何网站上加载)时,我尝试不使用jQuery来完成此任务。

我已经看到并实现了链接中给出的答案:
How to position popover over a highlighted portion of text?
How to position a popup div based on the position of where the cursor clicks
Using mouse/cursor coordinates to position popup

不幸的是,大多数答案都在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放置在各个位置,并将clientXclientY替换为pageXpageY,但似乎无济于事。我坚信问题出在节点NewPara及其位置上,但是我无法确定它。

更新:修改了代码,但最初的问题仍然存在。

1 个答案:

答案 0 :(得分:0)

有两个主要问题将修复弹出窗口的显示位置。
首先是document.body应该用document.documentElement替换,以将范围放在body标记之外并放入html标记。
下一个主要问题是leftOffsettopOffset。它们都永远不会转换为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";
    };
};

这可以解决排名问题。