2020-12-23 05:40:30 +02:00
|
|
|
|
import { attachClickEvent } from "../helpers/dom";
|
2020-08-24 17:09:31 +03:00
|
|
|
|
import { horizontalMenu } from "./horizontalMenu";
|
2021-01-01 18:24:49 +04:00
|
|
|
|
import ButtonIcon from "./buttonIcon";
|
|
|
|
|
import Scrollable from "./scrollable";
|
2021-02-15 19:49:58 +04:00
|
|
|
|
import { TransitionSlider } from "./transition";
|
2020-06-13 11:19:39 +03:00
|
|
|
|
|
|
|
|
|
export interface SliderTab {
|
2020-06-19 14:49:55 +03:00
|
|
|
|
onOpen?: () => void,
|
|
|
|
|
onOpenAfterTimeout?: () => void,
|
2020-06-13 11:19:39 +03:00
|
|
|
|
onClose?: () => void,
|
|
|
|
|
onCloseAfterTimeout?: () => void
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-01 18:24:49 +04:00
|
|
|
|
export class SliderSuperTab implements SliderTab {
|
|
|
|
|
public container: HTMLElement;
|
|
|
|
|
|
|
|
|
|
public header: HTMLElement;
|
2020-11-25 21:36:18 +02:00
|
|
|
|
public closeBtn: HTMLElement;
|
2021-01-01 18:24:49 +04:00
|
|
|
|
public title: HTMLElement;
|
|
|
|
|
|
|
|
|
|
public content: HTMLElement;
|
|
|
|
|
public scrollable: Scrollable;
|
|
|
|
|
|
|
|
|
|
public id: number;
|
2020-11-25 21:36:18 +02:00
|
|
|
|
|
2021-01-06 13:16:53 +04:00
|
|
|
|
constructor(protected slider: SidebarSlider, protected destroyable = false) {
|
2021-01-01 18:24:49 +04:00
|
|
|
|
this.container = document.createElement('div');
|
|
|
|
|
this.container.classList.add('sidebar-slider-item');
|
|
|
|
|
|
|
|
|
|
// * Header
|
|
|
|
|
this.header = document.createElement('div');
|
|
|
|
|
this.header.classList.add('sidebar-header');
|
|
|
|
|
|
2021-01-11 19:21:03 +04:00
|
|
|
|
this.closeBtn = ButtonIcon('arrow_back sidebar-close-button', {noRipple: true});
|
2021-01-01 18:24:49 +04:00
|
|
|
|
this.title = document.createElement('div');
|
|
|
|
|
this.title.classList.add('sidebar-header__title');
|
|
|
|
|
this.header.append(this.closeBtn, this.title);
|
|
|
|
|
|
|
|
|
|
// * Content
|
|
|
|
|
this.content = document.createElement('div');
|
|
|
|
|
this.content.classList.add('sidebar-content');
|
|
|
|
|
|
|
|
|
|
this.scrollable = new Scrollable(this.content, undefined, undefined, true);
|
|
|
|
|
|
|
|
|
|
this.container.append(this.header, this.content);
|
|
|
|
|
|
2020-11-25 21:36:18 +02:00
|
|
|
|
this.id = this.slider.addTab(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public close() {
|
|
|
|
|
return this.slider.closeTab(this.id);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-06 13:16:53 +04:00
|
|
|
|
public async open(...args: any[]) {
|
|
|
|
|
if(this.init) {
|
|
|
|
|
const result = this.init();
|
|
|
|
|
this.init = null;
|
|
|
|
|
await (result instanceof Promise ? result : Promise.resolve());
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 21:36:18 +02:00
|
|
|
|
return this.slider.selectTab(this);
|
|
|
|
|
}
|
2021-01-01 23:44:31 +04:00
|
|
|
|
|
2021-01-06 13:16:53 +04:00
|
|
|
|
protected init(): Promise<any> | any {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-01 23:44:31 +04:00
|
|
|
|
// * fix incompability
|
|
|
|
|
public onOpen() {
|
|
|
|
|
|
|
|
|
|
}
|
2021-01-06 13:16:53 +04:00
|
|
|
|
|
2021-01-31 03:52:14 +02:00
|
|
|
|
public onCloseAfterTimeout() {
|
2021-01-06 13:16:53 +04:00
|
|
|
|
if(this.destroyable) { // ! WARNING, пока что это будет работать только с самой последней внутренней вкладкой !
|
|
|
|
|
delete this.slider.tabs[this.id];
|
|
|
|
|
this.container.remove();
|
|
|
|
|
}
|
2021-01-31 03:52:14 +02:00
|
|
|
|
}
|
2020-11-25 21:36:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 02:37:22 +03:00
|
|
|
|
const TRANSITION_TIME = 250;
|
2020-06-19 14:49:55 +03:00
|
|
|
|
|
2020-06-13 11:19:39 +03:00
|
|
|
|
export default class SidebarSlider {
|
2021-01-06 13:16:53 +04:00
|
|
|
|
protected _selectTab: ReturnType<typeof horizontalMenu>;
|
2020-12-11 04:06:16 +02:00
|
|
|
|
public historyTabIds: number[] = [];
|
2021-01-01 18:24:49 +04:00
|
|
|
|
public tabsContainer: HTMLElement;
|
2020-06-13 11:19:39 +03:00
|
|
|
|
|
2020-11-25 21:36:18 +02:00
|
|
|
|
constructor(public sidebarEl: HTMLElement, public tabs: {[id: number]: SliderTab} = {}, private canHideFirst = false) {
|
2021-01-01 18:24:49 +04:00
|
|
|
|
this.tabsContainer = this.sidebarEl.querySelector('.sidebar-slider');
|
2021-02-15 19:49:58 +04:00
|
|
|
|
this._selectTab = TransitionSlider(this.tabsContainer, 'navigation', TRANSITION_TIME);
|
2020-09-24 02:37:22 +03:00
|
|
|
|
if(!canHideFirst) {
|
|
|
|
|
this._selectTab(0);
|
|
|
|
|
}
|
2020-06-13 11:19:39 +03:00
|
|
|
|
|
|
|
|
|
Array.from(this.sidebarEl.querySelectorAll('.sidebar-close-button') as any as HTMLElement[]).forEach(el => {
|
2020-12-23 05:40:30 +02:00
|
|
|
|
attachClickEvent(el, () => this.closeTab());
|
2020-06-13 11:19:39 +03:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:06:16 +02:00
|
|
|
|
public closeTab = (tabId?: number) => {
|
2020-12-24 11:13:21 +02:00
|
|
|
|
if(tabId !== undefined && this.historyTabIds[this.historyTabIds.length - 1] !== tabId) {
|
2020-11-25 21:36:18 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//console.log('sidebar-close-button click:', this.historyTabIDs);
|
2020-12-11 04:06:16 +02:00
|
|
|
|
let closingId = this.historyTabIds.pop(); // pop current
|
|
|
|
|
this.onCloseTab(closingId);
|
|
|
|
|
this._selectTab(this.historyTabIds[this.historyTabIds.length - 1] ?? (this.canHideFirst ? -1 : 0));
|
2020-11-25 21:36:18 +02:00
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
2021-01-01 18:24:49 +04:00
|
|
|
|
public selectTab(id: number | SliderSuperTab): boolean {
|
|
|
|
|
if(id instanceof SliderSuperTab) {
|
2020-11-25 21:36:18 +02:00
|
|
|
|
id = id.id;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-24 11:13:21 +02:00
|
|
|
|
if(this.historyTabIds[this.historyTabIds.length - 1] === id) {
|
2020-09-24 02:37:22 +03:00
|
|
|
|
return false;
|
2020-06-16 23:48:08 +03:00
|
|
|
|
}
|
2020-06-19 14:49:55 +03:00
|
|
|
|
|
|
|
|
|
const tab = this.tabs[id];
|
|
|
|
|
if(tab) {
|
|
|
|
|
if(tab.onOpen) {
|
|
|
|
|
tab.onOpen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(tab.onOpenAfterTimeout) {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
tab.onOpenAfterTimeout();
|
2020-09-24 02:37:22 +03:00
|
|
|
|
}, TRANSITION_TIME);
|
2020-06-19 14:49:55 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:06:16 +02:00
|
|
|
|
this.historyTabIds.push(id);
|
2020-06-13 11:19:39 +03:00
|
|
|
|
this._selectTab(id);
|
2020-09-24 02:37:22 +03:00
|
|
|
|
return true;
|
2020-06-13 11:19:39 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public removeTabFromHistory(id: number) {
|
2020-12-24 11:13:21 +02:00
|
|
|
|
this.historyTabIds.findAndSplice(i => i === id);
|
2020-06-13 11:19:39 +03:00
|
|
|
|
this.onCloseTab(id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public onCloseTab(id: number) {
|
|
|
|
|
let tab = this.tabs[id];
|
|
|
|
|
if(tab) {
|
2020-06-19 14:49:55 +03:00
|
|
|
|
if(tab.onClose) {
|
2020-06-13 11:19:39 +03:00
|
|
|
|
tab.onClose();
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-19 14:49:55 +03:00
|
|
|
|
if(tab.onCloseAfterTimeout) {
|
2020-06-13 11:19:39 +03:00
|
|
|
|
setTimeout(() => {
|
|
|
|
|
tab.onCloseAfterTimeout();
|
2020-09-24 02:37:22 +03:00
|
|
|
|
}, TRANSITION_TIME);
|
2020-06-13 11:19:39 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-25 21:36:18 +02:00
|
|
|
|
|
2021-01-01 18:24:49 +04:00
|
|
|
|
public addTab(tab: SliderSuperTab) {
|
2020-11-25 21:36:18 +02:00
|
|
|
|
let id: number;
|
|
|
|
|
if(tab.container.parentElement) {
|
2021-01-01 18:24:49 +04:00
|
|
|
|
id = Array.from(this.tabsContainer.children).findIndex(el => el === tab.container);
|
2020-11-25 21:36:18 +02:00
|
|
|
|
} else {
|
2021-01-01 18:24:49 +04:00
|
|
|
|
id = this.tabsContainer.childElementCount;
|
|
|
|
|
this.tabsContainer.append(tab.container);
|
2020-11-25 21:36:18 +02:00
|
|
|
|
|
|
|
|
|
if(tab.closeBtn) {
|
|
|
|
|
tab.closeBtn.addEventListener('click', () => this.closeTab());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tabs[id] = tab;
|
|
|
|
|
|
|
|
|
|
return id;
|
|
|
|
|
}
|
2020-06-13 11:19:39 +03:00
|
|
|
|
}
|