summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
blob: 4209ca0d6e23698e164e3ff7a2de02694ce8c596 (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';

class FilteredSearchDropdown {
  constructor(droplab, dropdown, input, filter) {
    this.droplab = droplab;
    this.hookId = input && input.id;
    this.input = input;
    this.filter = filter;
    this.dropdown = dropdown;
    this.loadingTemplate = `<div class="filter-dropdown-loading">
      <i class="fa fa-spinner fa-spin"></i>
    </div>`;
    this.bindEvents();
  }

  bindEvents() {
    this.itemClickedWrapper = this.itemClicked.bind(this);
    this.dropdown.addEventListener('click.dl', this.itemClickedWrapper);
  }

  unbindEvents() {
    this.dropdown.removeEventListener('click.dl', this.itemClickedWrapper);
  }

  getCurrentHook() {
    return this.droplab.hooks.filter(h => h.id === this.hookId)[0] || null;
  }

  itemClicked(e, getValueFunction) {
    const { selected } = e.detail;

    if (selected.tagName === 'LI' && selected.innerHTML) {
      const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(this.filter, selected);

      if (!dataValueSet) {
        const value = getValueFunction(selected);
        gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value, true);
      }

      this.resetFilters();
      this.dismissDropdown();
      this.dispatchInputEvent();
    }
  }

  setAsDropdown() {
    this.input.setAttribute(DATA_DROPDOWN_TRIGGER, `#${this.dropdown.id}`);
  }

  setOffset(offset = 0) {
    if (window.innerWidth > 480) {
      this.dropdown.style.left = `${offset}px`;
    } else {
      this.dropdown.style.left = '0px';
    }
  }

  renderContent(forceShowList = false) {
    const currentHook = this.getCurrentHook();
    if (forceShowList && currentHook && currentHook.list.hidden) {
      currentHook.list.show();
    }
  }

  render(forceRenderContent = false, forceShowList = false) {
    this.setAsDropdown();

    const currentHook = this.getCurrentHook();
    const firstTimeInitialized = currentHook === null;

    if (firstTimeInitialized || forceRenderContent) {
      this.renderContent(forceShowList);
    } else if (currentHook.list.list.id !== this.dropdown.id) {
      this.renderContent(forceShowList);
    }
  }

  dismissDropdown() {
    // Focusing on the input will dismiss dropdown
    // (default droplab functionality)
    this.input.focus();
  }

  dispatchInputEvent() {
    // Propogate input change to FilteredSearchDropdownManager
    // so that it can determine which dropdowns to open
    this.input.dispatchEvent(new CustomEvent('input', {
      bubbles: true,
      cancelable: true,
    }));
  }

  dispatchFormSubmitEvent() {
    // dispatchEvent() is necessary as form.submit() does not
    // trigger event handlers
    this.input.form.dispatchEvent(new Event('submit'));
  }

  hideDropdown() {
    const currentHook = this.getCurrentHook();
    if (currentHook) {
      currentHook.list.hide();
    }
  }

  resetFilters() {
    const hook = this.getCurrentHook();

    if (hook) {
      const data = hook.list.data || [];
      const results = data.map((o) => {
        const updated = o;
        updated.droplab_hidden = false;
        return updated;
      });
      hook.list.render(results);
    }
  }
}

window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown;