UNPKG

@siberiaweb/components

Version:
631 lines (501 loc) 15.6 kB
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 );