Skip to content

Commit df216e2

Browse files
committed
Update focus trap when form is updated
1 parent d17ac55 commit df216e2

File tree

1 file changed

+47
-22
lines changed

1 file changed

+47
-22
lines changed

system/application/views/melons/cantaloupe/js/scalarsearch.jquery.js

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,16 @@
6363
this.element.addClass('search');
6464
this.bodyContent = $('<div class="body_copy"></div>').appendTo(this.element);
6565

66+
var handleFormUpdated = function() {
67+
this.removeFocusTrap()
68+
this.setupFocusTrap()
69+
}
70+
6671
this.modal = this.bodyContent.bootstrapModal({title: 'Search', size_class:'modal-lg'});
6772
if (typeof CustomSearchManager === 'function') {
68-
this.searchManager = new CustomSearchManager(this.modal)
73+
this.searchManager = new CustomSearchManager(this.modal, handleFormUpdated.bind(this))
6974
} else {
70-
this.searchManager = new SearchManager(this.modal)
75+
this.searchManager = new SearchManager(this.modal, handleFormUpdated.bind(this))
7176
}
7277

7378
this.ontologyMenu = this.searchManager.getOntologyMenu();
@@ -83,7 +88,8 @@
8388
ScalarSearch.prototype.showSearch = function() {
8489
this.modal.modal('show');
8590
setTimeout(() => {
86-
this.searchManager.getFirstFocusable().focus()
91+
this.searchManager.getInitialFocusable().focus()
92+
this.setupFocusTrap()
8793
}, 500)
8894
}
8995

@@ -97,57 +103,62 @@
97103
}
98104
this.searchManager.setSearchField(query)
99105
this.showSearch()
100-
console.log('do search')
101106
setTimeout(() => {
102107
this.searchManager.doSearch(query)
103-
this.setupFocusTrap()
104108
}, 500)
105109
}
106110

107111
ScalarSearch.prototype.setupFocusTrap = function() {
108112

109-
var closeBtn = this.modal.find( '.close' )
110-
var firstFocusable = this.searchManager.getFirstFocusable()
111-
var lastFocusable = this.searchManager.getLastFocusable()
113+
this.closeBtn = this.modal.find( '.close' )
114+
this.firstFocusable = this.searchManager.getFirstFocusable()
115+
this.lastFocusable = this.searchManager.getLastFocusable()
112116

113-
console.log(firstFocusable, lastFocusable)
117+
var me = this
114118

115-
// tabbing forward from close button brings focus to search field
116-
closeBtn.on('keydown', (e) => {
119+
// tab from close btn to first/last focusable
120+
this.closeBtn.on('keydown.focusTrap', function(e) {
117121
var keyCode = e.keyCode || e.which;
118122
if (keyCode == 9) {
119123
if (!e.shiftKey) {
120124
e.preventDefault();
121-
firstFocusable.focus();
125+
me.firstFocusable.focus();
122126
} else {
123127
e.preventDefault();
124-
lastFocusable.focus()
128+
me.lastFocusable.focus()
125129
}
126130
}
127131
});
128132

129-
// tabbing backwards from search field link brings focus to close button
130-
firstFocusable.on('keydown', (e) => {
133+
// tab back from first focusable to close btn
134+
this.firstFocusable.on('keydown.focusTrap', function(e) {
131135
var keyCode = e.keyCode || e.which;
132136
if(keyCode == 9) {
133137
if (e.shiftKey) {
134138
e.preventDefault();
135-
closeBtn.focus();
139+
me.closeBtn.focus();
136140
}
137141
}
138142
});
139143

140-
lastFocusable.on('keydown', (e) => {
144+
// tap forward from last focusable to close btn
145+
this.lastFocusable.on('keydown.focusTrap', function(e) {
141146
var keyCode = e.keyCode || e.which;
142147
if(keyCode == 9) {
143148
if (!e.shiftKey) {
144149
e.preventDefault();
145-
closeBtn.focus();
150+
me.closeBtn.focus();
146151
}
147152
}
148153
});
149154
}
150155

156+
ScalarSearch.prototype.removeFocusTrap = function() {
157+
if (this.closeBtn) this.closeBtn.off('keydown.focusTrap')
158+
if (this.firstFocusable) this.firstFocusable.off('keydown.focusTrap')
159+
if (this.lastFocusable) this.lastFocusable.off('keydown.focusTrap')
160+
}
161+
151162
ScalarSearch.prototype.getOntologyData = function() {
152163
let me = this;
153164
let newURL = $('link#approot').attr('href').replace('application', 'ontologies');
@@ -244,8 +255,9 @@
244255
})( jQuery, window, document );
245256

246257
class SearchManager {
247-
constructor(modal) {
258+
constructor(modal, onFormUpdated) {
248259
this.modal = modal
260+
this.onFormUpdated = onFormUpdated
249261
this.bodyContent = this.modal.find('.modal-body')
250262
this.setup()
251263
}
@@ -299,7 +311,9 @@ class SearchManager {
299311
this.doSearch(this.searchField.val());
300312
});
301313

302-
this.updateForm();
314+
// wait a frame so init has a chance to happen
315+
setTimeout(this.updateForm.bind(this), 1);
316+
303317
$('#modal_scope').on('change', (event) => {
304318
this.updateForm();
305319
})
@@ -309,12 +323,21 @@ class SearchManager {
309323
this.searchField.val(query);
310324
}
311325

312-
getFirstFocusable() {
326+
getInitialFocusable() {
313327
return this.searchField
314328
}
315329

330+
getFirstFocusable() {
331+
return this.modal.find('#modal_search_term')
332+
}
333+
316334
getLastFocusable() {
317-
return this.modal.find('.vis_footer button').last()
335+
var visFooterBtns = this.modal.find('.vis_footer button')
336+
if (visFooterBtns.length > 0) {
337+
return visFooterBtns.last()
338+
} else {
339+
return this.modal.find('button[type="submit"]')
340+
}
318341
}
319342

320343
updateForm() {
@@ -323,6 +346,7 @@ class SearchManager {
323346
} else {
324347
$('.search_metadata_option').show()
325348
}
349+
if (this.onFormUpdated) this.onFormUpdated()
326350
}
327351

328352
getOntologyMenu() {
@@ -514,6 +538,7 @@ class SearchManager {
514538
} else {
515539
this.scalarvis.setOptions(visOptions)
516540
}
541+
if (this.onFormUpdated) this.onFormUpdated()
517542
}
518543
}
519544
}

0 commit comments

Comments
 (0)