list_cursor: Convert list_cursor to an ES6 class ListCursor.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-07-22 16:48:16 -07:00 committed by Tim Abbott
parent 9d90ae0e69
commit 2e94914be4
7 changed files with 82 additions and 81 deletions

View File

@ -102,6 +102,7 @@
"Filter": false, "Filter": false,
"Handlebars": false, "Handlebars": false,
"LightboxCanvas": false, "LightboxCanvas": false,
"ListCursor": false,
"MessageListData": false, "MessageListData": false,
"MessageListView": false, "MessageListView": false,
"Plotly": false, "Plotly": false,
@ -162,7 +163,6 @@
"jQuery": false, "jQuery": false,
"keydown_util": false, "keydown_util": false,
"lightbox": false, "lightbox": false,
"list_cursor": false,
"list_render": false, "list_render": false,
"list_util": false, "list_util": false,
"loading": false, "loading": false,

View File

@ -2,7 +2,7 @@ zrequire("list_cursor");
run_test("config errors", () => { run_test("config errors", () => {
blueslip.expect("error", "Programming error"); blueslip.expect("error", "Programming error");
list_cursor({}); new ListCursor({});
}); });
function basic_conf() { function basic_conf() {
@ -25,7 +25,7 @@ function basic_conf() {
run_test("misc errors", () => { run_test("misc errors", () => {
const conf = basic_conf(); const conf = basic_conf();
const cursor = list_cursor(conf); const cursor = new ListCursor(conf);
// Test that we just ignore empty // Test that we just ignore empty
// lists for unknown keys. // lists for unknown keys.
@ -37,10 +37,10 @@ run_test("misc errors", () => {
cursor.get_row("nada"); cursor.get_row("nada");
blueslip.expect("error", "Caller is not checking keys for list_cursor.go_to"); blueslip.expect("error", "Caller is not checking keys for ListCursor.go_to");
cursor.go_to(undefined); cursor.go_to(undefined);
blueslip.expect("error", "Cannot highlight key for list_cursor: nada"); blueslip.expect("error", "Cannot highlight key for ListCursor: nada");
cursor.go_to("nada"); cursor.go_to("nada");
cursor.prev(); cursor.prev();
@ -49,7 +49,7 @@ run_test("misc errors", () => {
run_test("single item list", () => { run_test("single item list", () => {
const conf = basic_conf(); const conf = basic_conf();
const cursor = list_cursor(conf); const cursor = new ListCursor(conf);
const valid_key = "42"; const valid_key = "42";
const li_stub = { const li_stub = {

View File

@ -288,7 +288,7 @@ function keydown_enter_key() {
} }
exports.set_cursor_and_filter = function () { exports.set_cursor_and_filter = function () {
exports.user_cursor = list_cursor({ exports.user_cursor = new ListCursor({
list: buddy_list, list: buddy_list,
highlight_class: "highlighted_user", highlight_class: "highlighted_user",
}); });
@ -296,12 +296,12 @@ exports.set_cursor_and_filter = function () {
exports.user_filter = new UserSearch({ exports.user_filter = new UserSearch({
update_list: update_users_for_search, update_list: update_users_for_search,
reset_items: exports.reset_users, reset_items: exports.reset_users,
on_focus: exports.user_cursor.reset, on_focus: () => exports.user_cursor.reset(),
}); });
const $input = exports.user_filter.input_field(); const $input = exports.user_filter.input_field();
$input.on("blur", exports.user_cursor.clear); $input.on("blur", () => exports.user_cursor.clear());
keydown_util.handle({ keydown_util.handle({
elem: $input, elem: $input,

View File

@ -192,7 +192,7 @@ class BuddyList extends BuddyListConf {
const pos = this.keys.indexOf(key); const pos = this.keys.indexOf(key);
if (pos < 0) { if (pos < 0) {
// TODO: See list_cursor.get_row() for why this is // TODO: See ListCursor.get_row() for why this is
// a bit janky now. // a bit janky now.
return []; return [];
} }

View File

@ -6,6 +6,7 @@
declare let FetchStatus: any; declare let FetchStatus: any;
declare let Filter: any; declare let Filter: any;
declare let LightboxCanvas: any; declare let LightboxCanvas: any;
declare let ListCursor: any;
declare let MessageListData: any; declare let MessageListData: any;
declare let MessageListView: any; declare let MessageListView: any;
declare let UserSearch: any; declare let UserSearch: any;
@ -59,7 +60,6 @@ declare let input_pill: any;
declare let invite: any; declare let invite: any;
declare let keydown_util: any; declare let keydown_util: any;
declare let lightbox: any; declare let lightbox: any;
declare let list_cursor: any;
declare let list_render: any; declare let list_render: any;
declare let list_util: any; declare let list_util: any;
declare let loading: any; declare let loading: any;

View File

@ -1,35 +1,38 @@
const list_cursor = function (opts) { class ListCursor {
const self = {}; constructor({highlight_class, list}) {
const config_ok =
const config_ok = highlight_class &&
opts.highlight_class && list &&
opts.list && list.scroll_container_sel &&
opts.list.scroll_container_sel && list.find_li &&
opts.list.find_li && list.first_key &&
opts.list.first_key && list.prev_key &&
opts.list.prev_key && list.next_key;
opts.list.next_key; if (!config_ok) {
if (!config_ok) { blueslip.error("Programming error");
blueslip.error("Programming error");
return;
}
self.clear = function () {
if (self.curr_key === undefined) {
return; return;
} }
const row = self.get_row(self.curr_key);
this.highlight_class = highlight_class;
this.list = list;
}
clear() {
if (this.curr_key === undefined) {
return;
}
const row = this.get_row(this.curr_key);
if (row) { if (row) {
row.clear(); row.clear();
} }
self.curr_key = undefined; this.curr_key = undefined;
}; }
self.get_key = function () { get_key() {
return self.curr_key; return this.curr_key;
}; }
self.get_row = function (key) { get_row(key) {
// TODO: The list class should probably do more of the work // TODO: The list class should probably do more of the work
// here, so we're not so coupled to jQuery, and // here, so we're not so coupled to jQuery, and
// so we instead just get back a widget we can say // so we instead just get back a widget we can say
@ -41,7 +44,7 @@ const list_cursor = function (opts) {
return; return;
} }
const li = opts.list.find_li({ const li = this.list.find_li({
key, key,
force_render: true, force_render: true,
}); });
@ -51,91 +54,89 @@ const list_cursor = function (opts) {
} }
return { return {
highlight() { highlight: () => {
li.addClass(opts.highlight_class); li.addClass(this.highlight_class);
self.adjust_scroll(li); this.adjust_scroll(li);
}, },
clear() { clear: () => {
li.removeClass(opts.highlight_class); li.removeClass(this.highlight_class);
}, },
}; };
}; }
self.adjust_scroll = function (li) { adjust_scroll(li) {
const scroll_container = $(opts.list.scroll_container_sel); const scroll_container = $(this.list.scroll_container_sel);
scroll_util.scroll_element_into_container(li, scroll_container); scroll_util.scroll_element_into_container(li, scroll_container);
}; }
self.redraw = function () { redraw() {
// We should only call this for situations like the buddy // We should only call this for situations like the buddy
// list where we redraw the whole list without necessarily // list where we redraw the whole list without necessarily
// changing it, so we just want to re-highlight the current // changing it, so we just want to re-highlight the current
// row in the new DOM. If you are filtering, for now you // row in the new DOM. If you are filtering, for now you
// should call the 'reset()' method. // should call the 'reset()' method.
const row = self.get_row(self.curr_key); const row = this.get_row(this.curr_key);
if (row === undefined) { if (row === undefined) {
return; return;
} }
row.highlight(); row.highlight();
}; }
self.go_to = function (key) { go_to(key) {
if (key === undefined) { if (key === undefined) {
blueslip.error("Caller is not checking keys for list_cursor.go_to"); blueslip.error("Caller is not checking keys for ListCursor.go_to");
return; return;
} }
if (key === self.curr_key) { if (key === this.curr_key) {
return; return;
} }
self.clear(); this.clear();
const row = self.get_row(key); const row = this.get_row(key);
if (row === undefined) { if (row === undefined) {
blueslip.error("Cannot highlight key for list_cursor: " + key); blueslip.error("Cannot highlight key for ListCursor: " + key);
return; return;
} }
self.curr_key = key; this.curr_key = key;
row.highlight(); row.highlight();
}; }
self.reset = function () { reset() {
self.clear(); this.clear();
const key = opts.list.first_key(); const key = this.list.first_key();
if (key === undefined) { if (key === undefined) {
self.curr_key = undefined; this.curr_key = undefined;
return; return;
} }
self.go_to(key); this.go_to(key);
}; }
self.prev = function () { prev() {
if (self.curr_key === undefined) { if (this.curr_key === undefined) {
return; return;
} }
const key = opts.list.prev_key(self.curr_key); const key = this.list.prev_key(this.curr_key);
if (key === undefined) { if (key === undefined) {
// leave the current key // leave the current key
return; return;
} }
self.go_to(key); this.go_to(key);
}; }
self.next = function () { next() {
if (self.curr_key === undefined) { if (this.curr_key === undefined) {
// This is sort of a special case where we went from // This is sort of a special case where we went from
// an empty filter to having data. // an empty filter to having data.
self.reset(); this.reset();
return; return;
} }
const key = opts.list.next_key(self.curr_key); const key = this.list.next_key(this.curr_key);
if (key === undefined) { if (key === undefined) {
// leave the current key // leave the current key
return; return;
} }
self.go_to(key); this.go_to(key);
}; }
}
return self; module.exports = ListCursor;
}; window.ListCursor = ListCursor;
module.exports = list_cursor;
window.list_cursor = list_cursor;

View File

@ -509,7 +509,7 @@ exports.set_event_handlers = function () {
$(this).off("scroll"); $(this).off("scroll");
}); });
exports.stream_cursor = list_cursor({ exports.stream_cursor = new ListCursor({
list: { list: {
scroll_container_sel: "#stream-filters-container", scroll_container_sel: "#stream-filters-container",
find_li(opts) { find_li(opts) {
@ -545,7 +545,7 @@ exports.set_event_handlers = function () {
}); });
$search_input.on("click", focus_stream_filter); $search_input.on("click", focus_stream_filter);
$search_input.on("focusout", exports.stream_cursor.clear); $search_input.on("focusout", () => exports.stream_cursor.clear());
$search_input.on("input", update_streams_for_search); $search_input.on("input", update_streams_for_search);
}; };