Reputation: 34089
I have few input html elements. On change event (tab-out) of input im making a ajax post and get back html. and then i replace the existing html with this new html. Doing so looses the focus on next input element. However before i make the ajax post im storing id of the currently focused element so that i can refocus the same input after html is replaced. But its not working
below is my code
<div id="mycontainer">
<input id="input1" />
<input id="input2" />
<input id="input3" />
</div>
$(function () {
$("input").change(function () {
$.ajax(
{
data: "somedata",
url: "someurl",
method: "POST"
})
.done(function (response) {
var currentElement = $(':focus').attr("id");
$("#mycontainer").html(response)
$("#" + currentElement).focus();
})
})
})
Upvotes: 0
Views: 2100
Reputation: 92274
Change event fires after the blur event, so focus has moved. If you want to focus on the element that was changed, you can use event.target
to get a reference to the input that changed.
$("input").change(function (event) {
$.ajax({
data: "somedata",
url: "someurl",
method: "POST"
}) .done(function (response) {
var currentElement = event.target.id;
$("#mycontainer").html(response)
$("#" + currentElement).focus();
});
})
If you want focus to remain where it is, your code should work, here's the proof.
const HTML = `
<input id="input1" />
<input id="input2" />
<input id="input3" />
`;
$(() => {
$("input").change(() => {
// Add async code to fake ajax
new Promise((resolve, reject) => {
setTimeout(() => resolve(HTML), 100);
}).then(response => {
const currentElement = $(':focus').attr("id");
$("#mycontainer").html(response)
$("#" + currentElement).focus();
});
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mycontainer">
<input id="input1" />
<input id="input2" />
<input id="input3" />
</div>
However, as mentioned in my comment, this is poor approach because you lose the handlers, so you'll have to reset the handlers too and maybe scroll position. To avoid this, you can make your AJAX return data and update only the bits that need to be updated.
Upvotes: 2
Reputation: 2688
When you click somewhere on the page (including the button / link that loads your ajax content), the clicked element immediately takes the focus. So just before changing the html, it is already too late to store the focused id. You need to store it on focus change instead.
Edit: Since there is no 'click' involved in the OP's question, I'm proposing an updated version of the above solution: Storing the changed input and running ajax stuff in focus handler.
let changedInput;
$(document).on('focus', 'input', function() {
if (changedInput) {
// do whatever with changedInput.val() needed here
changedInput = null;
const currentElement = $(this).attr('id');
$.ajax({
data: "somedata",
url: "someurl",
method: "POST"
})
.done(function(response) {
$("#mycontainer").html(response);
$("#" + currentElement).focus();
})
}
});
$(document).on('change', 'input', function() {
changedInput = this;
})
/* BEGIN FAKE AJAX STUFF
*
*/
let counter = 0;
$.ajax = function(params) {
$('#msg').text("Fake AJAX Loading...");
return {
done: function(cb) {
setTimeout(function() {
$('#msg').text("");
cb(`
<div id="mycontainer">
<input value="${counter}" id="input1" />
<input value="${counter}" id="input2" />
<input value="${counter++}" id="input3" />
</div>
`);
}, 300);
}
}
}
/* END FAKE AJAX STUFF */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:20px;" id="msg"></div>
<div id="mycontainer">
<input value="" id="input1" />
<input value="" id="input2" />
<input value="" id="input3" />
</div>
Upvotes: 1