typeahead: Pass query to sorter instead of using hacky this.

This commit is contained in:
evykassirer 2024-03-24 20:40:21 -07:00 committed by Tim Abbott
parent 9fc6793809
commit f0578c318c
7 changed files with 27 additions and 28 deletions

View File

@ -192,7 +192,7 @@ class Typeahead<ItemType extends string | object> {
input_element: InputElement;
items: number;
matcher: (item: ItemType, query: string) => boolean;
sorter: (items: ItemType[]) => ItemType[];
sorter: (items: ItemType[], query: string) => ItemType[];
highlighter_html: (item: ItemType, query: string) => string | undefined;
updater: (
item: ItemType,
@ -384,7 +384,7 @@ class Typeahead<ItemType extends string | object> {
process(items: ItemType[]): this {
const matching_items = $.grep(items, (item) => this.matcher(item, this.query));
const final_items = this.sorter(matching_items);
const final_items = this.sorter(matching_items, this.query);
if (!final_items.length) {
return this.shown ? this.hide() : this;
@ -705,7 +705,7 @@ type TypeaheadOptions<ItemType> = {
openInputFieldOnKeyUp?: () => void;
option_label?: (matching_items: ItemType[], item: ItemType) => string | false;
parentElement?: string;
sorter: (items: ItemType[]) => ItemType[];
sorter: (items: ItemType[], query: string) => ItemType[];
stopAdvance?: boolean;
tabIsEnter?: boolean;
trigger_selection?: (event: JQuery.KeyDownEvent) => boolean;

View File

@ -1118,10 +1118,10 @@ export function initialize_topic_edit_typeahead(form_field, stream_name, dropup)
highlighter_html(item) {
return typeahead_helper.render_typeahead_item({primary: item});
},
sorter(items) {
const sorted = typeahead_helper.sorter(this.query, items, (x) => x);
if (sorted.length > 0 && !sorted.includes(this.query)) {
sorted.unshift(this.query);
sorter(items, query) {
const sorted = typeahead_helper.sorter(query, items, (x) => x);
if (sorted.length > 0 && !sorted.includes(query)) {
sorted.unshift(query);
}
return sorted;
},
@ -1207,10 +1207,10 @@ export function initialize({on_enter_send}) {
highlighter_html(item) {
return typeahead_helper.render_typeahead_item({primary: item});
},
sorter(items) {
const sorted = typeahead_helper.sorter(this.query, items, (x) => x);
if (sorted.length > 0 && !sorted.includes(this.query)) {
sorted.unshift(this.query);
sorter(items, query) {
const sorted = typeahead_helper.sorter(query, items, (x) => x);
if (sorted.length > 0 && !sorted.includes(query)) {
sorted.unshift(query);
}
return sorted;
},

View File

@ -176,8 +176,8 @@ export function initialize_custom_pronouns_type_fields(element_id) {
source() {
return commonly_used_pronouns;
},
sorter(items) {
return bootstrap_typeahead.defaultSorter(items, this.query);
sorter(items, query) {
return bootstrap_typeahead.defaultSorter(items, query);
},
highlighter_html(item) {
return typeahead_helper.render_typeahead_item({primary: item});

View File

@ -99,8 +99,7 @@ export function set_up($input, pills, opts) {
}
return matches;
},
sorter(matches) {
const query = this.query;
sorter(matches, query) {
if (include_streams(query)) {
return typeahead_helper.sort_streams(matches, query.trim().slice(1));
}

View File

@ -170,8 +170,8 @@ function build_page() {
const q = query.trim().toLowerCase();
return item.toLowerCase().startsWith(q);
},
sorter(items) {
return bootstrap_typeahead.defaultSorter(items, this.query);
sorter(items, query) {
return bootstrap_typeahead.defaultSorter(items, query);
},
});

View File

@ -796,28 +796,28 @@ test("initialize", ({override, override_rewire, mock_template}) => {
// Notice that alphabetical sorting isn't managed by this sorter,
// it is a result of the topics already being sorted after adding
// them with add_topic().
options.query = "furniture";
actual_value = options.sorter(["furniture"]);
let query = "furniture";
actual_value = options.sorter(["furniture"], query);
expected_value = ["furniture"];
assert.deepEqual(actual_value, expected_value);
// A literal match at the beginning of an element puts it at the top.
options.query = "ice";
actual_value = options.sorter(["even more ice", "ice", "more ice"]);
query = "ice";
actual_value = options.sorter(["even more ice", "ice", "more ice"], query);
expected_value = ["ice", "even more ice", "more ice"];
assert.deepEqual(actual_value, expected_value);
// The sorter should return the query as the first element if there
// isn't a topic with such name.
// This only happens if typeahead is providing other suggestions.
options.query = "e"; // Letter present in "furniture" and "ice"
actual_value = options.sorter(["furniture", "ice"]);
query = "e"; // Letter present in "furniture" and "ice"
actual_value = options.sorter(["furniture", "ice"], query);
expected_value = ["e", "furniture", "ice"];
assert.deepEqual(actual_value, expected_value);
// Suggest the query if this query doesn't match any existing topic.
options.query = "non-existing-topic";
actual_value = options.sorter([]);
query = "non-existing-topic";
actual_value = options.sorter([], query);
expected_value = [];
assert.deepEqual(actual_value, expected_value);

View File

@ -233,17 +233,17 @@ run_test("set_up", ({mock_template, override}) => {
(function test_sorter() {
if (opts.stream) {
sort_streams_called = false;
config.sorter.call(fake_stream_this);
config.sorter([], fake_stream_this.query);
assert.ok(sort_streams_called);
}
if (opts.user_group) {
sort_recipients_called = false;
config.sorter.call(fake_group_this, [testers]);
config.sorter([testers], fake_group_this.query);
assert.ok(sort_recipients_called);
}
if (opts.user) {
sort_recipients_called = false;
config.sorter.call(fake_person_this, [me]);
config.sorter([me], fake_person_this.query);
assert.ok(sort_recipients_called);
}
})();