From 11668ee85b4cd181efa7baa2386047091acf3c17 Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Wed, 4 Aug 2021 16:28:07 +0200 Subject: [PATCH] PERF: generates dates tooltip on demand (#13944) --- .../initializers/discourse-local-dates.js.es6 | 205 +++++++++++------- .../discourse-local-dates.js.es6 | 6 +- .../common/discourse-local-dates.scss | 4 + 3 files changed, 137 insertions(+), 78 deletions(-) diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 index 53d8d04dcc4..108fae47934 100644 --- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 +++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 @@ -1,10 +1,72 @@ +import deprecated from "discourse-common/lib/deprecated"; +import { getOwner } from "discourse-common/lib/get-owner"; +import { hidePopover, showPopover } from "discourse/lib/d-popover"; import LocalDateBuilder from "../lib/local-date-builder"; -import showModal from "discourse/lib/show-modal"; import { withPluginApi } from "discourse/lib/plugin-api"; +import showModal from "discourse/lib/show-modal"; + +export function applyLocalDates(dates, siteSettings) { + if (!siteSettings.discourse_local_dates_enabled) { + return; + } + + const currentUserTZ = moment.tz.guess(); + + dates.forEach((element) => { + const opts = buildOptionsFromElement(element, siteSettings); + + const localDateBuilder = new LocalDateBuilder(opts, currentUserTZ).build(); + element.innerText = ""; + element.insertAdjacentHTML( + "beforeend", + ` + + + + ${localDateBuilder.formated} + ` + ); + element.setAttribute("aria-label", localDateBuilder.textPreview); + + const classes = ["cooked-date"]; + if (localDateBuilder.pastEvent) { + classes.push("past"); + } + element.classList.add(...classes); + }); +} + +function buildOptionsFromElement(element, siteSettings) { + const opts = {}; + const dataset = element.dataset; + opts.time = dataset.time; + opts.date = dataset.date; + opts.recurring = dataset.recurring; + opts.timezones = ( + dataset.timezones || + siteSettings.discourse_local_dates_default_timezones || + "Etc/UTC" + ) + .split("|") + .filter(Boolean); + opts.timezone = dataset.timezone; + opts.calendar = (dataset.calendar || "on") === "on"; + opts.displayedTimezone = dataset.displayedTimezone; + opts.format = dataset.format || (opts.time ? "LLL" : "LL"); + opts.countdown = dataset.countdown; + return opts; +} function initializeDiscourseLocalDates(api) { - api.decorateCooked( - ($elem) => $(".discourse-local-date", $elem).applyLocalDates(), + const siteSettings = api.container.lookup("site-settings:main"); + + api.decorateCookedElement( + (elem) => { + applyLocalDates( + elem.querySelectorAll(".discourse-local-date"), + siteSettings + ); + }, { id: "discourse-local-date" } ); @@ -30,87 +92,84 @@ function initializeDiscourseLocalDates(api) { }); } +function buildHtmlPreview(element, siteSettings) { + const opts = buildOptionsFromElement(element, siteSettings); + const localDateBuilder = new LocalDateBuilder( + opts, + moment.tz.guess() + ).build(); + + const htmlPreviews = localDateBuilder.previews.map((preview) => { + const previewNode = document.createElement("div"); + previewNode.classList.add("preview"); + if (preview.current) { + previewNode.classList.add("current"); + } + + const timezoneNode = document.createElement("span"); + timezoneNode.classList.add("timezone"); + timezoneNode.innerText = preview.timezone; + previewNode.appendChild(timezoneNode); + + const dateTimeNode = document.createElement("span"); + dateTimeNode.classList.add("date-time"); + dateTimeNode.innerText = preview.formated; + previewNode.appendChild(dateTimeNode); + + return previewNode; + }); + + const previewsNode = document.createElement("div"); + previewsNode.classList.add("locale-dates-previews"); + htmlPreviews.forEach((htmlPreview) => previewsNode.appendChild(htmlPreview)); + + return previewsNode.outerHTML; +} + export default { name: "discourse-local-dates", + showDatePopover(event) { + const siteSettings = getOwner(this).lookup("site-settings:main"); + + if (event?.target?.classList?.contains("discourse-local-date")) { + showPopover(event, { + htmlContent: buildHtmlPreview(event.target, siteSettings), + }); + } + }, + + hideDatePopover(event) { + if (event?.target?.classList?.contains("discourse-local-date")) { + hidePopover(event); + } + }, + initialize(container) { + const router = container.lookup("router:main"); + router.on("routeWillChange", hidePopover); + + window.addEventListener("click", this.showDatePopover); + window.addEventListener("mouseover", this.showDatePopover); + window.addEventListener("mouseout", this.hideDatePopover); + const siteSettings = container.lookup("site-settings:main"); if (siteSettings.discourse_local_dates_enabled) { - const currentUserTZ = moment.tz.guess(); - $.fn.applyLocalDates = function () { - return this.each(function () { - const opts = {}; - const dataset = this.dataset; - opts.time = dataset.time; - opts.date = dataset.date; - opts.recurring = dataset.recurring; - opts.timezones = ( - dataset.timezones || - siteSettings.discourse_local_dates_default_timezones || - "Etc/UTC" - ) - .split("|") - .filter(Boolean); - opts.timezone = dataset.timezone; - opts.calendar = (dataset.calendar || "on") === "on"; - opts.displayedTimezone = dataset.displayedTimezone; - opts.format = dataset.format || (opts.time ? "LLL" : "LL"); - opts.countdown = dataset.countdown; + deprecated( + "`$.applyLocalDates()` is deprecated, import and use `applyLocalDates()` instead." + ); - const localDateBuilder = new LocalDateBuilder( - opts, - currentUserTZ - ).build(); - - const htmlPreviews = localDateBuilder.previews.map((preview) => { - const previewNode = document.createElement("div"); - previewNode.classList.add("preview"); - if (preview.current) { - previewNode.classList.add("current"); - } - - const timezoneNode = document.createElement("span"); - timezoneNode.classList.add("timezone"); - timezoneNode.innerText = preview.timezone; - previewNode.appendChild(timezoneNode); - - const dateTimeNode = document.createElement("span"); - dateTimeNode.classList.add("date-time"); - dateTimeNode.innerText = preview.formated; - previewNode.appendChild(dateTimeNode); - - return previewNode; - }); - - const previewsNode = document.createElement("div"); - previewsNode.classList.add("locale-dates-previews"); - htmlPreviews.forEach((htmlPreview) => - previewsNode.appendChild(htmlPreview) - ); - - this.innerText = ""; - this.insertAdjacentHTML( - "beforeend", - ` - - - - ${localDateBuilder.formated} - ` - ); - this.setAttribute("aria-label", localDateBuilder.textPreview); - this.dataset.htmlTooltip = previewsNode.outerHTML; - - const classes = ["cooked-date"]; - if (localDateBuilder.pastEvent) { - classes.push("past"); - } - this.classList.add(...classes); - }); + return applyLocalDates(this.toArray(), siteSettings); }; withPluginApi("0.8.8", initializeDiscourseLocalDates); } }, + + teardown() { + window.removeEventListener("click", this.showDatePopover); + window.removeEventListener("mouseover", this.showDatePopover); + window.removeEventListener("mouseout", this.hideDatePopover); + }, }; diff --git a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6 index 69ecd7f75a4..7dee925e88f 100644 --- a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6 +++ b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6 @@ -140,11 +140,7 @@ function closeBuffer(buffer, state, text) { } export function setup(helper) { - helper.allowList([ - "span.discourse-local-date", - "span[data-*]", - "span[aria-label]", - ]); + helper.allowList(["span.discourse-local-date", "span[aria-label]"]); helper.registerOptions((opts, siteSettings) => { opts.datesEmailFormat = siteSettings.discourse_local_dates_email_format; diff --git a/plugins/discourse-local-dates/assets/stylesheets/common/discourse-local-dates.scss b/plugins/discourse-local-dates/assets/stylesheets/common/discourse-local-dates.scss index 08436eb090b..3c7db2310ae 100644 --- a/plugins/discourse-local-dates/assets/stylesheets/common/discourse-local-dates.scss +++ b/plugins/discourse-local-dates/assets/stylesheets/common/discourse-local-dates.scss @@ -1,4 +1,8 @@ .discourse-local-date { + > * { + pointer-events: none; + } + &.cooked-date { color: var(--primary); cursor: pointer;