打开Safari上下文菜单下面的文本选择

发布于 2025-01-22 08:14:36 字数 2823 浏览 1 评论 0原文

我需要在编辑器中的文本选择上方显示工具栏。这很容易。 不幸的是,iOS上的Safari似乎也更喜欢在文本选择上方打开其复制/粘贴/格式上下文菜单。但是Facebook似乎已经找到了一种避免这种情况的方法:

” ”,

但是在与远程调试器花了近两个小时的时间之后,试图找出他们如何实现这一目标,我'我放弃。我只是无法弄清楚。

我已经建立了一个非常明确的原型,该原型在文本选择上方显示工具栏(下面)。这在我的MacBook(在这种情况下使用Chrome)上正常工作:

​它们在几乎相同的位置上打开,因此无法与我的工具栏进行互动。

我真的很想知道Facebook如何解决它。任何帮助将不胜感激。谢谢:-)

准骨原型:

var toolbar = document.querySelector("div.Toolbar");
toolbar.style.display = "none";

document.onselectionchange = function()
{
    var sel = getSelection();

    if (sel.rangeCount > 0)
    {
        var ran = sel.getRangeAt(0);

        if (ran.collapsed === false)
        {
            var rect = ran.getBoundingClientRect();
            var rectTop = rect.top;
            var rectCenter = rect.left + (rect.width / 2);

            toolbar.style.display = "";
            toolbar.style.left = (rectCenter - (toolbar.offsetWidth / 2)) + "px";
            toolbar.style.top = (rectTop - toolbar.offsetHeight) + "px";

            if (parseFloat(toolbar.style.top) < 0)
            {
                toolbar.style.top = "0px";
            }
            if (parseFloat(toolbar.style.left) < 0)
            {
                toolbar.style.left = "0px";
            }
        }
        else
        {
            toolbar.style.display = "none";
        }
    }
    else
    {
        toolbar.style.display = "none";
    }
}
body
{
    padding: 2em;
}

div.Toolbar
{
    display: inline-block;
    position: fixed;
    background: orange;
    box-shadow: 0px 0px 0.2em #333;
    padding: 0.3em;
}

div[contenteditable="true"]
{
    width: 600px;
    height: 300px;
    border: 1px solid gray;
    padding: 0.5em;
}
<div class="Toolbar">
    Buttons go here
</div>
<div contenteditable="true">
  Try selecting some of this text in the editor. The toolbar shows up above the text selection as intended. But on an iPad we also get Safari's context menu which opens on top of our custom toolbar. Facebook has successfully solved this somehow - but how the heck did they do it?
</div>

I need to show a toolbar ABOVE a text selection in an editor. That's easy.
Unfortunately Safari on iOS seems to prefer opening its copy/paste/formatting context menu above text selections as well. But Facebook seems to have figured out a way to avoid this:

Screenshot - Safari's Context Menu opens below text selection on Facebook

But after spending almost two hours with a remote debugger trying to figure out how the heck they achieved this, I'm giving up. I just can't figure it out.

I have built a very barebone prototype which displays a toolbar above a text selection (attached below). This works fine on my MacBook (using Chrome in this case):

Screenshot - showing custom toolbar displayed above text selection

But as the next screenshot demonstrates, Safari's context menu on an iPad conflicts with my toolbar. They open in almost the same position, making it impossible to interact with my toolbar.

Screenshot - showing Safari's context menu positioned above custom toolbar

I'm really keen to know how Facebook solved it. Any help would be greatly appreciated. Thank you :-)

Barebone prototype:

var toolbar = document.querySelector("div.Toolbar");
toolbar.style.display = "none";

document.onselectionchange = function()
{
    var sel = getSelection();

    if (sel.rangeCount > 0)
    {
        var ran = sel.getRangeAt(0);

        if (ran.collapsed === false)
        {
            var rect = ran.getBoundingClientRect();
            var rectTop = rect.top;
            var rectCenter = rect.left + (rect.width / 2);

            toolbar.style.display = "";
            toolbar.style.left = (rectCenter - (toolbar.offsetWidth / 2)) + "px";
            toolbar.style.top = (rectTop - toolbar.offsetHeight) + "px";

            if (parseFloat(toolbar.style.top) < 0)
            {
                toolbar.style.top = "0px";
            }
            if (parseFloat(toolbar.style.left) < 0)
            {
                toolbar.style.left = "0px";
            }
        }
        else
        {
            toolbar.style.display = "none";
        }
    }
    else
    {
        toolbar.style.display = "none";
    }
}
body
{
    padding: 2em;
}

div.Toolbar
{
    display: inline-block;
    position: fixed;
    background: orange;
    box-shadow: 0px 0px 0.2em #333;
    padding: 0.3em;
}

div[contenteditable="true"]
{
    width: 600px;
    height: 300px;
    border: 1px solid gray;
    padding: 0.5em;
}
<div class="Toolbar">
    Buttons go here
</div>
<div contenteditable="true">
  Try selecting some of this text in the editor. The toolbar shows up above the text selection as intended. But on an iPad we also get Safari's context menu which opens on top of our custom toolbar. Facebook has successfully solved this somehow - but how the heck did they do it?
</div>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冰雪梦之恋 2025-01-29 08:14:36

我找到了解决方案。

快速答案:添加带有onclick或onMousedown处理程序的“按钮”。

扩展解决方案:
我决定继续进行项目,然后将工具栏安装在视口顶部。但是随着项目的进行,我想在这个问题上进行第二次拍摄 - 这次上下文菜单与我的自定义工具栏没有重叠。事实证明,在这种情况下,仅存在一个元素(&lt; div&gt;代表按钮的元素), onclick onMousedown注册足以使Safari意识到这可能是避免使用UI碰撞的东西。坦率地说,我不喜欢这种“ AI”,但至少现在有一个解释。

var button = document.createElement("div");
button.className = "ToolbarButton ToolbarButtonBold";
button.onmousedown = function() { /* ... */ }; // This saves the day
toolbar.appendChild(button);

I found the solution.

Quick answer: Add a "button" with an onclick or onmousedown handler.

Expanding on the solution:
I decided to go ahead with my project and simply attach the toolbar at the top of the viewport instead. But as the project progressed, I wanted to take a second shot at this problem - and this time the Context Menu did not overlap with my custom toolbar. It turned out that the mere presence of an element (<div> element representing a button in this case) with an onclick or onmousedown handler registered, was enough to make Safari realize that this is probably something where UI collisions should be avoided. Quite frankly I'm not a fan of this kind of "A.I", but at least there is an explaination now.

var button = document.createElement("div");
button.className = "ToolbarButton ToolbarButtonBold";
button.onmousedown = function() { /* ... */ }; // This saves the day
toolbar.appendChild(button);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文