Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-3456 Collapse all button support #1394

Open
wants to merge 17 commits into
base: 4.6
Choose a base branch
from
1 change: 1 addition & 0 deletions src/bundle/Resources/config/bazinga_js_translation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ active_domains:
- 'ibexa_user_invitation'
- 'ibexa_content_type'
- 'ibexa_dropdown'
- 'ibexa_collapse'
- 'ibexa_popup_menu'
- 'messages'
82 changes: 80 additions & 2 deletions src/bundle/Resources/public/js/scripts/core/collapse.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,99 @@
(function (global, doc) {
(function (global, doc, bootstrap, Translator) {
let toggleAllTimeout;
const TOGGLE_TIMEOUT = 200;
bozatko marked this conversation as resolved.
Show resolved Hide resolved
const toggleAllBtns = [...doc.querySelectorAll(`[data-multi-collapse-btn-id]`)];
const toggleMultiCollapseBtn = (btn, changeToCollapseAll) => {
const displayedText = changeToCollapseAll
? Translator.trans(/*@Desc("Collapse all sections")*/ 'collapse.collapse_all', {}, 'ibexa_collapse')
bozatko marked this conversation as resolved.
Show resolved Hide resolved
: Translator.trans(/*@Desc("Expand all sections")*/ 'collapse.expand_all', {}, 'ibexa_collapse');

btn.innerText = displayedText;
btn.classList.toggle('ibexa-multi-collapse__btn--expand-all-label', !changeToCollapseAll);
};

doc.querySelectorAll('.ibexa-collapse').forEach((collapseNode) => {
const toggleButton = collapseNode.querySelector('.ibexa-collapse__toggle-btn');
const isCollapsed = toggleButton.classList.contains('collapsed');

collapseNode.classList.toggle('ibexa-collapse--collapsed', isCollapsed);
collapseNode.dataset.collapsed = isCollapsed;

const multiCollapseNode = collapseNode.closest(`[data-multi-collapse-body]`);

collapseNode.addEventListener('hide.bs.collapse', (event) => {
event.stopPropagation();

collapseNode.classList.add('ibexa-collapse--collapsed');
collapseNode.dataset.collapsed = true;
});

collapseNode.addEventListener('show.bs.collapse', (event) => {
event.stopPropagation();

collapseNode.classList.remove('ibexa-collapse--collapsed');
collapseNode.dataset.collapsed = false;
});

if (!multiCollapseNode || !toggleAllBtns.length) {
return;
}

const currentToggleAllBtn = doc.querySelector(`[data-multi-collapse-btn-id="${multiCollapseNode.dataset.multiCollapseBody}"]`);
const attachClickToggleHandler = (section) => {
section.addEventListener('click', () => {
const currentCollapsibleBtns = [...multiCollapseNode.querySelectorAll('[data-bs-toggle]')];

global.clearTimeout(toggleAllTimeout);

toggleAllTimeout = global.setTimeout(() => {
const collapsedCount = currentCollapsibleBtns.filter((btn) => btn.classList.contains('collapsed')).length;
const shouldBeToggled = collapsedCount === currentCollapsibleBtns.length || collapsedCount === 0;

if (shouldBeToggled) {
toggleMultiCollapseBtn(currentToggleAllBtn, collapsedCount === 0);
}
}, TOGGLE_TIMEOUT);
});
};

collapseNode.querySelectorAll('[data-bs-toggle]').forEach(attachClickToggleHandler);
});
})(window, window.document);

const handleCollapseAction = (multiCollapseNode, isExpandAction) => {
multiCollapseNode.querySelectorAll('.ibexa-collapse').forEach((collapseNode) => {
const isElementCollapsed = collapseNode.classList.contains('ibexa-collapse--collapsed');
const shouldBeToggled = isExpandAction === isElementCollapsed;

if (shouldBeToggled) {
const element = bootstrap.Collapse.getOrCreateInstance(collapseNode.querySelector('.ibexa-multi-collapse__single-item'));

bozatko marked this conversation as resolved.
Show resolved Hide resolved
if (isExpandAction) {
element.show();
} else {
element.hide();
}
}
});
};
const attachAllElementsToggler = (btn) => {
btn.addEventListener('click', () => {
const collapseId = btn.dataset.multiCollapseBtnId;

if (!collapseId) {
return;
}

const multiCollapseBodyNode = doc.querySelector(`[data-multi-collapse-body="${collapseId}"]`);

global.clearTimeout(toggleAllTimeout);

toggleAllTimeout = global.setTimeout(() => {
const isExpandingAction = btn.classList.contains('ibexa-multi-collapse__btn--expand-all-label');

handleCollapseAction(multiCollapseBodyNode, isExpandingAction);
toggleMultiCollapseBtn(btn, isExpandingAction);
}, TOGGLE_TIMEOUT);
});
};
toggleAllBtns.forEach(attachAllElementsToggler);
})(window, window.document, window.bootstrap, window.Translator);
4 changes: 4 additions & 0 deletions src/bundle/Resources/public/scss/_anchor-navigation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
&:last-child {
border-bottom: none;
}

&--no-border {
border-bottom: none;
}
}

&__section-group {
Expand Down
32 changes: 32 additions & 0 deletions src/bundle/Resources/public/scss/_multi-collapse.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.ibexa-multi-collapse {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved styles from product-catalog. Based on previous review comment let me know if I still should change class name to ibexa-pc-...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if those styles are moved from PC where will be a base twig template for a multi-collapse feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed: There is no base twig template due to its too general purpose

&__header {
display: flex;
align-items: center;
justify-content: space-between;
}

&__content {
width: 100%;
margin: calculateRem(16px) 0;
}

&__input {
margin-top: calculateRem(16px);
}

&__group {
.ibexa-collapse {
&__header {
display: flex;
border-bottom: calculateRem(1px) solid $ibexa-color-light;
}

&__toggle-btn:not(.ibexa-collapse__toggle-btn--status) {
font-size: $ibexa-text-font-size-large;
font-weight: bold;
margin-right: auto;
padding-left: 0;
}
}
}
}
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 @@ -102,6 +102,7 @@
@import 'autosave';
@import 'side-menu';
@import 'collapse';
@import 'multi-collapse';
@import 'tag-view-select';
@import 'grid-view';
@import 'grid-view-item';
Expand Down
21 changes: 21 additions & 0 deletions src/bundle/Resources/translations/ibexa_collapse.en.xliff
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
</header>
<body>
<trans-unit id="4436e5415672ea41ee48dbda15f8cb25baae6c64" resname="collapse.collapse_all">
<source>Collapse all sections</source>
<target state="new">Collapse all sections</target>
<note>key: collapse.collapse_all</note>
</trans-unit>
<trans-unit id="5f80091b211b46190856ec877c535d63aee17627" resname="collapse.expand_all">
<source>Expand all sections</source>
<target state="new">Expand all sections</target>
<note>key: collapse.expand_all</note>
</trans-unit>
</body>
</file>
</xliff>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% trans_default_domain 'ibexa_collapse' %}

<div class="ibexa-multi-collapse__header">
<button type="button" data-multi-collapse-btn-id="{{ multi_collapse_btn_id }}" class="ibexa-multi-collapse-btn btn ibexa-btn ibexa-btn--small ibexa-btn--ghost">
{{ 'collapse.collapse_all'|trans({}, 'ibexa_collapse')|desc('Collapse all sections') }}
</button>
</div>
Loading