Skip to content

Commit 5393525

Browse files
authored
IBX-3456 Added collapse all button (#1394)
1 parent a31f978 commit 5393525

File tree

7 files changed

+147
-2
lines changed

7 files changed

+147
-2
lines changed

src/bundle/Resources/config/bazinga_js_translation.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ active_domains:
1313
- 'ibexa_content_type'
1414
- 'ibexa_dropdown'
1515
- 'ibexa_popup_menu'
16+
- 'ibexa_collapse'
1617
- 'messages'
Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,99 @@
1-
(function (global, doc) {
1+
(function (global, doc, bootstrap, Translator) {
2+
let toggleAllTimeout;
3+
const TOGGLE_TIMEOUT = 200;
4+
const toggleAllBtns = [...doc.querySelectorAll(`[data-multi-collapse-btn-id]`)];
5+
const toggleMultiCollapseBtn = (btn, changeToCollapseAll) => {
6+
const displayedText = changeToCollapseAll
7+
? Translator.trans(/*@Desc("Collapse all sections")*/ 'collapse.collapse_all', {}, 'ibexa_collapse')
8+
: Translator.trans(/*@Desc("Expand all sections")*/ 'collapse.expand_all', {}, 'ibexa_collapse');
9+
10+
btn.innerText = displayedText;
11+
btn.classList.toggle('ibexa-multi-collapse__btn--expand-all-label', !changeToCollapseAll);
12+
};
13+
214
doc.querySelectorAll('.ibexa-collapse').forEach((collapseNode) => {
315
const toggleButton = collapseNode.querySelector('.ibexa-collapse__toggle-btn');
416
const isCollapsed = toggleButton.classList.contains('collapsed');
517

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

21+
const multiCollapseNode = collapseNode.closest(`[data-multi-collapse-body]`);
22+
923
collapseNode.addEventListener('hide.bs.collapse', (event) => {
1024
event.stopPropagation();
25+
1126
collapseNode.classList.add('ibexa-collapse--collapsed');
1227
collapseNode.dataset.collapsed = true;
1328
});
1429

1530
collapseNode.addEventListener('show.bs.collapse', (event) => {
1631
event.stopPropagation();
32+
1733
collapseNode.classList.remove('ibexa-collapse--collapsed');
1834
collapseNode.dataset.collapsed = false;
1935
});
36+
37+
if (!multiCollapseNode || !toggleAllBtns.length) {
38+
return;
39+
}
40+
41+
const currentToggleAllBtn = doc.querySelector(`[data-multi-collapse-btn-id="${multiCollapseNode.dataset.multiCollapseBody}"]`);
42+
const attachClickToggleHandler = (section) => {
43+
section.addEventListener('click', () => {
44+
const currentCollapsibleBtns = [...multiCollapseNode.querySelectorAll('[data-bs-toggle]')];
45+
46+
global.clearTimeout(toggleAllTimeout);
47+
48+
toggleAllTimeout = global.setTimeout(() => {
49+
const collapsedCount = currentCollapsibleBtns.filter((btn) => btn.classList.contains('collapsed')).length;
50+
const shouldBeToggled = collapsedCount === currentCollapsibleBtns.length || collapsedCount === 0;
51+
52+
if (shouldBeToggled) {
53+
toggleMultiCollapseBtn(currentToggleAllBtn, collapsedCount === 0);
54+
}
55+
}, TOGGLE_TIMEOUT);
56+
});
57+
};
58+
59+
collapseNode.querySelectorAll('[data-bs-toggle]').forEach(attachClickToggleHandler);
2060
});
21-
})(window, window.document);
61+
62+
const handleCollapseAction = (multiCollapseNode, isExpandAction) => {
63+
multiCollapseNode.querySelectorAll('.ibexa-collapse').forEach((collapseNode) => {
64+
const isElementCollapsed = collapseNode.classList.contains('ibexa-collapse--collapsed');
65+
const shouldBeToggled = isExpandAction === isElementCollapsed;
66+
67+
if (shouldBeToggled) {
68+
const element = bootstrap.Collapse.getOrCreateInstance(collapseNode.querySelector('.ibexa-multi-collapse__single-item'));
69+
70+
if (isExpandAction) {
71+
element.show();
72+
} else {
73+
element.hide();
74+
}
75+
}
76+
});
77+
};
78+
const attachAllElementsToggler = (btn) => {
79+
btn.addEventListener('click', () => {
80+
const collapseId = btn.dataset.multiCollapseBtnId;
81+
82+
if (!collapseId) {
83+
return;
84+
}
85+
86+
const multiCollapseBodyNode = doc.querySelector(`[data-multi-collapse-body="${collapseId}"]`);
87+
88+
global.clearTimeout(toggleAllTimeout);
89+
90+
toggleAllTimeout = global.setTimeout(() => {
91+
const isExpandingAction = btn.classList.contains('ibexa-multi-collapse__btn--expand-all-label');
92+
93+
handleCollapseAction(multiCollapseBodyNode, isExpandingAction);
94+
toggleMultiCollapseBtn(btn, isExpandingAction);
95+
}, TOGGLE_TIMEOUT);
96+
});
97+
};
98+
toggleAllBtns.forEach(attachAllElementsToggler);
99+
})(window, window.document, window.bootstrap, window.Translator);

src/bundle/Resources/public/scss/_anchor-navigation.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
&:last-child {
1919
border-bottom: none;
2020
}
21+
22+
&--no-border {
23+
border-bottom: none;
24+
}
2125
}
2226

2327
&__section-group {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.ibexa-multi-collapse {
2+
&__header {
3+
display: flex;
4+
align-items: center;
5+
justify-content: space-between;
6+
}
7+
8+
&__content {
9+
width: 100%;
10+
margin: calculateRem(16px) 0;
11+
padding-left: calculateRem(4px);
12+
}
13+
14+
&__input {
15+
margin-top: calculateRem(16px);
16+
}
17+
18+
&__group {
19+
.ibexa-collapse {
20+
&__header {
21+
display: flex;
22+
border-bottom: calculateRem(1px) solid $ibexa-color-light;
23+
}
24+
25+
&__toggle-btn:not(.ibexa-collapse__toggle-btn--status) {
26+
font-size: $ibexa-text-font-size-large;
27+
font-weight: bold;
28+
margin-right: auto;
29+
padding-left: 0;
30+
}
31+
}
32+
}
33+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
@import 'autosave';
103103
@import 'side-menu';
104104
@import 'collapse';
105+
@import 'multi-collapse';
105106
@import 'tag-view-select';
106107
@import 'grid-view';
107108
@import 'grid-view-item';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
3+
<file source-language="en" target-language="en" datatype="plaintext" original="not.available">
4+
<header>
5+
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
6+
<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>
7+
</header>
8+
<body>
9+
<trans-unit id="4436e5415672ea41ee48dbda15f8cb25baae6c64" resname="collapse.collapse_all">
10+
<source>Collapse all sections</source>
11+
<target state="new">Collapse all sections</target>
12+
<note>key: collapse.collapse_all</note>
13+
</trans-unit>
14+
<trans-unit id="5f80091b211b46190856ec877c535d63aee17627" resname="collapse.expand_all">
15+
<source>Expand all sections</source>
16+
<target state="new">Expand all sections</target>
17+
<note>key: collapse.expand_all</note>
18+
</trans-unit>
19+
</body>
20+
</file>
21+
</xliff>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{% trans_default_domain 'ibexa_collapse' %}
2+
3+
<div class="ibexa-multi-collapse__header">
4+
<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">
5+
{{ 'collapse.collapse_all'|trans({}, 'ibexa_collapse')|desc('Collapse all sections') }}
6+
</button>
7+
</div>

0 commit comments

Comments
 (0)