summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
blob: 134bdc6ad80aef288e97c92762d9045da77eb6e9 (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
123
(() => {
  const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';

  class FilteredSearchDropdown {
    constructor(droplab, dropdown, input, filter) {
      this.droplab = droplab;
      this.hookId = input && input.getAttribute('data-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.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;
})();