Skip to content

Commit 936dec1

Browse files
committed
Added search bar
1 parent b8d620f commit 936dec1

File tree

6 files changed

+99
-15
lines changed

6 files changed

+99
-15
lines changed

src/bundle/Resources/public/js/scripts/core/multilevel.popup.menu.js

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
const isTopBranch = !triggerElement.classList.contains('ibexa-popup-menu__item');
7272
const branchItems = this.getBranchItems(branchElement);
7373
const offset = isTopBranch ? [0, 3] : [-8, 2];
74+
const branchSearchInput = branchElement.querySelector('.ibexa-multilevel-popup-menu__search-input');
7475

7576
const popperInstance = Popper.createPopper(referenceElement ?? triggerElement, branchElement, {
7677
placement,
@@ -91,6 +92,8 @@
9192
],
9293
});
9394

95+
branchSearchInput.addEventListener('keyup', this.filterBranchItems, false);
96+
branchSearchInput.addEventListener('input', this.filterBranchItems, false);
9497
branchElement.popperInstance = popperInstance;
9598

9699
if (isTopBranch) {
@@ -151,6 +154,8 @@
151154
}
152155

153156
updateBranchOpenState(branchElement) {
157+
const searchInput = branchElement.querySelector('.ibexa-multilevel-popup-menu__search-input');
158+
const isSearchInputFilled = !!searchInput?.value;
154159
const isSubbranchOpened = (otherBranchElement) => {
155160
return (
156161
otherBranchElement &&
@@ -159,7 +164,7 @@
159164
};
160165
const isBranchOrAnySubbranchHovered = [...this.hoveredItemsBranches, ...this.hoveredBranches].some(isSubbranchOpened);
161166

162-
if (isBranchOrAnySubbranchHovered) {
167+
if (isBranchOrAnySubbranchHovered || isSearchInputFilled) {
163168
this.openBranch(branchElement);
164169
} else {
165170
this.closeWithSubbranches(branchElement);
@@ -213,13 +218,21 @@
213218
}
214219

215220
generateMenu(menuTree) {
216-
const { triggerElement, groups, placement, fallbackPlacements, processAfterCreated: processBranchAfterCreated } = menuTree;
221+
const {
222+
triggerElement,
223+
groups,
224+
placement,
225+
fallbackPlacements,
226+
processAfterCreated: processBranchAfterCreated,
227+
hasSearch,
228+
} = menuTree;
217229

218230
const branchElement = this.generateBranch(
219231
{
220232
triggerElement,
221233
placement,
222234
fallbackPlacements,
235+
hasSearch,
223236
},
224237
processBranchAfterCreated,
225238
);
@@ -250,7 +263,7 @@
250263
}
251264

252265
generateBranch(data, processAfterCreated = () => {}) {
253-
const { triggerElement, placement, fallbackPlacements } = data;
266+
const { triggerElement, placement, fallbackPlacements, hasSearch = false } = data;
254267
const { branchTemplate } = this.container.dataset;
255268

256269
const container = doc.createElement('div');
@@ -259,6 +272,9 @@
259272
container.insertAdjacentHTML('beforeend', renderedItem);
260273

261274
const newBranchElement = container.querySelector('.ibexa-multilevel-popup-menu__branch');
275+
const searchInputWrapper = newBranchElement.querySelector('.ibexa-multilevel-popup-menu__search');
276+
277+
searchInputWrapper.classList.toggle('ibexa-multilevel-popup-menu__search--hidden', !hasSearch);
262278

263279
processAfterCreated(newBranchElement, data);
264280

@@ -304,7 +320,9 @@
304320

305321
processAfterCreated(newGroupElement, data);
306322

307-
branchElement.appendChild(newGroupElement);
323+
const newGroupContainer = branchElement.querySelector('.ibexa-multilevel-popup-menu__groups');
324+
325+
newGroupContainer.appendChild(newGroupElement);
308326

309327
return newGroupElement;
310328
}
@@ -365,15 +383,46 @@
365383
return;
366384
}
367385

386+
const { target } = event;
368387
const isPopupMenuExpanded = !topBranch.classList.contains('ibexa-popup-menu--hidden');
369-
const isClickInsideTrigger = this.triggerElement.contains(event.target);
388+
const isClickInsideTrigger = this.triggerElement.contains(target);
389+
const isTargetBranch = target.classList.contains('ibexa-multilevel-popup-menu__branch');
390+
const targetBranch = target.closest('.ibexa-multilevel-popup-menu__branch');
391+
const isClickInsideMenu = isTargetBranch || !!targetBranch;
370392

371-
if (!isPopupMenuExpanded || isClickInsideTrigger) {
393+
if (!isPopupMenuExpanded || isClickInsideTrigger || isClickInsideMenu) {
372394
return;
373395
}
374396

397+
const branchsSearchInput = doc.querySelectorAll('.ibexa-multilevel-popup-menu__search-input');
398+
399+
branchsSearchInput.forEach((searchInput) => {
400+
if (searchInput.value !== '') {
401+
const searchInputBranch = searchInput.closest('.ibexa-multilevel-popup-menu__branch');
402+
403+
searchInput.value = '';
404+
searchInputBranch.dispatchEvent(new Event('mouseleave'));
405+
searchInput.dispatchEvent(new Event('input'));
406+
}
407+
});
408+
375409
this.closeWithSubbranches(topBranch);
376410
}
411+
412+
filterBranchItems(event) {
413+
const searchInput = event.currentTarget;
414+
const branch = searchInput.closest('.ibexa-multilevel-popup-menu__branch');
415+
const branchItems = branch.querySelectorAll('.ibexa-popup-menu__group > .ibexa-popup-menu__item');
416+
const phraseLowerCase = searchInput.value.toLowerCase();
417+
418+
branchItems.forEach((item) => {
419+
const { label } = item.dataset;
420+
const labelLowerCase = label.toLowerCase();
421+
const hideItem = !labelLowerCase.includes(phraseLowerCase);
422+
423+
item.classList.toggle('ibexa-popup-menu__item--hidden', hideItem);
424+
});
425+
}
377426
}
378427

379428
ibexa.addConfig('core.MultilevelPopupMenu', MultilevelPopupMenu);

src/bundle/Resources/public/js/scripts/embedded.item.actions.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(function (global, doc, ibexa, Routing, Translator, Popper) {
2+
const MIN_ITEMS_NUMBER_TO_SHOW_SEARCH = 10;
23
const MENU_PROPS = {
3-
placement: 'bottom-end',
4+
placement: 'bottom-start',
45
fallbackPlacements: ['bottom-start', 'top-end', 'top-start'],
56
};
67
const token = document.querySelector('meta[name="CSRF-Token"]').content;
@@ -117,6 +118,7 @@
117118
return {
118119
label: Translator.trans(/*@Desc("Edit")*/ 'embedded_items.action.edit', {}, 'ibexa_content'),
119120
branch: {
121+
hasSearch: languages.length >= MIN_ITEMS_NUMBER_TO_SHOW_SEARCH,
120122
groups: [
121123
{
122124
id: 'edit-group',
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.ibexa-multilevel-popup-menu {
2+
&__search {
3+
margin-bottom: calculateRem(4px);
4+
padding: 0 calculateRem(8px);
5+
6+
&--hidden {
7+
display: none;
8+
}
9+
}
10+
11+
&__search-input {
12+
border-radius: $ibexa-border-radius;
13+
}
14+
15+
&__groups {
16+
max-height: calculateRem(390px);
17+
overflow-y: auto;
18+
}
19+
}

src/bundle/Resources/public/scss/ibexa.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
@import 'links';
9191
@import 'footer';
9292
@import 'popup-menu';
93+
@import 'multilevel-popup-menu';
9394
@import 'header-user-menu';
9495
@import 'main-header';
9596
@import 'main-container';

src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_branch.html.twig

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,29 @@
88
}) -%}
99

1010
{%- block branch -%}
11+
{% trans_default_domain 'ibexa_dropdown' %}
12+
1113
<div {{ html.attributes(branch_attr, is_template) }}>
14+
<div class="ibexa-multilevel-popup-menu__search {{ not hasSearch|default(false) ? 'ibexa-multilevel-popup-menu__search--hidden' }}">
15+
<input
16+
type="text"
17+
placeholder="{{ 'dropdown.search'|trans|desc('Search...') }}"
18+
class="ibexa-input ibexa-input--small ibexa-input--text form-control ibexa-multilevel-popup-menu__search-input"
19+
/>
20+
</div>
21+
1222
{%- block branch_groups -%}
13-
{%- for group in groups -%}
14-
{%- set group_params = group|merge({
15-
items: group.items|default([]),
16-
group_attr: group.group_attr|default({}),
17-
}) -%}
23+
<div class="ibexa-multilevel-popup-menu__groups">
24+
{%- for group in groups -%}
25+
{%- set group_params = group|merge({
26+
items: group.items|default([]),
27+
group_attr: group.group_attr|default({}),
28+
}) -%}
1829

19-
{%- include '@ibexadesign/ui/component/multilevel_popup_menu/multilevel_popup_menu_group.html.twig'
20-
with group_params -%}
21-
{%- endfor -%}
30+
{%- include '@ibexadesign/ui/component/multilevel_popup_menu/multilevel_popup_menu_group.html.twig'
31+
with group_params -%}
32+
{%- endfor -%}
33+
</div>
2234
{%- endblock -%}
2335
</div>
2436
{%- endblock -%}

src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_item.html.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class: ('ibexa-popup-menu__item ibexa-multilevel-popup-menu__item '
77
~ (branch|default(null) ? 'ibexa-popup-menu__item--has-subitems ')
88
~ item_attr.class|default(''))|trim,
9+
'data-label': label,
910
}) -%}
1011

1112
{%- set action_attr = action_attr|default({})|merge({

0 commit comments

Comments
 (0)