2021-03-11 05:43:45 +01:00
|
|
|
import $ from "jquery";
|
|
|
|
|
2021-03-16 23:38:59 +01:00
|
|
|
import * as blueslip from "./blueslip";
|
2021-02-28 00:37:30 +01:00
|
|
|
import * as scroll_util from "./scroll_util";
|
|
|
|
|
2021-02-24 05:00:20 +01:00
|
|
|
export class ListCursor {
|
2020-07-23 01:48:16 +02:00
|
|
|
constructor({highlight_class, list}) {
|
|
|
|
const config_ok =
|
|
|
|
highlight_class &&
|
|
|
|
list &&
|
|
|
|
list.scroll_container_sel &&
|
|
|
|
list.find_li &&
|
|
|
|
list.first_key &&
|
|
|
|
list.prev_key &&
|
|
|
|
list.next_key;
|
|
|
|
if (!config_ok) {
|
|
|
|
blueslip.error("Programming error");
|
|
|
|
return;
|
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
this.highlight_class = highlight_class;
|
|
|
|
this.list = list;
|
2018-04-21 14:59:03 +02:00
|
|
|
}
|
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
clear() {
|
|
|
|
if (this.curr_key === undefined) {
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
const row = this.get_row(this.curr_key);
|
2018-04-21 14:59:03 +02:00
|
|
|
if (row) {
|
|
|
|
row.clear();
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.curr_key = undefined;
|
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
get_key() {
|
|
|
|
return this.curr_key;
|
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
get_row(key) {
|
2018-04-21 14:59:03 +02:00
|
|
|
// TODO: The list class should probably do more of the work
|
|
|
|
// here, so we're not so coupled to jQuery, and
|
|
|
|
// so we instead just get back a widget we can say
|
2020-07-20 21:24:26 +02:00
|
|
|
// something like widget.trigger("select") on. This will
|
2018-04-21 14:59:03 +02:00
|
|
|
// be especially important if we do lazy rendering.
|
|
|
|
// It would also give the caller more flexibility on
|
|
|
|
// the actual styling.
|
|
|
|
if (key === undefined) {
|
2020-09-24 07:50:36 +02:00
|
|
|
return undefined;
|
2018-04-21 14:59:03 +02:00
|
|
|
}
|
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
const li = this.list.find_li({
|
2020-07-20 22:18:43 +02:00
|
|
|
key,
|
2018-07-16 15:16:33 +02:00
|
|
|
force_render: true,
|
|
|
|
});
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-06-18 16:22:48 +02:00
|
|
|
if (!li || li.length === 0) {
|
2020-09-24 07:50:36 +02:00
|
|
|
return undefined;
|
2018-04-21 14:59:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2020-07-23 01:48:16 +02:00
|
|
|
highlight: () => {
|
|
|
|
li.addClass(this.highlight_class);
|
|
|
|
this.adjust_scroll(li);
|
2018-04-21 14:59:03 +02:00
|
|
|
},
|
2020-07-23 01:48:16 +02:00
|
|
|
clear: () => {
|
|
|
|
li.removeClass(this.highlight_class);
|
2018-04-21 14:59:03 +02:00
|
|
|
},
|
|
|
|
};
|
2020-07-23 01:48:16 +02:00
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
adjust_scroll(li) {
|
|
|
|
const scroll_container = $(this.list.scroll_container_sel);
|
2018-07-26 22:13:37 +02:00
|
|
|
scroll_util.scroll_element_into_container(li, scroll_container);
|
2020-07-23 01:48:16 +02:00
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
redraw() {
|
2018-04-21 14:59:03 +02:00
|
|
|
// We should only call this for situations like the buddy
|
|
|
|
// list where we redraw the whole list without necessarily
|
|
|
|
// changing it, so we just want to re-highlight the current
|
|
|
|
// row in the new DOM. If you are filtering, for now you
|
|
|
|
// should call the 'reset()' method.
|
2020-07-23 01:48:16 +02:00
|
|
|
const row = this.get_row(this.curr_key);
|
2018-04-21 14:59:03 +02:00
|
|
|
|
|
|
|
if (row === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
row.highlight();
|
2020-07-23 01:48:16 +02:00
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
go_to(key) {
|
2018-04-21 14:59:03 +02:00
|
|
|
if (key === undefined) {
|
2020-07-23 01:48:16 +02:00
|
|
|
blueslip.error("Caller is not checking keys for ListCursor.go_to");
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
if (key === this.curr_key) {
|
2018-08-24 14:37:54 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.clear();
|
|
|
|
const row = this.get_row(key);
|
2018-04-21 14:59:03 +02:00
|
|
|
if (row === undefined) {
|
2020-07-23 01:48:16 +02:00
|
|
|
blueslip.error("Cannot highlight key for ListCursor: " + key);
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.curr_key = key;
|
2018-04-21 14:59:03 +02:00
|
|
|
row.highlight();
|
2020-07-23 01:48:16 +02:00
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
reset() {
|
|
|
|
this.clear();
|
|
|
|
const key = this.list.first_key();
|
2018-04-21 14:59:03 +02:00
|
|
|
if (key === undefined) {
|
2020-07-23 01:48:16 +02:00
|
|
|
this.curr_key = undefined;
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.go_to(key);
|
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
prev() {
|
|
|
|
if (this.curr_key === undefined) {
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
const key = this.list.prev_key(this.curr_key);
|
2018-04-21 14:59:03 +02:00
|
|
|
if (key === undefined) {
|
|
|
|
// leave the current key
|
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.go_to(key);
|
|
|
|
}
|
2018-04-21 14:59:03 +02:00
|
|
|
|
2020-07-23 01:48:16 +02:00
|
|
|
next() {
|
|
|
|
if (this.curr_key === undefined) {
|
2018-04-21 14:59:03 +02:00
|
|
|
// This is sort of a special case where we went from
|
|
|
|
// an empty filter to having data.
|
2020-07-23 01:48:16 +02:00
|
|
|
this.reset();
|
2018-04-21 14:59:03 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
const key = this.list.next_key(this.curr_key);
|
2018-04-21 14:59:03 +02:00
|
|
|
if (key === undefined) {
|
|
|
|
// leave the current key
|
|
|
|
return;
|
|
|
|
}
|
2020-07-23 01:48:16 +02:00
|
|
|
this.go_to(key);
|
|
|
|
}
|
|
|
|
}
|