Skip to content

Commit b96ce3c

Browse files
committed
OLMIS-8114: Show errors when leaving table row
Clicking outside a table row on plain page content now shows the row validation errors.
1 parent ceb624e commit b96ce3c

2 files changed

Lines changed: 62 additions & 3 deletions

File tree

src/openlmis-table/tr-focused.directive.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
.module('openlmis-table')
3333
.directive('tr', directive);
3434

35-
function directive() {
35+
directive.$inject = ['$rootScope'];
36+
37+
function directive($rootScope) {
3638
var focusInRow, focusedRow, rows = [];
3739

3840
return {
@@ -43,7 +45,8 @@
4345
function link(scope, element) {
4446
if (!rows.length) {
4547
angular.element('body')
46-
.on('focusin', setSelectedRow);
48+
.on('focusin', setSelectedRow)
49+
.on('focusout', clearSelectedRowOnLeave);
4750
}
4851

4952
if (rows.indexOf(element) === -1) {
@@ -76,7 +79,8 @@
7679

7780
if (!rows.length) {
7881
angular.element('body')
79-
.off('focusin', setSelectedRow);
82+
.off('focusin', setSelectedRow)
83+
.off('focusout', clearSelectedRowOnLeave);
8084
}
8185
}
8286
}
@@ -97,6 +101,25 @@
97101
focusInRow = undefined;
98102
}
99103

104+
function clearSelectedRowOnLeave(event) {
105+
var related = event.relatedTarget ||
106+
(event.originalEvent && event.originalEvent.relatedTarget);
107+
108+
// When focus moves to another focusable element a focusin follows and
109+
// setSelectedRow handles the change. Only act when focus leaves to a
110+
// non-focusable target (e.g. clicking outside the table), where no
111+
// focusin fires and the row would otherwise keep the is-focused class.
112+
if (related) {
113+
return;
114+
}
115+
116+
if (focusedRow) {
117+
focusedRow.removeClass('is-focused');
118+
focusedRow = undefined;
119+
$rootScope.$evalAsync();
120+
}
121+
}
122+
100123
}
101124

102125
})();

src/openlmis-table/tr-focused.directive.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,40 @@ describe('TR Focused Directive', function() {
5959
expect(tr.hasClass('is-focused')).toBe(false);
6060
});
6161

62+
it('removes is-focused when focus leaves the row to a non-focusable target', function() {
63+
var tr = this.table.find('tr:first');
64+
65+
this.table.find('input:first').focus();
66+
this.$rootScope.$apply();
67+
68+
expect(tr.hasClass('is-focused')).toBe(true);
69+
70+
angular.element('body').triggerHandler({
71+
type: 'focusout',
72+
relatedTarget: null
73+
});
74+
this.$rootScope.$apply();
75+
76+
expect(tr.hasClass('is-focused')).toBe(false);
77+
});
78+
79+
it('keeps is-focused when focus moves to another focusable element', function() {
80+
var tr = this.table.find('tr:first');
81+
82+
this.table.find('input:first').focus();
83+
this.$rootScope.$apply();
84+
85+
expect(tr.hasClass('is-focused')).toBe(true);
86+
87+
// A focusout with a relatedTarget is followed by a focusin that
88+
// setSelectedRow handles, so the focusout handler must not clear here.
89+
angular.element('body').triggerHandler({
90+
type: 'focusout',
91+
relatedTarget: this.table.find('input:last')[0]
92+
});
93+
this.$rootScope.$apply();
94+
95+
expect(tr.hasClass('is-focused')).toBe(true);
96+
});
97+
6298
});

0 commit comments

Comments
 (0)