mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 03:53:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import * as scroll_util from "./scroll_util";
 | |
| 
 | |
| export class ListCursor {
 | |
|     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;
 | |
|         }
 | |
| 
 | |
|         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) {
 | |
|             row.clear();
 | |
|         }
 | |
|         this.curr_key = undefined;
 | |
|     }
 | |
| 
 | |
|     get_key() {
 | |
|         return this.curr_key;
 | |
|     }
 | |
| 
 | |
|     get_row(key) {
 | |
|         // 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
 | |
|         //       something like widget.trigger("select") on.  This will
 | |
|         //       be especially important if we do lazy rendering.
 | |
|         //       It would also give the caller more flexibility on
 | |
|         //       the actual styling.
 | |
|         if (key === undefined) {
 | |
|             return undefined;
 | |
|         }
 | |
| 
 | |
|         const li = this.list.find_li({
 | |
|             key,
 | |
|             force_render: true,
 | |
|         });
 | |
| 
 | |
|         if (!li || li.length === 0) {
 | |
|             return undefined;
 | |
|         }
 | |
| 
 | |
|         return {
 | |
|             highlight: () => {
 | |
|                 li.addClass(this.highlight_class);
 | |
|                 this.adjust_scroll(li);
 | |
|             },
 | |
|             clear: () => {
 | |
|                 li.removeClass(this.highlight_class);
 | |
|             },
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     adjust_scroll(li) {
 | |
|         const scroll_container = $(this.list.scroll_container_sel);
 | |
|         scroll_util.scroll_element_into_container(li, scroll_container);
 | |
|     }
 | |
| 
 | |
|     redraw() {
 | |
|         // 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.
 | |
|         const row = this.get_row(this.curr_key);
 | |
| 
 | |
|         if (row === undefined) {
 | |
|             return;
 | |
|         }
 | |
|         row.highlight();
 | |
|     }
 | |
| 
 | |
|     go_to(key) {
 | |
|         if (key === undefined) {
 | |
|             blueslip.error("Caller is not checking keys for ListCursor.go_to");
 | |
|             return;
 | |
|         }
 | |
|         if (key === this.curr_key) {
 | |
|             return;
 | |
|         }
 | |
|         this.clear();
 | |
|         const row = this.get_row(key);
 | |
|         if (row === undefined) {
 | |
|             blueslip.error("Cannot highlight key for ListCursor: " + key);
 | |
|             return;
 | |
|         }
 | |
|         this.curr_key = key;
 | |
|         row.highlight();
 | |
|     }
 | |
| 
 | |
|     reset() {
 | |
|         this.clear();
 | |
|         const key = this.list.first_key();
 | |
|         if (key === undefined) {
 | |
|             this.curr_key = undefined;
 | |
|             return;
 | |
|         }
 | |
|         this.go_to(key);
 | |
|     }
 | |
| 
 | |
|     prev() {
 | |
|         if (this.curr_key === undefined) {
 | |
|             return;
 | |
|         }
 | |
|         const key = this.list.prev_key(this.curr_key);
 | |
|         if (key === undefined) {
 | |
|             // leave the current key
 | |
|             return;
 | |
|         }
 | |
|         this.go_to(key);
 | |
|     }
 | |
| 
 | |
|     next() {
 | |
|         if (this.curr_key === undefined) {
 | |
|             // This is sort of a special case where we went from
 | |
|             // an empty filter to having data.
 | |
|             this.reset();
 | |
|             return;
 | |
|         }
 | |
|         const key = this.list.next_key(this.curr_key);
 | |
|         if (key === undefined) {
 | |
|             // leave the current key
 | |
|             return;
 | |
|         }
 | |
|         this.go_to(key);
 | |
|     }
 | |
| }
 |