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(this.options.selectorClearIcon);
|
42 | const input = this.element.querySelector(this.options.selectorSearchInput);
|
43 | if (!input) {
|
44 | throw new Error('Cannot find the search input.');
|
45 | }
|
46 |
|
47 | if (closeIcon) {
|
48 | this.manage(
|
49 | on(closeIcon, 'click', () => {
|
50 | svgToggleClass(closeIcon, this.options.classClearHidden, true);
|
51 | input.value = '';
|
52 | input.focus();
|
53 | })
|
54 | );
|
55 | }
|
56 |
|
57 | this.manage(
|
58 | on(this.element, 'click', evt => {
|
59 | const toggleItem = eventMatches(evt, this.options.selectorIconContainer);
|
60 | if (toggleItem) this.toggleLayout(toggleItem);
|
61 | })
|
62 | );
|
63 |
|
64 | this.manage(
|
65 | on(input, 'input', evt => {
|
66 | if (closeIcon) this.showClear(evt.target.value, closeIcon);
|
67 | })
|
68 | );
|
69 | }
|
70 |
|
71 | /**
|
72 | * Toggles between the grid and list layout.
|
73 | * @param {HTMLElement} element The element contining the layout toggle.
|
74 | */
|
75 | toggleLayout(element) {
|
76 | toArray(element.querySelectorAll(this.options.selectorSearchView)).forEach(item => {
|
77 | item.classList.toggle(this.options.classLayoutHidden);
|
78 | });
|
79 | }
|
80 |
|
81 | /**
|
82 | * Toggles the clear icon visibility
|
83 | * @param {HTMLElement} value The element serving as the search input.
|
84 | * @param {HTMLElement} icon The element serving as close icon.
|
85 | */
|
86 | showClear(value, icon) {
|
87 | svgToggleClass(icon, this.options.classClearHidden, value.length === 0);
|
88 | }
|
89 |
|
90 | /**
|
91 | * The component options.
|
92 | * If `options` is specified in the constructor,
|
93 | * {@linkcode Search.create .create()}, or {@linkcode Search.init .init()},
|
94 | * properties in this object are overriden for the instance being created
|
95 | * and how {@linkcode Search.init .init()} works.
|
96 | * @member Search.options
|
97 | * @type {Object}
|
98 | * @property {string} [options.selectorInit]
|
99 | * The selector to find search UIs with options.
|
100 | * @property {string} [options.selectorSearchView]
|
101 | * The selector to find the search view icon containers.
|
102 | * @property {string} [options.selectorSearchInput]
|
103 | * The selector to find the search input.
|
104 | * @property {string} [options.selectorClearIcon]
|
105 | * The selector for the clear icon that clears the search box.
|
106 | * @property {string} [options.selectorIconContainer] The data attribute selector for the icon layout container.
|
107 | * @property {string} [options.classClearHidden] The class used to hide the clear icon.
|
108 | * @property {string} [options.classLayoutHidden] The class used to hide nonselected layout view.
|
109 | */
|
110 | static get options() {
|
111 | const { prefix } = settings;
|
112 | return {
|
113 | selectorInit: '[data-search]',
|
114 | selectorSearchView: '[data-search-view]',
|
115 | selectorSearchInput: `.${prefix}--search-input`,
|
116 | selectorClearIcon: `.${prefix}--search-close`,
|
117 | selectorIconContainer: `.${prefix}--search-button[data-search-toggle]`,
|
118 | classClearHidden: `${prefix}--search-close--hidden`,
|
119 | classLayoutHidden: `${prefix}--search-view--hidden`,
|
120 | };
|
121 | }
|
122 |
|
123 | /**
|
124 | * The map associating DOM element and search instance.
|
125 | * @member Search.components
|
126 | * @type {WeakMap}
|
127 | */
|
128 | static components /* #__PURE_CLASS_PROPERTY__ */ = new WeakMap();
|
129 | }
|
130 |
|
131 | export default Search;
|