/* * Copyright (c) 2010, 2025 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {aria, BreadcrumbBarEventMap, BreadcrumbBarLayout, BreadcrumbBarModel, BreadcrumbItem, HtmlComponent, InitModelOf, ObjectOrChildModel, scout, TabbableCoordinator, Widget} from '../index'; export class BreadcrumbBar extends Widget implements BreadcrumbBarModel { declare model: BreadcrumbBarModel; declare eventMap: BreadcrumbBarEventMap; declare self: BreadcrumbBar; breadcrumbItems: BreadcrumbItem[] = []; ellipsisBreadcrumbItem: BreadcrumbItem; tabbableCoordinator: TabbableCoordinator; constructor() { super(); this._addWidgetProperties(['breadcrumbItems']); } protected override _init(model: InitModelOf) { super._init(model); this.tabbableCoordinator = scout.create(TabbableCoordinator, {parent: this}); this._setBreadcrumbItems(this.breadcrumbItems); } protected override _render() { this.$container = this.$parent.appendDiv('breadcrumb-bar'); this.htmlComp = HtmlComponent.install(this.$container, this.session); this.htmlComp.setLayout(new BreadcrumbBarLayout(this)); } protected override _renderProperties() { super._renderProperties(); this._renderBreadcrumbItems(); } setBreadcrumbItems(breadcrumbItems: ObjectOrChildModel[]) { this.setProperty('breadcrumbItems', breadcrumbItems); } protected _setBreadcrumbItems(breadcrumbItems: BreadcrumbItem[]) { this._setProperty('breadcrumbItems', breadcrumbItems); this.tabbableCoordinator.setItems(breadcrumbItems); } protected _renderBreadcrumbItems() { this.breadcrumbItems.forEach((breadcrumbItem: BreadcrumbItem, index: number) => { if (index === 1) { this._renderEllipsis(); // render ellipsis after first item } breadcrumbItem.render(); }); this._updateMarkers(); // Invalidate layout because breadcrumb bar may now be longer or shorter this.htmlComp.invalidateLayoutTree(); } protected _renderEllipsis() { if (this.ellipsisBreadcrumbItem) { this.ellipsisBreadcrumbItem.destroy(); } if (this.breadcrumbItems.length <= 2) { return; } this.ellipsisBreadcrumbItem = scout.create(BreadcrumbItem, { parent: this, text: '...', enabled: false }); this.ellipsisBreadcrumbItem.render(); } protected _updateMarkers() { const visibleCrumbs = []; this.breadcrumbItems.forEach(breadcrumb => { if (breadcrumb.rendered) { breadcrumb.$container.removeClass('first last'); aria.current(breadcrumb.$container, null); if (breadcrumb.visible) { visibleCrumbs.push(breadcrumb); } } }); if (visibleCrumbs.length) { visibleCrumbs[0].$container.addClass('first'); let lastCrumb = visibleCrumbs[visibleCrumbs.length - 1]; lastCrumb.$container.addClass('last'); aria.current(lastCrumb.$container, 'page'); } } }