@progress/kendo-angular-filter
Version:
Kendo UI Angular Filter
162 lines (161 loc) • 8.66 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* 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 }]; } });