123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /* eslint-disable no-param-reassign */
- /* eslint-disable @typescript-eslint/no-var-requires */
- /* eslint-disable no-underscore-dangle */
- import { fromEvent } from 'rxjs';
- import { debounceTime, throttleTime } from 'rxjs/operators';
- export const objIsEmpty = (obj: Record<string, unknown>): boolean =>
- !Object.keys(obj).length;
- export const watchScroll = (
- viewAreaElement: HTMLElement | null,
- cb: (state: ScrollStateType) => void,
- ): ScrollStateType => {
- let rAF: number | null = null;
- const element = viewAreaElement as HTMLElement;
- const state = {
- right: true,
- down: true,
- lastX: element.scrollLeft,
- lastY: element.scrollTop,
- subscriber: {},
- };
- const debounceScroll = (): void => {
- if (rAF) {
- return;
- }
- // schedule an invocation of scroll for next animation frame.
- rAF = window.requestAnimationFrame(() => {
- rAF = null;
- const currentX = element.scrollLeft;
- const { lastX } = state;
- if (currentX !== lastX) {
- state.right = currentX > lastX;
- }
- state.lastX = currentX;
- const currentY = element.scrollTop;
- const { lastY } = state;
- if (currentY !== lastY) {
- state.down = currentY > lastY;
- }
- state.lastY = currentY;
- cb(state);
- });
- };
- const subscriber = fromEvent(element, 'scroll')
- .pipe(throttleTime(100), debounceTime(100))
- .subscribe(debounceScroll);
- state.subscriber = subscriber;
- return state;
- };
- export const scrollIntoView = (
- element: HTMLElement,
- spot?: { top: number },
- skipOverflowHiddenElements = false,
- ): void => {
- let parent = element.offsetParent as HTMLElement;
- let offsetY = element.offsetTop + element.clientTop;
- if (!parent) {
- return; // no need to scroll
- }
- while (
- (parent.clientHeight === parent.scrollHeight &&
- parent.clientWidth === parent.scrollWidth) ||
- (skipOverflowHiddenElements &&
- getComputedStyle(parent).overflow === 'hidden')
- ) {
- if (parent.dataset._scaleY) {
- offsetY /= parseInt(parent.dataset._scaleY, 10);
- }
- offsetY += parent.offsetTop;
- parent = parent.offsetParent as HTMLElement;
- if (!parent) {
- return; // no need to scroll
- }
- }
- if (spot) {
- if (spot.top !== undefined) {
- offsetY += spot.top;
- }
- }
- parent.scrollTop = offsetY;
- };
- export const scaleCheck = (scale: number): number => {
- if (typeof scale === 'number' && scale >= 50 && scale <= 250) {
- return Math.round(scale * 100) / 10000;
- }
- if (scale < 50) {
- return 0.5;
- }
- return 2.5;
- };
- export const downloadFileWithUri = (name: string, uri: string): void => {
- const ele = document.createElement('a');
- ele.download = name;
- ele.href = uri;
- ele.target = '_blank';
- document.body.appendChild(ele);
- ele.click();
- document.body.removeChild(ele);
- ele.remove();
- };
- export const uploadFile = (extension: string): Promise<string> =>
- new Promise((resolve) => {
- const fileInput = document.createElement('input');
- fileInput.type = 'file';
- fileInput.accept = extension;
- fileInput.onchange = (): void => {
- if (fileInput.files) {
- const reader = new FileReader();
- reader.onload = (): void => {
- const contents = reader.result as string;
- resolve(contents);
- };
- if (extension.includes('xfdf')) {
- reader.readAsText(fileInput.files[0]);
- } else {
- reader.readAsDataURL(fileInput.files[0]);
- }
- }
- };
- document.body.appendChild(fileInput);
- fileInput.click();
- });
- const componentToHex = (c: number): string => {
- const hex = c.toString(16);
- return hex.length === 1 ? `0${hex}` : hex;
- };
- export const hexToRgb = (
- hex: string,
- ): { r: number; g: number; b: number } | null => {
- const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
- return result
- ? {
- r: parseInt(result[1], 16),
- g: parseInt(result[2], 16),
- b: parseInt(result[3], 16),
- }
- : null;
- };
- export const rgbToHex = (r: number, g: number, b: number): string =>
- `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
- export const floatToHex = (r: number, g: number, b: number): string =>
- rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
- type ScaleDataType = CoordType & {
- operator: string;
- clickX: number;
- clickY: number;
- moveX: number;
- moveY: number;
- };
- export const calcDragAndDropScale = ({
- top,
- left,
- width = 0,
- height = 0,
- operator,
- clickX,
- clickY,
- moveX,
- moveY,
- }: ScaleDataType): CoordType => {
- let scaleCoord = {
- left,
- top,
- width,
- height,
- };
- switch (operator) {
- case 'top':
- scaleCoord = {
- ...scaleCoord,
- top: moveY - (clickY - top),
- height: height + (clickY - moveY),
- };
- break;
- case 'top-left':
- scaleCoord = {
- top: moveY - (clickY - top),
- left: moveX - (clickX - left),
- height: height + (clickY - moveY),
- width: width + (clickX - moveX),
- };
- break;
- case 'left':
- scaleCoord = {
- ...scaleCoord,
- left: moveX - (clickX - left),
- width: width + (clickX - moveX),
- };
- break;
- case 'bottom-left':
- scaleCoord = {
- ...scaleCoord,
- left: moveX - (clickX - left),
- width: width + (clickX - moveX),
- height: height + moveY - clickY,
- };
- break;
- case 'bottom':
- scaleCoord = {
- ...scaleCoord,
- height: height + moveY - clickY,
- };
- break;
- case 'bottom-right':
- scaleCoord = {
- ...scaleCoord,
- width: width + moveX - clickX,
- height: height + moveY - clickY,
- };
- break;
- case 'right':
- scaleCoord = {
- ...scaleCoord,
- width: width + moveX - clickX,
- };
- break;
- case 'top-right':
- scaleCoord = {
- ...scaleCoord,
- top: moveY - (clickY - top),
- width: width + moveX - clickX,
- height: height + (clickY - moveY),
- };
- break;
- default:
- break;
- }
- return scaleCoord;
- };
- const FRACTIONDIGITS = 2;
- type NormalizeRoundFunc = (num: number, fractionDigits?: number) => number;
- export const normalizeRound: NormalizeRoundFunc = (num, fractionDigits) => {
- const frac = fractionDigits || FRACTIONDIGITS;
- return Math.round(num * 10 ** frac) / 10 ** frac;
- };
- const printDocument = (documentId: string): void => {
- const iframe = document.getElementById(documentId) as HTMLIFrameElement;
- const doc = iframe.contentWindow as { print: () => void };
- if (doc && typeof doc.print === 'undefined') {
- setTimeout(() => {
- printDocument(documentId);
- }, 1000);
- } else {
- setTimeout(() => {
- doc.print();
- }, 3000);
- }
- };
- export const printPdf = async (url: string): Promise<void> => {
- // eslint-disable-next-line global-require
- const printJS = require('print-js');
- const isIE11 = !!(window.navigator && window.navigator.msSaveOrOpenBlob);
- if (!isIE11) {
- printJS(url);
- } else {
- const wrapper = document.getElementById('embed-wrapper') as HTMLElement;
- wrapper.style.display = 'flex';
- const ele = document.createElement('embed');
- ele.setAttribute('type', 'application/pdf');
- ele.setAttribute('id', 'pdf-embed');
- ele.style.width = '70%';
- ele.style.height = '70%';
- ele.style.position = 'fixed';
- ele.style.top = '0';
- ele.style.left = '0';
- ele.style.bottom = '0';
- ele.style.right = '0';
- ele.style.margin = 'auto';
- ele.setAttribute('src', url);
- wrapper.appendChild(ele);
- printDocument('pdf-embed');
- }
- };
- export const strip = (number: number): number => {
- return parseFloat(parseFloat(number.toString()).toPrecision(12));
- };
|