diff options
| author | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2026-03-22 16:13:59 +0100 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+studip@gmail.com> | 2026-03-22 16:13:59 +0100 |
| commit | 1620fc15d1d21989fb38d9f3596cdf03f8535ff5 (patch) | |
| tree | fe16b79cba4b1105ccbc9c4ab16b4b606dd10950 | |
| parent | dda96cbbdf9237d90297ed1559f0a4d27713b2ec (diff) | |
implement logic that may collapse list, fixes #6380biest-6380
| -rw-r--r-- | app/controllers/course/overview.php | 4 | ||||
| -rw-r--r-- | lib/classes/CourseDateList.php | 4 | ||||
| -rw-r--r-- | resources/assets/javascripts/bootstrap/lists.js | 57 | ||||
| -rw-r--r-- | resources/assets/javascripts/entry-base.js | 1 | ||||
| -rw-r--r-- | templates/dates/course_date_list.php | 13 |
5 files changed, 76 insertions, 3 deletions
diff --git a/app/controllers/course/overview.php b/app/controllers/course/overview.php index 4325de8..e87417e 100644 --- a/app/controllers/course/overview.php +++ b/app/controllers/course/overview.php @@ -67,7 +67,9 @@ class Course_OverviewController extends AuthenticatedController $this->next_date = $this->course->getNextDate(); $this->first_date = $this->course->getFirstDate(); $show_link = $GLOBALS["perm"]->have_studip_perm('autor', $this->course_id) && $this->course->isToolActive('schedule'); - $this->times_rooms = $this->course->getAllDatesInSemester()->toHtml(); + $this->times_rooms = $this->course->getAllDatesInSemester()->toHtml( + as_collapsible_list: true + ); //Load lecturers: $lecturers = $this->course->getMembersWithStatus('dozent'); diff --git a/lib/classes/CourseDateList.php b/lib/classes/CourseDateList.php index cb1c504..02261e0 100644 --- a/lib/classes/CourseDateList.php +++ b/lib/classes/CourseDateList.php @@ -180,7 +180,8 @@ class CourseDateList implements Stringable public function toHtml( bool $group_by_rooms = false, bool $with_room_names = false, - bool $with_cancelled_dates = false + bool $with_cancelled_dates = false, + bool $as_collapsible_list = false ) : string { if ($this->isEmpty()) { return _('Die Zeiten der Veranstaltung stehen nicht fest.'); @@ -230,6 +231,7 @@ class CourseDateList implements Stringable } else { $template = $GLOBALS['template_factory']->open('dates/course_date_list'); $template->with_room_names = $with_room_names; + $template->as_collapsible_list = $as_collapsible_list; $template->collection = $this; } $template->with_cancelled_dates = $with_cancelled_dates; diff --git a/resources/assets/javascripts/bootstrap/lists.js b/resources/assets/javascripts/bootstrap/lists.js new file mode 100644 index 0000000..ac7b85c --- /dev/null +++ b/resources/assets/javascripts/bootstrap/lists.js @@ -0,0 +1,57 @@ +import {$gettext} from "@/assets/javascripts/lib/gettext"; + +(() => { + let uniqueId = 0; + + STUDIP.ready(() => { + document.querySelectorAll('.collapsible-list').forEach(list => { + if (!list.matches('ol,ul')) { + console.error('Not applicable for anything else than ol/ul lists'); + } + + const data = list.dataset; + + if (data.collapsibleListInitialized !== undefined) { + return; + } + + data.collapsibleListInitialized = true; + + const label = data.label ?? $gettext('Einträge'); + const max = Number.parseInt(data.collapseAfter ?? 5, 10); + const items = Array.from(list.children); + const hiddenItems = items.slice(max); + const hiddenCount = hiddenItems.length; + + if (hiddenCount === 0) { + return; + } + + const id = list.getAttribute('id') ?? `collapsable-list-${uniqueId++}`; + list.setAttribute('id', id); + + const button = Object.assign(document.createElement('button'), { + className: 'as-link', + textContent: '', + type: 'button', + }); + button.setAttribute('aria-controls', id); + + const update = (collapsed) => { + button.textContent = collapsed + ? $gettext('%{count} weitere %{label} anzeigen', {count: hiddenCount, label}) + : $gettext('weniger %{label} anzeigen', {label}); + button.setAttribute('aria-expanded', collapsed ? 'false' : 'true'); + hiddenItems.forEach(li => li.toggleAttribute('hidden', collapsed)); + }; + + update(true); + + button.addEventListener('click', () => { + update(button.getAttribute('aria-expanded') === 'true'); + }); + + list.after(button); + }); + }); +})(); diff --git a/resources/assets/javascripts/entry-base.js b/resources/assets/javascripts/entry-base.js index ad114f1..b4f807c 100644 --- a/resources/assets/javascripts/entry-base.js +++ b/resources/assets/javascripts/entry-base.js @@ -15,6 +15,7 @@ import "./jquery-bundle.js" import "./init.js" import "./bootstrap/responsive.js" import "./bootstrap/vue.js" +import "./bootstrap/lists.js" import "./studip-ui.js" import "./bootstrap/fullscreen.js" diff --git a/templates/dates/course_date_list.php b/templates/dates/course_date_list.php index bcc9eb7..5f2fd56 100644 --- a/templates/dates/course_date_list.php +++ b/templates/dates/course_date_list.php @@ -3,14 +3,25 @@ * @var CourseDateList $collection * @var bool $with_room_names * @var bool $with_cancelled_dates + * @var bool $as_collapsible_list * * @var SeminarCycleDate $regular_date * @var CourseDate $single_date * @var CourseExDate $cancelled_date */ ?> +<?php +$html_attributes = HTMLAttributes::from([ + 'class' => 'list-unstyled', +]); + +if ($as_collapsible_list) { + $html_attributes['class'] = 'collapsible-list'; + $html_attributes['data-label'] = _('Termine'); +} +?> <? if (!$collection->isEmpty()) : ?> - <ul class="list-unstyled"> + <ul <?= $html_attributes ?>> <? foreach ($collection->getRegularDates() as $regular_date) : ?> <li> <?= $regular_date->toString($with_room_names ? 'long-start' : 'long-start-without-room', true) ?> |
