@siberiaweb/components
Version:
631 lines (501 loc) • 15.6 kB
text/typescript
import { CellContentAlign, FieldType, SortOrder } from "./Types";
import CSS from "./CSS";
import Icon from "../icon/Icon";
import WebComponent from "@siberiaweb/webcomponent/lib/WebComponent";
/**
* Столбец.
*/
export default class Col extends WebComponent {
/**
* Наименование компонента.
*/
public static readonly COMPONENT_NAME: string = "sw-grid-col";
/**
* Заголовок.
*/
public static readonly ATTR_CAPTION = "caption";
/**
* Класс CSS.
*/
public static readonly ATTR_CLASS = "class";
/**
* Выравнивание содержания.
*/
public static readonly ATTR_CONTENT_ALIGN = "content-align";
/**
* Ширина по умолчанию.
*/
public static readonly ATTR_DEFAULT_WIDTH = "default-width";
/**
* Наименование поля в наборе данных.
*/
public static readonly ATTR_FIELD_NAME = "field-name";
/**
* Тип данных поля в наборе данных.
*/
public static readonly ATTR_FIELD_TYPE = "field-type";
/**
* Форматирование при выводе.
*/
public static readonly ATTR_FORMAT = "format";
/**
* Скрытый столбец.
*/
public static readonly ATTR_HIDDEN = "hidden";
/**
* Минимальная ширина.
*/
public static readonly ATTR_MIN_WIDTH = "min-width";
/**
* Наименование.
*/
public static readonly ATTR_NAME = "name";
/**
* Шаблон, описывающий формат данных в наборе данных.
*/
public static readonly ATTR_PATTERN = "pattern";
/**
* Изменение размера отключено.
*/
public static readonly ATTR_RESIZE_DISABLED = "resize-disabled";
/**
* Сортировка отключена.
*/
public static readonly ATTR_SORT_DISABLED = "sort-disabled";
/**
* Тип данных поля по умолчанию.
*/
public static readonly DEFAULT_FIELD_TYPE: FieldType = "text";
/**
* Минимальная ширина.
*/
private _minWidth: number = 0;
/**
* Порядок сортировки.
*/
private _sortOrder: SortOrder = "none";
/**
* Шаблон содержания ячейки.
*/
private cellContentTemplate: HTMLTemplateElement = document.createElement( "template" );
/**
* Ячейка.
*/
private readonly cell: HTMLTableCellElement;
/**
* Элемент для изменения ширины столбца.
*/
private readonly resizer: HTMLDivElement;
/**
* Индикатор сортировки.
*/
private readonly sortIndicator: Icon;
/**
* Наблюдаемые атрибуты.
*/
public static get observedAttributes(): string[] {
return WebComponent.observedAttributes.concat( [
Col.ATTR_CONTENT_ALIGN,
Col.ATTR_CLASS,
Col.ATTR_MIN_WIDTH,
Col.ATTR_RESIZE_DISABLED,
Col.ATTR_SORT_DISABLED
] );
}
/**
* Создание ячейки.
*/
private createCell(): HTMLTableCellElement {
return document.createElement( "td" );
}
/**
* Создание элемента для изменения ширины столбца.
*/
private createResizer(): HTMLDivElement {
let resizer: HTMLDivElement = document.createElement( "div" );
resizer.classList.add( CSS.COL_RESIZER, CSS.COL_RESIZE_CURSOR );
return resizer;
}
/**
* Создание индикатора сортировки.
*/
private createSortIndicator(): Icon {
let icon: Icon = document.createElement( Icon.COMPONENT_NAME ) as Icon;
icon.classList.add( CSS.SORT_INDICATOR );
return icon;
}
/**
* Обработка изменения атрибута "class".
*/
protected attrClassChange(): void {
this.cell.removeAttribute( Col.ATTR_CLASS );
for ( let className of this.classList ) {
this.cell.classList.add( className );
}
}
/**
* Обработка изменения атрибута "content-align".
*/
protected attrContentAlignChange(): void {
this.cell.classList.remove( CSS.CELL_CONTENT_ALIGN_CENTER, CSS.CELL_CONTENT_ALIGN_RIGHT );
switch ( this.contentAlign ) {
case "center":
this.cell.classList.add( CSS.CELL_CONTENT_ALIGN_CENTER );
break;
case "right":
this.cell.classList.add( CSS.CELL_CONTENT_ALIGN_RIGHT );
break;
}
}
/**
* Обработка изменения атрибута "min-width".
*
* @param newValue Новое значение.
*/
protected attrMinWidthChange(
newValue: string | null
): void {
let value: number = newValue === null ? 0 : parseInt( newValue );
if ( isNaN( value ) || ( value < 0 ) ) {
value = 0;
}
this._minWidth = value;
if ( this.offsetWidth < this.minWidth ) {
this.setWidth( this.minWidth );
}
}
/**
* Обработка изменения атрибута "resize-disabled".
*/
protected attrResizeDisabledChange(): void {
if ( this.resizeDisabled ) {
this.resizer.remove();
}
else if ( !this.cell.contains( this.resizer ) ) {
this.cell.appendChild( this.resizer );
}
}
/**
* Обработка изменения атрибута "sort-disabled".
*/
protected attrSortDisabledChange(): void {
if ( this.sortDisabled ) {
this.sortIndicator.remove();
}
else if ( !this.cell.contains( this.sortIndicator ) ) {
this.cell.appendChild( this.sortIndicator );
}
}
/**
* @override
*/
protected attributeChangedCallback(
name: string,
oldValue: string | null,
newValue: string | null
): void {
super.attributeChangedCallback( name, oldValue, newValue );
switch ( name ) {
case Col.ATTR_CLASS:
this.attrClassChange();
break;
case Col.ATTR_CONTENT_ALIGN:
this.attrContentAlignChange();
break;
case Col.ATTR_MIN_WIDTH:
this.attrMinWidthChange( newValue );
break;
case Col.ATTR_RESIZE_DISABLED:
this.attrResizeDisabledChange();
break;
case Col.ATTR_SORT_DISABLED:
this.attrSortDisabledChange();
break;
}
}
/**
* @override
*/
protected firstConnectedCallback() {
super.firstConnectedCallback();
let cellContentTemplate: HTMLTemplateElement | null = this.querySelector( "template" );
if ( cellContentTemplate !== null ) {
this.cellContentTemplate.content.appendChild( cellContentTemplate.content );
}
else if ( this.textContent ) {
this.cellContentTemplate.content.append( this.textContent );
}
this.cell.appendChild( this.cellContentTemplate.content.cloneNode( true ) );
if ( !this.resizeDisabled ) {
this.cell.appendChild( this.resizer );
}
if ( !this.sortDisabled ) {
this.cell.appendChild( this.sortIndicator );
}
}
/**
* Получение заголовка.
*/
public get caption(): string {
return this.getAttributeOrDefault( Col.ATTR_CAPTION, "" );
}
/**
* Установка заголовка.
*
* @param value Значение.
*/
public set caption(
value: string
) {
this.setAttribute( Col.ATTR_CAPTION, value );
}
/**
* Получение выравнивания содержания.
*/
public get contentAlign(): CellContentAlign {
switch ( this.getAttribute( Col.ATTR_CONTENT_ALIGN ) ) {
case "center":
return "center";
case "right":
return "right";
default:
return "left";
}
}
/**
* Установка выравнивания.
*/
public set contentAlign(
value: CellContentAlign
) {
this.setAttribute( Col.ATTR_CONTENT_ALIGN, value );
}
/**
* Получение наименования поля в наборе данных.
*/
public get fieldName(): string {
return this.getAttributeOrDefault( Col.ATTR_FIELD_NAME, "" );
}
/**
* Установка наименования поля в наборе данных.
*
* @param value Значение.
*/
public set fieldName(
value: string
) {
this.setAttribute( Col.ATTR_FIELD_NAME, value );
}
/**
* Получение типа данных поля в наборе данных.
*/
public get fieldType(): FieldType {
switch ( this.getAttribute( Col.ATTR_FIELD_TYPE ) ) {
case "boolean":
return "boolean";
case "date":
return "date";
case "date-string":
return "date-string";
case "number":
return "number";
default:
return "text";
}
}
/**
* Установка типа данных поля в наборе данных.
*/
public set fieldType(
value: FieldType
) {
this.setAttribute( Col.ATTR_FIELD_TYPE, value );
}
/**
* Получение форматирования при выводе.
*/
public get format(): string {
return this.getAttributeOrDefault( Col.ATTR_FORMAT, "" );
}
/**
* Установка форматирования при выводе.
*
* @param value Значение.
*/
public set format(
value: string
) {
this.setAttribute( Col.ATTR_FORMAT, value );
}
/**
* Получение минимальной ширины.
*/
public get minWidth(): number {
return this._minWidth;
}
/**
* Установка минимальной ширины.
*
* @param value Значение.
*/
public set minWidth(
value: number
) {
this.setAttribute( Col.ATTR_MIN_WIDTH, value.toString() );
}
/**
* Получение наименования.
*/
public get name(): string {
return this.getAttributeOrDefault( Col.ATTR_NAME, "" );
}
/**
* Установка наименования.
*
* @param value Значение.
*/
public set name(
value: string
) {
this.setAttribute( Col.ATTR_NAME, value );
}
/**
* Получение шаблона, описывающего формат данных в наборе данных.
*/
public get pattern(): string {
return this.getAttributeOrDefault( Col.ATTR_PATTERN, "" );
}
/**
* Установка шаблона, описывающего формат данных в наборе данных.
*
* @param value Значение.
*/
public set pattern(
value: string
) {
this.setAttribute( Col.ATTR_PATTERN, value );
}
/**
* Получение признака отключения изменения ширины.
*/
public get resizeDisabled(): boolean {
return this.hasAttribute( Col.ATTR_RESIZE_DISABLED );
}
/**
* Установка признака отключения изменения ширины.
*
* @param value Значение.
*/
public set resizeDisabled(
value: boolean
) {
this.toggleAttribute( Col.ATTR_RESIZE_DISABLED, value );
}
/**
* Получение признака отключения сортировки.
*/
public get sortDisabled(): boolean {
return this.hasAttribute( Col.ATTR_SORT_DISABLED );
}
/**
* Установка признака отключения сортировки.
*
* @param value Значение.
*/
public set sortDisabled(
value: boolean
) {
this.toggleAttribute( Col.ATTR_SORT_DISABLED, value );
}
/**
* Получение порядка сортировки.
*/
public get sortOrder(): SortOrder {
return this._sortOrder;
}
/**
* Установка порядка сортировки.
*
* @param value Значение.
*/
public set sortOrder(
value: SortOrder
) {
this._sortOrder = value;
this.cell.classList.remove( CSS.SORT, CSS.SORT_ASC, CSS.SORT_DESC );
if ( this._sortOrder === "asc" ) {
this.cell.classList.add( CSS.SORT, CSS.SORT_ASC );
}
else if ( this._sortOrder === "desc" ) {
this.cell.classList.add( CSS.SORT, CSS.SORT_DESC );
}
}
/**
* Установка следующего порядка сортировки.
*/
public setNextSortOrder(): void {
if ( this.sortOrder === "asc" ) {
this.sortOrder = "desc";
}
else if ( this.sortOrder === "desc" ) {
this.sortOrder = "none";
}
else {
this.sortOrder = "asc";
}
}
/**
* Получение ширины по умолчанию.
*/
public getDefaultWidth(): number {
let defaultWidth: number = parseInt( this.getAttributeOrDefault( Col.ATTR_DEFAULT_WIDTH, "0" ) );
if ( isNaN( defaultWidth ) || ( defaultWidth < 0 ) ) {
defaultWidth = 0;
}
return defaultWidth;
}
/**
* Установка ширины столбца в пикселях.
*
* @param value Значение.
*/
public setWidth(
value: number
): void {
if ( value < this.minWidth ) {
value = this.minWidth;
}
this.cell.style.minWidth = value + "px";
this.cell.style.width = value + "px";
}
/**
* Получение шаблона содержания ячейки.
*/
public getCellContentTemplate(): HTMLTemplateElement {
let template: HTMLTemplateElement = document.createElement( "template" );
template.content.appendChild( this.cellContentTemplate.content.cloneNode( true ) );
return template;
}
/**
* Получение ячейки.
*/
public getCell(): HTMLTableCellElement {
return this.cell;
}
/**
* Получение элемента для изменения размера столбца.
*/
public getResizer(): HTMLDivElement {
return this.resizer;
}
/**
* Конструктор.
*/
constructor() {
super();
this.cell = this.createCell();
this.resizer = this.createResizer();
this.sortIndicator = this.createSortIndicator();
}
}
Col.define( Icon );