function GitLabDropdown()

in app/assets/javascripts/gl_dropdown.js [238:394]


function GitLabDropdown(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 (_.isString(this.filterInput)) {
    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 (_.isObject(this.options.data) && !_.isFunction(this.options.data)) {
      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');
    });
  }
}