mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-27 10:03:56 +00:00 
			
		
		
		
	click_handlers: Convert module to TypeScript.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
		
				
					committed by
					
						 Tim Abbott
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							4f297bee32
						
					
				
				
					commit
					26aa19db43
				
			| @@ -63,7 +63,7 @@ EXEMPT_FILES = make_set( | ||||
|         "web/src/bootstrap_typeahead.ts", | ||||
|         "web/src/browser_history.ts", | ||||
|         "web/src/buddy_list.ts", | ||||
|         "web/src/click_handlers.js", | ||||
|         "web/src/click_handlers.ts", | ||||
|         "web/src/compose.js", | ||||
|         "web/src/compose_actions.ts", | ||||
|         "web/src/compose_banner.ts", | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| // You won't find every click handler here, but it's a good place to start!
 | ||||
| 
 | ||||
| import $ from "jquery"; | ||||
| import assert from "minimalistic-assert"; | ||||
| import * as tippy from "tippy.js"; | ||||
| 
 | ||||
| // You won't find every click handler here, but it's a good place to start!
 | ||||
| import {z} from "zod"; | ||||
| 
 | ||||
| import render_buddy_list_tooltip_content from "../templates/buddy_list_tooltip_content.hbs"; | ||||
| 
 | ||||
| @@ -41,12 +42,12 @@ import * as ui_util from "./ui_util.ts"; | ||||
| import {parse_html} from "./ui_util.ts"; | ||||
| import * as util from "./util.ts"; | ||||
| 
 | ||||
| export function initialize() { | ||||
| export function initialize(): void { | ||||
|     // MESSAGE CLICKING
 | ||||
| 
 | ||||
|     function initialize_long_tap() { | ||||
|     function initialize_long_tap(): void { | ||||
|         const MS_DELAY = 750; | ||||
|         const meta = { | ||||
|         const meta: {touchdown: boolean; current_target: number | undefined; invalid?: boolean} = { | ||||
|             touchdown: false, | ||||
|             current_target: undefined, | ||||
|         }; | ||||
| @@ -69,7 +70,7 @@ export function initialize() { | ||||
|                 // Later we check whether after MS_DELAY the user is still
 | ||||
|                 // long touching the same message as it can be possible that
 | ||||
|                 // user touched another message within MS_DELAY period.
 | ||||
|                 if (meta.touchdown === true && !meta.invalid && id === meta.current_target) { | ||||
|                 if (meta.touchdown && !meta.invalid && id === meta.current_target) { | ||||
|                     $(this).trigger("longtap"); | ||||
|                 } | ||||
|             }, MS_DELAY); | ||||
| @@ -95,7 +96,7 @@ export function initialize() { | ||||
|         initialize_long_tap(); | ||||
|     } | ||||
| 
 | ||||
|     function is_clickable_message_element($target) { | ||||
|     function is_clickable_message_element($target: JQuery<Element>): boolean { | ||||
|         // This function defines all the elements within a message
 | ||||
|         // body that have UI behavior other than starting a reply.
 | ||||
| 
 | ||||
| @@ -158,7 +159,8 @@ export function initialize() { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const select_message_function = function (e) { | ||||
|     const select_message_function = function (this: HTMLElement, e: JQuery.TriggeredEvent): void { | ||||
|         assert(e.target instanceof Element); | ||||
|         if (is_clickable_message_element($(e.target))) { | ||||
|             // If this click came from a hyperlink, don't trigger the
 | ||||
|             // reply action.  The simple way of doing this is simply
 | ||||
| @@ -172,7 +174,7 @@ export function initialize() { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (document.getSelection().type === "Range") { | ||||
|         if (document.getSelection()?.type === "Range") { | ||||
|             // Drags on the message (to copy message text) shouldn't trigger a reply.
 | ||||
|             return; | ||||
|         } | ||||
| @@ -199,7 +201,7 @@ export function initialize() { | ||||
|                 // This might happen for locally echoed messages, for example.
 | ||||
|                 return; | ||||
|             } | ||||
|             window.location = hash_util.by_conversation_and_time_url(message); | ||||
|             window.location.href = hash_util.by_conversation_and_time_url(message); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| @@ -216,7 +218,7 @@ export function initialize() { | ||||
|         $("#main_div").on("click", ".messagebox", select_message_function); | ||||
|         // on the other hand, on mobile it should be done with a long tap.
 | ||||
|     } else { | ||||
|         $("#main_div").on("longtap", ".messagebox", function (e) { | ||||
|         $("#main_div").on("longtap", ".messagebox", function (this: HTMLElement, e) { | ||||
|             const sel = window.getSelection(); | ||||
|             // if one matches, remove the current selections.
 | ||||
|             // after a longtap that is valid, there should be no text selected.
 | ||||
| @@ -242,10 +244,11 @@ export function initialize() { | ||||
| 
 | ||||
|         const message_id = rows.id($(this).closest(".message_row")); | ||||
|         const message = message_store.get(message_id); | ||||
|         assert(message !== undefined); | ||||
|         starred_messages_ui.toggle_starred_and_update_server(message); | ||||
|     }); | ||||
| 
 | ||||
|     $("#main_div").on("click", ".message_reaction", function (e) { | ||||
|     $("#main_div").on("click", ".message_reaction", function (this: HTMLElement, e) { | ||||
|         e.stopPropagation(); | ||||
| 
 | ||||
|         if (page_params.is_spectator) { | ||||
| @@ -254,7 +257,7 @@ export function initialize() { | ||||
|         } | ||||
| 
 | ||||
|         emoji_picker.hide_emoji_popover(); | ||||
|         const local_id = $(this).attr("data-reaction-id"); | ||||
|         const local_id = $(this).attr("data-reaction-id")!; | ||||
|         const message_id = rows.get_message_id(this); | ||||
|         reactions.process_reaction_click(message_id, local_id); | ||||
|         $(".tooltip").remove(); | ||||
| @@ -268,16 +271,16 @@ export function initialize() { | ||||
|         e.preventDefault(); | ||||
|     }); | ||||
| 
 | ||||
|     $("#main_div").on("click", "a.stream", function (e) { | ||||
|     $("#main_div").on("click", "a.stream", function (this: HTMLAnchorElement, e) { | ||||
|         e.preventDefault(); | ||||
|         // Note that we may have an href here, but we trust the stream id more,
 | ||||
|         // so we re-encode the hash.
 | ||||
|         const stream_id = Number.parseInt($(this).attr("data-stream-id"), 10); | ||||
|         const stream_id = Number.parseInt($(this).attr("data-stream-id")!, 10); | ||||
|         if (stream_id) { | ||||
|             browser_history.go_to_location(hash_util.by_stream_url(stream_id)); | ||||
|             return; | ||||
|         } | ||||
|         window.location.href = $(this).attr("href"); | ||||
|         window.location.href = this.href; | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("click", "#scroll-to-bottom-button-clickable-area", (e) => { | ||||
| @@ -310,7 +313,8 @@ export function initialize() { | ||||
|         const $row = message_lists.current.get_row(rows.id($(this).closest(".message_row"))); | ||||
|         const message_id = rows.id($row); | ||||
|         const message = message_lists.current.get(message_id); | ||||
|         stream_popover.build_move_topic_to_stream_popover( | ||||
|         assert(message?.type === "stream"); | ||||
|         void stream_popover.build_move_topic_to_stream_popover( | ||||
|             message.stream_id, | ||||
|             message.topic, | ||||
|             false, | ||||
| @@ -357,28 +361,36 @@ export function initialize() { | ||||
|         e.preventDefault(); | ||||
| 
 | ||||
|         const row_id = rows.id($(this).closest(".message_row")); | ||||
|         $(`#edit_form_${CSS.escape(row_id)} .file_input`).trigger("click"); | ||||
|         $(`#edit_form_${CSS.escape(`${row_id}`)} .file_input`).trigger("click"); | ||||
|     }); | ||||
|     $("body").on("focus", ".message_edit_form .message_edit_content", (e) => { | ||||
|         compose_state.set_last_focused_compose_type_input(e.target); | ||||
|     $("body").on( | ||||
|         "focus", | ||||
|         ".message_edit_form textarea.message_edit_content", | ||||
|         function (this: HTMLTextAreaElement, _event) { | ||||
|             compose_state.set_last_focused_compose_type_input(this); | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     $("body").on("click", ".message_edit_form .markdown_preview", function (this: HTMLElement, e) { | ||||
|         e.preventDefault(); | ||||
|         message_edit.show_preview_area($(this)); | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("click", ".message_edit_form .markdown_preview", (e) => { | ||||
|         e.preventDefault(); | ||||
|         message_edit.show_preview_area($(e.target)); | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("click", ".message_edit_form .undo_markdown_preview", (e) => { | ||||
|         e.preventDefault(); | ||||
|         message_edit.clear_preview_area($(e.target)); | ||||
|     }); | ||||
|     $("body").on( | ||||
|         "click", | ||||
|         ".message_edit_form .undo_markdown_preview", | ||||
|         function (this: HTMLElement, e) { | ||||
|             e.preventDefault(); | ||||
|             message_edit.clear_preview_area($(this)); | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     // RESOLVED TOPICS
 | ||||
|     $("body").on("click", ".message_header .on_hover_topic_resolve", (e) => { | ||||
|         e.stopPropagation(); | ||||
|         const $recipient_row = $(e.target).closest(".recipient_row"); | ||||
|         const message_id = rows.id_for_recipient_row($recipient_row); | ||||
|         const topic_name = $(e.target).attr("data-topic-name"); | ||||
|         const topic_name = $(e.target).attr("data-topic-name")!; | ||||
|         message_edit.toggle_resolve_topic(message_id, topic_name, false, $recipient_row); | ||||
|     }); | ||||
| 
 | ||||
| @@ -386,35 +398,39 @@ export function initialize() { | ||||
|         e.stopPropagation(); | ||||
|         const $recipient_row = $(e.target).closest(".recipient_row"); | ||||
|         const message_id = rows.id_for_recipient_row($recipient_row); | ||||
|         const topic_name = $(e.target).attr("data-topic-name"); | ||||
|         const topic_name = $(e.target).attr("data-topic-name")!; | ||||
|         message_edit.toggle_resolve_topic(message_id, topic_name, false, $recipient_row); | ||||
|     }); | ||||
| 
 | ||||
|     // RECIPIENT BARS
 | ||||
| 
 | ||||
|     function get_row_id_for_narrowing(narrow_link_elem) { | ||||
|     function get_row_id_for_narrowing(narrow_link_elem: HTMLElement): number { | ||||
|         const $group = rows.get_closest_group(narrow_link_elem); | ||||
|         const msg_id = rows.id_for_recipient_row($group); | ||||
| 
 | ||||
|         assert(message_lists.current !== undefined); | ||||
|         const nearest = message_lists.current.get(msg_id); | ||||
|         const nearest = message_lists.current.get(msg_id)!; | ||||
|         const selected = message_lists.current.selected_message(); | ||||
|         if (util.same_recipient(nearest, selected)) { | ||||
|         if (selected !== undefined && util.same_recipient(nearest, selected)) { | ||||
|             return selected.id; | ||||
|         } | ||||
|         return nearest.id; | ||||
|     } | ||||
| 
 | ||||
|     $("#message_feed_container").on("click", ".narrows_by_recipient", function (e) { | ||||
|         if (e.metaKey || e.ctrlKey || e.shiftKey) { | ||||
|             return; | ||||
|         } | ||||
|         e.preventDefault(); | ||||
|         const row_id = get_row_id_for_narrowing(this); | ||||
|         message_view.narrow_by_recipient(row_id, {trigger: "message header"}); | ||||
|     }); | ||||
|     $("#message_feed_container").on( | ||||
|         "click", | ||||
|         ".narrows_by_recipient", | ||||
|         function (this: HTMLElement, e) { | ||||
|             if (e.metaKey || e.ctrlKey || e.shiftKey) { | ||||
|                 return; | ||||
|             } | ||||
|             e.preventDefault(); | ||||
|             const row_id = get_row_id_for_narrowing(this); | ||||
|             message_view.narrow_by_recipient(row_id, {trigger: "message header"}); | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     $("#message_feed_container").on("click", ".narrows_by_topic", function (e) { | ||||
|     $("#message_feed_container").on("click", ".narrows_by_topic", function (this: HTMLElement, e) { | ||||
|         if (e.metaKey || e.ctrlKey || e.shiftKey) { | ||||
|             return; | ||||
|         } | ||||
| @@ -455,22 +471,25 @@ export function initialize() { | ||||
| 
 | ||||
|     // Doesn't show tooltip on touch devices.
 | ||||
|     function do_render_buddy_list_tooltip( | ||||
|         $elem, | ||||
|         title_data, | ||||
|         get_target_node, | ||||
|         check_reference_removed, | ||||
|         $elem: JQuery, | ||||
|         title_data: buddy_data.TitleData, | ||||
|         get_target_node?: (tippy_instance: tippy.Instance) => HTMLElement, | ||||
|         check_reference_removed?: ( | ||||
|             mutation: MutationRecord, | ||||
|             tippy_instance: tippy.Instance, | ||||
|         ) => boolean, | ||||
|         subtree = false, | ||||
|         parent_element_to_append = null, | ||||
|         parent_element_to_append: HTMLElement | null = null, | ||||
|         is_custom_observer_needed = true, | ||||
|     ) { | ||||
|         let placement = "left"; | ||||
|         let observer; | ||||
|     ): void { | ||||
|         let placement: tippy.Placement = "left"; | ||||
|         let observer: MutationObserver; | ||||
|         if (window.innerWidth < media_breakpoints_num.md) { | ||||
|             // On small devices display tooltips based on available space.
 | ||||
|             // This will default to "bottom" placement for this tooltip.
 | ||||
|             placement = "auto"; | ||||
|         } | ||||
|         tippy.default($elem[0], { | ||||
|         tippy.default(util.the($elem), { | ||||
|             // Quickly display and hide right sidebar tooltips
 | ||||
|             // so that they don't stick and overlap with
 | ||||
|             // each other.
 | ||||
| @@ -494,12 +513,14 @@ export function initialize() { | ||||
|                 if (!is_custom_observer_needed) { | ||||
|                     return; | ||||
|                 } | ||||
|                 assert(get_target_node !== undefined); | ||||
|                 assert(check_reference_removed !== undefined); | ||||
|                 // We cannot use MutationObserver directly on the reference element because
 | ||||
|                 // it will be removed and we need to attach it on an element which will remain in the DOM.
 | ||||
|                 const target_node = get_target_node(instance); | ||||
|                 // We only need to know if any of the `li` elements were removed.
 | ||||
|                 const config = {attributes: false, childList: true, subtree}; | ||||
|                 const callback = function (mutationsList) { | ||||
|                 const callback: MutationCallback = function (mutationsList) { | ||||
|                     for (const mutation of mutationsList) { | ||||
|                         // Hide instance if reference is in the removed node list.
 | ||||
|                         if (check_reference_removed(mutation, instance)) { | ||||
| @@ -510,7 +531,7 @@ export function initialize() { | ||||
|                 observer = new MutationObserver(callback); | ||||
|                 observer.observe(target_node, config); | ||||
|             }, | ||||
|             appendTo: () => parent_element_to_append || document.body, | ||||
|             appendTo: () => parent_element_to_append ?? document.body, | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| @@ -519,15 +540,18 @@ export function initialize() { | ||||
|         e.stopPropagation(); | ||||
|         const user_id_string = $(e.currentTarget) | ||||
|             .closest(".user_sidebar_entry") | ||||
|             .attr("data-user-id"); | ||||
|             .attr("data-user-id")!; | ||||
|         const title_data = buddy_data.get_title_data(user_id_string, false); | ||||
| 
 | ||||
|         // `target_node` is the `ul` element since it stays in DOM even after updates.
 | ||||
|         function get_target_node() { | ||||
|             return $(e.target).parents(".buddy-list-section")[0]; | ||||
|         function get_target_node(): HTMLElement { | ||||
|             return util.the($(e.target).parents(".buddy-list-section")); | ||||
|         } | ||||
| 
 | ||||
|         function check_reference_removed(mutation, instance) { | ||||
|         function check_reference_removed( | ||||
|             mutation: MutationRecord, | ||||
|             instance: tippy.Instance, | ||||
|         ): boolean { | ||||
|             return Array.prototype.includes.call( | ||||
|                 mutation.removedNodes, | ||||
|                 instance.reference.parentElement, | ||||
| @@ -546,8 +570,9 @@ export function initialize() { | ||||
|         */ | ||||
|         $(".user_sidebar_entry .status-emoji-name").off("mouseenter").off("mouseleave"); | ||||
|         $(".user_sidebar_entry .status-emoji-name").on("mouseenter", () => { | ||||
|             const instance = $elem[0]._tippy; | ||||
|             if (instance && instance.state.isVisible) { | ||||
|             const element: tippy.ReferenceElement = util.the($elem); | ||||
|             const instance = element._tippy; | ||||
|             if (instance?.state.isVisible) { | ||||
|                 instance.destroy(); | ||||
|             } | ||||
|         }); | ||||
| @@ -562,22 +587,25 @@ export function initialize() { | ||||
|     }); | ||||
| 
 | ||||
|     // DIRECT MESSAGE LIST TOOLTIPS (not displayed on touch devices)
 | ||||
|     $("body").on("mouseenter", ".dm-user-status", (e) => { | ||||
|     $("body").on("mouseenter", ".dm-user-status", function (this: HTMLElement, e) { | ||||
|         e.stopPropagation(); | ||||
|         const $elem = $(e.currentTarget); | ||||
|         const user_ids_string = $elem.attr("data-user-ids-string"); | ||||
|         const $elem = $(this); | ||||
|         const user_ids_string = $elem.attr("data-user-ids-string")!; | ||||
|         // This converts from 'true' in the DOM to true.
 | ||||
|         const is_group = JSON.parse($elem.attr("data-is-group")); | ||||
|         const is_group = z.boolean().parse(JSON.parse($elem.attr("data-is-group")!)); | ||||
| 
 | ||||
|         const title_data = buddy_data.get_title_data(user_ids_string, is_group); | ||||
| 
 | ||||
|         // Since anything inside `#left_sidebar_scroll_container` can be replaced, it is our target node here.
 | ||||
|         function get_target_node() { | ||||
|             return document.querySelector("#left_sidebar_scroll_container"); | ||||
|         function get_target_node(): HTMLElement { | ||||
|             return document.querySelector("#left_sidebar_scroll_container")!; | ||||
|         } | ||||
| 
 | ||||
|         // Whole list is just replaced, so we need to check for that.
 | ||||
|         function check_reference_removed(mutation, instance) { | ||||
|         function check_reference_removed( | ||||
|             mutation: MutationRecord, | ||||
|             instance: tippy.Instance, | ||||
|         ): boolean { | ||||
|             return Array.prototype.includes.call( | ||||
|                 mutation.removedNodes, | ||||
|                 $(instance.reference).parents(".dm-list")[0], | ||||
| @@ -600,8 +628,9 @@ export function initialize() { | ||||
|         */ | ||||
|         $(".dm-user-status .status-emoji-name").off("mouseenter").off("mouseleave"); | ||||
|         $(".dm-user-status .status-emoji-name").on("mouseenter", () => { | ||||
|             const instance = $elem[0]._tippy; | ||||
|             if (instance && instance.state.isVisible) { | ||||
|             const element: tippy.ReferenceElement = util.the($elem); | ||||
|             const instance = element._tippy; | ||||
|             if (instance?.state.isVisible) { | ||||
|                 instance.destroy(); | ||||
|             } | ||||
|         }); | ||||
| @@ -616,10 +645,9 @@ export function initialize() { | ||||
|     }); | ||||
| 
 | ||||
|     // Left sidebar channel rows
 | ||||
|     $("body").on("click", ".channel-new-topic-button", (e) => { | ||||
|     $("body").on("click", ".channel-new-topic-button", function (this: HTMLElement, e) { | ||||
|         e.stopPropagation(); | ||||
|         const elem = e.currentTarget; | ||||
|         const stream_id = Number.parseInt(elem.dataset.streamId, 10); | ||||
|         const stream_id = Number.parseInt(this.dataset.streamId!, 10); | ||||
|         compose_actions.start({ | ||||
|             message_type: "stream", | ||||
|             stream_id, | ||||
| @@ -630,18 +658,29 @@ export function initialize() { | ||||
|     }); | ||||
| 
 | ||||
|     // Recent conversations direct messages (Not displayed on small widths)
 | ||||
|     $("body").on("mouseenter", ".recent_topic_stream .pm_status_icon", (e) => { | ||||
|         e.stopPropagation(); | ||||
|         const $elem = $(e.currentTarget); | ||||
|         const user_ids_string = $elem.attr("data-user-ids-string"); | ||||
|         // Don't show tooltip for group direct messages.
 | ||||
|         if (!user_ids_string || user_ids_string.split(",").length !== 1) { | ||||
|             return; | ||||
|         } | ||||
|         const title_data = recent_view_ui.get_pm_tooltip_data(user_ids_string); | ||||
|         const noop = () => {}; | ||||
|         do_render_buddy_list_tooltip($elem, title_data, noop, noop, false, undefined, false); | ||||
|     }); | ||||
|     $("body").on( | ||||
|         "mouseenter", | ||||
|         ".recent_topic_stream .pm_status_icon", | ||||
|         function (this: HTMLElement, e) { | ||||
|             e.stopPropagation(); | ||||
|             const $elem = $(this); | ||||
|             const user_ids_string = $elem.attr("data-user-ids-string"); | ||||
|             // Don't show tooltip for group direct messages.
 | ||||
|             if (!user_ids_string || user_ids_string.split(",").length !== 1) { | ||||
|                 return; | ||||
|             } | ||||
|             const title_data = recent_view_ui.get_pm_tooltip_data(user_ids_string); | ||||
|             do_render_buddy_list_tooltip( | ||||
|                 $elem, | ||||
|                 title_data, | ||||
|                 undefined, | ||||
|                 undefined, | ||||
|                 false, | ||||
|                 undefined, | ||||
|                 false, | ||||
|             ); | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     // MISC
 | ||||
| 
 | ||||
| @@ -652,7 +691,7 @@ export function initialize() { | ||||
|             "#buddy-list-users-matching-view", | ||||
|         ].join(", "); | ||||
| 
 | ||||
|         $(sel).on("click", "a", function () { | ||||
|         $(sel).on("click", "a", function (this: HTMLElement) { | ||||
|             this.blur(); | ||||
|         }); | ||||
|     } | ||||
| @@ -687,11 +726,11 @@ export function initialize() { | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("click", "[data-overlay-trigger]", function () { | ||||
|         const target = $(this).attr("data-overlay-trigger"); | ||||
|         const target = $(this).attr("data-overlay-trigger")!; | ||||
|         browser_history.go_to_location(target); | ||||
|     }); | ||||
| 
 | ||||
|     function handle_compose_click(e) { | ||||
|     function handle_compose_click(e: JQuery.ClickEvent): void { | ||||
|         const $target = $(e.target); | ||||
|         // Emoji clicks should be handled by their own click handler in emoji_picker.js
 | ||||
|         if ($target.is(".emoji_map, img.emoji, .drag, .compose_gif_icon, .compose_control_menu")) { | ||||
| @@ -724,9 +763,13 @@ export function initialize() { | ||||
|         compose_actions.cancel(); | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("focus", "#compose-textarea", (e) => { | ||||
|         compose_state.set_last_focused_compose_type_input(e.target); | ||||
|     }); | ||||
|     $("body").on( | ||||
|         "focus", | ||||
|         "textarea#compose-textarea", | ||||
|         function (this: HTMLTextAreaElement, _event: JQuery.Event) { | ||||
|             compose_state.set_last_focused_compose_type_input(this); | ||||
|         }, | ||||
|     ); | ||||
| 
 | ||||
|     // LEFT SIDEBAR
 | ||||
| 
 | ||||
| @@ -789,18 +832,22 @@ export function initialize() { | ||||
| 
 | ||||
|     // Chrome focuses an element when dragging it which can be confusing when
 | ||||
|     // users involuntarily drag something and we show them the focus outline.
 | ||||
|     $("body").on("dragstart", "a", (e) => e.target.blur()); | ||||
|     $("body").on("dragstart", "a", function (this: HTMLElement) { | ||||
|         this.blur(); | ||||
|     }); | ||||
| 
 | ||||
|     // Don't focus links on middle click.
 | ||||
|     $("body").on("mouseup", "a", (e) => { | ||||
|     $("body").on("mouseup", "a", function (this: HTMLElement, e) { | ||||
|         if (e.button === 1) { | ||||
|             // middle click
 | ||||
|             e.target.blur(); | ||||
|             this.blur(); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // Don't focus links on context menu.
 | ||||
|     $("body").on("contextmenu", "a", (e) => e.target.blur()); | ||||
|     $("body").on("contextmenu", "a", function (this: HTMLElement) { | ||||
|         this.blur(); | ||||
|     }); | ||||
| 
 | ||||
|     $("body").on("click", ".language_selection_widget button", (e) => { | ||||
|         e.preventDefault(); | ||||
| @@ -844,7 +891,7 @@ export function initialize() { | ||||
|                 $("textarea#compose-textarea").trigger("focus"); | ||||
|                 return; | ||||
|             } else if ( | ||||
|                 !window.getSelection().toString() && | ||||
|                 !window.getSelection()?.toString() && | ||||
|                 // Clicking any input or text area should not close
 | ||||
|                 // the compose box; this means using the sidebar
 | ||||
|                 // filters or search widgets won't unnecessarily close
 | ||||
| @@ -82,7 +82,7 @@ have a target of "_blank". | ||||
|  | ||||
| The "info:" items use our info overlay system | ||||
| in web/src/info_overlay.ts.  They are dispatched | ||||
| using a click handler in web/src/click_handlers.js. | ||||
| using a click handler in web/src/click_handlers.ts. | ||||
| The click handler uses "[data-overlay-trigger]" as | ||||
| the selector and then calls browser_history.go_to_location. | ||||
| */ | ||||
|   | ||||
| @@ -633,7 +633,7 @@ export function initialize(): void { | ||||
|         /* | ||||
|             Status emoji tooltips for most locations in the app. This | ||||
|             basic tooltip logic is overridden by separate logic in | ||||
|             click_handlers.js for the left and right sidebars, to | ||||
|             click_handlers.ts for the left and right sidebars, to | ||||
|             avoid problematic interactions with the main tooltips for | ||||
|             those regions. | ||||
|         */ | ||||
|   | ||||
| @@ -19,7 +19,7 @@ import * as audible_notifications from "./audible_notifications.ts"; | ||||
| import * as blueslip from "./blueslip.ts"; | ||||
| import * as bot_data from "./bot_data.ts"; | ||||
| import * as channel from "./channel.ts"; | ||||
| import * as click_handlers from "./click_handlers.js"; | ||||
| import * as click_handlers from "./click_handlers.ts"; | ||||
| import * as common from "./common.ts"; | ||||
| import * as compose from "./compose.js"; | ||||
| import * as compose_closed_ui from "./compose_closed_ui.ts"; | ||||
|   | ||||
| @@ -376,7 +376,7 @@ test("handlers", ({override, override_rewire, mock_template}) => { | ||||
|  | ||||
|     (function test_click_handler() { | ||||
|         init(); | ||||
|         // We wire up the click handler in click_handlers.js, | ||||
|         // We wire up the click handler in click_handlers.ts, | ||||
|         // so this just tests the called function. | ||||
|         narrowed = false; | ||||
|         activity_ui.narrow_for_user({$li: $alice_li}); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user