diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6 b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6 index 15fcee7bb7..65bfa99fc6 100644 --- a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6 +++ b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js.no-module.es6 @@ -1,294 +1,284 @@ (function($) { - $.fn.applyLocalDates = function(repeat) { - const processElement = ($element, options = {}) => { - if (this.timeout) clearTimeout(this.timeout); + const DATE_TEMPLATE = ` + + + + + + + `; - repeat = repeat || true; - const utc = moment().utc(); - const dateTime = options.time - ? `${options.date} ${options.time}` - : options.date; - let utcDateTime; + const PREVIEW_TEMPLATE = ` +
+ + +
+ `; - let displayedTimezone; + function processElement($element, options = {}) { + clearTimeout(this.timeout); + + const utc = moment().utc(); + const dateTime = options.time + ? `${options.date} ${options.time}` + : options.date; + let utcDateTime; + + let displayedTimezone; + if (options.time) { + displayedTimezone = options.displayedTimezone || moment.tz.guess(); + } else { + displayedTimezone = + options.displayedTimezone || options.timezone || moment.tz.guess(); + } + + // if timezone given we convert date and time from given zone to Etc/UTC + if (options.timezone) { + utcDateTime = _applyZoneToDateTime(dateTime, options.timezone); + } else { + utcDateTime = moment.utc(dateTime); + } + + if (utcDateTime < utc) { + // if event is in the past we want to bump it no next occurrence when + // recurring is set + if (options.recurring) { + utcDateTime = _applyRecurrence(utcDateTime, options.recurring); + } else { + $element.addClass("past"); + } + } + + // once we have the correct UTC date we want + // we adjust it to watching user timezone + const adjustedDateTime = utcDateTime.tz(displayedTimezone); + + const previews = _generatePreviews( + adjustedDateTime.clone(), + displayedTimezone, + options + ); + const textPreview = _generateTextPreview(previews); + const htmlPreview = _generateHtmlPreview(previews); + + const formatedDateTime = _applyFormatting( + adjustedDateTime, + displayedTimezone, + options + ); + + $element + .html(DATE_TEMPLATE) + .attr("title", textPreview) + .attr("data-html-tooltip", `
${htmlPreview}
`) + .addClass("cooked-date") + .find(".relative-time") + .text(formatedDateTime); + + this.timeout = setTimeout(() => processElement($element, options), 10000); + } + + function _formatTimezone(timezone) { + return timezone + .replace("_", " ") + .replace("Etc/", "") + .split("/"); + } + + function _zoneWithoutPrefix(timezone) { + const parts = _formatTimezone(timezone); + return parts[1] || parts[0]; + } + + function _applyZoneToDateTime(dateTime, timezone) { + return moment.tz(dateTime, timezone).utc(); + } + + function _translateCalendarKey(time, key) { + const translated = I18n.t(`discourse_local_dates.relative_dates.${key}`, { + time: "LT" + }); + + if (time) { + return translated + .split("LT") + .map(w => `[${w}]`) + .join("LT"); + } else { + return `[${translated.replace(" LT", "")}]`; + } + } + + function _calendarFormats(time) { + return { + sameDay: _translateCalendarKey(time, "today"), + nextDay: _translateCalendarKey(time, "tomorrow"), + lastDay: _translateCalendarKey(time, "yesterday"), + sameElse: "L" + }; + } + + function _isEqualZones(timezoneA, timezoneB) { + return ( + moment.tz(timezoneA).utcOffset() === moment.tz(timezoneB).utcOffset() + ); + } + + function _applyFormatting(dateTime, displayedTimezone, options) { + const sameTimezone = _isEqualZones(displayedTimezone, moment.tz.guess()); + const inCalendarRange = dateTime.isBetween( + moment().subtract(2, "days"), + moment().add(2, "days") + ); + + if (options.calendar && inCalendarRange) { + if (sameTimezone) { + if (options.time) { + dateTime = dateTime.calendar(null, _calendarFormats(options.time)); + } else { + dateTime = dateTime.calendar(null, _calendarFormats(null)); + } + } else { + dateTime = dateTime.format(options.format); + dateTime = dateTime.replace("TZ", ""); + dateTime = `${dateTime} (${_zoneWithoutPrefix(displayedTimezone)})`; + } + } else { if (options.time) { - displayedTimezone = options.displayedTimezone || moment.tz.guess(); - } else { - displayedTimezone = - options.displayedTimezone || options.timezone || moment.tz.guess(); - } + dateTime = dateTime.format(options.format); - // if timezone given we convert date and time from given zone to Etc/UTC - if (options.timezone) { - utcDateTime = _applyZoneToDateTime(dateTime, options.timezone); - } else { - utcDateTime = moment.utc(dateTime); - } - - if (utcDateTime < utc) { - // if event is in the past we want to bump it no next occurrence when - // recurring is set - if (options.recurring) { - utcDateTime = _applyRecurrence(utcDateTime, options.recurring); - } else { - $element.addClass("past"); - } - } - - // once we have the correct UTC date we want - // we adjust it to watching user timezone - const adjustedDateTime = utcDateTime.tz(displayedTimezone); - - const previews = _generatePreviews( - adjustedDateTime.clone(), - displayedTimezone, - options - ); - const textPreview = _generateTextPreview(previews); - const htmlPreview = _generateHtmlPreview(previews); - - const formatedDateTime = _applyFormatting( - adjustedDateTime, - displayedTimezone, - options - ); - - const $dateTemplate = ` - - - - - - - `; - - $element - .html($dateTemplate) - .attr("title", textPreview) - .attr("data-html-tooltip", `
${htmlPreview}
`) - .addClass("cooked-date") - .find(".relative-time") - .text(formatedDateTime); - - if (repeat) { - this.timeout = setTimeout( - () => processElement($element, options), - 10000 - ); - } - }; - - const _formatTimezone = timezone => - timezone - .replace("_", " ") - .replace("Etc/", "") - .split("/"); - - const _zoneWithoutPrefix = timezone => { - const parts = _formatTimezone(timezone); - return parts[1] || parts[0]; - }; - - const _applyZoneToDateTime = (dateTime, timezone) => { - return moment.tz(dateTime, timezone).utc(); - }; - - const _calendarFormats = time => { - const _translate = key => { - const translated = I18n.t( - `discourse_local_dates.relative_dates.${key}`, - { - time: "LT" - } - ); - - if (time) { - return translated - .split("LT") - .map(w => `[${w}]`) - .join("LT"); - } else { - return `[${translated.replace(" LT", "")}]`; - } - }; - - return { - sameDay: _translate("today"), - nextDay: _translate("tomorrow"), - lastDay: _translate("yesterday"), - sameElse: "L" - }; - }; - - const compareZones = (timezoneA, timezoneB) => { - return ( - moment.tz(timezoneA).utcOffset() === moment.tz(timezoneB).utcOffset() - ); - }; - - const _applyFormatting = (dateTime, displayedTimezone, options) => { - const sameTimezone = compareZones(displayedTimezone, moment.tz.guess()); - const inCalendarRange = dateTime.isBetween( - moment().subtract(2, "days"), - moment().add(2, "days") - ); - - if (options.calendar && inCalendarRange) { - if (sameTimezone) { - if (options.time) { - dateTime = dateTime.calendar(null, _calendarFormats(options.time)); - } else { - dateTime = dateTime.calendar(null, _calendarFormats(null)); - } - } else { - dateTime = dateTime.format(options.format); + if (options.displayedTimezone && !sameTimezone) { dateTime = dateTime.replace("TZ", ""); dateTime = `${dateTime} (${_zoneWithoutPrefix(displayedTimezone)})`; + } else { + dateTime = dateTime.replace( + "TZ", + _formatTimezone(displayedTimezone).join(": ") + ); } } else { - if (options.time) { - dateTime = dateTime.format(options.format); + dateTime = dateTime.format(options.format); - if (options.displayedTimezone && !sameTimezone) { - dateTime = dateTime.replace("TZ", ""); - dateTime = `${dateTime} (${_zoneWithoutPrefix(displayedTimezone)})`; - } else { - dateTime = dateTime.replace( - "TZ", - _formatTimezone(displayedTimezone).join(": ") - ); - } + if (!sameTimezone) { + dateTime = dateTime.replace("TZ", ""); + dateTime = `${dateTime} (${_zoneWithoutPrefix(displayedTimezone)})`; } else { - dateTime = dateTime.format(options.format); - - if (!sameTimezone) { - dateTime = dateTime.replace("TZ", ""); - dateTime = `${dateTime} (${_zoneWithoutPrefix(displayedTimezone)})`; - } else { - dateTime = dateTime.replace( - "TZ", - _zoneWithoutPrefix(displayedTimezone) - ); - } + dateTime = dateTime.replace( + "TZ", + _zoneWithoutPrefix(displayedTimezone) + ); } } + } - return dateTime; - }; + return dateTime; + } - const _applyRecurrence = (dateTime, recurring) => { - const parts = recurring.split("."); - const count = parseInt(parts[0], 10); - const type = parts[1]; - const diff = moment().diff(dateTime, type); - const add = Math.ceil(diff + count); + function _applyRecurrence(dateTime, recurring) { + const parts = recurring.split("."); + const count = parseInt(parts[0], 10); + const type = parts[1]; + const diff = moment().diff(dateTime, type); + const add = Math.ceil(diff + count); - return dateTime.add(add, type); - }; + return dateTime.add(add, type); + } - const createDateTimeRange = (dateTime, timezone) => { - const startRange = dateTime.tz(timezone).format("LLL"); - const separator = "→"; - const endRange = dateTime - .add(24, "hours") - .tz(timezone) - .format("LLL"); + function _createDateTimeRange(dateTime, timezone) { + const startRange = dateTime.tz(timezone).format("LLL"); + const separator = "→"; + const endRange = dateTime + .add(24, "hours") + .tz(timezone) + .format("LLL"); - return `${startRange} ${separator} ${endRange}`; - }; + return `${startRange} ${separator} ${endRange}`; + } - const _generatePreviews = (dateTime, displayedTimezone, options) => { - const previewedTimezones = []; - const watchingUserTimezone = moment.tz.guess(); - const timezones = options.timezones.filter( - timezone => timezone !== watchingUserTimezone - ); + function _generatePreviews(dateTime, displayedTimezone, options) { + const previewedTimezones = []; + const watchingUserTimezone = moment.tz.guess(); + const timezones = options.timezones.filter( + timezone => timezone !== watchingUserTimezone + ); - if (!compareZones(displayedTimezone, watchingUserTimezone)) { - previewedTimezones.push({ - timezone: watchingUserTimezone, - current: true, - dateTime: options.time - ? dateTime.tz(watchingUserTimezone).format("LLL") - : createDateTimeRange(dateTime, watchingUserTimezone) - }); - } - - if ( - options.timezone && - displayedTimezone === watchingUserTimezone && - options.timezone !== displayedTimezone && - !compareZones(displayedTimezone, options.timezone) - ) { - timezones.unshift(options.timezone); - } - - timezones.filter(z => z).forEach(timezone => { - if (compareZones(timezone, displayedTimezone)) { - return; - } - - if (compareZones(timezone, watchingUserTimezone)) { - timezone = watchingUserTimezone; - } - - previewedTimezones.push({ - timezone, - dateTime: options.time - ? dateTime.tz(timezone).format("LLL") - : createDateTimeRange(dateTime, timezone) - }); + if (!_isEqualZones(displayedTimezone, watchingUserTimezone)) { + previewedTimezones.push({ + timezone: watchingUserTimezone, + current: true, + dateTime: options.time + ? dateTime.tz(watchingUserTimezone).format("LLL") + : _createDateTimeRange(dateTime, watchingUserTimezone) }); + } - if (!previewedTimezones.length) { - previewedTimezones.push({ - timezone: "Etc/UTC", - dateTime: options.time - ? dateTime.tz("Etc/UTC").format("LLL") - : createDateTimeRange(dateTime, "Etc/UTC") - }); + if ( + options.timezone && + displayedTimezone === watchingUserTimezone && + options.timezone !== displayedTimezone && + !_isEqualZones(displayedTimezone, options.timezone) + ) { + timezones.unshift(options.timezone); + } + + timezones.filter(z => z).forEach(timezone => { + if (_isEqualZones(timezone, displayedTimezone)) { + return; } - return _.uniq(previewedTimezones, "timezone"); - }; + if (_isEqualZones(timezone, watchingUserTimezone)) { + timezone = watchingUserTimezone; + } - const _generateTextPreview = previews => { - return previews - .map(preview => { - const formatedZone = _zoneWithoutPrefix(preview.timezone); + previewedTimezones.push({ + timezone, + dateTime: options.time + ? dateTime.tz(timezone).format("LLL") + : _createDateTimeRange(dateTime, timezone) + }); + }); - if (preview.dateTime.match(/TZ/)) { - return preview.dateTime.replace(/TZ/, formatedZone); - } else { - return `${formatedZone} ${preview.dateTime}`; - } - }) - .join(", "); - }; + if (!previewedTimezones.length) { + previewedTimezones.push({ + timezone: "Etc/UTC", + dateTime: options.time + ? dateTime.tz("Etc/UTC").format("LLL") + : _createDateTimeRange(dateTime, "Etc/UTC") + }); + } - const _generateHtmlPreview = previews => { - const $htmlTooltip = $("
"); + return _.uniq(previewedTimezones, "timezone"); + } - const $previewTemplate = $(` -
- - -
- `); + function _generateTextPreview(previews) { + return previews + .map(preview => { + const formatedZone = _zoneWithoutPrefix(preview.timezone); - previews.forEach(preview => { - const $template = $previewTemplate.clone(); + if (preview.dateTime.match(/TZ/)) { + return preview.dateTime.replace(/TZ/, formatedZone); + } else { + return `${formatedZone} ${preview.dateTime}`; + } + }) + .join(", "); + } + + function _generateHtmlPreview(previews) { + return previews + .map(preview => { + const $template = $(PREVIEW_TEMPLATE); if (preview.current) $template.addClass("current"); $template.find(".timezone").text(_zoneWithoutPrefix(preview.timezone)); $template.find(".date-time").text(preview.dateTime); - $htmlTooltip.append($template); - }); - - return $htmlTooltip.html(); - }; + return $template[0].outerHTML; + }) + .join(""); + } + $.fn.applyLocalDates = function() { return this.each(function() { const $element = $(this);