Files @ 734a0b713d2d
Branch filter:

Location: symposion_app/static/src/js/schedule.js

734a0b713d2d 7.8 KiB application/javascript Show Annotation Show as Raw Download as Raw
Joel Addison
Improve printed schedule

Show each day on a new page when printed.
Hide elements that do not assist with printed copy (current time, etc).
$(function() {
    var SLOT_REFRESH_INTERVAL = 60 * 1000;
    var haveScrolledToCurrentSlot = false;

    /* Schedule display localisation */
    var showCurrentTab = function() {
        var fragment = window.location.hash.toLowerCase().substring(1);

        var dayTabs = $('#schedule-tabs .schedule-day');
        if (dayTabs.length === 0) return;

        if (fragment) {
            var fragmentId = "#schedule_day_" + fragment + "-tab";
            $(fragmentId).tab('show');
        } else {
            // Show tab based on current time.
            var now = luxon.DateTime.local();
            for (var i = 0; i < dayTabs.length; ++i) {
                var dayTab = $(dayTabs[i]);
                var tabDate = dayTab.data('date');

                var scheduleDate = luxon.DateTime.fromISO(tabDate, { zone: CONF_TZ });
                var startOfDay = scheduleDate.startOf('day');
                var endOfDay = scheduleDate.endOf('day');
                if (now >= startOfDay && now < endOfDay) {
                    tabShown = true;
                    dayTab.tab('show');
                    break;
                }
            }
        }
    }

    var updateScheduleGrid = function() {
        var rowHeaders = $('.calendar-row th.time');
        for (var i = 0; i < rowHeaders.length; ++i) {
            var rowHeader = $(rowHeaders[i]);
            var rowTime = rowHeader.data('time');
            var scheduleDate = luxon.DateTime.fromISO(rowTime, { zone: CONF_TZ });
            var localDate = scheduleDate.toLocal();

            // If the schedule date is already in the user's TZ, skip it.
            if (scheduleDate.offset === localDate.offset) break;

            var confFormatted = scheduleDate.toLocaleString({
                weekday: scheduleDate.weekday === localDate.weekday ? undefined : 'short',
                hour: 'numeric',
                minute: 'numeric',
                timeZoneName: 'short',
            });
            var localFormatted = localDate.toLocaleString({
                weekday: scheduleDate.weekday === localDate.weekday ? undefined : 'short',
                hour: 'numeric',
                minute: 'numeric',
                timeZoneName: 'short',
            });
            var timeText = rowHeader.find('p').text();
            rowHeader.find('p').html(confFormatted + '<br><em>(' + localFormatted + ')</em>');
        }
    }

    var updatePresentationTimes = function() {
        var presentationTimes = $('span.presentation-time');
        for (var i = 0; i < presentationTimes.length; ++i) {
            var presentationTime = $(presentationTimes[i]);
            var startTime = presentationTime.data('starttime');
            var endTime = presentationTime.data('endtime');
            var confStartTime = luxon.DateTime.fromISO(startTime, { zone: CONF_TZ });
            var confEndTime = luxon.DateTime.fromISO(endTime, { zone: CONF_TZ });

            var localStartTime = confStartTime.toLocal();
            var localEndTime = confEndTime.toLocal();

            // If the conf date is already in the user's TZ, skip it.
            if (confStartTime.offset === localStartTime.offset) break;

            var confStartTimeFormatted = confStartTime.toLocaleString({
                weekday: 'short',
                month: 'short',
                day: '2-digit',
                hour: 'numeric',
                minute: 'numeric',
            });
            var confEndTimeFormatted = confEndTime.toLocaleString({
                hour: 'numeric',
                minute: 'numeric',
                timeZoneName: 'short',
            });
            var localStartTimeFormatted = localStartTime.toLocaleString({
                weekday: confStartTime.weekday === localStartTime.weekday ? undefined : 'short',
                month: confStartTime.weekday === localStartTime.weekday ? undefined : 'short',
                day: confStartTime.weekday === localStartTime.weekday ? undefined : '2-digit',
                hour: 'numeric',
                minute: 'numeric',
            });
            var localEndTimeFormatted = localEndTime.toLocaleString({
                weekday: localStartTime.weekday === localEndTime.weekday ? undefined : 'short',
                month: localStartTime.weekday === localEndTime.weekday ? undefined : 'short',
                day: localStartTime.weekday === localEndTime.weekday ? undefined : '2-digit',
                hour: 'numeric',
                minute: 'numeric',
                timeZoneName: 'short',
            });

            presentationTime.html(confStartTimeFormatted + ' - ' + confEndTimeFormatted + ' <em>(' + localStartTimeFormatted + ' - ' + localEndTimeFormatted + ')</em>');
        }
    }

    var highlightCurrentSlots = function() {
        var now = luxon.DateTime.local();

        var slots = $('td.slot');
        for (var i = 0; i < slots.length; ++i) {
            var slot = $(slots[i]);
            var startTime = slot.data('starttime');
            var endTime = slot.data('endtime');
            var confStartTime = luxon.DateTime.fromISO(startTime, { zone: CONF_TZ });
            var confEndTime = luxon.DateTime.fromISO(endTime, { zone: CONF_TZ });

            if (confStartTime <= now && confEndTime > now) {
                slot.addClass("slot-active");

                if (!haveScrolledToCurrentSlot) {
                    haveScrolledToCurrentSlot = true;
                    slot[0].scrollIntoView();
                }
            } else {
                slot.removeClass("slot-active");
            }
        }
    }

    var updateClock = function() {
        var clock = $('div.conf-clock');
        if (clock.length === 0) {
            var template = document.createElement('template');
            template.innerHTML = '<div class="conf-clock d-print-none"></div>';
            var clockDiv = template.content.firstChild;
            document.body.appendChild(clockDiv);
            clock = $(clockDiv);
        }

        var now = luxon.DateTime.local();
        var confFormatted = now.setZone(CONF_TZ).toLocaleString({
            weekday: 'short',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            timeZoneName: 'short',
            hour12: false,
        });
        clock.html('Conf Time:<br><span class="time">' + confFormatted + '</span>');
    }

    var embeddedView = function() {
        var urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('embed')) {
            $('header').remove();
            $('footer').remove();

            $('a').each(function() {
                var anchor = $(this);
                var path = anchor.attr('href');
                if (path.startsWith('/')) {
                    var separator = path.indexOf('?') === -1 ? '?' : '&';
                    anchor.attr('href', path + separator + 'embed')
                } else if (path.startsWith('http')) {
                    anchor.attr('target', '_blank');
                }
            });
            return true;
        }
        return false;
    }

    /* Schedule Editing */
    $("a.edit-slot").click(function(e) {
        $("#slotEditModal").load($(this).data("action"), function() {
            $("#slotEditModal").modal("show");
        });
        e.preventDefault();
    });

    $("form#schedule-builder :submit").click(function(e) {
        var name = this.name;
        if(name == 'delete') {
            if (!confirm("Are you sure you want to delete the schedule?"))
                {
                    e.preventDefault();
                    return;
                }
        }
    });

    /* Update schedule display */
    var embedded = embeddedView();
    showCurrentTab();
    updateScheduleGrid();
    updatePresentationTimes();
    highlightCurrentSlots();
    var slotRefresh = setInterval(highlightCurrentSlots, SLOT_REFRESH_INTERVAL);
    if (!embedded) {
        updateClock();
        var clockRefresh = setInterval(updateClock, 5000);
    }
});