summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js')
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js43
1 files changed, 42 insertions, 1 deletions
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
index 162491312a8..a1dd12ff769 100644
--- a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
@@ -29,6 +29,26 @@ const FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-fil
const NO_FILTER_INPUT = '.dropdown-input .dropdown-input-field.dropdown-no-filter';
+let mouseEventListenersAdded = false;
+let mousedownTarget = null;
+let mouseupTarget = null;
+
+function addGlobalMouseEventListeners() {
+ // Remember mousedown and mouseup locations.
+ // Required in the `hide.bs.dropdown` listener for
+ // dropdown close prevention in some cases.
+ document.addEventListener('mousedown', ({ target }) => {
+ mousedownTarget = target;
+ });
+ document.addEventListener('mouseup', ({ target }) => {
+ mouseupTarget = target;
+ });
+ document.addEventListener('click', () => {
+ mousedownTarget = null;
+ mouseupTarget = null;
+ });
+}
+
export class GitLabDropdown {
constructor(el1, options) {
let selector;
@@ -36,9 +56,14 @@ export class GitLabDropdown {
this.el = el1;
this.options = options;
this.updateLabel = this.updateLabel.bind(this);
- this.hidden = this.hidden.bind(this);
this.opened = this.opened.bind(this);
+ this.hide = this.hide.bind(this);
+ this.hidden = this.hidden.bind(this);
this.shouldPropagate = this.shouldPropagate.bind(this);
+ if (!mouseEventListenersAdded) {
+ addGlobalMouseEventListeners();
+ mouseEventListenersAdded = true;
+ }
self = this;
selector = $(this.el).data('target');
this.dropdown = selector != null ? $(selector) : $(this.el).parent();
@@ -132,6 +157,7 @@ export class GitLabDropdown {
}
// Event listeners
this.dropdown.on('shown.bs.dropdown', this.opened);
+ this.dropdown.on('hide.bs.dropdown', this.hide);
this.dropdown.on('hidden.bs.dropdown', this.hidden);
$(this.el).on('update.label', this.updateLabel);
this.dropdown.on('click', '.dropdown-menu, .dropdown-menu-close', this.shouldPropagate);
@@ -334,6 +360,21 @@ export class GitLabDropdown {
$menu.css('bottom', '100%');
}
+ hide(e) {
+ // Prevent dropdowns with a search from being closed when the
+ // mousedown event happened inside the dropdown box and only
+ // the mouseup event did not.
+ if (this.options.search && mousedownTarget) {
+ const isIn = (element, $possibleContainer) => Boolean($possibleContainer.has(element).length);
+ const $menu = this.dropdown.find('.dropdown-menu');
+ const mousedownInsideDropdown = isIn(mousedownTarget, $menu);
+ const mouseupOutsideDropdown = !isIn(mouseupTarget, $menu);
+ if (mousedownInsideDropdown && mouseupOutsideDropdown) {
+ e.preventDefault();
+ }
+ }
+ }
+
hidden(e) {
this.resetRows();
this.removeArrowKeyEvent();