Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Autofocus' attribute works once, but not twice, on input elements

I code in d3.js, and sometimes use input elements to, well, gather input from the user without using a form. This works fine.

But I notice I can't apply the autofocus attribute consistently on a dynamic page; it works only the first time it's applied.

An example is below, with all coding. Notice how autofocus works perfectly the first time the input element appears. It doesn't work at all the second time, even though the coding is the same.

Fixing this would improve the UX on smartphones in particular.

Note: The .focus() method doesn't work, and I think that's because it can only be applied to input elements that are part of a form.

h1,
p,
input {
  font-family: sans-serif;
}

h1 {
  font-size: 1rem;
}

input {
  padding: 0.5rem;
  border-radius: 1rem;
  color: gray;
  opacity: 0;
}

input::placeholder {
  font-weight: normal;
  color: silver;
}

input:focus {
  outline: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div id="container">
  <h1>Testing the autofocus</h1>
</div>

<script>
  // wait 2 seconds, then create input element with autofocus
  d3.timeout(function() {
    createFirstInput();
  }, 2000);

  function createFirstInput() {
    d3.select("h1")
      .text("Creating first input field")
    d3.select("#container")
      .append("input")
      .attr("type", "text")
      .attr("placeholder", "input goes here")
      .attr("autofocus", "autofocus")
      .transition()
      .duration(2000)
      .style("opacity", 1);
    d3.select("#container")
      .append("p")
      .text("autofocus works; cursor appears in input field");
    // delete input field after 5 seconds
    d3.timeout(function() {
      d3.select("h1")
        .text("Creating second input field");
      d3.selectAll("input, p")
        .remove();
      // create second input field
      createSecondInput();
    }, 5000);
  }

  function createSecondInput() {
    // wait 2 seconds, then create input element with autofocus
    d3.timeout(function() {
      d3.select("#container")
        .append("input")
        .attr("type", "text")
        .attr("placeholder", "input goes here")
        .attr("autofocus", "autofocus")
        .transition()
        .duration(2000)
        .style("opacity", 1);
      d3.select("#container")
        .append("p")
        .text("autofocus doesn't work; no cursor in input field");
    }, 2000);
  }
</script>
like image 330
Markus Avatar asked Jan 29 '26 23:01

Markus


1 Answers

The focus() method does work:

input.node().focus();

Here, input is the D3 selection that appends the input (by the way, name your selections! It's a good practice). By using node() on that selection we get the actual DOM element, to which we use the focus() method.

Here is the demo:

h1,
p,
input {
  font-family: sans-serif;
}

h1 {
  font-size: 1rem;
}

input {
  padding: 0.5rem;
  border-radius: 1rem;
  color: gray;
  opacity: 0;
}

input::placeholder {
  font-weight: normal;
  color: silver;
}

input:focus {
  outline: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div id="container">
  <h1>Testing the autofocus</h1>
</div>

<script>
  // wait 2 seconds, then create input element with autofocus
  d3.timeout(function() {
    createFirstInput();
  }, 2000);

  function createFirstInput() {
    d3.select("h1")
      .text("Creating first input field")
    d3.select("#container")
      .append("input")
      .attr("type", "text")
      .attr("placeholder", "input goes here")
      .attr("autofocus", "autofocus")
      .transition()
      .duration(2000)
      .style("opacity", 1);
    d3.select("#container")
      .append("p")
      .text("autofocus works; cursor appears in input field");
    // delete input field after 5 seconds
    d3.timeout(function() {
      d3.select("h1")
        .text("Creating second input field");
      d3.selectAll("input, p")
        .remove();
      // create second input field
      createSecondInput();
    }, 5000);
  }

  function createSecondInput() {
    // wait 2 seconds, then create input element with autofocus
    d3.timeout(function() {
      var input = d3.select("#container")
        .append("input")
        .attr("type", "text")
        .attr("placeholder", "input goes here")
        .attr("autofocus", "autofocus")
        .transition()
        .duration(2000)
        .style("opacity", 1);
      input.node().focus();
      d3.select("#container")
        .append("p")
        .text("autofocus with focus() method does work");
    }, 2000);
  }
</script>
like image 128
Gerardo Furtado Avatar answered Jan 31 '26 13:01

Gerardo Furtado



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!