[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX][UX] Calendar: make viewlist="table" list periods respect calendar_list_begins_focus

"Adrien Mbuya Maloba \(@adrienmaloba\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <6a3feddb2277d_381997b818324@gitlab-sidekiq-low-urgency-cpu-bound-v2-656d6f88d7-vdwhn.mail>

Adrien Mbuya Maloba pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
da498906 by MAGENE Sem Joel at 2026-06-27T18:17:59+03:00
[FIX][UX] Calendar: make viewlist="table" list periods respect calendar_list_begins_focus
---
* [FIX][UX] Calendar: make viewlist="table" list periods respect calendar_list_begins_focus

See merge request tikiwiki/tiki!10589

- - - - -


4 changed files:

- lib/calendar/calendarlib.php
- src/js/jquery-tiki/tiki-calendar.js
- templates/tiki-calendar.tpl
- tiki-calendar_setup.php


Changes:

=====================================
lib/calendar/calendarlib.php
=====================================
@@ -185,6 +185,7 @@ class CalendarLib extends TikiLib
             'maxHourOfDay'     => $maxHourOfDay,
             'slotDuration'     => '00:' . str_pad($prefs['calendar_timespan'], 2, '0', STR_PAD_LEFT),
             'initialDate'      => date("Y-m-d"),
+            'calendarListBeginsFocus' => $prefs['calendar_list_begins_focus'] === 'y',
             'canEditAnything' => $canEditAnything,
             'calendars' => $calendars,
         ];


=====================================
src/js/jquery-tiki/tiki-calendar.js
=====================================
@@ -138,14 +138,67 @@ $.fn.setupEventCalendar = function (
         let activeMonthRangeSpan = normalizeMonthRangeSpan(eventCalendarParams.initialMonthRangeSpan);
         const listPeriodOptions = {
             week: { label: tr("Week"), duration: { weeks: 1 } },
-            month: { label: tr("Month"), duration: { months: 1 } },
-            quarter: { label: tr("Quarter"), duration: { months: 3 } },
-            semester: { label: tr("Semester"), duration: { months: 6 } },
-            year: { label: tr("Year"), duration: { years: 1 } },
+            month: { label: tr("Month"), duration: { months: 1 }, focusMonths: 1 },
+            quarter: { label: tr("Quarter"), duration: { months: 3 }, focusMonths: 3 },
+            semester: { label: tr("Semester"), duration: { months: 6 }, focusMonths: 6 },
+            year: { label: tr("Year"), duration: { years: 1 }, focusMonths: 12 },
         };
         const listPeriodNames = Object.keys(listPeriodOptions);
         const normalizeListPeriod = (period) => (listPeriodNames.includes(period) ? period : "year");
         let activeListPeriod = normalizeListPeriod(eventCalendarParams.initialListPeriod);
+        // Keep the user's focus separate from aligned ranges such as January-December.
+        let activeListFocusDate = null;
+        let activeListFocusDay = null;
+        let pendingListNavigation = null;
+        const getCalendarDate = () => moment(calendarContainer[0].getOption("date"));
+        const getListFocusDate = () => (activeListFocusDate?.isValid() ? activeListFocusDate.clone() : getCalendarDate());
+        const setListFocusDate = (date, preserveFocusDay = false) => {
+            const focusDate = moment(date);
+            if (!focusDate.isValid()) {
+                return;
+            }
+            activeListFocusDate = focusDate;
+            if (!preserveFocusDay) {
+                activeListFocusDay = focusDate.date();
+            }
+        };
+        const getListDuration = (periodOptions, focusDate) => {
+            if (!eventCalendarParams.calendarListBeginsFocus) {
+                return { ...periodOptions.duration };
+            }
+            if (!periodOptions.focusMonths) {
+                return { days: 7 };
+            }
+            return { days: focusDate.clone().add(periodOptions.focusMonths, "months").diff(focusDate, "days") };
+        };
+        const getNavigatedListFocusDate = (direction) => {
+            const focusDate = getListFocusDate();
+            const periodOptions = listPeriodOptions[activeListPeriod];
+            if (!periodOptions.focusMonths) {
+                return focusDate.add(direction * 7, "days");
+            }
+            const focusDay = activeListFocusDay || focusDate.date();
+            const targetDate = focusDate.date(1).add(direction * periodOptions.focusMonths, "months");
+            return targetDate.date(Math.min(focusDay, targetDate.daysInMonth()));
+        };
+        // Native toolbar navigation changes the date first; datesSet then reapplies the exact List range.
+        const bindListNavigation = () => {
+            ["prev", "next", "today"].forEach((action) => {
+                const button = calendarEl.querySelector(".ec-" + action);
+                if (button && !button.dataset.listNavigationBound) {
+                    button.addEventListener(
+                        "click",
+                        () => {
+                            if (eventCalendarParams.initialView === "listYear") {
+                                pendingListNavigation = action;
+                            }
+                        },
+                        true
+                    );
+                    button.dataset.listNavigationBound = "1";
+                }
+            });
+        };
         const getListPeriodButtons = () => {
             const listPeriodContainer = calendarEl.querySelector("#list-period-controls");
             if (!listPeriodContainer) {
@@ -176,13 +229,12 @@ $.fn.setupEventCalendar = function (
             const selectedPeriod = listPeriodOptions[normalizedPeriod];
             activeListPeriod = normalizedPeriod;
             eventCalendarParams.initialListPeriod = normalizedPeriod;
-            if (normalizedPeriod === "year") {
-                const currentDate = moment(calendarContainer[0].getOption("date"));
-                if (currentDate.isValid()) {
-                    calendarContainer[0].setOption("date", currentDate.startOf("year").toDate());
-                }
-            }
-            calendarContainer[0].setOption("duration", { ...selectedPeriod.duration });
+            const focusDate = getListFocusDate();
+            setListFocusDate(focusDate, activeListFocusDate?.isValid());
+            const displayDate =
+                !eventCalendarParams.calendarListBeginsFocus && normalizedPeriod === "year" ? focusDate.clone().startOf("year") : focusDate;
+            calendarContainer[0].setOption("date", displayDate.toDate());
+            calendarContainer[0].setOption("duration", getListDuration(selectedPeriod, focusDate));
             calendarContainer[0].setOption("dayCellFormat", function (dayCell) {
                 return moment(dayCell).format("D");
             });
@@ -260,10 +312,20 @@ $.fn.setupEventCalendar = function (
             viewDidMount: function (data) {
                 // Normalize view type because callback payload can expose either `data.type` or `data.view.type`.
                 const currentViewType = data?.type ?? data?.view?.type;
+                const previousViewType = eventCalendarParams.initialView;
                 if (currentViewType) {
                     eventCalendarParams.initialView = currentViewType;
                 }
+                if (previousViewType === "listYear" && currentViewType !== "listYear" && activeListFocusDate?.isValid()) {
+                    calendarContainer[0].setOption("date", activeListFocusDate.toDate());
+                    activeListFocusDate = null;
+                    activeListFocusDay = null;
+                    pendingListNavigation = null;
+                } else if (currentViewType === "listYear" && previousViewType !== "listYear") {
+                    setListFocusDate(getCalendarDate());
+                }
                 $(calendarEl).tikiModal();
+                bindListNavigation();
                 if (currentViewType == "dayGridMonth" || currentViewType == "listMonth") {
                     removeListPeriodControls();
                     if (!calendarEl.querySelector("#quarter")) {
@@ -341,6 +403,16 @@ $.fn.setupEventCalendar = function (
                     }
                 }
             },
+            datesSet: function (data) {
+                if (data?.view?.type !== "listYear" || !pendingListNavigation) {
+                    return;
+                }
+                const navigation = pendingListNavigation;
+                pendingListNavigation = null;
+                const focusDate = navigation === "today" ? getCalendarDate() : getNavigatedListFocusDate(navigation === "next" ? 1 : -1);
+                setListFocusDate(focusDate, navigation !== "today");
+                applyListPeriod(activeListPeriod);
+            },
             eventDidMount: function (arg) {
                 const event = arg.event;
                 const element = $(arg.el);


=====================================
templates/tiki-calendar.tpl
=====================================
@@ -121,9 +121,8 @@
                 </div>
             {else}
                 {jq}
-                    let today = new Date();
                     var printingParams = {pdf_export: '{{$pdf_export}}', pdf_warning: '{{$pdf_warning}}', pref_print_pdf_from_url: '{{$prefs.print_pdf_from_url}}'};
-                    $('.calendar-container').defineParameterOfMultipleCalendar({{$eventCalendarParams|json_encode}}, printingParams, '.calendar-container', today.toISOString().split('T')[0], undefined, undefined, undefined);
+                    $('.calendar-container').defineParameterOfMultipleCalendar({{$eventCalendarParams|json_encode}}, printingParams, '.calendar-container', {{$eventCalendarParams.initialDate|json_encode}}, undefined, undefined, undefined);
                 {/jq}
             {/if}
             


=====================================
tiki-calendar_setup.php
=====================================
@@ -445,6 +445,7 @@ $smarty->assign(
         'slotDuration'     => $slotDuration,
         'initialView'      => $initialView,
         'initialDate'      => "$focus_year-$focus_month-$focus_day",
+        'calendarListBeginsFocus' => $prefs['calendar_list_begins_focus'] === 'y',
     ]
 );
 



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/da498906eedaf1ce908eac1d77340e9b1abe54b0

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/da498906eedaf1ce908eac1d77340e9b1abe54b0
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.