4

Assuming we have a DOM:

...
<div>
  // child nodes
</div>
<div id="needsToNotBeFocusable"> 
  // child nodes 
</div>
...

Is there a way to make <div id="needsToNotBeFocusable"> and its child nodes not focusable?

Setting tabindex="-1" on each child node will ruin already existing tabindexes.

da0k0B0y
  • 53
  • 1
  • 7

2 Answers2

0

Firstly, there's a distinction between "not-focusable by tab key" and "never-focusable (programmatically, by click, or by tab)". The former is achieved with setting the tabindex="-1" attribute, the latter by adding a disabled attribute.

input {display:block}
<input>
<input>
disabled: <input disabled>
tab -1: <input tabindex="-1">
<input>
<input>

Setting tabindex="-1" on each child node will ruin already existing tabindexes.

I don't see what you mean. How could tabindex be ruined for a un-tab-focusable element?

Is there a way to make and its child nodes not focusable?

Div's can't be focused in the normal sense (though they can be scrolled to). But making its children unfocusable simply requires iterating its children (possibly multiple levels deep) and either settint tabindex or disabled.

let recursiveUnfocusable = el => {
  el.disabled = true;
  [...el.children].forEach(recursiveUnfocusable);
};

let div = document.querySelector('#needsToNotBeFocusable');
recursiveUnfocusable(div);
...
<div>
  <input><input><input>
</div>
<div id="needsToNotBeFocusable"> 
  <input><input><input>
  <div>
    <input><input><input>
  </div>
</div>
...
junvar
  • 11,151
  • 2
  • 30
  • 46
  • 1
    *"Setting tabindex="-1" on each child node will ruin already existing tabindexes."* means OP has tab indexes set for when they are focusable. – epascarello Nov 13 '19 at 15:51
  • Still don't get it. How can an element be unfocusable and have a 'tab index set for when they are focusable'? – junvar Nov 13 '19 at 15:52
  • Thanks for your answer. > I don't see what you mean. How could tabindex be ruined for a un-tab-focusable element? Child nodes of `
    ` have their own tabindexes, so iterating all child nodes and setting tabindexes to -1 will overwrite already existing structure.
    – da0k0B0y Nov 13 '19 at 15:53
  • 1
    But why do you need an **unfocusable** child element to have `tabindex` set? – junvar Nov 13 '19 at 16:15
  • Because they still exist on the page. Upon let's say, pressing a button `
    ` should be focusable again
    – da0k0B0y Nov 13 '19 at 16:19
  • ah, so you want them unfocusable **temporarily**. I don't see how anyone could have guess this without you saying so. In that case, just store the previous tabindex to another attribute, and then restore it. – junvar Nov 13 '19 at 16:39
  • `[...el.children].forEach(recursiveUnfocusable);` so no matter what the element is you are adding the attribute? yikes – epascarello Nov 13 '19 at 17:08
0

You probably want to use data attributes to hold the tab index and set it when you enable it.

document.querySelector("#inp1").addEventListener("input", function() {
  var enabled = this.value.length > 0
  document.querySelectorAll("#needsToNotBeFocusable [data-index]").forEach(function(elem) {
    elem.tabIndex = enabled ? elem.dataset.index : -1
  })
})
<div>
  <input id="inp1" tabIndex="1" placeholder="tab 1" />
</div>
<div id="needsToNotBeFocusable">
  <input data-index="2" tabIndex="-1" placeholder="tab 2" />
  <input data-index="5" tabIndex="-1" placeholder="tab 5" />
  <input data-index="3" tabIndex="-1" placeholder="tab 3" />
  <input data-index="6" tabIndex="-1" placeholder="tab 6" />
  <input data-index="4" tabIndex="-1" placeholder="tab 4" />
</div>
<input tabIndex="7" placeholder="tab 7"/>
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • Nice suggestion, but inapplicable in my case since `
    ` child nodes actually form a huge DOM tree so that's why iterating over it wasn't an option for me from the beginning since it can really hurt performance.
    – da0k0B0y Nov 13 '19 at 16:35
  • well there is not much you can really do. Either you disable the components, remove them from the page, or you remove the tab index. – epascarello Nov 13 '19 at 16:39