为什么 D3 只在第一次关注输入时起作用?

Why does D3's focus on an input work only the first time?

可以focus on an input field using D3, without even the need to go through setTimeout(我不知道为什么,但我没有抱怨)。

但这只适用于第一次。第二次按下 Set 后(即:SetResetSet),输入字段不会获得焦点。为什么?

将回调设置为焦点 after the transition is complete 出现错误。

<!DOCTYPE HTML>
<head>
    <style>
        div { width: 300px; }
        div#outerdiv  { height: 500px; background-color: #ccc; }
        div#topdiv    { height: 400px; background-color: #dff; }
        div#bottomdiv { height: 0px;   background-color: #ffd; display: 'none' }
        input:focus { background-color: pink; }
    </style>
</head>
<body>
    <div id="outerdiv">
        <div id="topdiv">
            <button onclick=open_form();>Set</button>
            <button onclick=close_form();>Reset</button>
        </div>

        <div id="bottomdiv">
            <form action="javascript:close_form()">
                Name:
                <input type="text" id="myTextField" name="name">
                <input type="submit" name="submit" value="Submit">
            </form>
        </div>
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

    <script>
        function open_form() {
            d3.select('#topdiv').transition().duration(500)
              .style('height', '100px');
            d3.select('#bottomdiv').transition().duration(500)
              .style('height', '300px').style('display', 'inline-block');

            d3.select("#myTextField").node().focus();
        } 
        function close_form() {
            d3.select('#topdiv').transition().duration(500)
              .style('height', '390px');
            d3.select('#bottomdiv').transition().duration(500)
              .style('height', '10px').style('display', 'none');
        }
    </script>
</body>

无法找到#myTextField,因为它正在转换。您可以通过删除 display: inline-block 的过渡来解决此问题,如下所示。

function open_form() {
    d3.select('#topdiv').transition().duration(500)
      .style('height', '100px');
    d3.select('#bottomdiv').style('display', 'inline-block');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '300px');
    d3.select("#myTextField").node().focus();
} 

每次您点击 重置 按钮,即当调用 close_form() 时,您的 #bottomdiv 会转换为 display: none:

d3.select('#bottomdiv').transition().duration(500)
    .style('height', '10px').style('display', 'none');

不过这有一些副作用。查看 focus management 上的 HTML5 规范表明,未呈现的元素也不可聚焦:

7.4.2 Focus management

An element is focusable if all of the following conditions are met:

因此,下次您点击 Set 时调用 open_form() 输入无法聚焦,因为到 inline-block 的转换尚未结束然而。解决此问题的最简单方法是 listen 用于转换的 end 事件,该事件在转换结束后触发。

   d3.select('#bottomdiv').transition().duration(500)
       .style('height', '300px').style('display', 'inline-block')
       .on("end", () => d3.select("#myTextField").node().focus());

查看以下代码片段以了解工作演示:

function open_form() {
    d3.select('#topdiv').transition().duration(500)
      .style('height', '100px');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '300px').style('display', 'inline-block')
      .on("end", () => d3.select("#myTextField").node().focus());

} 
function close_form() {
    d3.select('#topdiv').transition().duration(500)
      .style('height', '390px');
    d3.select('#bottomdiv').transition().duration(500)
      .style('height', '10px').style('display', 'none');
}
div { width: 300px; }
div#outerdiv  { height: 500px; background-color: #ccc; }
div#topdiv    { height: 400px; background-color: #dff; }
div#bottomdiv { height: 0px;   background-color: #ffd; display: 'none' }
input:focus { background-color: pink; }
<body>
    <div id="outerdiv">
        <div id="topdiv">
            <button onclick=open_form();>Set</button>
            <button onclick=close_form();>Reset</button>
        </div>

        <div id="bottomdiv">
            <form action="javascript:close_form()">
                Name:
                <input type="text" id="myTextField" name="name">
                <input type="submit" name="submit" value="Submit">
            </form>
        </div>
    </div>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>

</body>