通过元素传递鼠标悬停

Passing mouseover through element

我正在开发一个具有语法高亮功能的正则表达式分析器。

我的网站使用了两个内容可编辑的 div 的叠加层。

由于很难获得光标位置并保持它,即使添加和减去标签,我决定最好的方法是有两个内容可编辑的 div,一个在另一个之上。第一个 (#rInput) 非常简单。如果不是因为一些令人讨厌的问题让我从 textarea 切换,它可能是一个 textarea。第二个 (#rSyntax) 从 rInput 获取其值并提供语法突出显示。我确保两者总是滚动到相同的位置,以便覆盖是完美的(但是,我还在 rSyntax 上使用透明(rgba(...))字体,这样如果瞬间同步延迟应该发生,文字仍然清晰。)

在上面的下半部分快照中,contenteditable rSyntax 的代码是这样的:

<span class="cglayer">(test<span class="cglayer">(this)</span>string)</span>

rInput,恰好位于顶部,仅包含此

(test(this)string)

此方法的问题在于,当用户将鼠标悬停在上方时,我想提供一些替代工具提示(或 javascript 版本)。当用户将鼠标悬停在 rInput 上时,我想将鼠标悬停事件传递给 rSyntax.

的元素

我想将鼠标悬停在 (test ... string) 上以显示 "Capturing group 1",而将鼠标悬停在 (this) 上将显示 "Capturing group 2",或者如果它是 (?:test),它会说 "Non-capturing group".

这个术语有点难理解,因为搜索 "above" 和 "below" 之类的东西会得到很多与 z-index.

无关的结果

我确实找到了 css 属性 pointer-events,它在最短的时间内听起来很理想,但不允许您过滤指针事件(设置 rInput 以接收单击、滚动,但将 mouseover 传递给 rSyntax 及其子元素。

我发现 document.elementFromPoint 可能提供解决方案,但我不太确定如何解决。我想我会尝试 document.getElementById('rInput').getElementFromPoint(mouseX,mouseY),但是这个功能对子元素不可用。

理论上,我可以在 mousemove 上隐藏 rInput,使用 setTimeout 将其快速放回原位,然后当鼠标悬停在 rSyntax 的子元素上时应该出现工具提示,但事实并非如此这似乎不是最佳解决方案,因为我不希望 rSyntax 可点击。点击应始终转到 rInput

可以在 rInput 获得焦点时禁用鼠标悬停魔法,但是 rSyntax 的工具提示将不起作用,虽然我没有尝试过这种方法,但我不会确保将单击事件从 rSyntax 传递到 rInput 是否会正确定位光标。

有什么方法可以做到这一点吗?

更新

最好的解决方案是将语法突出显示 rSyntax 移动到 iframe,因为这样我就可以通过 elementFromPoint() 而不会闪烁 div,这确实是一个巨大的改进。

$(document).on("mousemove", "#rInput", function (e) {
    $element = $(document.getElementById('frSyntax').contentDocument.elementFromPoint(e.pageX,e.pageY));
    if ($element.attr("id") != "frSyntax" && $element.attr("id") != "rSyntax" && $element.attr("title") && $element.attr("title").length) {
        $mother.find(".dashed").removeClass("dashed")
        $element.addClass("dashed")
        $("#syntip").html($element.attr("title"))
        $("#syntip").css({"top": e.pageY+10, "left": e.pageX, "display": "inline-block"})
    } else {
        $mother.find(".dashed").removeClass("dashed");
        $("#syntip").hide()
    }
}) 

在我的 $(document).ready(... 开头,我添加了这个

$('#frSyntax').load(function(){
    $mother = $("#frSyntax").contents();
    //frSyntax is the name of the iframe.
    $syntax = $mother.find("#rSyntax")
});

第一个解决方案

我会把它留在这里,以防有人想要它。

从进一步的研究中,我觉得唯一的方法是 mousemove 使元素消失的魔法,找到下面的元素,document.elementFromPosition,然后将其弹出。

如果有人有更好的选择,我仍在寻找建议。

麻烦的是这个"flickering"会导致mousemovemouseover一直触发,这是不必要的。所以我创建了一个变量来记录坐标,并且只在鼠标实际移动时应用更改。

$(document).on("mousemove", "#rInput", function (e) {
    if (holdmouse != (e.pageX + "," + e.pageY)) {
        $("#rInput").hide();
        element = $(document.elementFromPoint(e.pageX,e.pageY));
        if (element.attr("id") != "rInput" && element.attr("id") != "rSyntax") {
            $(".classes, .cglayer").css("border-bottom","none");
            element.css("border-bottom","2px dashed black")
            $("#syntip").html(element.attr("title"))
            $("#syntip").css({"top": e.pageY+10, "left": e.pageX, "display": "inline-block"})
            holdmouse = e.pageX + "," + e.pageY
        } else {
            $(".classes, .cglayer").css("border-bottom","none");
            $("#syntip").hide()
        }
        $("#rInput").show()
    }
})