text: /* eslint-disable max-classes-per-file, one-var, consistent-return */
  
  import $ from 'jquery';
  import { escape } from 'lodash';
  import fuzzaldrinPlus from 'fuzzaldrin-plus';
  import axios from './lib/utils/axios_utils';
  import { visitUrl } from './lib/utils/url_utility';
  import { isObject } from './lib/utils/type_utility';
  import renderItem from './gl_dropdown/render';
  
  const BLUR_KEYCODES = [27, 40];
  
  const HAS_VALUE_CLASS = 'has-value';
  
  const LOADING_CLASS = 'is-loading';
  
  const PAGE_TWO_CLASS = 'is-page-two';
  
  const ACTIVE_CLASS = 'is-active';
  
  const INDETERMINATE_CLASS = 'is-indeterminate';
  
  let currentIndex = -1;
  
  const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
  
  const SELECTABLE_CLASSES = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES}, .option-hidden)`;
  
  const CURSOR_SELECT_SCROLL_PADDING = 5;
  
  const FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)';
  
  const NO_FILTER_INPUT = '.dropdown-input .dropdown-input-field.dropdown-no-filter';
  
  class GitLabDropdownInput {
    constructor(input, options) {
      this.input = input;
      this.options = options;
      this.fieldName = this.options.fieldName || 'field-name';
      const $inputContainer = this.input.parent();
      const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
      $clearButton.on('click', e => {
        // Clear click
        e.preventDefault();
        e.stopPropagation();
        return this.input
          .val('')
          .trigger('input')
          .focus();
      });
  
      this.input
        .on('keydown', e => {
          const keyCode = e.which;
          if (keyCode === 13 && !options.elIsInput) {
            e.preventDefault();
          }
        })
        .on('input', e => {
          let val = e.currentTarget.value || this.options.inputFieldName;
          val = val
            .split(' ')
            .join('-') // replaces space with dash
            .replace(/[^a-zA-Z0-9 -]/g, '')
            .toLowerCase() // replace non alphanumeric
            .replace(/(-)\1+/g, '-'); // replace repeated dashes
          this.cb(this.options.fieldName, val, {}, true);
          this.input
            .closest('.dropdown')
            .find('.dropdown-toggle-text')
            .text(val);
        });
    }
  
    onInput(cb) {
      this.cb = cb;
    }
  }
  
  class GitLabDropdownFilter {
    constructor(input, options) {
      let ref, timeout;
      this.input = input;
      this.options = options;
      // eslint-disable-next-line no-cond-assign
      this.filterInputBlur = (ref = this.options.filterInputBlur) != null ? ref : true;
      const $inputContainer = this.input.parent();
      const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
      $clearButton.on('click', e => {
        // Clear click
        e.preventDefault();
        e.stopPropagation();
        return this.input
          .val('')
          .trigger('input')
          .focus();
      });
      // Key events
      timeout = '';
      this.input
        .on('keydown', e => {
          const keyCode = e.which;
          if (keyCode === 13 && !options.elIsInput) {
            e.preventDefault();
          }
        })
        .on('input', () => {
          if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
            $inputContainer.addClass(HAS_VALUE_CLASS);
          } else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
            $inputContainer.removeClass(HAS_VALUE_CLASS);
          }
          // Only filter asynchronously only if option remote is set
          if (this.options.remote) {
            clearTimeout(timeout);
            // eslint-disable-next-line no-return-assign
            return (timeout = setTimeout(() => {
              $inputContainer.parent().addClass('is-loading');
  
              return this.options.query(this.input.val(), data => {
                $inputContainer.parent().removeClass('is-loading');
                return this.options.callback(data);
              });
            }, 250));
          }
          return this.filter(this.input.val());
        });
    }
  
    static shouldBlur(keyCode) {
      return BLUR_KEYCODES.indexOf(keyCode) !== -1;
    }
  
    filter(searchText) {
      let group, results, tmp;
      if (this.options.onFilter) {
        this.options.onFilter(searchText);
      }
      const data = this.options.data();
      if (data != null && !this.options.filterByText) {
        results = data;
        if (searchText !== '') {
          // When data is an array of objects therefore [object Array] e.g.
          // [
          //   { prop: 'foo' },
          //   { prop: 'baz' }
          // ]
          if (Array.isArray(data)) {
            results = fuzzaldrinPlus.filter(data, searchText, {
              key: this.options.keys,
            });
          }
          // If data is grouped therefore an [object Object]. e.g.
          // {
          //   groupName1: [
          //     { prop: 'foo' },
          //     { prop: 'baz' }
          //   ],
          //   groupName2: [
          //     { prop: 'abc' },
          //     { prop: 'def' }
          //   ]
          // }
          else if (isObject(data)) {
            results = {};
            Object.keys(data).forEach(key => {
              group = data[key];
              tmp = fuzzaldrinPlus.filter(group, searchText, {
                key: this.options.keys,
              });
              if (tmp.length) {
                results[key] = tmp.map(item => item);
              }
            });
          }
        }
        return this.options.callback(results);
      }
      const elements = this.options.elements();
      if (searchText) {
        // eslint-disable-next-line func-names
        elements.each(function() {
          const $el = $(this);
          const matches = fuzzaldrinPlus.match($el.text().trim(), searchText);
          if (!$el.is('.dropdown-header')) {
            if (matches.length) {
              return $el.show().removeClass('option-hidden');
            }
            return $el.hide().addClass('option-hidden');
          }
        });
      } else {
        elements.show().removeClass('option-hidden');
      }
  
      elements
        .parent()
        .find('.dropdown-menu-empty-item')
        .toggleClass('hidden', elements.is(':visible'));
    }
  }
  
  class GitLabDropdownRemote {
    constructor(dataEndpoint, options) {
      this.dataEndpoint = dataEndpoint;
      this.options = options;
    }
  
    execute() {
      if (typeof this.dataEndpoint === 'string') {
        return this.fetchData();
      } else if (typeof this.dataEndpoint === 'function') {
        if (this.options.beforeSend) {
          this.options.beforeSend();
        }
        return this.dataEndpoint('', data => {
          // Fetch the data by calling the data function
          if (this.options.success) {
            this.options.success(data);
          }
          if (this.options.beforeSend) {
            return this.options.beforeSend();
          }
        });
      }
    }
  
    fetchData() {
      if (this.options.beforeSend) {
        this.options.beforeSend();
      }
  
      // Fetch the data through ajax if the data is a string
      return axios.get(this.dataEndpoint).then(({ data }) => {
        if (this.options.success) {
          return this.options.success(data);
        }
      });
    }
  }
  
  class GitLabDropdown {
    constructor(el1, options) {
      let selector, self;
      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.shouldPropagate = this.shouldPropagate.bind(this);
      self = this;
      selector = $(this.el).data('target');
      this.dropdown = selector != null ? $(selector) : $(this.el).parent();
      // Set Defaults
      this.filterInput = this.options.filterInput || this.getElement(FILTER_INPUT);
      this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
      this.highlight = Boolean(this.options.highlight);
      this.icon = Boolean(this.options.icon);
      this.filterInputBlur =
        this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
      // If no input is passed create a default one
      self = this;
      // If selector was passed
      if (typeof this.filterInput === 'string') {
        this.filterInput = this.getElement(this.filterInput);
      }
      const searchFields = this.options.search ? this.options.search.fields : [];
      if (this.options.data) {
        // If we provided data
        // data could be an array of objects or a group of arrays
        if (typeof this.options.data === 'object' && !(this.options.data instanceof Function)) {
          this.fullData = this.options.data;
          currentIndex = -1;
          this.parseData(this.options.data);
          this.focusTextInput();
        } else {
          this.remote = new GitLabDropdownRemote(this.options.data, {
            dataType: this.options.dataType,
            beforeSend: this.toggleLoading.bind(this),
            success: data => {
              this.fullData = data;
              this.parseData(this.fullData);
              this.focusTextInput();
  
              // Update dropdown position since remote data may have changed dropdown size
              this.dropdown.find('.dropdown-menu-toggle').dropdown('update');
  
              if (
                this.options.filterable &&
                this.filter &&
                this.filter.input &&
                this.filter.input.val() &&
                this.filter.input.val().trim() !== ''
              ) {
                return this.filter.input.trigger('input');
              }
            },
            instance: this,
          });
        }
      }
      if (this.noFilterInput.length) {
        this.plainInput = new GitLabDropdownInput(this.noFilterInput, this.options);
        this.plainInput.onInput(this.addInput.bind(this));
      }
      // Init filterable
      if (this.options.filterable) {
        this.filter = new GitLabDropdownFilter(this.filterInput, {
          elIsInput: $(this.el).is('input'),
          filterInputBlur: this.filterInputBlur,
          filterByText: this.options.filterByText,
          onFilter: this.options.onFilter,
          remote: this.options.filterRemote,
          query: this.options.data,
          keys: searchFields,
          instance: this,
          elements: () => {
            selector = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
            if (this.dropdown.find('.dropdown-toggle-page').length) {
              selector = `.dropdown-page-one ${selector}`;
            }
            return $(selector, this.dropdown);
          },
          data: () => this.fullData,
          callback: data => {
            this.parseData(data);
            if (this.filterInput.val() !== '') {
              selector = SELECTABLE_CLASSES;
              if (this.dropdown.find('.dropdown-toggle-page').length) {
                selector = `.dropdown-page-one ${selector}`;
              }
              if ($(this.el).is('input')) {
                currentIndex = -1;
              } else {
                $(selector, this.dropdown)
                  .first()
                  .find('a')
                  .addClass('is-focused');
                currentIndex = 0;
              }
            }
          },
        });
      }
      // Event listeners
      this.dropdown.on('shown.bs.dropdown', this.opened);
      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);
      this.dropdown.on('keyup', e => {
        // Escape key
        if (e.which === 27) {
          return $('.dropdown-menu-close', this.dropdown).trigger('click');
        }
      });
      this.dropdown.on('blur', 'a', e => {
        let $dropdownMenu, $relatedTarget;
        if (e.relatedTarget != null) {
          $relatedTarget = $(e.relatedTarget);
          $dropdownMenu = $relatedTarget.closest('.dropdown-menu');
          if ($dropdownMenu.length === 0) {
            return this.dropdown.removeClass('show');
          }
        }
      });
      if (this.dropdown.find('.dropdown-toggle-page').length) {
        this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on('click', e => {
          e.preventDefault();
          e.stopPropagation();
          return this.togglePage();
        });
      }
      if (this.options.selectable) {
        selector = '.dropdown-content a';
        if (this.dropdown.find('.dropdown-toggle-page').length) {
          selector = '.dropdown-page-one .dropdown-content a';
        }
        this.dropdown.on('click', selector, e => {
          const $el = $(e.currentTarget);
          const selected = self.rowClicked($el);
          const selectedObj = selected ? selected[0] : null;
          const isMarking = selected ? selected[1] : null;
          if (this.options.clicked) {
            this.options.clicked.call(this, {
              selectedObj,
              $el,
              e,
              isMarking,
            });
          }
  
          // Update label right after all modifications in dropdown has been done
          if (this.options.toggleLabel) {
            this.updateLabel(selectedObj, $el, this);
          }
  
          $el.trigger('blur');
        });
      }
    }
  
    // Finds an element inside wrapper element
    getElement(selector) {
      return this.dropdown.find(selector);
    }
  
    toggleLoading() {
      return $('.dropdown-menu', this.dropdown).toggleClass(LOADING_CLASS);
    }
  
    togglePage() {
      const menu = $('.dropdown-menu', this.dropdown);
      if (menu.hasClass(PAGE_TWO_CLASS)) {
        if (this.remote) {
          this.remote.execute();
        }
      }
      menu.toggleClass(PAGE_TWO_CLASS);
      // Focus first visible input on active page
      return this.dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus();
    }
  
    parseData(data) {
      let groupData, html;
      this.renderedData = data;
      if (this.options.filterable && data.length === 0) {
        // render no matching results
        html = [this.noResults()];
      }
      // Handle array groups
      else if (isObject(data)) {
        html = [];
  
        Object.keys(data).forEach(name => {
          groupData = data[name];
          html.push(
            this.renderItem(
              {
                content: name,
                type: 'header',
              },
              name,
            ),
          );
          this.renderData(groupData, name).map(item => html.push(item));
        });
      } else {
        // Render each row
        html = this.renderData(data);
      }
      // Render the full menu
      const fullHtml = this.renderMenu(html);
      return this.appendMenu(fullHtml);
    }
  
    renderData(data, group) {
      return data.map((obj, index) => this.renderItem(obj, group || false, index));
    }
  
    shouldPropagate(e) {
      let $target;
      if (this.options.multiSelect || this.options.shouldPropagate === false) {
        $target = $(e.target);
        if (
          $target &&
          !$target.hasClass('dropdown-menu-close') &&
          !$target.hasClass('dropdown-menu-close-icon') &&
          !$target.data('isLink')
        ) {
          e.stopPropagation();
  
          // This prevents automatic scrolling to the top
          if ($target.closest('a').length) {
            return false;
          }
        }
  
        return true;
      }
    }
  
    filteredFullData() {
      return this.fullData.filter(
        r =>
          typeof r === 'object' &&
          !Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
          !Object.prototype.hasOwnProperty.call(r, 'header'),
      );
    }
  
    opened(e) {
      this.resetRows();
      this.addArrowKeyEvent();
  
      const dropdownToggle = this.dropdown.find('.dropdown-menu-toggle');
      const hasFilterBulkUpdate = dropdownToggle.hasClass('js-filter-bulk-update');
      const shouldRefreshOnOpen = dropdownToggle.hasClass('js-gl-dropdown-refresh-on-open');
      const hasMultiSelect = dropdownToggle.hasClass('js-multiselect');
  
      // Makes indeterminate items effective
      if (this.fullData && (shouldRefreshOnOpen || hasFilterBulkUpdate)) {
        this.parseData(this.fullData);
      }
  
      // Process the data to make sure rendered data
      // matches the correct layout
      const inputValue = this.filterInput.val();
      if (this.fullData && hasMultiSelect && this.options.processData && inputValue.length === 0) {
        this.options.processData.call(
          this.options,
          inputValue,
          this.filteredFullData(),
          this.parseData.bind(this),
        );
      }
  
      const contentHtml = $('.dropdown-content', this.dropdown).html();
      if (this.remote && contentHtml === '') {
        this.remote.execute();
      } else {
        this.focusTextInput();
      }
  
      if (this.options.showMenuAbove) {
        this.positionMenuAbove();
      }
  
      if (this.options.opened) {
        if (this.options.preserveContext) {
          this.options.opened(e);
        } else {
          this.options.opened.call(this, e);
        }
      }
  
      return this.dropdown.trigger('shown.gl.dropdown');
    }
  
    positionMenuAbove() {
      const $menu = this.dropdown.find('.dropdown-menu');
  
      $menu.addClass('dropdown-open-top');
      $menu.css('top', 'initial');
      $menu.css('bottom', '100%');
    }
  
    hidden(e) {
      this.resetRows();
      this.removeArrowKeyEvent();
      const $input = this.dropdown.find('.dropdown-input-field');
      if (this.options.filterable) {
        $input.blur();
      }
      if (this.dropdown.find('.dropdown-toggle-page').length) {
        $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
      }
      if (this.options.hidden) {
        this.options.hidden.call(this, e);
      }
      return this.dropdown.trigger('hidden.gl.dropdown');
    }
  
    // Render the full menu
    renderMenu(html) {
      if (this.options.renderMenu) {
        return this.options.renderMenu(html);
      }
      return $('<ul>').append(html);
    }
  
    // Append the menu into the dropdown
    appendMenu(html) {
      return this.clearMenu().append(html);
    }
  
    clearMenu() {
      let selector = '.dropdown-content';
      if (this.dropdown.find('.dropdown-toggle-page').length) {
        if (this.options.containerSelector) {
          selector = this.options.containerSelector;
        } else {
          selector = '.dropdown-page-one .dropdown-content';
        }
      }
  
      return $(selector, this.dropdown).empty();
    }
  
    renderItem(data, group, index) {
      let parent;
  
      if (this.dropdown && this.dropdown[0]) {
        parent = this.dropdown[0].parentNode;
      }
  
      return renderItem({
        instance: this,
        options: {
          ...this.options,
          icon: this.icon,
          highlight: this.highlight,
          highlightText: text => this.highlightTextMatches(text, this.filterInput.val()),
          highlightTemplate: this.highlightTemplate.bind(this),
          parent,
        },
        data,
        group,
        index,
      });
    }
  
    // eslint-disable-next-line class-methods-use-this
    highlightTemplate(text, template) {
      return `"<b>${escape(text)}</b>" ${template}`;
    }
  
    // eslint-disable-next-line class-methods-use-this
    highlightTextMatches(text, term) {
      const occurrences = fuzzaldrinPlus.match(text, term);
      const { indexOf } = [];
  
      return text
        .split('')
        .map((character, i) => {
          if (indexOf.call(occurrences, i) !== -1) {
            return `<b>${character}</b>`;
          }
          return character;
        })
        .join('');
    }
  
    // eslint-disable-next-line class-methods-use-this
    noResults() {
      return '<li class="dropdown-menu-empty-item"><a>No matching results</a></li>';
    }
  
    rowClicked(el) {
      let field, groupName, selectedIndex, selectedObject, isMarking;
      const { fieldName } = this.options;
      const isInput = $(this.el).is('input');
      if (this.renderedData) {
        groupName = el.data('group');
        if (groupName) {
          selectedIndex = el.data('index');
          selectedObject = this.renderedData[groupName][selectedIndex];
        } else {
          selectedIndex = el.closest('li').index();
          this.selectedIndex = selectedIndex;
          selectedObject = this.renderedData[selectedIndex];
        }
      }
  
      if (this.options.vue) {
        if (el.hasClass(ACTIVE_CLASS)) {
          el.removeClass(ACTIVE_CLASS);
        } else {
          el.addClass(ACTIVE_CLASS);
        }
  
        return [selectedObject];
      }
  
      field = [];
      const value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
      if (isInput) {
        field = $(this.el);
      } else if (value != null) {
        field = this.dropdown
          .parent()
          .find(`input[name='${fieldName}'][value='${value.toString().replace(/'/g, "\\'")}']`);
      }
  
      if (this.options.isSelectable && !this.options.isSelectable(selectedObject, el)) {
        return [selectedObject];
      }
  
      if (el.hasClass(ACTIVE_CLASS) && value !== 0) {
        isMarking = false;
        el.removeClass(ACTIVE_CLASS);
        if (field && field.length) {
          this.clearField(field, isInput);
        }
      } else if (el.hasClass(INDETERMINATE_CLASS)) {
        isMarking = true;
        el.addClass(ACTIVE_CLASS);
        el.removeClass(INDETERMINATE_CLASS);
        if (field && field.length && value == null) {
          this.clearField(field, isInput);
        }
        if ((!field || !field.length) && fieldName) {
          this.addInput(fieldName, value, selectedObject);
        }
      } else {
        isMarking = true;
        if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) {
          this.dropdown.find(`.${ACTIVE_CLASS}`).removeClass(ACTIVE_CLASS);
          if (!isInput) {
            this.dropdown
              .parent()
              .find(`input[name='${fieldName}']`)
              .remove();
          }
        }
        if (field && field.length && value == null) {
          this.clearField(field, isInput);
        }
        // Toggle active class for the tick mark
        el.addClass(ACTIVE_CLASS);
        if (value != null) {
          if ((!field || !field.length) && fieldName) {
            this.addInput(fieldName, value, selectedObject);
          } else if (field && field.length) {
            field.val(value).trigger('change');
          }
        }
      }
  
      return [selectedObject, isMarking];
    }
  
    focusTextInput() {
      if (this.options.filterable) {
        const initialScrollTop = $(window).scrollTop();
  
        if (this.dropdown.is('.show') && !this.filterInput.is(':focus')) {
          this.filterInput.focus();
        }
  
        if ($(window).scrollTop() < initialScrollTop) {
          $(window).scrollTop(initialScrollTop);
        }
      }
    }
  
    addInput(fieldName, value, selectedObject, single) {
      // Create hidden input for form
      if (single) {
        $(`input[name="${fieldName}"]`).remove();
      }
  
      const $input = $('<input>')
        .attr('type', 'hidden')
        .attr('name', fieldName)
        .val(value);
      if (this.options.inputId != null) {
        $input.attr('id', this.options.inputId);
      }
  
      if (this.options.multiSelect) {
        Object.keys(selectedObject).forEach(attribute => {
          $input.attr(`data-${attribute}`, selectedObject[attribute]);
        });
      }
  
      if (this.options.inputMeta) {
        $input.attr('data-meta', selectedObject[this.options.inputMeta]);
      }
  
      this.dropdown.before($input).trigger('change');
    }
  
    selectRowAtIndex(index) {
      // If we pass an option index
      let selector;
      if (typeof index !== 'undefined') {
        selector = `${SELECTABLE_CLASSES}:eq(${index}) a`;
      } else {
        selector = '.dropdown-content .is-focused';
      }
      if (this.dropdown.find('.dropdown-toggle-page').length) {
        selector = `.dropdown-page-one ${selector}`;
      }
      // simulate a click on the first link
      const $el = $(selector, this.dropdown);
      if ($el.length) {
        const href = $el.attr('href');
        if (href && href !== '#') {
          visitUrl(href);
        } else {
          $el.trigger('click');
        }
      }
    }
  
    addArrowKeyEvent() {
      const ARROW_KEY_CODES = [38, 40];
      let selector = SELECTABLE_CLASSES;
      if (this.dropdown.find('.dropdown-toggle-page').length) {
        selector = `.dropdown-page-one ${selector}`;
      }
      return $('body').on('keydown', e => {
        let $listItems, PREV_INDEX;
        const currentKeyCode = e.which;
        if (ARROW_KEY_CODES.indexOf(currentKeyCode) !== -1) {
          e.preventDefault();
          e.stopImmediatePropagation();
          PREV_INDEX = currentIndex;
          $listItems = $(selector, this.dropdown);
          // if @options.filterable
          //   $input.blur()
          if (currentKeyCode === 40) {
            // Move down
            if (currentIndex < $listItems.length - 1) {
              currentIndex += 1;
            }
          } else if (currentKeyCode === 38) {
            // Move up
            if (currentIndex > 0) {
              currentIndex -= 1;
            }
          }
          if (currentIndex !== PREV_INDEX) {
            this.highlightRowAtIndex($listItems, currentIndex);
          }
          return false;
        }
        if (currentKeyCode === 13 && currentIndex !== -1) {
          e.preventDefault();
          this.selectRowAtIndex();
        }
      });
    }
  
    // eslint-disable-next-line class-methods-use-this
    removeArrowKeyEvent() {
      return $('body').off('keydown');
    }
  
    resetRows() {
      currentIndex = -1;
      $('.is-focused', this.dropdown).removeClass('is-focused');
    }
  
    highlightRowAtIndex($listItems, index) {
      if (!$listItems) {
        // eslint-disable-next-line no-param-reassign
        $listItems = $(SELECTABLE_CLASSES, this.dropdown);
      }
  
      // Remove the class for the previously focused row
      $('.is-focused', this.dropdown).removeClass('is-focused');
      // Update the class for the row at the specific index
      const $listItem = $listItems.eq(index);
      $listItem.find('a:first-child').addClass('is-focused');
      // Dropdown content scroll area
      const $dropdownContent = $listItem.closest('.dropdown-content');
      const dropdownScrollTop = $dropdownContent.scrollTop();
      const dropdownContentHeight = $dropdownContent.outerHeight();
      const dropdownContentTop = $dropdownContent.prop('offsetTop');
      const dropdownContentBottom = dropdownContentTop + dropdownContentHeight;
      // Get the offset bottom of the list item
      const listItemHeight = $listItem.outerHeight();
      const listItemTop = $listItem.prop('offsetTop');
      const listItemBottom = listItemTop + listItemHeight;
      if (!index) {
        // Scroll the dropdown content to the top
        $dropdownContent.scrollTop(0);
      } else if (index === $listItems.length - 1) {
        // Scroll the dropdown content to the bottom
        $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight'));
      } else if (listItemBottom > dropdownContentBottom + dropdownScrollTop) {
        // Scroll the dropdown content down
        $dropdownContent.scrollTop(
          listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING,
        );
      } else if (listItemTop < dropdownContentTop + dropdownScrollTop) {
        // Scroll the dropdown content up
        return $dropdownContent.scrollTop(
          listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING,
        );
      }
    }
  
    updateLabel(selected = null, el = null, instance = null) {
      let toggleText = this.options.toggleLabel(selected, el, instance);
      if (this.options.updateLabel) {
        // Option to override the dropdown label text
        toggleText = this.options.updateLabel;
      }
  
      return $(this.el)
        .find('.dropdown-toggle-text')
        .text(toggleText);
    }
  
    // eslint-disable-next-line class-methods-use-this
    clearField(field, isInput) {
      return isInput ? field.val('') : field.remove();
    }
  }
  
  // eslint-disable-next-line func-names
  $.fn.glDropdown = function(opts) {
    // eslint-disable-next-line func-names
    return this.each(function() {
      if (!$.data(this, 'glDropdown')) {
        return $.data(this, 'glDropdown', new GitLabDropdown(this, opts));
      }
    });
  };
  