PageSourceSearch

https://minoko.com.ua/catalog/view/javascript/itc-custom-select.js

js minoko.com.ua collected 2026-10-07 19:41:58 UTC 4,993 bytes, 158 lines download raw bytes

1class ItcCustomSelect {
2  static EL = 'itc-select';
3  static EL_SHOW = 'itc-select_show';
4  static EL_OPTION = 'itc-select__option';
5  static EL_OPTION_SELECTED = 'itc-select__option_selected';
6  static DATA = '[data-select]';
7  static DATA_TOGGLE = '[data-select="toggle"]';
8
9  static template(params) {
10    const { name, options, targetValue } = params;
11    const items = [];
12    let selectedIndex = -1;
13    let selectedValue = '';
14    let selectedContent = 'Выберите из списка';
15    options.forEach((option, index) => {
16      let selectedClass = '';
17      if (option[0] === targetValue) {
18        selectedClass = ` ${this.EL_OPTION_SELECTED}`;
19        selectedIndex = index;
20        selectedValue = option[0];
21        selectedContent = option[1];
22      }
23      items.push(`<li class="itc-select__option${selectedClass}" data-select="option"
24        data-value="${option[0]}" data-index="${index}">${option[1]}</li>`);
25    });
26    return `<button type="button" class="itc-select__toggle" name="${name}"
27      value="${selectedValue}" data-select="toggle" data-index="${selectedIndex}">
28      ${selectedContent}</button><div class="itc-select__dropdown">
29      <ul class="itc-select__options">${items.join('')}</ul></div>`;
30  }
31
32  static hideOpenSelect() {
33    document.addEventListener('click', (e) => {
34      if (!e.target.closest(`.${this.EL}`)) {
35        const elsActive = document.querySelectorAll(`.${this.EL_SHOW}`);
36        elsActive.forEach((el) => {
37          el.classList.remove(this.EL_SHOW);
38        });
39      }
40    });
41  }
42  static create(target, params) {
43    this._el = typeof target === 'string' ? document.querySelector(target) : target;
44    if (this._el) {
45      return new this(target, params);
46    }
47    return null;
48  }
49  constructor(target, params) {
50    this._el = typeof target === 'string' ? document.querySelector(target) : target;
51    this._params = params || {};
52    this._onClickFn = this._onClick.bind(this);
53    if (this._params.options) {
54      this._el.innerHTML = this.constructor.template(this._params);
55      this._el.classList.add(this.constructor.EL);
56    }
57    this._elToggle = this._el.querySelector(this.constructor.DATA_TOGGLE);
58    this._el.addEventListener('click', this._onClickFn);
59  }
60
61  _onClick(e) {
62    const { target } = e;
63    const type = target.closest(this.constructor.DATA).dataset.select;
64    if (type === 'toggle') {
65      this.toggle();
66    } else if (type === 'option') {
67      this._changeValue(target);
68    }
69  }
70
71  _updateOption(el) {
72    const elOption = el.closest(`.${this.constructor.EL_OPTION}`);
73    const elOptionSel = this._el.querySelector(`.${this.constructor.EL_OPTION_SELECTED}`);
74    if (elOptionSel) {
75      elOptionSel.classList.remove(this.constructor.EL_OPTION_SELECTED);
76    }
77    elOption.classList.add(this.constructor.EL_OPTION_SELECTED);
78    this._elToggle.textContent = elOption.textContent;
79    this._elToggle.value = elOption.dataset.value;
80    this._elToggle.dataset.index = elOption.dataset.index;
81    this._el.dispatchEvent(new CustomEvent('itc.select.change'));
82    this._params.onSelected ? this._params.onSelected(this, elOption) : null;
83    return elOption.dataset.value;
84  }
85
86  _reset() {
87    const selected = this._el.querySelector(`.${this.constructor.EL_OPTION_SELECTED}`);
88    if (selected) {
89      selected.classList.remove(this.constructor.EL_OPTION_SELECTED);
90    }
91    this._elToggle.textContent = 'Выберите из списка';
92    this._elToggle.value = '';
93    this._elToggle.dataset.index = '-1';
94    this._el.dispatchEvent(new CustomEvent('itc.select.change'));
95    this._params.onSelected ? this._params.onSelected(this, null) : null;
96    return '';
97  }
98
99  _changeValue(el) {
100    if (el.classList.contains(this.constructor.EL_OPTION_SELECTED)) {
101      return;
102    }
103    this._updateOption(el);
104    this.hide();
105  }
106
107  show() {
108    document.querySelectorAll(this.constructor.EL_SHOW)
109      .forEach((el) => {
110        el.classList.remove(this.constructor.EL_SHOW);
111      });
112    this._el.classList.add(`${this.constructor.EL_SHOW}`);
113  }
114
115  hide() {
116    this._el.classList.remove(this.constructor.EL_SHOW);
117  }
118
119  toggle() {
120    this._el.classList.contains(this.constructor.EL_SHOW) ? this.hide() : this.show();
121  }
122
123  dispose() {
124    this._el.removeEventListener('click', this._onClickFn);
125  }
126
127  get value() {
128    return this._elToggle.value;
129  }
130
131  set value(value) {
132    let isExists = false;
133    this._el.querySelectorAll('.select__option')
134      .forEach((option) => {
135        if (option.dataset.value === value) {
136          isExists = true;
137          this._updateOption(option);
138        }
139      });
140    if (!isExists) {
141      this._reset();
142    }
143  }
144
145  get selectedIndex() {
146    return this._elToggle.dataset.index;
147  }
148
149  set selectedIndex(index) {
150    const option = this._el.querySelector(`.select__option[data-index="${index}"]`);
151    if (option) {
152      this._updateOption(option);
153    }
154    this._reset();
155  }
156}
157
158ItcCustomSelect.hideOpenSelect();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.