mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 01:25:37 -05:00
101 lines
4.0 KiB
TypeScript
101 lines
4.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
|
|
import * as types from 'vs/base/common/types';
|
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
|
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
|
|
|
export function isHidden(element: HTMLElement): boolean {
|
|
return element.style.display === 'none';
|
|
}
|
|
|
|
/**
|
|
* Converts a size value into its string representation. This will add px to the end unless
|
|
* it already ends with %. If the size value is undefined it will return the defaultValue as-is.
|
|
* @param size The size value to convert
|
|
* @param defaultValue The default value to use if the size is undefined
|
|
*/
|
|
export function convertSize(size: number | string | undefined, defaultValue?: string): string {
|
|
defaultValue = defaultValue || '';
|
|
if (types.isUndefinedOrNull(size)) {
|
|
return defaultValue;
|
|
}
|
|
let convertedSize: string = size ? size.toString() : defaultValue;
|
|
convertedSize = convertedSize.toLowerCase();
|
|
if (!convertedSize.endsWith('px') && !convertedSize.endsWith('%')) {
|
|
convertedSize = convertedSize + 'px';
|
|
}
|
|
return convertedSize;
|
|
}
|
|
|
|
/**
|
|
* Converts a size value into its number representation. Supports px, em and unspecified units.
|
|
* @param size The size value to convert
|
|
*/
|
|
export function convertSizeToNumber(size: number | string | undefined): number {
|
|
if (size && typeof (size) === 'string') {
|
|
if (size.toLowerCase().endsWith('px')) {
|
|
return +size.replace('px', '');
|
|
} else if (size.toLowerCase().endsWith('em')) {
|
|
return +size.replace('em', '') * 11;
|
|
}
|
|
} else if (!size) {
|
|
return 0;
|
|
}
|
|
return +size;
|
|
}
|
|
|
|
const tabbableElementsQuerySelector = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]';
|
|
|
|
/**
|
|
* Get the focusable elements inside a HTML element
|
|
* @param container The container element inside which we should look for the focusable elements
|
|
* @returns The focusable elements
|
|
*/
|
|
export function getFocusableElements(container: HTMLElement): HTMLElement[] {
|
|
const elements = [];
|
|
container.querySelectorAll(tabbableElementsQuerySelector).forEach((element: HTMLElement) => {
|
|
const style = window.getComputedStyle(element);
|
|
// We should only return the elements that are visible. There are many ways to hide an element, for example setting the
|
|
// visibility attribute to hidden/collapse, setting the display property to none, or if one of its ancestors is invisible.
|
|
if (element.offsetWidth > 0 && element.offsetHeight > 0 && style.visibility === 'visible') {
|
|
elements.push(element);
|
|
}
|
|
});
|
|
return elements;
|
|
}
|
|
|
|
/**
|
|
* Trap the keyboard navigation (Tab/Shift+Tab) inside the specified container
|
|
* @param container The container element to trap the keyboard focus in
|
|
* @returns The object to be disposed when the trap should be removed.
|
|
*/
|
|
export function trapKeyboardNavigation(container: HTMLElement): IDisposable {
|
|
return addDisposableListener(container, EventType.KEY_DOWN, (e) => {
|
|
const focusableElements = getFocusableElements(container);
|
|
if (focusableElements.length === 0) {
|
|
return;
|
|
}
|
|
const firstFocusable = focusableElements[0];
|
|
const lastFocusable = focusableElements[focusableElements.length - 1];
|
|
const event = new StandardKeyboardEvent(e);
|
|
let elementToFocus = undefined;
|
|
if (event.equals(KeyMod.Shift | KeyCode.Tab) && firstFocusable === document.activeElement) {
|
|
// Backward navigation
|
|
elementToFocus = lastFocusable;
|
|
} else if (event.equals(KeyCode.Tab) && lastFocusable === document.activeElement) {
|
|
// Forward navigation
|
|
elementToFocus = firstFocusable;
|
|
}
|
|
|
|
if (elementToFocus) {
|
|
e.preventDefault();
|
|
elementToFocus.focus();
|
|
}
|
|
});
|
|
}
|