From 2e1c050b667be17c989c0fd4393fb2dba717b655 Mon Sep 17 00:00:00 2001 From: Lukasz Ostafin Date: Mon, 16 Oct 2023 21:52:49 +0200 Subject: [PATCH] Added search bar --- .../js/scripts/core/multilevel.popup.menu.js | 59 +++++++++++++++++-- .../js/scripts/embedded.item.actions.js | 2 + .../public/scss/_multilevel-popup-menu.scss | 9 +++ src/bundle/Resources/public/scss/ibexa.scss | 1 + .../multilevel_popup_menu_branch.html.twig | 28 ++++++--- .../multilevel_popup_menu_item.html.twig | 1 + 6 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 src/bundle/Resources/public/scss/_multilevel-popup-menu.scss diff --git a/src/bundle/Resources/public/js/scripts/core/multilevel.popup.menu.js b/src/bundle/Resources/public/js/scripts/core/multilevel.popup.menu.js index 9776a69f16..7761bf2c69 100644 --- a/src/bundle/Resources/public/js/scripts/core/multilevel.popup.menu.js +++ b/src/bundle/Resources/public/js/scripts/core/multilevel.popup.menu.js @@ -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, @@ -91,6 +92,8 @@ ], }); + branchSearchInput.addEventListener('keyup', this.filterBranchItems, false); + branchSearchInput.addEventListener('input', this.filterBranchItems, false); branchElement.popperInstance = popperInstance; if (isTopBranch) { @@ -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 && @@ -159,7 +164,7 @@ }; const isBranchOrAnySubbranchHovered = [...this.hoveredItemsBranches, ...this.hoveredBranches].some(isSubbranchOpened); - if (isBranchOrAnySubbranchHovered) { + if (isBranchOrAnySubbranchHovered || isSearchInputFilled) { this.openBranch(branchElement); } else { this.closeWithSubbranches(branchElement); @@ -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, ); @@ -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'); @@ -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); @@ -276,6 +292,8 @@ triggerElement.classList.add('ibexa-popup-menu__item--has-subitems'); } + //here generate branch + return newBranchElement; } @@ -365,15 +383,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); diff --git a/src/bundle/Resources/public/js/scripts/embedded.item.actions.js b/src/bundle/Resources/public/js/scripts/embedded.item.actions.js index d3f3e12c8a..51f84d6fe6 100644 --- a/src/bundle/Resources/public/js/scripts/embedded.item.actions.js +++ b/src/bundle/Resources/public/js/scripts/embedded.item.actions.js @@ -1,4 +1,5 @@ (function (global, doc, ibexa, Routing, Translator, Popper) { + const MIN_ITEMS_NUMBER_TO_SHOW_SEARCH = 10; const MENU_PROPS = { placement: 'bottom-end', fallbackPlacements: ['bottom-start', 'top-end', 'top-start'], @@ -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', diff --git a/src/bundle/Resources/public/scss/_multilevel-popup-menu.scss b/src/bundle/Resources/public/scss/_multilevel-popup-menu.scss new file mode 100644 index 0000000000..f3ef167ace --- /dev/null +++ b/src/bundle/Resources/public/scss/_multilevel-popup-menu.scss @@ -0,0 +1,9 @@ +.ibexa-multilevel-popup-menu { + &__search { + padding: 0 calculateRem(8px); + + &--hidden { + display: none; + } + } +} diff --git a/src/bundle/Resources/public/scss/ibexa.scss b/src/bundle/Resources/public/scss/ibexa.scss index e5ae89c97e..d0d6278233 100644 --- a/src/bundle/Resources/public/scss/ibexa.scss +++ b/src/bundle/Resources/public/scss/ibexa.scss @@ -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'; diff --git a/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_branch.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_branch.html.twig index f9bbd8c76f..7dfaa63291 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_branch.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_branch.html.twig @@ -8,17 +8,29 @@ }) -%} {%- block branch -%} + {% trans_default_domain 'ibexa_dropdown' %} +
+ + {%- block branch_groups -%} - {%- for group in groups -%} - {%- set group_params = group|merge({ - items: group.items|default([]), - group_attr: group.group_attr|default({}), - }) -%} +
+ {%- 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 -%} +
{%- endblock -%}
{%- endblock -%} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_item.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_item.html.twig index 6310c7c82e..dcf0aa6ebd 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_item.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/multilevel_popup_menu/multilevel_popup_menu_item.html.twig @@ -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({