Initial
This commit is contained in:
178
resources/app/client/apps/sidebar/sidebar-tab.js
Normal file
178
resources/app/client/apps/sidebar/sidebar-tab.js
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* An abstract pattern followed by the different tabs of the sidebar
|
||||
* @abstract
|
||||
* @interface
|
||||
*/
|
||||
class SidebarTab extends Application {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
/**
|
||||
* A reference to the pop-out variant of this SidebarTab, if one exists
|
||||
* @type {SidebarTab}
|
||||
* @protected
|
||||
*/
|
||||
this._popout = null;
|
||||
|
||||
/**
|
||||
* Denote whether this is the original version of the sidebar tab, or a pop-out variant
|
||||
* @type {SidebarTab}
|
||||
*/
|
||||
this._original = null;
|
||||
|
||||
// Adjust options
|
||||
if ( this.options.popOut ) this.options.classes.push("sidebar-popout");
|
||||
this.options.classes.push(`${this.tabName}-sidebar`);
|
||||
|
||||
// Register the tab as the sidebar singleton
|
||||
if ( !this.popOut && ui.sidebar ) ui.sidebar.tabs[this.tabName] = this;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
id: null,
|
||||
popOut: false,
|
||||
width: 300,
|
||||
height: "auto",
|
||||
classes: ["tab", "sidebar-tab"],
|
||||
baseApplication: "SidebarTab"
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
get id() {
|
||||
return `${this.options.id}${this._original ? "-popout" : ""}`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* The base name of this sidebar tab
|
||||
* @type {string}
|
||||
*/
|
||||
get tabName() {
|
||||
return this.constructor.defaultOptions.id ?? this.id;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Rendering */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async getData(options={}) {
|
||||
return {
|
||||
cssId: this.id,
|
||||
cssClass: this.options.classes.join(" "),
|
||||
tabName: this.tabName,
|
||||
user: game.user
|
||||
};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async _render(force=false, options={}) {
|
||||
await super._render(force, options);
|
||||
if ( this._popout ) await this._popout._render(force, options);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async _renderInner(data) {
|
||||
let html = await super._renderInner(data);
|
||||
if ( ui.sidebar?.activeTab === this.id ) html.addClass("active");
|
||||
if ( this.popOut ) html.removeClass("tab");
|
||||
return html;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Methods */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Activate this SidebarTab, switching focus to it
|
||||
*/
|
||||
activate() {
|
||||
ui.sidebar.activateTab(this.tabName);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
async close(options) {
|
||||
if ( this.popOut ) {
|
||||
const base = this._original;
|
||||
if ( base ) base._popout = null;
|
||||
return super.close(options);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Create a second instance of this SidebarTab class which represents a singleton popped-out container
|
||||
* @returns {SidebarTab} The popped out sidebar tab instance
|
||||
*/
|
||||
createPopout() {
|
||||
if ( this._popout ) return this._popout;
|
||||
|
||||
// Retain options from the main tab
|
||||
const options = {...this.options, popOut: true};
|
||||
delete options.id;
|
||||
delete options.classes;
|
||||
|
||||
// Create a popout application
|
||||
const pop = new this.constructor(options);
|
||||
this._popout = pop;
|
||||
pop._original = this;
|
||||
return pop;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Render the SidebarTab as a pop-out container
|
||||
*/
|
||||
renderPopout() {
|
||||
const pop = this.createPopout();
|
||||
pop.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Event Handlers */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Handle lazy loading for sidebar images to only load them once they become observed
|
||||
* @param {HTMLElement[]} entries The entries which are now observed
|
||||
* @param {IntersectionObserver} observer The intersection observer instance
|
||||
*/
|
||||
_onLazyLoadImage(entries, observer) {
|
||||
for ( let e of entries ) {
|
||||
if ( !e.isIntersecting ) continue;
|
||||
const li = e.target;
|
||||
|
||||
// Background Image
|
||||
if ( li.dataset.backgroundImage ) {
|
||||
li.style["background-image"] = `url("${li.dataset.backgroundImage}")`;
|
||||
delete li.dataset.backgroundImage;
|
||||
}
|
||||
|
||||
// Avatar image
|
||||
const img = li.querySelector("img");
|
||||
if ( img && img.dataset.src ) {
|
||||
img.src = img.dataset.src;
|
||||
delete img.dataset.src;
|
||||
}
|
||||
|
||||
// No longer observe the target
|
||||
observer.unobserve(e.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user