diff --git a/local/browser-testing/src/Resize.ts b/local/browser-testing/src/Resize.ts index 745ab0d..7332d20 100644 --- a/local/browser-testing/src/Resize.ts +++ b/local/browser-testing/src/Resize.ts @@ -1,19 +1,36 @@ -// @ts-ignore -import { - createDiv, - appendChildren, - parent, - style, - on, - off, - addClass, - WH, - XY, - clientSize, - each, -} from './support'; - type ResizeListener = (width: number, height: number) => void; +interface WH { + w: T; + h: T; +} +interface XY { + x: T; + y: T; +} + +const splitEventNames = (eventNames: string) => eventNames.split(' '); +const on = ( + target: EventTarget, + eventNames: string, + listener: (event: T) => any +): void => { + splitEventNames(eventNames).forEach((eventName) => { + target.addEventListener(eventName, listener as EventListener); + }); +}; +const off = ( + target: EventTarget, + eventNames: string, + listener: (event: T) => any +): void => { + splitEventNames(eventNames).forEach((eventName) => { + target.removeEventListener(eventName, listener as EventListener); + }); +}; +const clientSize = (elm: HTMLElement): WH => ({ + w: elm.clientWidth, + h: elm.clientHeight, +}); export const resize = (element: HTMLElement) => { const resizeListeners: ResizeListener[] = []; @@ -23,9 +40,10 @@ export const resize = (element: HTMLElement) => { const strSelectStartEvent = 'selectstart'; const dragStartSize: WH = { w: 0, h: 0 }; const dragStartPosition: XY = { x: 0, y: 0 }; - const resizeBtn = createDiv('resizeBtn'); - appendChildren(element, resizeBtn); - addClass(element, 'resizer'); + const resizeBtn = document.createElement('div'); + resizeBtn.classList.add('resizeBtn'); + element.append(resizeBtn); + element.classList.add('resizer'); // eslint-disable-next-line @typescript-eslint/no-unused-vars let dragResizeBtn: HTMLElement | undefined; @@ -47,14 +65,14 @@ export const resize = (element: HTMLElement) => { height: dragStartSize.h + mouseOffsetHolder.pageY - dragStartPosition.y, }; - style(dragResizer, sizeStyle); + dragResizer!.style.width = `${sizeStyle.width}px`; + dragResizer!.style.height = `${sizeStyle.height}px`; - each(resizeListeners, (listener: ResizeListener) => { + resizeListeners.forEach((listener: ResizeListener) => { if (listener) { listener(sizeStyle.width, sizeStyle.height); } }); - event.stopPropagation(); }; @@ -67,38 +85,33 @@ export const resize = (element: HTMLElement) => { dragResizeBtn = undefined; }; - on( - resizeBtn, - strMouseTouchDownEvent, - (event: MouseEvent | TouchEvent) => { - const { currentTarget } = event; - const correctButton = (event as MouseEvent).buttons === 1 || event.which === 1; - const isTouchEvent = (event as TouchEvent).touches !== undefined; - const mouseOffsetHolder = isTouchEvent - ? (event as TouchEvent).touches[0] - : (event as MouseEvent); + on(resizeBtn, strMouseTouchDownEvent, (event: MouseEvent | TouchEvent) => { + const { currentTarget } = event; + const correctButton = (event as MouseEvent).buttons === 1 || event.which === 1; + const isTouchEvent = (event as TouchEvent).touches !== undefined; + const mouseOffsetHolder = isTouchEvent + ? (event as TouchEvent).touches[0] + : (event as MouseEvent); - if (correctButton || isTouchEvent) { - dragStartPosition.x = mouseOffsetHolder.pageX; - dragStartPosition.y = mouseOffsetHolder.pageY; + if (correctButton || isTouchEvent) { + dragStartPosition.x = mouseOffsetHolder.pageX; + dragStartPosition.y = mouseOffsetHolder.pageY; - dragResizeBtn = currentTarget as HTMLElement; - dragResizer = parent(currentTarget as HTMLElement) as HTMLElement; + dragResizeBtn = currentTarget as HTMLElement; + dragResizer = (currentTarget as HTMLElement).parentElement as HTMLElement; - const cSize = clientSize(element); - dragStartSize.w = cSize.w; - dragStartSize.h = cSize.h; + const cSize = clientSize(element); + dragStartSize.w = cSize.w; + dragStartSize.h = cSize.h; - on(document, strSelectStartEvent, onSelectStart, { _passive: false }); - on(document, strMouseTouchMoveEvent, resizerResize, { _passive: false }); - on(document, strMouseTouchUpEvent, resizerResized, { _passive: false }); + on(document, strSelectStartEvent, onSelectStart); + on(document, strMouseTouchMoveEvent, resizerResize); + on(document, strMouseTouchUpEvent, resizerResized); - event.preventDefault(); - event.stopPropagation(); - } - }, - { _passive: false } - ); + event.preventDefault(); + event.stopPropagation(); + } + }); return { addResizeListener(listener: ResizeListener) { diff --git a/local/browser-testing/src/support/dom/class.ts b/local/browser-testing/src/support/dom/class.ts deleted file mode 100644 index c1b8bb7..0000000 --- a/local/browser-testing/src/support/dom/class.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { isString } from '../utils/types'; -import { each } from '../utils/array'; -import { keys } from '../utils/object'; - -type ClassContainingElement = Node | Element | false | null | undefined; -type ClassName = string | false | null | undefined; - -const rnothtmlwhite = /[^\x20\t\r\n\f]+/g; -const classListAction = ( - elm: ClassContainingElement, - className: ClassName, - action: (elmClassList: DOMTokenList, clazz: string) => boolean | void -): boolean => { - const classList = elm && (elm as Element).classList; - let clazz: string; - let i = 0; - let result = false; - - if (classList && className && isString(className)) { - const classes: Array = className.match(rnothtmlwhite) || []; - result = classes.length > 0; - while ((clazz = classes[i++])) { - result = !!action(classList, clazz) && result; - } - } - return result; -}; - -/** - * Check whether the given element has the given class name(s). - * @param elm The element. - * @param className The class name(s). - */ -export const hasClass = (elm: ClassContainingElement, className: ClassName): boolean => - classListAction(elm, className, (classList, clazz) => classList.contains(clazz)); - -/** - * Removes the given class name(s) from the given element. - * @param elm The element. - * @param className The class name(s) which shall be removed. (separated by spaces) - */ -export const removeClass = (elm: ClassContainingElement, className: ClassName): void => { - classListAction(elm, className, (classList, clazz) => classList.remove(clazz)); -}; - -/** - * Adds the given class name(s) to the given element. - * @param elm The element. - * @param className The class name(s) which shall be added. (separated by spaces) - * @returns A function which removes the added class name(s). - */ -export const addClass = (elm: ClassContainingElement, className: ClassName): (() => void) => { - classListAction(elm, className, (classList, clazz) => classList.add(clazz)); - return removeClass.bind(0, elm, className); -}; - -/** - * Takes two className strings, compares them and returns the difference as array. - * @param classNameA ClassName A. - * @param classNameB ClassName B. - */ -export const diffClass = (classNameA: ClassName, classNameB: ClassName) => { - const classNameASplit = classNameA && classNameA.split(' '); - const classNameBSplit = classNameB && classNameB.split(' '); - const tempObj = {}; - - each(classNameASplit, (className) => { - tempObj[className] = 1; - }); - each(classNameBSplit, (className) => { - if (tempObj[className]) { - delete tempObj[className]; - } else { - tempObj[className] = 1; - } - }); - - return keys(tempObj); -}; diff --git a/local/browser-testing/src/support/dom/create.ts b/local/browser-testing/src/support/dom/create.ts deleted file mode 100644 index 012edea..0000000 --- a/local/browser-testing/src/support/dom/create.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { each } from '../utils/array'; -import { contents } from './traversal'; -import { removeElements } from './manipulation'; - -/** - * Creates a div DOM node. - */ -export const createDiv = (classNames?: string): HTMLDivElement => { - const div = document.createElement('div'); - if (classNames) { - div.setAttribute('class', classNames); - } - return div; -}; - -/** - * Creates DOM nodes modeled after the passed html string and returns the root dom nodes as a array. - * @param html The html string after which the DOM nodes shall be created. - */ -export const createDOM = (html: string): ReadonlyArray => { - const createdDiv = createDiv(); - createdDiv.innerHTML = html.trim(); - - return each(contents(createdDiv), (elm) => removeElements(elm)); -}; diff --git a/local/browser-testing/src/support/dom/dimensions.ts b/local/browser-testing/src/support/dom/dimensions.ts deleted file mode 100644 index 1cfdf38..0000000 --- a/local/browser-testing/src/support/dom/dimensions.ts +++ /dev/null @@ -1,68 +0,0 @@ -export interface WH { - w: T; - h: T; -} - -const elementHasDimensions = (elm: HTMLElement): boolean => - !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length); -const zeroObj: WH = { - w: 0, - h: 0, -}; - -/** - * Returns the window inner- width and height. - */ -export const windowSize = (): WH => ({ - w: window.innerWidth, - h: window.innerHeight, -}); - -/** - * Returns the scroll- width and height of the passed element. If the element is null the width and height values are 0. - * @param elm The element of which the scroll- width and height shall be returned. - */ -export const offsetSize = (elm: HTMLElement | null | undefined): WH => - elm - ? { - w: elm.offsetWidth, - h: elm.offsetHeight, - } - : zeroObj; - -/** - * Returns the client- width and height of the passed element. If the element is null the width and height values are 0. - * @param elm The element of which the client- width and height shall be returned. - */ -export const clientSize = (elm: HTMLElement | false | null | undefined): WH => - elm - ? { - w: elm.clientWidth, - h: elm.clientHeight, - } - : zeroObj; - -/** - * Returns the client- width and height of the passed element. If the element is null the width and height values are 0. - * @param elm The element of which the client- width and height shall be returned. - */ -export const scrollSize = (elm: HTMLElement | false | null | undefined): WH => - elm - ? { - w: elm.scrollWidth, - h: elm.scrollHeight, - } - : zeroObj; - -/** - * Returns the BoundingClientRect of the passed element. - * @param elm The element of which the BoundingClientRect shall be returned. - */ -export const getBoundingClientRect = (elm: HTMLElement): DOMRect => elm.getBoundingClientRect(); - -/** - * Determines whether the passed element has any dimensions. - * @param elm The element. - */ -export const hasDimensions = (elm: HTMLElement | false | null | undefined): boolean => - elm ? elementHasDimensions(elm as HTMLElement) : false; diff --git a/local/browser-testing/src/support/dom/events.ts b/local/browser-testing/src/support/dom/events.ts deleted file mode 100644 index 845bdc2..0000000 --- a/local/browser-testing/src/support/dom/events.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { isUndefined } from '../utils/types'; -import { each, push, runEachAndClear } from '../utils/array'; - -let passiveEventsSupport: boolean; -const supportPassiveEvents = (): boolean => { - if (isUndefined(passiveEventsSupport)) { - passiveEventsSupport = false; - try { - /* eslint-disable */ - // @ts-ignore - window.addEventListener( - 'test', - null, - Object.defineProperty({}, 'passive', { - get() { - passiveEventsSupport = true; - }, - }) - ); - /* eslint-enable */ - } catch (e) {} - } - return passiveEventsSupport; -}; -const splitEventNames = (eventNames: string) => eventNames.split(' '); - -export interface OnOptions { - _capture?: boolean; - _passive?: boolean; - _once?: boolean; -} - -/** - * Removes the passed event listener for the passed events with the passed options. - * @param target The element from which the listener shall be removed. - * @param eventNames The eventsnames for which the listener shall be removed. - * @param listener The listener which shall be removed. - * @param capture The options of the removed listener. - */ -export const off = ( - target: EventTarget, - eventNames: string, - listener: (event: T) => any, - capture?: boolean -): void => { - each(splitEventNames(eventNames), (eventName) => { - target.removeEventListener(eventName, listener as EventListener, capture); - }); -}; - -/** - * Adds the passed event listener for the passed eventnames with the passed options. - * @param target The element to which the listener shall be added. - * @param eventNames The eventsnames for which the listener shall be called. - * @param listener The listener which is called on the eventnames. - * @param options The options of the added listener. - */ -export const on = ( - target: EventTarget, - eventNames: string, - listener: (event: T) => any, - options?: OnOptions -): (() => void) => { - const doSupportPassiveEvents = supportPassiveEvents(); - const passive = (doSupportPassiveEvents && options && options._passive) ?? doSupportPassiveEvents; - const capture = (options && options._capture) || false; - const once = (options && options._once) || false; - const offListeners: (() => void)[] = []; - const nativeOptions: AddEventListenerOptions | boolean = doSupportPassiveEvents - ? { - passive, - capture, - } - : capture; - - each(splitEventNames(eventNames), (eventName) => { - const finalListener = ( - once - ? (evt: T) => { - target.removeEventListener(eventName, finalListener, capture); - listener && listener(evt); - } - : listener - ) as EventListener; - - push(offListeners, off.bind(null, target, eventName, finalListener, capture)); - target.addEventListener(eventName, finalListener, nativeOptions); - }); - - return runEachAndClear.bind(0, offListeners); -}; - -/** - * Shorthand for the stopPropagation event Method. - * @param evt The event of which the stopPropagation method shall be called. - */ -export const stopPropagation = (evt: Event): void => evt.stopPropagation(); - -/** - * Shorthand for the preventDefault event Method. - * @param evt The event of which the preventDefault method shall be called. - */ -export const preventDefault = (evt: Event): void => evt.preventDefault(); - -/** - * Shorthand for the stopPropagation and preventDefault event Method. - * @param evt The event of which the stopPropagation and preventDefault methods shall be called. - */ -export const stopAndPrevent = (evt: Event): void => - (stopPropagation(evt) as undefined) || (preventDefault(evt) as undefined); diff --git a/local/browser-testing/src/support/dom/index.ts b/local/browser-testing/src/support/dom/index.ts deleted file mode 100644 index c298aa6..0000000 --- a/local/browser-testing/src/support/dom/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './class'; -export * from './create'; -export * from './dimensions'; -export * from './events'; -export * from './style'; -export * from './manipulation'; -export * from './offset'; -export * from './traversal'; diff --git a/local/browser-testing/src/support/dom/manipulation.ts b/local/browser-testing/src/support/dom/manipulation.ts deleted file mode 100644 index bb48866..0000000 --- a/local/browser-testing/src/support/dom/manipulation.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { isArrayLike } from '../utils/types'; -import { each, from } from '../utils/array'; -import { parent } from './traversal'; - -type NodeCollection = ArrayLike | Node | false | null | undefined; - -/** - * Inserts Nodes before the given preferredAnchor element. - * @param parentElm The parent of the preferredAnchor element or the element which shall be the parent of the inserted Nodes. - * @param preferredAnchor The element before which the Nodes shall be inserted or null if the elements shall be appended at the end. - * @param insertedElms The Nodes which shall be inserted. - */ -const before = ( - parentElm: Node | false | null | undefined, - preferredAnchor: Node | false | null | undefined, - insertedElms: NodeCollection -): void => { - if (insertedElms && parentElm) { - let anchor: Node | false | null | undefined = preferredAnchor; - let fragment: DocumentFragment | Node | null | undefined; - - if (isArrayLike(insertedElms)) { - fragment = document.createDocumentFragment(); - - // append all insertedElms to the fragment and if one of these is the anchor, change the anchor - each(insertedElms, (insertedElm) => { - if (insertedElm === anchor) { - anchor = insertedElm.previousSibling; - } - fragment!.appendChild(insertedElm); - }); - } else { - fragment = insertedElms; - } - - // if the preferred anchor isn't null set it to a valid anchor - if (preferredAnchor) { - if (!anchor) { - anchor = parentElm.firstChild; - } else if (anchor !== preferredAnchor) { - anchor = anchor.nextSibling; - } - } - - parentElm.insertBefore(fragment, anchor || null); - } -}; - -/** - * Appends the given children at the end of the given Node. - * @param node The Node to which the children shall be appended. - * @param children The Nodes which shall be appended. - */ -export const appendChildren = ( - node: Node | false | null | undefined, - children: NodeCollection -): void => { - before(node, null, children); -}; - -/** - * Prepends the given children at the start of the given Node. - * @param node The Node to which the children shall be prepended. - * @param children The Nodes which shall be prepended. - */ -export const prependChildren = ( - node: Node | false | null | undefined, - children: NodeCollection -): void => { - before(node, node && node.firstChild, children); -}; - -/** - * Inserts the given Nodes before the given Node. - * @param node The Node before which the given Nodes shall be inserted. - * @param insertedNodes The Nodes which shall be inserted. - */ -export const insertBefore = ( - node: Node | false | null | undefined, - insertedNodes: NodeCollection -): void => { - before(parent(node), node, insertedNodes); -}; - -/** - * Inserts the given Nodes after the given Node. - * @param node The Node after which the given Nodes shall be inserted. - * @param insertedNodes The Nodes which shall be inserted. - */ -export const insertAfter = ( - node: Node | false | null | undefined, - insertedNodes: NodeCollection -): void => { - before(parent(node), node && node.nextSibling, insertedNodes); -}; - -/** - * Removes the given Nodes from their parent. - * @param nodes The Nodes which shall be removed. - */ -export const removeElements = (nodes: NodeCollection): void => { - if (isArrayLike(nodes)) { - each(from(nodes), (e) => removeElements(e)); - } else if (nodes) { - const parentElm = parent(nodes); - if (parentElm) { - parentElm.removeChild(nodes); - } - } -}; diff --git a/local/browser-testing/src/support/dom/offset.ts b/local/browser-testing/src/support/dom/offset.ts deleted file mode 100644 index 4c94902..0000000 --- a/local/browser-testing/src/support/dom/offset.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { getBoundingClientRect } from './dimensions'; - -export interface XY { - x: T; - y: T; -} - -const zeroObj: XY = { - x: 0, - y: 0, -}; - -/** - * Returns the offset- left and top coordinates of the passed element relative to the document. If the element is null the top and left values are 0. - * @param elm The element of which the offset- top and left coordinates shall be returned. - */ -export const absoluteCoordinates = (elm: HTMLElement | null | undefined): XY => { - const rect = elm ? getBoundingClientRect(elm) : 0; - return rect - ? { - x: rect.left + window.pageYOffset, - y: rect.top + window.pageXOffset, - } - : zeroObj; -}; - -/** - * Returns the offset- left and top coordinates of the passed element. If the element is null the top and left values are 0. - * @param elm The element of which the offset- top and left coordinates shall be returned. - */ -export const offsetCoordinates = (elm: HTMLElement | null | undefined): XY => - elm - ? { - x: elm.offsetLeft, - y: elm.offsetTop, - } - : zeroObj; diff --git a/local/browser-testing/src/support/dom/style.ts b/local/browser-testing/src/support/dom/style.ts deleted file mode 100644 index aa74f7b..0000000 --- a/local/browser-testing/src/support/dom/style.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { each, keys } from '../utils'; -import { isString, isNumber, isArray, isUndefined } from '../utils/types'; - -export interface TRBL { - t: number; - r: number; - b: number; - l: number; -} - -type StyleObject = { - [Key in keyof CSSStyleDeclaration | (CustomCssProps extends string ? CustomCssProps : '')]?: - | string - | number; -}; - -const cssNumber = { - // animationiterationcount: 1, - // columncount: 1, - // fillopacity: 1, - // flexgrow: 1, - // flexshrink: 1, - // fontweight: 1, - // lineheight: 1, - // order: 1, - // orphans: 1, - // widows: 1, - // zoom: 1, - opacity: 1, - zindex: 1, -}; - -const parseToZeroOrNumber = (value: string, toFloat?: boolean): number => { - /* istanbul ignore next */ - const num = toFloat ? parseFloat(value) : parseInt(value, 10); - // num === num means num is not NaN - /* istanbul ignore next */ - return num === num ? num : 0; // eslint-disable-line no-self-compare -}; - -const adaptCSSVal = (prop: string, val: string | number): string | number => - !cssNumber[prop.toLowerCase()] && isNumber(val) ? `${val}px` : val; - -const getCSSVal = (elm: HTMLElement, computedStyle: CSSStyleDeclaration, prop: string): string => - /* istanbul ignore next */ - computedStyle != null - ? computedStyle[prop] || computedStyle.getPropertyValue(prop) - : elm.style[prop]; - -const setCSSVal = (elm: HTMLElement, prop: string, val: string | number): void => { - try { - const { style: elmStyle } = elm; - if (!isUndefined(elmStyle[prop])) { - elmStyle[prop] = adaptCSSVal(prop, val); - } else { - elmStyle.setProperty(prop, val as string); - } - } catch (e) {} -}; - -/** - * Gets or sets the passed styles to the passed element. - * @param elm The element to which the styles shall be applied to / be read from. - * @param styles The styles which shall be set or read. - */ -export function style( - elm: HTMLElement | false | null | undefined, - styles: StyleObject -): void; -export function style(elm: HTMLElement | false | null | undefined, styles: string): string; -export function style( - elm: HTMLElement | false | null | undefined, - styles: Array | string -): { [key: string]: string }; -export function style( - elm: HTMLElement | false | null | undefined, - styles: StyleObject | Array | string -): { [key: string]: string } | string | void { - const getSingleStyle = isString(styles); - const getStyles = isArray(styles) || getSingleStyle; - - if (getStyles) { - let getStylesResult: string | Record = getSingleStyle ? '' : {}; - if (elm) { - const computedStyle: CSSStyleDeclaration = window.getComputedStyle(elm, null); - getStylesResult = getSingleStyle - ? getCSSVal(elm, computedStyle, styles as string) - : (styles as Array).reduce((result, key) => { - result[key] = getCSSVal(elm, computedStyle, key as string); - return result; - }, getStylesResult); - } - return getStylesResult; - } - elm && each(keys(styles), (key) => setCSSVal(elm, key, styles[key])); -} - -/** - * Hides the passed element (display: none). - * @param elm The element which shall be hidden. - */ -export const hide = (elm: HTMLElement | false | null | undefined): void => { - style(elm, { display: 'none' }); -}; - -/** - * Shows the passed element (display: block). - * @param elm The element which shall be shown. - */ -export const show = (elm: HTMLElement | false | null | undefined): void => { - style(elm, { display: 'block' }); -}; - -/** - * Returns the top right bottom left values of the passed css property. - * @param elm The element of which the values shall be returned. - * @param propertyPrefix The css property prefix. (e.g. "border") - * @param propertySuffix The css property suffix. (e.g. "width") - */ -export const topRightBottomLeft = ( - elm?: HTMLElement | false | null | undefined, - propertyPrefix?: string, - propertySuffix?: string -): TRBL => { - const finalPrefix = propertyPrefix ? `${propertyPrefix}-` : ''; - const finalSuffix = propertySuffix ? `-${propertySuffix}` : ''; - const top = `${finalPrefix}top${finalSuffix}`; - const right = `${finalPrefix}right${finalSuffix}`; - const bottom = `${finalPrefix}bottom${finalSuffix}`; - const left = `${finalPrefix}left${finalSuffix}`; - const result = style(elm, [top, right, bottom, left]); - return { - t: parseToZeroOrNumber(result[top]), - r: parseToZeroOrNumber(result[right]), - b: parseToZeroOrNumber(result[bottom]), - l: parseToZeroOrNumber(result[left]), - }; -}; diff --git a/local/browser-testing/src/support/dom/traversal.ts b/local/browser-testing/src/support/dom/traversal.ts deleted file mode 100644 index df1c7f7..0000000 --- a/local/browser-testing/src/support/dom/traversal.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { isElement } from '../utils/types'; -import { push, from } from '../utils/array'; - -type InputElementType = Node | Element | Node | false | null | undefined; -type OutputElementType = Node | Element | null; - -const elmPrototype = Element.prototype; - -/** - * Find all elements with the passed selector, outgoing (and including) the passed element or the document if no element was provided. - * @param selector The selector which has to be searched by. - * @param elm The element from which the search shall be outgoing. - */ -const find = (selector: string, elm?: InputElementType): Element[] => { - const arr: Array = []; - const rootElm = elm ? (isElement(elm) ? elm : null) : document; - - return rootElm ? push(arr, rootElm.querySelectorAll(selector)) : arr; -}; - -/** - * Find the first element with the passed selector, outgoing (and including) the passed element or the document if no element was provided. - * @param selector The selector which has to be searched by. - * @param elm The element from which the search shall be outgoing. - */ -const findFirst = (selector: string, elm?: InputElementType): OutputElementType => { - const rootElm = elm ? (isElement(elm) ? elm : null) : document; - - return rootElm ? rootElm.querySelector(selector) : null; -}; - -/** - * Determines whether the passed element is matching with the passed selector. - * @param elm The element which has to be compared with the passed selector. - * @param selector The selector which has to be compared with the passed element. Additional selectors: ':visible' and ':hidden'. - */ -const is = (elm: InputElementType, selector: string): boolean => { - if (isElement(elm)) { - /* istanbul ignore next */ - // eslint-disable-next-line - // @ts-ignore - const fn: (...args: any) => boolean = elmPrototype.matches || elmPrototype.msMatchesSelector; - return fn.call(elm, selector); - } - return false; -}; - -/** - * Returns the children (no text-nodes or comments) of the passed element which are matching the passed selector. An empty array is returned if the passed element is null. - * @param elm The element of which the children shall be returned. - * @param selector The selector which must match with the children elements. - */ -const children = (elm: InputElementType, selector?: string): ReadonlyArray => { - const childs: Array = []; - - return isElement(elm) - ? push( - childs, - from(elm.children).filter((child) => (selector ? is(child, selector) : child)) - ) - : childs; -}; - -/** - * Returns the childNodes (incl. text-nodes or comments etc.) of the passed element. An empty array is returned if the passed element is null. - * @param elm The element of which the childNodes shall be returned. - */ -const contents = (elm: InputElementType): ReadonlyArray => - elm ? from(elm.childNodes) : []; - -/** - * Returns the parent element of the passed element, or null if the passed element is null. - * @param elm The element of which the parent element shall be returned. - */ -const parent = (elm: InputElementType): OutputElementType => (elm ? elm.parentElement : null); - -const closest = (elm: InputElementType, selector: string): OutputElementType => { - if (isElement(elm)) { - const closestFn = elmPrototype.closest; - if (closestFn) { - return closestFn.call(elm, selector); - } - - do { - if (is(elm, selector)) { - return elm as Element; - } - elm = parent(elm); - } while (elm); - } - - return null; -}; - -/** - * Determines whether the given element lies between two selectors in the DOM. - * @param elm The element. - * @param highBoundarySelector The high boundary selector. - * @param deepBoundarySelector The deep boundary selector. - */ -const liesBetween = ( - elm: InputElementType, - highBoundarySelector: string, - deepBoundarySelector: string -): boolean => { - const closestHighBoundaryElm = elm && closest(elm, highBoundarySelector); - const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm); - const deepBoundaryIsValid = - closest(closestDeepBoundaryElm, highBoundarySelector) === closestHighBoundaryElm; - - return closestHighBoundaryElm && closestDeepBoundaryElm - ? closestHighBoundaryElm === elm || - closestDeepBoundaryElm === elm || - (deepBoundaryIsValid && - closest(closest(elm, deepBoundarySelector), highBoundarySelector) !== - closestHighBoundaryElm) - : false; -}; - -export { find, findFirst, is, children, contents, parent, liesBetween, closest }; diff --git a/local/browser-testing/src/support/index.ts b/local/browser-testing/src/support/index.ts deleted file mode 100644 index f20e8e8..0000000 --- a/local/browser-testing/src/support/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './dom'; -export * from './utils'; diff --git a/local/browser-testing/src/support/utils/array.ts b/local/browser-testing/src/support/utils/array.ts deleted file mode 100644 index 5c1e249..0000000 --- a/local/browser-testing/src/support/utils/array.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { isArrayLike, isString } from './types'; - -type PlainObject = Record; - -type RunEachItem = ((...args: any) => any | any[]) | null | undefined; - -/** - * Iterates through a array or object - * @param arrayLikeOrObject The array or object through which shall be iterated. - * @param callback The function which is responsible for the iteration. - * If the function returns true its treated like a "continue" statement. - * If the function returns false its treated like a "break" statement. - */ -export function each( - array: Array | ReadonlyArray, - callback: (value: T, indexOrKey: number, source: Array) => boolean | unknown -): Array | ReadonlyArray; -export function each( - array: Array | ReadonlyArray | false | null | undefined, - callback: (value: T, indexOrKey: number, source: Array) => boolean | unknown -): Array | ReadonlyArray | false | null | undefined; -export function each( - arrayLikeObject: ArrayLike, - callback: (value: T, indexOrKey: number, source: ArrayLike) => boolean | unknown -): ArrayLike; -export function each( - arrayLikeObject: ArrayLike | false | null | undefined, - callback: (value: T, indexOrKey: number, source: ArrayLike) => boolean | unknown -): ArrayLike | false | null | undefined; -export function each( - obj: PlainObject, - callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | unknown -): PlainObject; -export function each( - obj: PlainObject | false | null | undefined, - callback: (value: any, indexOrKey: string, source: PlainObject) => boolean | unknown -): PlainObject | false | null | undefined; -export function each( - source: Array | ArrayLike | ReadonlyArray | PlainObject | false | null | undefined, - callback: (value: T, indexOrKey: any, source: any) => boolean | unknown -): Array | ArrayLike | ReadonlyArray | PlainObject | false | null | undefined { - if (isArrayLike(source)) { - for (let i = 0; i < source.length; i++) { - if (callback(source[i], i, source) === false) { - break; - } - } - } else if (source) { - // cant use support func keys here due to circular dep - each(Object.keys(source), (key) => callback(source[key], key, source)); - } - return source; -} - -/** - * Returns the index of the given inside the given array or -1 if the given item isn't part of the given array. - * @param arr The array. - * @param item The item. - * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0. - */ -export const indexOf = (arr: T[], item: T, fromIndex?: number): number => - arr.indexOf(item, fromIndex); - -/** - * Pushesh all given items into the given array and returns it. - * @param array The array the items shall be pushed into. - * @param items The items which shall be pushed into the array. - */ -export const push = (array: T[], items: T | ArrayLike, arrayIsSingleItem?: boolean): T[] => { - !arrayIsSingleItem && !isString(items) && isArrayLike(items) - ? Array.prototype.push.apply(array, items as T[]) - : array.push(items as T); - return array; -}; - -/** - * Creates a shallow-copied Array instance from an array-like or iterable object. - * @param arr The object from which the array instance shall be created. - */ -export const from = (arr?: ArrayLike | Set) => { - const original = Array.from; - const result: T[] = []; - - if (original && arr) { - return original(arr); - } - - if (arr instanceof Set) { - arr.forEach((value) => { - push(result, value); - }); - } else { - each(arr, (elm) => { - push(result, elm); - }); - } - - return result; -}; - -/** - * Check whether the passed array is empty. - * @param array The array which shall be checked. - */ -export const isEmptyArray = (array: any[] | null | undefined): boolean => - !!array && array.length === 0; - -/** - * Calls all functions in the passed array/set of functions. - * @param arr The array filled with function which shall be called. - * @param args The args with which each function is called. - * @param keep True when the Set / array should not be cleared afterwards, false otherwise. - */ -export const runEachAndClear = (arr: RunEachItem[], args?: any[], keep?: boolean): void => { - // eslint-disable-next-line prefer-spread - const runFn = (fn: RunEachItem) => fn && fn.apply(undefined, args || []); - each(arr, runFn); - !keep && ((arr as any[]).length = 0); -}; diff --git a/local/browser-testing/src/support/utils/index.ts b/local/browser-testing/src/support/utils/index.ts deleted file mode 100644 index f1efd7b..0000000 --- a/local/browser-testing/src/support/utils/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './array'; -export * from './object'; -export * from './types'; diff --git a/local/browser-testing/src/support/utils/object.ts b/local/browser-testing/src/support/utils/object.ts deleted file mode 100644 index f143ac7..0000000 --- a/local/browser-testing/src/support/utils/object.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { isArray, isFunction, isPlainObject, isNull } from './types'; -import { each } from './array'; - -/** - * Determines whether the passed object has a property with the passed name. - * @param obj The object. - * @param prop The name of the property. - */ -export const hasOwnProperty = (obj: any, prop: string | number | symbol): boolean => - Object.prototype.hasOwnProperty.call(obj, prop); - -/** - * Returns the names of the enumerable string properties and methods of an object. - * @param obj The object of which the properties shall be returned. - */ -export const keys = (obj: any): Array => (obj ? Object.keys(obj) : []); - -type AssignDeep = { - (target: T, object1: U): T & U; - (target: T, object1: U, object2: V): T & U & V; - (target: T, object1: U, object2: V, object3: W): T & U & V & W; - (target: T, object1: U, object2: V, object3: W, object4: X): T & U & V & W & X; - (target: T, object1: U, object2: V, object3: W, object4: X, object5: Y): T & - U & - V & - W & - X & - Y; - ( - target: T, - object1?: U, - object2?: V, - object3?: W, - object4?: X, - object5?: Y, - object6?: Z - ): T & U & V & W & X & Y & Z; -}; - -// https://github.com/jquery/jquery/blob/master/src/core.js#L116 -export const assignDeep: AssignDeep = ( - target: T, - object1?: U, - object2?: V, - object3?: W, - object4?: X, - object5?: Y, - object6?: Z -): T & U & V & W & X & Y & Z => { - const sources: Array = [object1, object2, object3, object4, object5, object6]; - - // Handle case when target is a string or something (possible in deep copy) - if ((typeof target !== 'object' || isNull(target)) && !isFunction(target)) { - target = {} as T; - } - - each(sources, (source) => { - // Extend the base object - each(keys(source), (key) => { - const copy: any = source[key]; - - // Prevent Object.prototype pollution - // Prevent never-ending loop - if (target === copy) { - return true; - } - - const copyIsArray = isArray(copy); - - // Recurse if we're merging plain objects or arrays - if (copy && (isPlainObject(copy) || copyIsArray)) { - const src = target[key]; - let clone: any = src; - - // Ensure proper type for the source value - if (copyIsArray && !isArray(src)) { - clone = []; - } else if (!copyIsArray && !isPlainObject(src)) { - clone = {}; - } - - // Never move original objects, clone them - target[key] = assignDeep(clone, copy) as any; - } else { - target[key] = copy; - } - }); - }); - - // Return the modified object - return target as any; -}; - -/** - * Returns true if the given object is empty, false otherwise. - * @param obj The Object. - */ -export const isEmptyObject = (obj: any): boolean => { - /* eslint-disable no-restricted-syntax, guard-for-in */ - // eslint-disable-next-line no-unreachable-loop - for (const name in obj) return false; - return true; - /* eslint-enable */ -}; diff --git a/local/browser-testing/src/support/utils/types.ts b/local/browser-testing/src/support/utils/types.ts deleted file mode 100644 index 465f0d6..0000000 --- a/local/browser-testing/src/support/utils/types.ts +++ /dev/null @@ -1,97 +0,0 @@ -type PlainObject = Record; - -const ElementNodeType = Node.ELEMENT_NODE; -const { toString, hasOwnProperty } = Object.prototype; - -export const isUndefined = (obj: any): obj is undefined => obj === undefined; - -export const isNull = (obj: any): obj is null => obj === null; - -export const type = (obj: any): string => - isUndefined(obj) || isNull(obj) - ? `${obj}` - : toString - .call(obj) - .replace(/^\[object (.+)\]$/, '$1') - .toLowerCase(); - -export const isNumber = (obj: any): obj is number => typeof obj === 'number'; - -export const isString = (obj: any): obj is string => typeof obj === 'string'; - -export const isBoolean = (obj: any): obj is boolean => typeof obj === 'boolean'; - -export const isFunction = (obj: any): obj is (...args: any[]) => any => typeof obj === 'function'; - -export const isArray = (obj: any): obj is Array => Array.isArray(obj); - -export const isObject = (obj: any): boolean => - typeof obj === 'object' && !isArray(obj) && !isNull(obj); - -/** - * Returns true if the given object is array like, false otherwise. - * @param obj The Object - */ -export const isArrayLike = (obj: any): obj is ArrayLike => { - const length = !!obj && obj.length; - const lengthCorrectFormat = isNumber(length) && length > -1 && length % 1 == 0; // eslint-disable-line eqeqeq - - return isArray(obj) || (!isFunction(obj) && lengthCorrectFormat) - ? length > 0 && isObject(obj) - ? length - 1 in obj - : true - : false; -}; - -/** - * Returns true if the given object is a "plain" (e.g. { key: value }) object, false otherwise. - * @param obj The Object. - */ -export const isPlainObject = (obj: any): obj is PlainObject => { - if (!obj || !isObject(obj) || type(obj) !== 'object') return false; - - let key; - const cstr = 'constructor'; - const ctor = obj[cstr]; - const ctorProto = ctor && ctor.prototype; - const hasOwnConstructor = hasOwnProperty.call(obj, cstr); - const hasIsPrototypeOf = ctorProto && hasOwnProperty.call(ctorProto, 'isPrototypeOf'); - - if (ctor && !hasOwnConstructor && !hasIsPrototypeOf) { - return false; - } - - /* eslint-disable no-restricted-syntax */ - for (key in obj) { - /**/ - } - /* eslint-enable */ - - return isUndefined(key) || hasOwnProperty.call(obj, key); -}; - -/** - * Checks whether the given object is a HTMLElement. - * @param obj The object which shall be checked. - */ -export const isHTMLElement = (obj: any): obj is HTMLElement => { - const instanceofObj = HTMLElement; - return obj - ? instanceofObj - ? obj instanceof instanceofObj - : obj.nodeType === ElementNodeType - : false; -}; - -/** - * Checks whether the given object is a Element. - * @param obj The object which shall be checked. - */ -export const isElement = (obj: any): obj is Element => { - const instanceofObj = Element; - return obj - ? instanceofObj - ? obj instanceof instanceofObj - : obj.nodeType === ElementNodeType - : false; -};