mirror of https://github.com/zulip/zulip.git
typeahead: Pass input element to source instead of using hacky this.
This commit is contained in:
parent
bdf4449ebf
commit
fc3ab45b46
|
@ -203,7 +203,7 @@ class Typeahead<ItemType extends string | object> {
|
||||||
$container: JQuery;
|
$container: JQuery;
|
||||||
$menu: JQuery;
|
$menu: JQuery;
|
||||||
$header: JQuery;
|
$header: JQuery;
|
||||||
source: (query: string) => ItemType[];
|
source: (query: string, input_element: InputElement) => ItemType[];
|
||||||
dropup: boolean;
|
dropup: boolean;
|
||||||
fixed: boolean;
|
fixed: boolean;
|
||||||
automated: () => boolean;
|
automated: () => boolean;
|
||||||
|
@ -377,7 +377,7 @@ class Typeahead<ItemType extends string | object> {
|
||||||
return this.shown ? this.hide() : this;
|
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) {
|
if (!items && this.shown) {
|
||||||
this.hide();
|
this.hide();
|
||||||
|
@ -694,7 +694,7 @@ class Typeahead<ItemType extends string | object> {
|
||||||
type TypeaheadOptions<ItemType> = {
|
type TypeaheadOptions<ItemType> = {
|
||||||
highlighter_html: (item: ItemType, query: string) => string | undefined;
|
highlighter_html: (item: ItemType, query: string) => string | undefined;
|
||||||
items: number;
|
items: number;
|
||||||
source: (query: string) => ItemType[];
|
source: (query: string, input_element: InputElement) => ItemType[];
|
||||||
// optional options
|
// optional options
|
||||||
advanceKeyCodes?: number[];
|
advanceKeyCodes?: number[];
|
||||||
automated?: () => boolean;
|
automated?: () => boolean;
|
||||||
|
|
|
@ -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 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) {
|
if ($message_row.length === 1) {
|
||||||
// we are editing a message so we try to use its keys.
|
// we are editing a message so we try to use its keys.
|
||||||
const msg = message_store.get(rows.id($message_row));
|
const msg = message_store.get(rows.id($message_row));
|
||||||
|
@ -617,7 +617,7 @@ export function get_stream_topic_data(hacky_this) {
|
||||||
return opts;
|
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
|
This is just a "glue" function to work
|
||||||
around bootstrap. We want to control these
|
around bootstrap. We want to control these
|
||||||
|
@ -641,14 +641,13 @@ export function get_sorted_filtered_items(query) {
|
||||||
several years ago.)
|
several years ago.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fetcher = get_candidates.bind(this);
|
const big_results = get_candidates(query, input_element);
|
||||||
const big_results = fetcher(query);
|
|
||||||
|
|
||||||
if (!big_results) {
|
if (!big_results) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const opts = get_stream_topic_data(this);
|
const opts = get_stream_topic_data(input_element);
|
||||||
|
|
||||||
if (completing === "mention" || completing === "silent_mention") {
|
if (completing === "mention" || completing === "silent_mention") {
|
||||||
return filter_and_sort_mentions(big_results.is_silent, token, opts);
|
return filter_and_sort_mentions(big_results.is_silent, token, opts);
|
||||||
|
@ -678,8 +677,8 @@ const ALLOWED_MARKDOWN_FEATURES = {
|
||||||
timestamp: true,
|
timestamp: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function get_candidates(query) {
|
export function get_candidates(query, input_element) {
|
||||||
const split = split_at_cursor(query, this.input_element.$element);
|
const split = split_at_cursor(query, input_element.$element);
|
||||||
let current_token = tokenize_compose_str(split[0]);
|
let current_token = tokenize_compose_str(split[0]);
|
||||||
if (current_token === "") {
|
if (current_token === "") {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -987,19 +987,17 @@ test("initialize", ({override, override_rewire, mock_template}) => {
|
||||||
// For now we only test that get_sorted_filtered_items has been
|
// For now we only test that get_sorted_filtered_items has been
|
||||||
// properly set as the .source(). All its features are tested later on
|
// properly set as the .source(). All its features are tested later on
|
||||||
// in test_begins_typeahead().
|
// in test_begins_typeahead().
|
||||||
const fake_this = {
|
const input_element = {
|
||||||
input_element: {
|
$element: {},
|
||||||
$element: {},
|
type: "input",
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
let caret_called = false;
|
let caret_called = false;
|
||||||
fake_this.input_element.$element.caret = () => {
|
input_element.$element.caret = () => {
|
||||||
caret_called = true;
|
caret_called = true;
|
||||||
return 7;
|
return 7;
|
||||||
};
|
};
|
||||||
fake_this.input_element.$element.closest = () => [];
|
input_element.$element.closest = () => [];
|
||||||
let actual_value = options.source.call(fake_this, "test #s");
|
let actual_value = options.source("test #s", input_element);
|
||||||
assert.deepEqual(sorted_names_from(actual_value), ["Sweden", "The Netherlands"]);
|
assert.deepEqual(sorted_names_from(actual_value), ["Sweden", "The Netherlands"]);
|
||||||
assert.ok(caret_called);
|
assert.ok(caret_called);
|
||||||
|
|
||||||
|
@ -1330,29 +1328,15 @@ test("begins_typeahead", ({override, override_rewire}) => {
|
||||||
});
|
});
|
||||||
override(stream_topic_history_util, "get_server_history", noop);
|
override(stream_topic_history_util, "get_server_history", noop);
|
||||||
|
|
||||||
const begin_typehead_this = {
|
const input_element = {
|
||||||
input_element: {
|
$element: {},
|
||||||
$element: {},
|
type: "input",
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
completions: {
|
|
||||||
emoji: true,
|
|
||||||
mention: true,
|
|
||||||
silent_mention: true,
|
|
||||||
slash: true,
|
|
||||||
stream: true,
|
|
||||||
syntax: true,
|
|
||||||
topic: true,
|
|
||||||
timestamp: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function get_values(input, rest) {
|
function get_values(input, rest) {
|
||||||
// Stub out split_at_cursor that uses $(':focus')
|
// Stub out split_at_cursor that uses $(':focus')
|
||||||
override_rewire(ct, "split_at_cursor", () => [input, rest]);
|
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;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue