Features

  • Client-side PDF export of JavaScript monthly calendar component view
  • Page formats: Letter, A4
  • Orientation: Landscape, Portrait
  • Listing events below the calendar
  • Includes a trial version of DayPilot Pro for JavaScript (see License below)

License

Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript. Buy a license.

JPEG Export

In order to insert the calendar image into a PDF document we need to export it as JPEG image first:

var image = dp.exportAs("jpeg", {
  scale: 2,
  quality: 0.95
});

Full Source Code

The PDF document is created using jsPDF open-source library (MIT license).

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>JavaScript Monthly Calendar: PDF Export</title>

    <style type="text/css">
        p, body, td { font-family: Tahoma, Arial, Helvetica, sans-serif; font-size: 10pt; }
        body { padding: 0px; margin: 0px; background-color: #ffffff; }
        a { color: #1155a3; }
        .space { margin: 10px 0px 10px 0px; }
        .header { background: #003267; background: linear-gradient(to right, #011329 0%,#00639e 44%,#011329 100%); padding:20px 10px; color: white; box-shadow: 0px 0px 10px 5px rgba(0,0,0,0.75); }
        .header a { color: white; }
        .header h1 a { text-decoration: none; }
        .header h1 { padding: 0px; margin: 0px; }
        .main { padding: 10px; margin-top: 10px; }

        select, option { padding: 4px; }
        button {
            background-color: #3c78d8;
            border: 1px solid #1155cc;
            color: #fff;
            padding: 6px 20px;
            border-radius: 2px;
            cursor: pointer;
        }

    </style>

    <!-- DayPilot library -->
    <script src="js/daypilot/daypilot-all.min.js"></script>

    <!-- jsPDF: PDF generator -->
    <script src="js/jspdf/jspdf.min.js"></script>

</head>
<body>
<div class="header">
    <h1><a href='https://code.daypilot.org/32360/javascript-monthly-calendar-pdf-export'>JavaScript Monthly Calendar: PDF Export</a></h1>
    <div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React</div>
</div>


<div class="main">
    <div id="dp"></div>
    <div class="space">
        <h2>Export to PDF</h2>
        <select id="pdf-orientation">
            <option value="portrait">Portrait</option>
            <option value="landscape">Landscape</option>
        </select>
        <select id="pdf-format">
            <option value="letter">Letter</option>
            <option value="a4">A4</option>
        </select>
        <button id="export">Export</button>
    </div>
</div>

<script>

    var dp = new DayPilot.Month("dp", {
        onTimeRangeSelected: function (args) {
            DayPilot.Modal.prompt("Create a new event:", "Event 1").then(function (modal) {
                var dp = args.control;
                dp.clearSelection();
                if (!modal.result) {
                    return;
                }
                dp.events.add(new DayPilot.Event({
                    start: args.start,
                    end: args.end,
                    id: DayPilot.guid(),
                    text: modal.result
                }));
            });
        }
    });
    dp.events.list = [
        {
            id: "1",
            start: DayPilot.Date.today().addDays(1),
            end: DayPilot.Date.today().addDays(1),
            text: "Event 1",
            backColor: "#ffe599"
        },
        {
            id: "1",
            start: DayPilot.Date.today().addDays(1),
            end: DayPilot.Date.today().addDays(1),
            text: "Event 2",
            backColor: "#dd7e6b"
        },
        {
            id: "1",
            start: DayPilot.Date.today().addDays(2),
            end: DayPilot.Date.today().addDays(2),
            text: "Event 3",
            backColor: "#b6d7a8"
        }
    ];
    dp.init();

    var pdfConfig = {
        "letter-portrait": {
            orientation: "portrait",
            unit: "in",
            format: "letter",
            maxWidth: 7,
            maxHeight: 9,
            left: 0.5,
            top: 1,
            space: 0.2,
            lineHeight: 0.2
        },
        "letter-landscape": {
            orientation: "landscape",
            unit: "in",
            format: "letter",
            maxWidth: 9,
            maxHeight: 7,
            left: 0.5,
            top: 1,
            space: 0.2,
            lineHeight: 0.2
        },
        "a4-portrait": {
            orientation: "portrait",
            unit: "cm",
            format: "a4",
            maxWidth: 18,
            maxHeight: 23,
            left: 1.5,
            top: 3,
            space: 0.5,
            lineHeight: 0.5
        },
        "a4-landscape": {
            orientation: "landscape",
            unit: "cm",
            format: "a4",
            maxWidth: 23,
            maxHeight: 18,
            left: 1.5,
            top: 3,
            space: 0.5,
            lineHeight: 0.5
        }
    };

    (function () {
        document.getElementById("export").addEventListener("click", function (e) {
            var orientation = document.getElementById("pdf-orientation").value;
            var format = document.getElementById("pdf-format").value;
            var config = pdfConfig[format + "-" + orientation];
            var blob = createPdfAsBlobOnePage(config);
            DayPilot.Util.downloadBlob(blob, "calendar.pdf");
        });
    })();

    function createPdfAsBlobOnePage(config) {

        var month = DayPilot.Date.today().toString("MMMM yyyy");

        var pdf = new jsPDF(config.orientation, config.unit, config.format);
        pdf.setFontSize(20);
        pdf.text(config.left, config.top, "Monthly Calendar: " + month);

        var image = dp.exportAs("jpeg", {
            scale: 2,
            quality: 0.95
        });

        var dimensions = image.dimensions();  // pixels
        var maxDimensions = {width: config.maxWidth, height: config.maxHeight};   // inches
        var adjusted = shrink(dimensions, maxDimensions);

        pdf.addImage(image.toDataUri(), 'JPEG', config.left, config.top + config.space, adjusted.width, adjusted.height);


        pdf.setFontSize(10);
        var offset = 0;

        offset += config.lineHeight;
        pdf.text(config.left, config.top + config.space + adjusted.height + offset, "Events:");


        dp.events.list.forEach(function(ev) {
          var text = ev.text + " - " + new DayPilot.Date(ev.start).toString("MMMM d, yyyy");

          offset += config.lineHeight;
          pdf.text(config.left, config.top + config.space + adjusted.height + offset, text);
        });

        return pdf.output("blob");
    }

    function shrink(dimensions, max) {
        var widthRatio = dimensions.width / max.width;
        var heightRatio = dimensions.height / max.height;

        var ratio = Math.max(widthRatio, heightRatio);
        ratio = Math.max(ratio, 1);

        var width = dimensions.width / ratio;
        var height = dimensions.height / ratio;
        return {width: width, height: height};
    }

</script>

</body>
</html>