/*global Calendar, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/
// Inserts shortcut buttons after all of the following:
//
//
"use strict";
{
const DateTimeShortcuts = {
calendars: [],
calendarInputs: [],
clockInputs: [],
clockHours: {
default_: [
[gettext_noop("Now"), -1],
[gettext_noop("Midnight"), 0],
[gettext_noop("6 a.m."), 6],
[gettext_noop("Noon"), 12],
[gettext_noop("6 p.m."), 18],
],
},
dismissClockFunc: [],
dismissCalendarFunc: [],
calendarDivName1: "calendarbox", // name of calendar
that gets toggled
calendarDivName2: "calendarin", // name of
that contains calendar
calendarLinkName: "calendarlink", // name of the link that is used to toggle
clockDivName: "clockbox", // name of clock
that gets toggled
clockLinkName: "clocklink", // name of the link that is used to toggle
shortCutsClass: "datetimeshortcuts", // class of the clock and cal shortcuts
timezoneWarningClass: "timezonewarning", // class of the warning for timezone mismatch
timezoneOffset: 0,
init: function () {
const serverOffset = document.body.dataset.adminUtcOffset;
if (serverOffset) {
const localOffset = new Date().getTimezoneOffset() * -60;
DateTimeShortcuts.timezoneOffset = localOffset - serverOffset;
}
for (const inp of document.getElementsByTagName("input")) {
if (
inp.type === "text" &&
inp.classList.contains("vTimeField")
) {
DateTimeShortcuts.addClock(inp);
DateTimeShortcuts.addTimezoneWarning(inp);
} else if (
inp.type === "text" &&
inp.classList.contains("vDateField")
) {
DateTimeShortcuts.addCalendar(inp);
DateTimeShortcuts.addTimezoneWarning(inp);
}
}
},
// Return the current time while accounting for the server timezone.
now: function () {
const serverOffset = document.body.dataset.adminUtcOffset;
if (serverOffset) {
const localNow = new Date();
const localOffset = localNow.getTimezoneOffset() * -60;
localNow.setTime(
localNow.getTime() + 1000 * (serverOffset - localOffset),
);
return localNow;
} else {
return new Date();
}
},
// Add a warning when the time zone in the browser and backend do not match.
addTimezoneWarning: function (inp) {
const warningClass = DateTimeShortcuts.timezoneWarningClass;
let timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;
// Only warn if there is a time zone mismatch.
if (!timezoneOffset) {
return;
}
// Check if warning is already there.
if (
inp.parentNode.parentNode.querySelectorAll("." + warningClass)
.length
) {
return;
}
const serverTimezone =
document.body.dataset.adminServerTimezone || gettext("server");
let message;
if (timezoneOffset > 0) {
message = ngettext(
"Note: Enter times in the %(timezone)s timezone. " +
"(You are %(offset)s hour ahead.)",
"Note: Enter times in the %(timezone)s timezone. " +
"(You are %(offset)s hours ahead.)",
timezoneOffset,
);
} else {
timezoneOffset *= -1;
message = ngettext(
"Note: Enter times in the %(timezone)s timezone. " +
"(You are %(offset)s hour behind.)",
"Note: Enter times in the %(timezone)s timezone. " +
"(You are %(offset)s hours behind.)",
timezoneOffset,
);
}
message = interpolate(
message,
{ timezone: serverTimezone, offset: timezoneOffset },
true,
);
const warning = document.createElement("div");
const id = inp.id;
const field_id = inp.closest("p.datetime")
? id.slice(0, id.lastIndexOf("_"))
: id;
warning.classList.add("help", warningClass);
warning.id = `${field_id}_timezone_warning_helptext`;
warning.textContent = message;
const errorList =
inp.parentNode.parentNode.querySelector("ul.errorlist");
if (errorList) {
errorList.before(warning);
} else {
inp.parentNode.before(warning);
}
},
// Add clock widget to a given field
addClock: function (inp) {
const num = DateTimeShortcuts.clockInputs.length;
DateTimeShortcuts.clockInputs[num] = inp;
DateTimeShortcuts.dismissClockFunc[num] = function () {
DateTimeShortcuts.dismissClock(num);
return true;
};
// Shortcut links (clock icon and "Now" link)
const shortcuts_span = document.createElement("span");
shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
const now_link = document.createElement("a");
now_link.href = "#";
now_link.textContent = gettext("Now");
now_link.role = "button";
now_link.addEventListener("click", function (e) {
e.preventDefault();
DateTimeShortcuts.handleClockQuicklink(num, -1);
});
const clock_link = document.createElement("a");
clock_link.href = "#";
clock_link.id = DateTimeShortcuts.clockLinkName + num;
clock_link.addEventListener("click", function (e) {
e.preventDefault();
// avoid triggering the document click handler to dismiss the clock
e.stopPropagation();
DateTimeShortcuts.openClock(num);
});
quickElement(
"span",
clock_link,
"",
"class",
"clock-icon",
"title",
gettext("Choose a Time"),
);
shortcuts_span.appendChild(document.createTextNode("\u00A0"));
shortcuts_span.appendChild(now_link);
shortcuts_span.appendChild(
document.createTextNode("\u00A0|\u00A0"),
);
shortcuts_span.appendChild(clock_link);
// Create clock link div
//
// Markup looks like:
//