Reputation: 625
I have following jQuery code:
$("#contact-form-applet").on("focusout",".dc2-ltfc", {ctx:this},function(event) {
var curRowDiv = $(this);
var rowObject = {};
curRowDiv.find("input, textarea").each(function(e){
rowObject[ $(this).attr("aria-label") ] = $(this).val();
});
console.log(rowObject);
});
The issue is that code is triggered every time a field loses a focus (field tab out) rather than complete div losing the focus.
Here is the JS Fiddle link demonstrating the problem.
I would like to trigger the code only when a particular row div losses focus, so that I can trigger update once and not every time a field in a row is updated.
Upvotes: 3
Views: 6935
Reputation: 628
Late to the party, but someone else may find it useful. My solution is somewhat hackish, but it is deterministic. It relies on how the JS engine schedules async processes on its single execution thread. The solution is in Angular for multiple rows of data, where I want to know if the user accessed a different field in the same row (don't trigger save) or left the row for a different row or anywhere else (trigger save). The div's (rows) are identified with the row index, but you can use any label for identifying the div depending on your use case.
Add the focusin and focusout event handlers to the div (displaying a row of data):
<div class="hover-row row"
*ngFor="let lineItem of line_items; let i = index"
(focusout)="onFocusOut(i)" (focusin)="onFocusIn(i)">
Then create these event handler functions:
onFocusOut(index) {
console.log('row focus out');
this.newAccessedIndex = -1;
setTimeout(() => this.saveLineItem(index), 0);
}
onFocusIn(index) {
console.log('row focus in');
this.newAccessedIndex = index;
}
saveLineItem(index) {
if (index == this.newAccessedIndex) {
console.log('stayed within row -> no save');
} else {
console.log('left row -> save');
}
}
The idea is that when leaving an input field in the row, focusout is triggered on the div. If a different input field is accessed in the same row, focusin is triggered for the div. In focusout we reset the index (label) of the last accessed row, in focusin we set the index. In focusout saveLineItem is called on a different execution thread, so when accessing tabbing in one row from one input field to the other, we get these console logs:
row focus out
row focus in
stayed within row -> no save
Upvotes: 0
Reputation: 3328
The jquery documentation says this:
The focusout event is sent to an element when it, or any element inside of it, loses focus.
Hence, focusout
event will fire each time when any of the child element loses its focus. Alternatively, you can use body
's keyup
and click
event to solve this by checking closest
element like this:
var previousId=null;
$('body').keyup(function (e) {
var code = e.keyCode || e.which;
if (code == '9') {
focusChange(e);
}
});
$('body').click(function (e) {
focusChange(e);
});
function focusChange(e) {
if (!previousId) {
previousId = $(e.target).closest('.dc2-ltfcc').attr('id');
return;
}
if (previousId != $(e.target).closest('.dc2-ltfcc').attr('id')) {
console.log('Exit');
previousId = null;
}
}
Here is the fiddler demonstrating the solution.
Upvotes: 1