diff --git a/Packages/ohif-core/client/components/base/mixins/select2.js b/Packages/ohif-core/client/components/base/mixins/select2.js index 7d863d033..03a8223ca 100644 --- a/Packages/ohif-core/client/components/base/mixins/select2.js +++ b/Packages/ohif-core/client/components/base/mixins/select2.js @@ -99,8 +99,9 @@ OHIF.mixins.select2 = new OHIF.Mixin({ // Get the focusable elements const elements = []; const $select2 = component.$element.nextAll('.select2:first'); + const $select2Selection = $select2.find('.select2-selection'); elements.push(component.$element[0]); - elements.push($select2.find('.select2-selection')[0]); + elements.push($select2Selection[0]); // Attach focus and blur handlers to focusable elements $(elements).on('focus', event => { @@ -130,6 +131,32 @@ OHIF.mixins.select2 = new OHIF.Mixin({ } }); + // Handle dropdown opening when focusing the selection element + $select2Selection.on('keydown ', event => { + const skipKeys = new Set([8, 9, 12, 16, 17, 18, 20, 27, 46, 91, 93]); + const functionKeysRegex = /F[0-9]([0-9])?$/; + const isFunctionKey = functionKeysRegex.test(event.key); + if (skipKeys.has(event.which) || isFunctionKey) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + // Open the select2 dropdown + instance.component.$element.select2('open'); + + // Check if the pressed key will produce a character + const searchSelector = '.select2-search__field'; + const $search = component.select2Instance.$dropdown.find(searchSelector); + const isChar = OHIF.ui.isCharacterKeyPress(event); + const char = event.key; + if ($search.length && isChar && char.length === 1) { + // Event needs to be triggered twice to work properly with this plugin + $search.val(char).trigger('input').trigger('input'); + } + }); + // Set select2 as initialized instance.isInitialized = true; }; @@ -177,9 +204,10 @@ OHIF.mixins.select2 = new OHIF.Mixin({ } const $searchInput = $container.find('.select2-search__field'); - $searchInput.on('keydown.focusOnEsc', event => { - if (event.which === 27) { - $searchInput.off('keydown.focusOnEsc'); + $searchInput.on('keydown.focusOnFinish', event => { + const keys = new Set([9, 13, 27]); + if (keys.has(event.which)) { + $searchInput.off('keydown.focusOnFinish'); instance.component.$element.focus(); } }); diff --git a/Packages/ohif-core/client/lib/ui.js b/Packages/ohif-core/client/lib/ui.js index 86aaa57ba..3e5aac43d 100644 --- a/Packages/ohif-core/client/lib/ui.js +++ b/Packages/ohif-core/client/lib/ui.js @@ -68,3 +68,23 @@ OHIF.ui.getScrollbarSize = () => { return [(w1 - w2), (h1 - h2)]; }; + +/** + * Check if the pressed key combination will result in a character input + * Got from https://stackoverflow.com/questions/4179708/how-to-detect-if-the-pressed-key-will-produce-a-character-inside-an-input-text + * + * @returns {Boolean} Wheter the pressed key combination will input a character or not + */ +OHIF.ui.isCharacterKeyPress = event => { + if (typeof event.which === 'undefined') { + // This is IE, which only fires keypress events for printable keys + return true; + } else if (typeof event.which === 'number' && event.which > 0) { + // In other browsers except old versions of WebKit, event.which is + // only greater than zero if the keypress is a printable key. + // We need to filter out backspace and ctrl/alt/meta key combinations + return !event.ctrlKey && !event.metaKey && !event.altKey && event.which !== 8; + } + + return false; +};