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>
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With