From 1d54b383bd471af0a45a96b2dcf8d62aec60f516 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sun, 5 Dec 2021 21:54:37 +0100 Subject: [PATCH] compose: Fix keyboard UI with new global time widget. Fixes #20130 --- static/js/compose.js | 11 +++--- static/js/composebox_typeahead.js | 58 +++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/static/js/compose.js b/static/js/compose.js index b009a1c15d..515978b390 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -615,11 +615,12 @@ export function initialize() { } }); - let instance = {}; $("body").on("click", ".time_pick", (e) => { e.preventDefault(); e.stopPropagation(); + $(e.target).toggleClass("has_popover"); + let target_textarea; let edit_message_id; const compose_click_target = compose_ui.get_compose_click_target(e); @@ -630,13 +631,13 @@ export function initialize() { target_textarea = $(compose_click_target).closest("form").find("textarea"); } - if (!instance.calendarContainer) { + if ($(e.target).hasClass("has_popover")) { const on_timestamp_selection = (val) => { const timestr = ` `; compose_ui.insert_syntax_and_focus(timestr, target_textarea); }; - instance = composebox_typeahead.show_flatpickr( + composebox_typeahead.show_flatpickr( $(compose_click_target)[0], on_timestamp_selection, new Date(), @@ -645,11 +646,7 @@ export function initialize() { position: "above center", }, ); - return; } - - instance.close(); - instance.destroy(); }); $("#compose").on("click", ".markdown_preview", (e) => { diff --git a/static/js/composebox_typeahead.js b/static/js/composebox_typeahead.js index 585b825036..5f77a95a34 100644 --- a/static/js/composebox_typeahead.js +++ b/static/js/composebox_typeahead.js @@ -13,6 +13,7 @@ import * as compose_pm_pill from "./compose_pm_pill"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import * as compose_validate from "./compose_validate"; +import {get_keydown_hotkey} from "./hotkey"; import {$t} from "./i18n"; import * as message_store from "./message_store"; import * as muted_users from "./muted_users"; @@ -786,13 +787,66 @@ export function show_flatpickr(element, callback, default_timestamp, options = { dateFormat: "Z", formatDate: (date) => formatISO(date), disableMobile: true, + onKeyDown: (selectedDates, dateStr, instance, event) => { + const hotkey = get_keydown_hotkey(event); + + if (["tab", "shift_tab"].includes(hotkey.name)) { + const elems = [ + instance.selectedDateElem, + instance.hourElement, + instance.minuteElement, + instance.amPM, + $(".flatpickr-confirm")[0], + ]; + const i = elems.indexOf(event.target); + const n = elems.length; + const remain = (i + (event.shiftKey ? -1 : 1)) % n; + const target = elems[Math.floor(remain >= 0 ? remain : remain + n)]; + event.preventDefault(); + event.stopPropagation(); + target.focus(); + } + + event.stopPropagation(); + }, ...options, }); const container = $($(instance.innerContainer).parent()); - container.on("click", ".flatpickr-calendar", (e) => { + + container.on("keydown", (e) => { + const hotkey = get_keydown_hotkey(e); + + if (!hotkey) { + return false; + } + + if (hotkey.name === "enter") { + if (e.target.classList[0] === "flatpickr-day") { + return true; // use flatpickr default implementation + } + $(element).toggleClass("has_popover"); + container.find(".flatpickr-confirm").trigger("click"); + } + + if (hotkey.name === "escape") { + $(element).toggleClass("has_popover"); + instance.close(); + instance.destroy(); + } + + if (["tab", "shift_tab"].includes(hotkey.name)) { + return true; // use flatpickr default implementation + } + + if (["right_arrow", "up_arrow", "left_arrow", "down_arrow"].includes(hotkey.name)) { + return true; // use flatpickr default implementation + } + e.stopPropagation(); e.preventDefault(); + + return true; }); container.on("click", ".flatpickr-confirm", () => { @@ -801,7 +855,7 @@ export function show_flatpickr(element, callback, default_timestamp, options = { instance.destroy(); }); instance.open(); - container.find(".flatpickr-monthDropdown-months").trigger("focus"); + instance.selectedDateElem.focus(); return instance; }