1 | /**
|
2 | * Copyright IBM Corp. 2016, 2018
|
3 | *
|
4 | * This source code is licensed under the Apache-2.0 license found in the
|
5 | * LICENSE file in the root directory of this source tree.
|
6 | */
|
7 |
|
8 | import settings from '../../globals/js/settings';
|
9 | import mixin from '../../globals/js/misc/mixin';
|
10 | import createComponent from '../../globals/js/mixins/create-component';
|
11 | import initComponentBySearch from '../../globals/js/mixins/init-component-by-search';
|
12 | import handles from '../../globals/js/mixins/handles';
|
13 | import eventMatches from '../../globals/js/misc/event-matches';
|
14 | import on from '../../globals/js/misc/on';
|
15 | import svgToggleClass from '../../globals/js/misc/svg-toggle-class';
|
16 |
|
17 | const toArray = (arrayLike) => Array.prototype.slice.call(arrayLike);
|
18 |
|
19 | class Search extends mixin(createComponent, initComponentBySearch, handles) {
|
20 | /**
|
21 | * Search with Options.
|
22 | * @extends CreateComponent
|
23 | * @extends InitComponentBySearch
|
24 | * @extends Handles
|
25 | * @param {HTMLElement} element The element working as the search component.
|
26 | * @param {object} [options] The component options
|
27 | * @property {string} [options.selectorInit]
|
28 | * The selector to find search UIs with options.
|
29 | * @property {string} [options.selectorSearchView]
|
30 | * The selector to find the search view icon containers.
|
31 | * @property {string} [options.selectorSearchInput]
|
32 | * The selector to find the search input.
|
33 | * @property {string} [options.selectorClearIcon]
|
34 | * The selector for the clear icon that clears the search box.
|
35 | * @property {string} [options.selectorIconContainer] The data attribute selector for the icon layout container.
|
36 | * @property {string} [options.classClearHidden] The class used to hide the clear icon.
|
37 | * @property {string} [options.classLayoutHidden] The class used to hide nonselected layout view.
|
38 | */
|
39 | constructor(element, options) {
|
40 | super(element, options);
|
41 | const closeIcon = this.element.querySelector(
|
42 | this.options.selectorClearIcon
|
43 | );
|
44 | const input = this.element.querySelector(this.options.selectorSearchInput);
|
45 | if (!input) {
|
46 | throw new Error('Cannot find the search input.');
|
47 | }
|
48 |
|
49 | if (closeIcon) {
|
50 | this.manage(
|
51 | on(closeIcon, 'click', () => {
|
52 | svgToggleClass(closeIcon, this.options.classClearHidden, true);
|
53 | input.value = '';
|
54 | input.focus();
|
55 | })
|
56 | );
|
57 | }
|
58 |
|
59 | this.manage(
|
60 | on(this.element, 'click', (evt) => {
|
61 | const toggleItem = eventMatches(
|
62 | evt,
|
63 | this.options.selectorIconContainer
|
64 | );
|
65 | if (toggleItem) this.toggleLayout(toggleItem);
|
66 | })
|
67 | );
|
68 |
|
69 | this.manage(
|
70 | on(input, 'input', (evt) => {
|
71 | if (closeIcon) this.showClear(evt.target.value, closeIcon);
|
72 | })
|
73 | );
|
74 | }
|
75 |
|
76 | /**
|
77 | * Toggles between the grid and list layout.
|
78 | * @param {HTMLElement} element The element contining the layout toggle.
|
79 | */
|
80 | toggleLayout(element) {
|
81 | toArray(element.querySelectorAll(this.options.selectorSearchView)).forEach(
|
82 | (item) => {
|
83 | item.classList.toggle(this.options.classLayoutHidden);
|
84 | }
|
85 | );
|
86 | }
|
87 |
|
88 | /**
|
89 | * Toggles the clear icon visibility
|
90 | * @param {HTMLElement} value The element serving as the search input.
|
91 | * @param {HTMLElement} icon The element serving as close icon.
|
92 | */
|
93 | showClear(value, icon) {
|
94 | svgToggleClass(icon, this.options.classClearHidden, value.length === 0);
|
95 | }
|
96 |
|
97 | /**
|
98 | * The component options.
|
99 | * If `options` is specified in the constructor,
|
100 | * {@linkcode Search.create .create()}, or {@linkcode Search.init .init()},
|
101 | * properties in this object are overriden for the instance being created
|
102 | * and how {@linkcode Search.init .init()} works.
|
103 | * @member Search.options
|
104 | * @type {object}
|
105 | * @property {string} [options.selectorInit]
|
106 | * The selector to find search UIs with options.
|
107 | * @property {string} [options.selectorSearchView]
|
108 | * The selector to find the search view icon containers.
|
109 | * @property {string} [options.selectorSearchInput]
|
110 | * The selector to find the search input.
|
111 | * @property {string} [options.selectorClearIcon]
|
112 | * The selector for the clear icon that clears the search box.
|
113 | * @property {string} [options.selectorIconContainer] The data attribute selector for the icon layout container.
|
114 | * @property {string} [options.classClearHidden] The class used to hide the clear icon.
|
115 | * @property {string} [options.classLayoutHidden] The class used to hide nonselected layout view.
|
116 | */
|
117 | static get options() {
|
118 | const { prefix } = settings;
|
119 | return {
|
120 | selectorInit: '[data-search]',
|
121 | selectorSearchView: '[data-search-view]',
|
122 | selectorSearchInput: `.${prefix}--search-input`,
|
123 | selectorClearIcon: `.${prefix}--search-close`,
|
124 | selectorIconContainer: `.${prefix}--search-button[data-search-toggle]`,
|
125 | classClearHidden: `${prefix}--search-close--hidden`,
|
126 | classLayoutHidden: `${prefix}--search-view--hidden`,
|
127 | };
|
128 | }
|
129 |
|
130 | /**
|
131 | * The map associating DOM element and search instance.
|
132 | * @member Search.components
|
133 | * @type {WeakMap}
|
134 | */
|
135 | static components /* #__PURE_CLASS_PROPERTY__ */ = new WeakMap();
|
136 | }
|
137 |
|
138 | export default Search;
|