gp-crm-ui
Version:
Модуль компонентов UI Имя модуля: `gp-crm-ui`
135 lines (118 loc) • 3.79 kB
text/typescript
import { Injectable } from '@angular/core';
// Интерфейсы
import {
IDelta,
IOffset
} from '../interfaces';
// Сервис вспомогательных функций
()
export class CrmHelperService {
// Фиксирование числа в диапазоне
public static clamp(
value: number,
min: number = 0,
max: number = Number.POSITIVE_INFINITY): number {
return Math.min(Math.max(value, min), max);
}
// Расстояние между двумя точками
public static distance(a: IOffset, b: IOffset): number {
const DOUBLE = 2;
return Math.sqrt(
Math.pow(a.left - b.left, DOUBLE) +
Math.pow(a.top - b.top, DOUBLE)
);
}
/**
* Получить путь из Node по событию
* @param event - событие
*/
public static eventPath(event: MouseEvent | any): Node[] {
const target = event.target || event.srcElement || event.currentTarget;
const composedPath = event.composedPath && event.composedPath();
const path = composedPath || event.path;
if (path) {
// Safari fix
return (path.indexOf(window) === -1)
? path.concat(window)
: path;
}
const getParents = (node: Node, memo: Node[] = []): Node[] => (
node.parentNode
? getParents(node.parentNode, memo.concat(node.parentNode))
: memo
);
return [target].concat(getParents(target), window);
}
/**
* Проверить принадлежность element к parent в иерархии
* @param parent - элемент родителя
* @param element - проверяемый элемент
*/
public static hasParent(parent: any, element: any): boolean {
let el = element;
while (el) {
if (el === parent) {
return true;
}
el = el.parentElement;
}
return false;
}
/**
* Расчет смещения элемента element от родительского элемента parent
* @param parent - элемент родителя
* @param element - проверяемый элемент
* Возвращает объект содержащий значения смещения left, top
* Учитывает смещения при помощи transform: translate
*/
public static getOffsetElement(parent: any, element: any): IOffset {
let el: any = null;
const offset: IOffset = {
left: 0,
top: 0
};
const hasParent = CrmHelperService.hasParent(parent, element);
if (element !== parent && hasParent) {
// Первый проход по иерархии (сбор смещений offsetLeft, offsetTop)
el = element;
while (el && el !== parent) {
offset.left += el.offsetLeft;
offset.top += el.offsetTop;
el = el.offsetParent;
}
// Второй проход по иерархии (сбор смещений transform)
el = element;
const INDEX_MATRIX = 1;
const INDEX_TX = 4;
const INDEX_TY = 5;
while (el && el !== parent) {
const style = window.getComputedStyle(el);
const mat = style.transform.match(/^matrix\((.+)\)$/);
if (mat) {
const matrix = mat[INDEX_MATRIX].split(', ');
const tx = parseFloat(matrix[INDEX_TX]);
const ty = parseFloat(matrix[INDEX_TY]);
if (!isNaN(tx)) { offset.left += tx; }
if (!isNaN(ty)) { offset.top += ty; }
}
el = el.parentElement;
}
}
return offset;
}
// Получить дельту из события прокрутки
public static getDeltaFromWheelEvent(event: any): IDelta {
const delta: IDelta = {
x: 0,
y: 0
};
const e = event || window.event;
const wheelDelta = -e.wheelDelta || e.detail;
if (e.shiftKey === true) {
delta.x = CrmHelperService.clamp(wheelDelta, -1, 1);
} else {
delta.y = CrmHelperService.clamp(wheelDelta, -1, 1);
}
return delta;
}
}