Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
876 views
in Technique[技术] by (71.8m points)

javascript - contenteditable with nested span. Who has the focus?

This question (to which I added a bounty) is related and gives the context and motivations (my GPLv3 MELT monitor on github; I added at last some README to it).

I am only interested in recent HTML5 compliant browsers (on GNU/Linux), e.g. Firefox 38 at least (and preferably 42) or Chrome 46 (on Debian/Sid desktop, x86-64)

So, suppose I have in my HTML5 page

<div id='myeditdiv' contenteditable='true'>
  <span class='foo_cl'>FOO<span class='bar_cl'>bar</span></span>
</div>

(actually the HTML is generated, and so is the DOM; I'm currently generating on the server side some javascript which constructs the DOM; of course I can change the generators!)

And I am clicking so that the focus come between the two OO. How can I get the DOM element of foo_cl, preferably with Jquery.

Same question when focusing between ar. I want the bar_cl span.

Of course, $(':focus') don't work. It gives the div

FWIW, it is commit 9109ae5b3d168f1 of the MELT monitor.

PS. See my (november 26th 2015) addenda to this question. Probably contenteditable is not useful to me, but tabindex surely is useful!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

To make any element focusable, not only interactive content ones, you have to set tabindex attribute.

In your sample, it would be:

<div id='myeditdiv' contenteditable='true'>
  <span class='foo_cl' tabindex="-1">FOO<span class='bar_cl' tabindex="-1">bar</span</span>
</div>

Note: negative tabindex makes element focusable but not tabbable because using tabbing method would start at 0 using absolute value (spec).

Now in jQuery, you could delegate focus event to these elements:

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

-jsFiddle-

As a side note, jQuery UI has a :focusable pseudo selector. If you wish to dynamically set tabindex attribute to not focusable elements, you could use:

$('[contenteditable]').find(':not(:focusable)').attr('tabindex', -1);

-jsFiddle (including jQuery UI)-

If you don't want to include jQuery UI just to get :focusable pseudo selector, you can create your own custom selector:

//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")));
        }
    });
})();

-jsFiddle-


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...