summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/blob/template_selector.js
blob: ae9bb3455f070123d5c0a810259d625c5b758133 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/* eslint-disable class-methods-use-this */

import $ from 'jquery';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';

export default class TemplateSelector {
  constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
    this.pattern = pattern;
    this.editor = editor;
    this.dropdown = dropdown;
    this.$dropdownContainer = wrapper;
    this.$filenameInput = $input || $('#file_name');
    this.$dropdownIcon = $('.dropdown-menu-toggle-icon', dropdown);
    this.$loadingIcon = $(
      '<div class="gl-spinner gl-spinner-orange gl-spinner-sm gl-absolute gl-top-3 gl-right-3 gl-display-none"></div>',
    ).insertAfter(this.$dropdownIcon);

    this.initDropdown(dropdown, data);
    this.listenForFilenameInput();
    this.renderMatchedDropdown();
    this.initAutosizeUpdateEvent();
  }

  initDropdown(dropdown, data) {
    return initDeprecatedJQueryDropdown($(dropdown), {
      data,
      filterable: true,
      selectable: true,
      toggleLabel: item => item.name,
      search: {
        fields: ['name'],
      },
      clicked: options => this.onDropdownClicked(options),
      text: item => item.name,
    });
  }

  // Subclasses can override this method to conditionally prevent fetching file templates
  onDropdownClicked(options) {
    this.fetchFileTemplate(options);
  }

  initAutosizeUpdateEvent() {
    this.autosizeUpdateEvent = document.createEvent('Event');
    this.autosizeUpdateEvent.initEvent('autosize:update', true, false);
  }

  listenForFilenameInput() {
    return this.$filenameInput.on('keyup blur', e => this.renderMatchedDropdown(e));
  }

  renderMatchedDropdown() {
    if (!this.$filenameInput.length) {
      return null;
    }

    const filenameMatches = this.pattern.test(this.$filenameInput.val().trim());

    if (!filenameMatches) {
      return this.$dropdownContainer.addClass('hidden');
    }
    return this.$dropdownContainer.removeClass('hidden');
  }

  fetchFileTemplate(options) {
    const { e } = options;
    const item = options.selectedObj;

    e.preventDefault();
    return this.requestFile(item);
  }

  requestFile() {
    // This `requestFile` method is an abstract method that should
    // be added by all subclasses.
  }

  setEditorContent(file, { skipFocus } = {}) {
    if (!file) return;

    const newValue = file.content;

    this.editor.setValue(newValue, 1);

    if (!skipFocus) this.editor.focus();

    if (this.editor instanceof $) {
      this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
      this.editor.trigger('input');
    }
  }

  getEditorContent() {
    return this.editor.getValue();
  }

  startLoadingSpinner() {
    this.$loadingIcon.removeClass('gl-display-none');
    this.$dropdownIcon.addClass('gl-display-none');
  }

  stopLoadingSpinner() {
    this.$loadingIcon.addClass('gl-display-none');
    this.$dropdownIcon.removeClass('gl-display-none');
  }
}