I have a normal HTML input box: <input id="ip">
.
And this input box has focused. I know this by looking at the screen and the fact document.activeElement
tells me so.
Now I want to replace this input node. And I do so with: var the_new_node = document.createElement("input"); the_new_node.id="ip"; the_input_node.replaceWith(the_new_node);
When I do this, however, the input box loses focus. document.activeElement
now points to the body. Is there anyway to prevent this?
Edit: I realise I can call .focus()
. Yet in my code I won't necessarily know if the node to be replaced will have an input
within it.
For instance, the in various 'virtual dom' implementations they replace segments of the dom tree while retaining focus. How do they do it?
If you want to only focus the new input if the element you're replacing had a focused element inside, you can code exactly that using .contains(document.activeElement)
:
function runReplace(idx) {
document.querySelectorAll("input")[0].focus();
setTimeout(() => {
let p = document.getElementById("par").children[idx];
let wasFocused = p.contains(document.activeElement);
let newNode = document.createElement("input");
newNode.type = "text";
newNode.value = "replacement for child #" + idx;
p.replaceWith(newNode);
if (wasFocused)
newNode.focus();
console.log("Replaced ", p, " with an input; wasFocused=", wasFocused);
}, 3000);
}
<div id="par">
<p>This is a paragraph with <b>an <input type="text" id="inp" value="<input>"> inside</b></p>
<p>This is a paragraph with no input inside</p>
</div>
<button onclick="runReplace(0)">Replace first paragraph in 3 seconds</button>
<button onclick="runReplace(1)">Replace second paragraph in 3 seconds</button>
There's no magic way the browser can "preserve" focus in face of replacing an arbitrary DOM sub-tree with another arbitrary sub-tree, so you have to do it manually.
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