typeahead: Pass input element to source instead of using hacky this.

This commit is contained in:
evykassirer 2024-03-29 17:35:01 -07:00 committed by Tim Abbott
parent bdf4449ebf
commit fc3ab45b46
3 changed files with 20 additions and 37 deletions

View File

@ -203,7 +203,7 @@ class Typeahead<ItemType extends string | object> {
$container: JQuery;
$menu: JQuery;
$header: JQuery;
source: (query: string) => ItemType[];
source: (query: string, input_element: InputElement) => ItemType[];
dropup: boolean;
fixed: boolean;
automated: () => boolean;
@ -377,7 +377,7 @@ class Typeahead<ItemType extends string | object> {
return this.shown ? this.hide() : this;
}
const items = this.source(this.query);
const items = this.source(this.query, this.input_element);
if (!items && this.shown) {
this.hide();
@ -694,7 +694,7 @@ class Typeahead<ItemType extends string | object> {
type TypeaheadOptions<ItemType> = {
highlighter_html: (item: ItemType, query: string) => string | undefined;
items: number;
source: (query: string) => ItemType[];
source: (query: string, input_element: InputElement) => ItemType[];
// optional options
advanceKeyCodes?: number[];
automated?: () => boolean;

View File

@ -600,9 +600,9 @@ export function get_person_suggestions(query, opts) {
});
}
export function get_stream_topic_data(hacky_this) {
export function get_stream_topic_data(input_element) {
const opts = {};
const $message_row = hacky_this.input_element.$element.closest(".message_row");
const $message_row = input_element.$element.closest(".message_row");
if ($message_row.length === 1) {
// we are editing a message so we try to use its keys.
const msg = message_store.get(rows.id($message_row));
@ -617,7 +617,7 @@ export function get_stream_topic_data(hacky_this) {
return opts;
}
export function get_sorted_filtered_items(query) {
export function get_sorted_filtered_items(query, input_element) {
/*
This is just a "glue" function to work
around bootstrap. We want to control these
@ -641,14 +641,13 @@ export function get_sorted_filtered_items(query) {
several years ago.)
*/
const fetcher = get_candidates.bind(this);
const big_results = fetcher(query);
const big_results = get_candidates(query, input_element);
if (!big_results) {
return false;
}
const opts = get_stream_topic_data(this);
const opts = get_stream_topic_data(input_element);
if (completing === "mention" || completing === "silent_mention") {
return filter_and_sort_mentions(big_results.is_silent, token, opts);
@ -678,8 +677,8 @@ const ALLOWED_MARKDOWN_FEATURES = {
timestamp: true,
};
export function get_candidates(query) {
const split = split_at_cursor(query, this.input_element.$element);
export function get_candidates(query, input_element) {
const split = split_at_cursor(query, input_element.$element);
let current_token = tokenize_compose_str(split[0]);
if (current_token === "") {
return false;

View File

@ -987,19 +987,17 @@ test("initialize", ({override, override_rewire, mock_template}) => {
// For now we only test that get_sorted_filtered_items has been
// properly set as the .source(). All its features are tested later on
// in test_begins_typeahead().
const fake_this = {
input_element: {
$element: {},
type: "input",
},
const input_element = {
$element: {},
type: "input",
};
let caret_called = false;
fake_this.input_element.$element.caret = () => {
input_element.$element.caret = () => {
caret_called = true;
return 7;
};
fake_this.input_element.$element.closest = () => [];
let actual_value = options.source.call(fake_this, "test #s");
input_element.$element.closest = () => [];
let actual_value = options.source("test #s", input_element);
assert.deepEqual(sorted_names_from(actual_value), ["Sweden", "The Netherlands"]);
assert.ok(caret_called);
@ -1330,29 +1328,15 @@ test("begins_typeahead", ({override, override_rewire}) => {
});
override(stream_topic_history_util, "get_server_history", noop);
const begin_typehead_this = {
input_element: {
$element: {},
type: "input",
},
options: {
completions: {
emoji: true,
mention: true,
silent_mention: true,
slash: true,
stream: true,
syntax: true,
topic: true,
timestamp: true,
},
},
const input_element = {
$element: {},
type: "input",
};
function get_values(input, rest) {
// Stub out split_at_cursor that uses $(':focus')
override_rewire(ct, "split_at_cursor", () => [input, rest]);
const values = ct.get_candidates.call(begin_typehead_this, input);
const values = ct.get_candidates(input, input_element);
return values;
}