ag-grid
Version:
Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
154 lines (119 loc) • 4.62 kB
text/typescript
import {Promise, Utils as _} from '../utils';
export class TabbedLayout {
private eGui: HTMLElement;
private eHeader: HTMLElement;
private eBody: HTMLElement;
private params: TabbedLayoutParams;
private afterAttachedParams: any;
private static TEMPLATE =
'<div>'+
'<div ref="tabHeader" class="ag-tab-header"></div>'+
'<div ref="tabBody" class="ag-tab-body"></div>'+
'</div>';
private items: TabbedItemWrapper[] = [];
private activeItem: TabbedItemWrapper;
constructor(params: TabbedLayoutParams) {
this.params = params;
this.eGui = document.createElement('div');
this.eGui.innerHTML = TabbedLayout.TEMPLATE;
this.eHeader = <HTMLElement> this.eGui.querySelector('[ref="tabHeader"]');
this.eBody = <HTMLElement> this.eGui.querySelector('[ref="tabBody"]');
_.addCssClass(this.eGui, params.cssClass);
if (params.items) {
params.items.forEach( item => this.addItem(item) );
}
}
public setAfterAttachedParams(params: any): void {
this.afterAttachedParams = params;
}
public getMinWidth(): number {
let eDummyContainer = document.createElement('span');
// position fixed, so it isn't restricted to the boundaries of the parent
eDummyContainer.style.position = 'fixed';
// we put the dummy into the body container, so it will inherit all the
// css styles that the real cells are inheriting
this.eGui.appendChild(eDummyContainer);
let minWidth = 0;
this.items.forEach( (itemWrapper: TabbedItemWrapper) => {
_.removeAllChildren(eDummyContainer);
let eClone: HTMLElement = <HTMLElement> itemWrapper.tabbedItem.bodyPromise.resolveNow(null, body=>body.cloneNode(true));
if (eClone == null) { return; }
eDummyContainer.appendChild(eClone);
if (minWidth<eDummyContainer.offsetWidth) {
minWidth = eDummyContainer.offsetWidth;
}
});
// finally check the parent tabs are no wider, as if they
// are, then these are the min width and not the child tabs
if (minWidth<this.eGui.offsetWidth) {
minWidth = this.eGui.offsetWidth;
}
this.eGui.removeChild(eDummyContainer);
return minWidth;
}
public showFirstItem(): void {
if (this.items.length>0) {
this.showItemWrapper(this.items[0]);
}
}
private addItem(item: TabbedItem): void {
let eHeaderButton = document.createElement('span');
eHeaderButton.appendChild(item.title);
_.addCssClass(eHeaderButton, 'ag-tab');
this.eHeader.appendChild(eHeaderButton);
let wrapper: TabbedItemWrapper = {
tabbedItem: item,
eHeaderButton: eHeaderButton
};
this.items.push(wrapper);
eHeaderButton.addEventListener('click', this.showItemWrapper.bind(this, wrapper));
}
public showItem(tabbedItem: TabbedItem): void {
let itemWrapper = _.find(this.items, (itemWrapper)=> {
return itemWrapper.tabbedItem === tabbedItem;
});
if (itemWrapper) {
this.showItemWrapper(itemWrapper);
}
}
private showItemWrapper(wrapper: TabbedItemWrapper): void {
if (this.params.onItemClicked) {
this.params.onItemClicked({item: wrapper.tabbedItem});
}
if (this.activeItem === wrapper) {
_.callIfPresent(this.params.onActiveItemClicked);
return;
}
_.removeAllChildren(this.eBody);
wrapper.tabbedItem.bodyPromise.then(body=> {
this.eBody.appendChild(body);
});
if (this.activeItem) {
_.removeCssClass(this.activeItem.eHeaderButton, 'ag-tab-selected');
}
_.addCssClass(wrapper.eHeaderButton, 'ag-tab-selected');
this.activeItem = wrapper;
if (wrapper.tabbedItem.afterAttachedCallback) {
wrapper.tabbedItem.afterAttachedCallback(this.afterAttachedParams);
}
}
public getGui(): HTMLElement {
return this.eGui;
}
}
export interface TabbedLayoutParams {
items: TabbedItem[];
cssClass?: string;
onItemClicked?: Function;
onActiveItemClicked?: Function;
}
export interface TabbedItem {
title: Element;
bodyPromise: Promise<HTMLElement>;
name: string;
afterAttachedCallback?: Function;
}
interface TabbedItemWrapper {
tabbedItem: TabbedItem;
eHeaderButton: HTMLElement;
}