Skip to content

Commit

Permalink
Added search bar
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasOsti committed Oct 17, 2023
1 parent b8d620f commit ab7e6f2
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
const isTopBranch = !triggerElement.classList.contains('ibexa-popup-menu__item');
const branchItems = this.getBranchItems(branchElement);
const offset = isTopBranch ? [0, 3] : [-8, 2];
const branchSearchInput = branchElement.querySelector('.ibexa-multilevel-popup-menu__search-input');

const popperInstance = Popper.createPopper(referenceElement ?? triggerElement, branchElement, {
placement,
Expand All @@ -91,6 +92,8 @@
],
});

branchSearchInput.addEventListener('keyup', this.filterBranchItems, false);
branchSearchInput.addEventListener('input', this.filterBranchItems, false);
branchElement.popperInstance = popperInstance;

if (isTopBranch) {
Expand Down Expand Up @@ -151,6 +154,8 @@
}

updateBranchOpenState(branchElement) {
const searchInput = branchElement.querySelector('.ibexa-multilevel-popup-menu__search-input');
const isSearchInputFilled = !!searchInput?.value;
const isSubbranchOpened = (otherBranchElement) => {
return (
otherBranchElement &&
Expand All @@ -159,7 +164,7 @@
};
const isBranchOrAnySubbranchHovered = [...this.hoveredItemsBranches, ...this.hoveredBranches].some(isSubbranchOpened);

if (isBranchOrAnySubbranchHovered) {
if (isBranchOrAnySubbranchHovered || isSearchInputFilled) {
this.openBranch(branchElement);
} else {
this.closeWithSubbranches(branchElement);
Expand Down Expand Up @@ -213,13 +218,21 @@
}

generateMenu(menuTree) {
const { triggerElement, groups, placement, fallbackPlacements, processAfterCreated: processBranchAfterCreated } = menuTree;
const {
triggerElement,
groups,
placement,
fallbackPlacements,
processAfterCreated: processBranchAfterCreated,
hasSearch,
} = menuTree;

const branchElement = this.generateBranch(
{
triggerElement,
placement,
fallbackPlacements,
hasSearch,
},
processBranchAfterCreated,
);
Expand Down Expand Up @@ -250,7 +263,7 @@
}

generateBranch(data, processAfterCreated = () => {}) {
const { triggerElement, placement, fallbackPlacements } = data;
const { triggerElement, placement, fallbackPlacements, hasSearch = false } = data;
const { branchTemplate } = this.container.dataset;

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

const newBranchElement = container.querySelector('.ibexa-multilevel-popup-menu__branch');
const searchInputWrapper = newBranchElement.querySelector('.ibexa-multilevel-popup-menu__search');

searchInputWrapper.classList.toggle('ibexa-multilevel-popup-menu__search--hidden', !hasSearch);

processAfterCreated(newBranchElement, data);

Expand All @@ -276,6 +292,8 @@
triggerElement.classList.add('ibexa-popup-menu__item--has-subitems');
}

//here generate branch

return newBranchElement;
}

Expand Down Expand Up @@ -304,7 +322,9 @@

processAfterCreated(newGroupElement, data);

branchElement.appendChild(newGroupElement);
const newGroupContainer = branchElement.querySelector('.ibexa-multilevel-popup-menu__groups');

newGroupContainer.appendChild(newGroupElement);

return newGroupElement;
}
Expand Down Expand Up @@ -365,15 +385,46 @@
return;
}

const { target } = event;
const isPopupMenuExpanded = !topBranch.classList.contains('ibexa-popup-menu--hidden');
const isClickInsideTrigger = this.triggerElement.contains(event.target);
const isClickInsideTrigger = this.triggerElement.contains(target);
const isTargetBranch = target.classList.contains('ibexa-multilevel-popup-menu__branch');
const targetBranch = target.closest('.ibexa-multilevel-popup-menu__branch');
const isClickInsideMenu = isTargetBranch || !!targetBranch;

if (!isPopupMenuExpanded || isClickInsideTrigger) {
if (!isPopupMenuExpanded || isClickInsideTrigger || isClickInsideMenu) {
return;
}

const branchsSearchInput = doc.querySelectorAll('.ibexa-multilevel-popup-menu__search-input');

branchsSearchInput.forEach((searchInput) => {
if (searchInput.value !== '') {
const searchInputBranch = searchInput.closest('.ibexa-multilevel-popup-menu__branch');

searchInput.value = '';
searchInputBranch.dispatchEvent(new Event('mouseleave'));
searchInput.dispatchEvent(new Event('input'));
}
});

this.closeWithSubbranches(topBranch);
}

filterBranchItems(event) {
const searchInput = event.currentTarget;
const branch = searchInput.closest('.ibexa-multilevel-popup-menu__branch');
const branchItems = branch.querySelectorAll('.ibexa-popup-menu__group > .ibexa-popup-menu__item');
const phraseLowerCase = searchInput.value.toLowerCase();

branchItems.forEach((item) => {
const { label } = item.dataset;
const labelLowerCase = label.toLowerCase();
const hideItem = !labelLowerCase.includes(phraseLowerCase);

item.classList.toggle('ibexa-popup-menu__item--hidden', hideItem);
});
}
}

ibexa.addConfig('core.MultilevelPopupMenu', MultilevelPopupMenu);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(function (global, doc, ibexa, Routing, Translator, Popper) {
const MIN_ITEMS_NUMBER_TO_SHOW_SEARCH = 10;
const MENU_PROPS = {
placement: 'bottom-end',
placement: 'bottom-start',
fallbackPlacements: ['bottom-start', 'top-end', 'top-start'],
};
const token = document.querySelector('meta[name="CSRF-Token"]').content;
Expand Down Expand Up @@ -117,6 +118,7 @@
return {
label: Translator.trans(/*@Desc("Edit")*/ 'embedded_items.action.edit', {}, 'ibexa_content'),
branch: {
hasSearch: languages.length >= MIN_ITEMS_NUMBER_TO_SHOW_SEARCH,
groups: [
{
id: 'edit-group',
Expand Down
19 changes: 19 additions & 0 deletions src/bundle/Resources/public/scss/_multilevel-popup-menu.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.ibexa-multilevel-popup-menu {
&__search {
margin-bottom: calculateRem(4px);
padding: 0 calculateRem(8px);

&--hidden {
display: none;
}
}

&__search-input {
border-radius: $ibexa-border-radius;
}

&__groups {
max-height: calculateRem(390px);
overflow-y: auto;
}
}
1 change: 1 addition & 0 deletions src/bundle/Resources/public/scss/ibexa.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
@import 'links';
@import 'footer';
@import 'popup-menu';
@import 'multilevel-popup-menu';
@import 'header-user-menu';
@import 'main-header';
@import 'main-container';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,29 @@
}) -%}

{%- block branch -%}
{% trans_default_domain 'ibexa_dropdown' %}

<div {{ html.attributes(branch_attr, is_template) }}>
<div class="ibexa-multilevel-popup-menu__search {{ not hasSearch|default(false) ? 'ibexa-multilevel-popup-menu__search--hidden' }}">
<input
type="text"
placeholder="{{ 'dropdown.search'|trans|desc('Search...') }}"
class="ibexa-input ibexa-input--small ibexa-input--text form-control ibexa-multilevel-popup-menu__search-input"
/>
</div>

{%- block branch_groups -%}
{%- for group in groups -%}
{%- set group_params = group|merge({
items: group.items|default([]),
group_attr: group.group_attr|default({}),
}) -%}
<div class="ibexa-multilevel-popup-menu__groups">
{%- for group in groups -%}
{%- set group_params = group|merge({
items: group.items|default([]),
group_attr: group.group_attr|default({}),
}) -%}

{%- include '@ibexadesign/ui/component/multilevel_popup_menu/multilevel_popup_menu_group.html.twig'
with group_params -%}
{%- endfor -%}
{%- include '@ibexadesign/ui/component/multilevel_popup_menu/multilevel_popup_menu_group.html.twig'
with group_params -%}
{%- endfor -%}
</div>
{%- endblock -%}
</div>
{%- endblock -%}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
class: ('ibexa-popup-menu__item ibexa-multilevel-popup-menu__item '
~ (branch|default(null) ? 'ibexa-popup-menu__item--has-subitems ')
~ item_attr.class|default(''))|trim,
'data-label': label,
}) -%}

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

0 comments on commit ab7e6f2

Please sign in to comment.