具有嵌套跨度的内容可编辑。谁有焦点?

Bas*_*tch 5 html javascript linux firefox jquery

这个问题(我添加了赏金)是相关的,并给出了背景和动机(我在 github 上的 GPLv3 MELT 监视器;我最后添加了一些自述文件)。

我只对最新的HTML5 兼容浏览器(在 GNU/Linux 上)感兴趣,例如 Firefox 38 至少(最好是 42)或 Chrome 46(在 Debian/Sid 桌面上,x86-64)

所以,假设我的 HTML5 页面中有

<div id='myeditdiv' contenteditable='true'>
  <span class='foo_cl'>FOO<span class='bar_cl'>bar</span></span>
</div>
Run Code Online (Sandbox Code Playgroud)

(实际上 HTML 已生成,DOM 也已生成;我当前正在服务器端生成一些构造 DOM 的 javascript;当然我可以更改生成器!)

我单击以使焦点位于两者之间OO。我如何获取 的 DOM 元素foo_cl,最好使用 Jquery。

当聚焦在 之间时同样的问题ar。我想要bar_cl跨度。

当然,$(':focus')不干活。它给出了div

FWIW,它是MELT 监视器的提交9109ae5b3d168f1 。

附言。请参阅我(2015 年 11 月 26 日对此问题的附录。可能contenteditable对我没用,但tabindex肯定有用!

A. *_*lff 2

要使任何元素(不仅仅是交互式内容元素)都可聚焦,您必须设置tabindex 属性

在您的示例中,它将是:

<div id='myeditdiv' contenteditable='true'>
  <span class='foo_cl' tabindex="-1">FOO<span class='bar_cl' tabindex="-1">bar</span</span>
</div>
Run Code Online (Sandbox Code Playgroud)

注意:负数tabindex使元素可聚焦0不可选项卡,因为使用选项卡方法将从使用绝对值( spec )开始。

现在在 jQuery 中,您可以将focus事件委托给这些元素:

$('[contenteditable]').on('focus', '*', function(e){
    e.stopPropagation();
    console.log(this);
});
Run Code Online (Sandbox Code Playgroud)

-jsFiddle-

附带说明一下,jQuery UI 有一个:focusable伪选择器。如果您希望动态地将tabindex属性设置为不可聚焦的元素,您可以使用:

$('[contenteditable]').find(':not(:focusable)').attr('tabindex', -1);
Run Code Online (Sandbox Code Playgroud)

-jsFiddle(包括 jQuery UI)-

如果您不想包含 jQuery UI 只是为了获取:focusable伪选择器,您可以创建自己的自定义选择器:

//include IIFE if not already including jQuery UI
(function () {
    function focusable(element, isTabIndexNotNaN) {
        var map, mapName, img,
        nodeName = element.nodeName.toLowerCase();
        if ("area" === nodeName) {
            map = element.parentNode;
            mapName = map.name;
            if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") {
                return false;
            }
            img = $("img[usemap='#" + mapName + "']")[0];
            return !!img && $(img).is(':visible');
        }
        return (/^(input|select|textarea|button|object)$/.test(nodeName) ? !element.disabled :
            "a" === nodeName ? element.href || isTabIndexNotNaN : isTabIndexNotNaN) &&
        // the element and all of its ancestors must be visible
        $(element).is(':visible');
    }
    $.extend($.expr[":"], {
        focusable: function (element) {
            return focusable(element, !isNaN($.attr(element, "tabindex")));
        }
    });
})();
Run Code Online (Sandbox Code Playgroud)

-jsFiddle-