[TikiWiki-commits] [Git][tikiwiki/tiki][27.x] [BP][ENH] Calendar: add fit to width option for calendar PDF export

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

Adrien Mbuya Maloba pushed to branch 27.x at Tiki Wiki CMS Groupware / Tiki


Commits:
aa5c65cf by Adrien Mbuya Maloba at 2026-06-14T20:01:41+03:00
[BP][ENH] Calendar: add fit to width option for calendar PDF export
---
* [BP][ENH] Calendar: add fit to width option for calendar PDF export
---
* [BP][ENH] Calendar: add fit to width option for calendar PDF export
---
* [ENH] Calendar: add fit to width option for calendar PDF export
---
* [ENH] Calendar: add fit to width option for calendar PDF export

See merge request tikiwiki/tiki!10283

See merge request tikiwiki/tiki!10506

See merge request tikiwiki/tiki!10515

See merge request tikiwiki/tiki!10517

- - - - -


4 changed files:

- lib/prefs/calendar.php
- lib/setup/javascript.php
- src/js/jquery-tiki/fullcalendar_to_pdf.js
- templates/admin/include_calendar.tpl


Changes:

=====================================
lib/prefs/calendar.php
=====================================
@@ -191,5 +191,15 @@ function prefs_calendar_list()
             'default' => '',
             'profile_reference' => 'calendar',
         ],
+        'calendar_pdf_export_layout' => [
+            'name' => tra('PDF export layout'),
+            'description' => tra('Choose how the exported PDF should be scaled.'),
+            'type' => 'list',
+            'options' => [
+                'fit_to_width' => tr('Fit to width'),
+                'fit_on_one_page' => tr('Fit on one page'),
+            ],
+            'default' => 'fit_on_one_page',
+        ],
     ];
 }


=====================================
lib/setup/javascript.php
=====================================
@@ -287,6 +287,7 @@ $jqueryTiki['bingMapsAPIKey'] = $prefs['geo_bingmaps_key'];
 $jqueryTiki['nextzenAPIKey'] = $prefs['geo_nextzen_key'];
 $jqueryTiki['numericFieldScroll'] = $prefs['unified_numeric_field_scroll'];
 $jqueryTiki['themeIconset'] = $prefs['theme_iconset'];
+$jqueryTiki['calendar_pdf_export_layout'] = $prefs['calendar_pdf_export_layout'];
 //set at 4 hours if empty
 $jqueryTiki['securityTimeout'] = ! empty($prefs['site_security_timeout']) ? $prefs['site_security_timeout']
     : TikiLib::lib('access')->getDefaultTimeout();


=====================================
src/js/jquery-tiki/fullcalendar_to_pdf.js
=====================================
@@ -33,15 +33,91 @@ $.fn.addFullCalendarPrint = function (buttonId, calendar) {
                 var heightLeft = imgHeight;
                 var doc = new jsPDF("p", "mm");
                 doc.setFontSize(14);
-                doc.text((210 - imgWidth) / 2, 20, calendarTitle);
+                const pageWidthMm = 210;
+                doc.text((pageWidthMm - imgWidth) / 2, 20, calendarTitle.replace(/\s+/g, " "));
 
-                if (imgHeight > pageHeight) {
-                    imgHeight = pageHeight;
-                    imgWidth = (canvas.width * imgHeight) / canvas.height;
-                }
+                // Fit calendar to width (multi-pages)
+                if (jqueryTiki.calendar_pdf_export_layout === "fit_to_width") {
+                    var marginTop = 30;
+                    var marginRight = 20;
+                    var marginBottom = 10;
+                    const pageHeightMm = 297;
+                    const printableHeight = pageHeightMm - marginTop - marginBottom;
+                    const pxPerMm = canvas.width / imgWidth; // Scale factor to convert canvas coordinates (px) into PDF units (mm)
+                    const pageHeightPx = printableHeight * pxPerMm;
+                    const pageNumberX = pageWidthMm - marginRight;
+                    const pageNumberY = pageHeightMm - marginBottom;
+                    const rows = $(calendarId + " tr[role='row']");
+                    const containerRect = elementToPrint[0].getBoundingClientRect();
+                    const rowBoundaries = [];
+
+                    rows.each(function () {
+                        const rect = this.getBoundingClientRect();
+                        rowBoundaries.push({
+                            top: rect.top - containerRect.top,
+                            bottom: rect.bottom - containerRect.top,
+                        });
+                    });
+
+                    const scaleFactor = canvas.height / elementToPrint[0].scrollHeight;
+
+                    const scaledRows = rowBoundaries.map((r) => ({
+                        top: r.top * scaleFactor,
+                        bottom: r.bottom * scaleFactor,
+                    }));
+
+                    function findSafeBreak(target) {
+                        let safe = target;
+                        for (let i = 0; i < scaledRows.length; i++) {
+                            if (scaledRows[i].top < target && scaledRows[i].bottom > target) {
+                                safe = scaledRows[i].top;
+                                break;
+                            }
+                        }
+                        return safe;
+                    }
 
-                doc.addImage(imgData, "JPEG", (210 - imgWidth) / 2, 30, imgWidth, heightLeft > pageHeight ? pageHeight : heightLeft);
+                    let startY = 0;
+                    let pageNumber = 1;
+                    // Generating new pages
+                    while (startY < canvas.height) {
+                        let target = startY + pageHeightPx;
+                        let endY = findSafeBreak(target);
 
+                        if (endY <= startY) {
+                            endY = Math.min(target, canvas.height);
+                        }
+
+                        endY = Math.min(endY, canvas.height);
+                        const sliceHeight = Math.max(0, endY - startY);
+                        if (sliceHeight <= 1) break;
+
+                        const pageCanvas = document.createElement("canvas");
+                        pageCanvas.width = canvas.width;
+                        pageCanvas.height = sliceHeight;
+                        const context = pageCanvas.getContext("2d");
+                        context.drawImage(canvas, 0, startY, canvas.width, sliceHeight, 0, 0, canvas.width, sliceHeight);
+                        const pageImage = pageCanvas.toDataURL("image/jpeg", 1.0);
+                        const renderedHeight = sliceHeight / pxPerMm;
+
+                        if (pageNumber > 1) {
+                            doc.addPage();
+                        }
+
+                        doc.addImage(pageImage, "JPEG", (pageWidthMm - imgWidth) / 2, marginTop, imgWidth, renderedHeight);
+                        doc.setFontSize(7);
+                        doc.text("Page " + pageNumber, pageNumberX, pageNumberY);
+                        pageNumber++;
+                        startY = endY;
+                    }
+                } else {
+                    // Calendar fit on one page
+                    if (imgHeight > pageHeight) {
+                        imgHeight = pageHeight;
+                        imgWidth = (canvas.width * imgHeight) / canvas.height;
+                    }
+                    doc.addImage(imgData, "JPEG", (pageWidthMm - imgWidth) / 2, 30, imgWidth, heightLeft > pageHeight ? pageHeight : heightLeft);
+                }
                 doc.save(calendarTitle + ".pdf");
             });
         }, 200);


=====================================
templates/admin/include_calendar.tpl
=====================================
@@ -48,6 +48,7 @@
         {preference name=calendar_watch_editor}
         {preference name=calendar_fc_premium_license}
         {preference name=calendar_holidays}
+        {preference name=calendar_pdf_export_layout}
     </fieldset>
     {include file='admin/include_apply_bottom.tpl'}
 </form>



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

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/aa5c65cf77e35c7d3b77a2bfc86e072cf9cf0720
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.