UNPKG

@progress/kendo-angular-filter

Version:
162 lines (161 loc) 8.66 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { ChangeDetectorRef, Injectable, Renderer2 } from '@angular/core'; import { Keys } from '@progress/kendo-angular-common'; import { selectors } from './util'; import * as i0 from "@angular/core"; /** * @hidden */ export class NavigationService { cdr; renderer; hierarchicalFilterItems = []; flattenFilterItems = []; currentToolbarItemIndex = 0; currentToolbarItemChildrenIndex = 0; isFilterNavigationActivated = true; isFilterExpressionComponentFocused = false; currentlyFocusedElement; constructor(cdr, renderer) { this.cdr = cdr; this.renderer = renderer; } processKeyDown(key, event) { switch (key) { case Keys.ArrowUp: { event.preventDefault(); if (!this.isFilterExpressionComponentFocused) { this.currentToolbarItemChildrenIndex = 0; if (this.currentToolbarItemIndex > 0) { this.currentToolbarItemIndex--; } const elementToFocus = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[0]; this.focusCurrentElement(elementToFocus); } break; } case Keys.ArrowDown: { event.preventDefault(); if (!this.isFilterExpressionComponentFocused) { this.currentToolbarItemChildrenIndex = 0; if (this.currentToolbarItemIndex < this.flattenFilterItems.length - 1) { this.currentToolbarItemIndex++; } const elementToFocus = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[0]; this.focusCurrentElement(elementToFocus); } break; } case Keys.Enter: { const isEventTargetKendoFilterToolbarItem = event.target.closest(selectors.kendoFilterToolbarItem); const isEventTargetButton = event.target.closest(selectors.kendoButton); if (this.isFilterNavigationActivated && !this.isFilterExpressionComponentFocused && isEventTargetKendoFilterToolbarItem && !isEventTargetButton) { event.preventDefault(); this.isFilterExpressionComponentFocused = true; const focusableElement = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[this.currentToolbarItemChildrenIndex]; const elementToFocus = focusableElement.querySelector(selectors.KendoDropDownListComponent) || focusableElement.querySelector(selectors.kendoInputInner) || focusableElement.querySelector(selectors.inputElement) || focusableElement.querySelector(selectors.textAreaElement); this.focusCurrentElement(elementToFocus); } break; } case Keys.Escape: { if (this.isFilterExpressionComponentFocused) { event.preventDefault(); this.isFilterExpressionComponentFocused = false; const elementToFocus = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[this.currentToolbarItemChildrenIndex]; this.focusCurrentElement(elementToFocus); } break; } case Keys.ArrowRight: { if (this.isFilterNavigationActivated && !this.isFilterExpressionComponentFocused) { event.preventDefault(); if (this.currentToolbarItemChildrenIndex < this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren.length - 1) { this.currentToolbarItemChildrenIndex++; } const elementToFocus = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[this.currentToolbarItemChildrenIndex]; this.focusCurrentElement(elementToFocus); } break; } case Keys.ArrowLeft: { if (this.isFilterNavigationActivated && !this.isFilterExpressionComponentFocused) { event.preventDefault(); if (this.currentToolbarItemChildrenIndex > 0) { this.currentToolbarItemChildrenIndex--; } const elementToFocus = this.flattenFilterItems[this.currentToolbarItemIndex].focusableChildren[this.currentToolbarItemChildrenIndex]; this.focusCurrentElement(elementToFocus); } break; } default: break; } } focusCurrentElement(element, isOnMouseDown) { this.renderer.setAttribute(this.currentlyFocusedElement, 'tabindex', '-1'); this.currentlyFocusedElement = element; if (element) { this.renderer.setAttribute(this.currentlyFocusedElement, 'tabindex', '0'); if (!isOnMouseDown) { this.currentlyFocusedElement.focus(); } } } flattenHierarchicalFilterItems(filterItems) { filterItems.forEach((filterRow) => { const flattenItem = { component: filterRow, isGroup: false, toolbarElement: filterRow.toolbarElement, focusableChildren: [] }; this.flattenFilterItems.push(flattenItem); if ((filterRow['operators'] && filterRow['filterItems']?.length > 0)) { this.setGroupItemChildren(flattenItem, filterRow); this.flattenHierarchicalFilterItems(filterRow['filterItems']); } else if (filterRow['operators'] && filterRow['filterItems']?.length === 0) { this.setGroupItemChildren(flattenItem, filterRow); } else { flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.filterFieldWrapper)); if (filterRow.toolbarElement.querySelector('.k-filter-operator')) { flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.filterOperatorWrapper)); } flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.filterValueEditorWrapper)); flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.removeButton)); } }); } setGroupItemChildren(flattenItem, filterRow) { flattenItem.isGroup = true; flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.andButton)); flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.orButton)); flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.addFilterButton)); flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.addGroupButton)); flattenItem.focusableChildren.push(filterRow.toolbarElement.querySelector(selectors.removeButton)); } setItemIndexes() { this.flattenFilterItems.forEach((item, index) => { item.component['itemNumber'] = index; }); this.cdr.detectChanges(); } reset(items) { this.flattenFilterItems = []; this.hierarchicalFilterItems = items; this.flattenHierarchicalFilterItems(items); this.setItemIndexes(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NavigationService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }]; } });