Skip to content

Commit

Permalink
Started replacing jQuery #3303
Browse files Browse the repository at this point in the history
  • Loading branch information
ComLock authored and alansemenov committed Oct 16, 2023
1 parent 1e8b4be commit 82aa181
Show file tree
Hide file tree
Showing 26 changed files with 207 additions and 52 deletions.
19 changes: 11 additions & 8 deletions src/main/resources/assets/admin/common/js/dom/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import {ElementRegistry} from './ElementRegistry';
import {assert, assertNotNull, assertState} from '../util/Assert';
import {ElementEvent} from './ElementEvent';
import * as DOMPurify from 'dompurify';
import {findHTMLElements} from './util/findHTMLElements';
import {selectHTMLElement} from './util/selectHTMLElement';
import {show} from './util/show';


export interface PurifyConfig {
addTags?: string[];
Expand Down Expand Up @@ -101,8 +105,8 @@ export class ElementFromHelperBuilder
}

static fromString(s: string, loadExistingChildren: boolean = true): ElementFromHelperBuilder {
let htmlEl = $(s).get(0);
let parentEl;
const htmlEl = selectHTMLElement(s);
let parentEl: Element | undefined;
if (htmlEl && htmlEl.parentElement) {
parentEl = Element.fromHtmlElement(htmlEl.parentElement);
}
Expand Down Expand Up @@ -267,7 +271,7 @@ export class Element {
}

static fromHtml(html: string, loadExistingChildren: boolean = true): Element {
const htmlEl = $(html).get(0);
const htmlEl = selectHTMLElement(html);

if (!htmlEl) {
return null;
Expand All @@ -283,14 +287,13 @@ export class Element {
}

static fromSelector(s: string, loadExistingChildren: boolean = true): Element[] {
return $(s).map((_index, elem) => {
let htmlEl = elem;
let parentEl;
return findHTMLElements(s).map((htmlEl) => {
let parentEl: Element | undefined;
if (htmlEl && htmlEl.parentElement) {
parentEl = Element.fromHtmlElement(htmlEl.parentElement);
}
return Element.fromHtmlElement(htmlEl, loadExistingChildren, parentEl);
}).get();
});
}

public loadExistingChildren(): Element {
Expand Down Expand Up @@ -378,7 +381,7 @@ export class Element {

show() {
// Using jQuery to show, since it seems to contain some smartness
$(this.el.getHTMLElement()).show();
show(this.el.getHTMLElement());
this.notifyShown(this, true);
}

Expand Down
51 changes: 32 additions & 19 deletions src/main/resources/assets/admin/common/js/dom/ElementHelper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import {Element} from './Element';
import {StringHelper} from '../util/StringHelper';
import {assert, assertNotNull} from '../util/Assert';
import {getData} from './util/getData';
import {getOuterHeightWithMargin} from './util/getOuterHeightWithMargin';
import {getOuterWidthWithMargin} from './util/getOuterWidthWithMargin';
import {getOffset} from './util/getOffset';
import {getOffsetParent} from './util/getOffsetParent';
import {getPosition} from './util/getPosition';
import {isVisible} from './util/isVisible';
import {setData} from './util/setData';
import {setInnerHtml} from './util/setInnerHtml';
import {setOffset} from './util/setOffset';


export interface ElementDimensions {
top: number;
Expand Down Expand Up @@ -100,7 +111,7 @@ export class ElementHelper {
}

setInnerHtml(value: string, escapeHtml: boolean = true): ElementHelper {
$(this.el).html(escapeHtml ? StringHelper.escapeHtml(value) : value);
setInnerHtml(this.el, escapeHtml ? StringHelper.escapeHtml(value) : value);
return this;
}

Expand All @@ -109,7 +120,7 @@ export class ElementHelper {
}

setText(value: string): ElementHelper {
$(this.el).text(value);
this.el.textContent = value;
return this;
}

Expand Down Expand Up @@ -138,13 +149,12 @@ export class ElementHelper {
setData(name: string, value: string): ElementHelper {
assert(!StringHelper.isEmpty(name), 'Name cannot be empty');
assert(!StringHelper.isEmpty(value), 'Value cannot be empty');
this.el.setAttribute('data-' + name, value);
$(this.el).data(name, value);
setData(this.el, name, value);
return this;
}

getData(name: string): string {
let data = $(this.el).data(name);
let data = getData(this.el, name);
return data ? data.toString() : undefined;
}

Expand Down Expand Up @@ -330,19 +340,19 @@ export class ElementHelper {
}

getWidth(): number {
return $(this.el).innerWidth();
return this.el.clientWidth;
}

getWidthWithoutPadding(): number {
return $(this.el).width();
return this.el.getBoundingClientRect().width;
}

getWidthWithBorder(): number {
return $(this.el).outerWidth();
return this.el.offsetWidth;
}

getWidthWithMargin(): number {
return $(this.el).outerWidth(true);
return getOuterWidthWithMargin(this.el);
}

getMinWidth(): number {
Expand All @@ -364,7 +374,7 @@ export class ElementHelper {
}

getHeight(): number {
return $(this.el).innerHeight();
return this.el.clientHeight;
}

setMaxHeight(value: string): ElementHelper {
Expand Down Expand Up @@ -396,15 +406,15 @@ export class ElementHelper {
}

getHeightWithoutPadding(): number {
return $(this.el).height();
return this.el.getBoundingClientRect().height;
}

getHeightWithBorder(): number {
return $(this.el).outerHeight();
return this.el.offsetHeight;
}

getHeightWithMargin(): number {
return $(this.el).outerHeight(true);
return getOuterHeightWithMargin(this.el);
}

setTop(value: string): ElementHelper {
Expand Down Expand Up @@ -658,12 +668,15 @@ export class ElementHelper {
getOffset(): {
top: number; left: number;
} {
return $(this.el).offset();
return getOffset(this.el);
}

/**
* Set the coordinates of every element, in the set of matched elements, relative to the document.
*/
setOffset(offset: { top: number; left: number; }): ElementHelper {
$(this.el).offset(offset);
return this;
setOffset(this.el, offset);
return this; // TODO: return this or this.el?
}

getDimensions(): ElementDimensions {
Expand Down Expand Up @@ -694,7 +707,7 @@ export class ElementHelper {
* @returns {HTMLElement}
*/
getOffsetParent(): HTMLElement {
return $(this.el).offsetParent()[0];
return getOffsetParent(this.el);
}

/**
Expand All @@ -704,7 +717,7 @@ export class ElementHelper {
getOffsetToParent(): {
top: number; left: number;
} {
return $(this.el).position();
return getPosition(this.el);
}

getOffsetTop(): number {
Expand Down Expand Up @@ -757,7 +770,7 @@ export class ElementHelper {
}

isVisible(): boolean {
return $(this.el).is(':visible');
return isVisible(this.el);
}

countChildren(): number {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export function animateScrollTop(
el: HTMLElement,
targetTop: number,
durationMs: number,
complete: () => void
) {
const startScrollTop = el.scrollTop;
const distance = targetTop - startScrollTop;
const framesPerSecond = 50;
const timeout = 1000 / framesPerSecond;
const intervals = durationMs / timeout;
const step = distance / intervals;
const timer = setInterval(() => {
if (el.scrollTop >= targetTop) {
clearInterval(timer);
if (el.scrollTop > targetTop) { // Handle overshoot (decimals)
el.scrollTop = targetTop;
}
complete();
} else {
el.scrollTop += step;
}
}, timeout);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const elementExists = (element: Element) => typeof(element) != 'undefined' && element != null;

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function findElements(
selector: string,
context: Document | Element = document
) {
return Array.from(context.querySelectorAll(selector));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {findElements} from './findElements';
import {isHTMLElement} from './isHTMLElement';

export function findHTMLElements(
selector: string,
context: Document | Element = document
): HTMLElement[] {
return findElements(selector, context).filter((el) => isHTMLElement(el)) as HTMLElement[];
}
6 changes: 6 additions & 0 deletions src/main/resources/assets/admin/common/js/dom/util/first.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function first(
selector: string,
context: Document | Element = document
) {
return context.querySelector(selector);
}
3 changes: 3 additions & 0 deletions src/main/resources/assets/admin/common/js/dom/util/getData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getData(el: Element, name: string): string | null {
return el.getAttribute(`data-${name}`);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function getInnerHeight(el: Element) {
return el.clientHeight;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function getOffset(el: Element) {
const box = el.getBoundingClientRect();
const docElem = document.documentElement;
return {
top: box.top + window.scrollY - docElem.clientTop,
left: box.left + window.scrollX - docElem.clientLeft
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {isHTMLElement} from './isHTMLElement';

export function getOffsetParent(el: HTMLElement): HTMLElement {
const maybeHTMLElement = el.offsetParent;
return isHTMLElement(maybeHTMLElement) ? maybeHTMLElement : el;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function getOuterHeightWithMargin(el: Element) {
const style = getComputedStyle(el);

return (
el.getBoundingClientRect().height +
parseFloat(style.marginTop) +
parseFloat(style.marginBottom)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function getOuterWidthWithMargin(el: Element) {
const style = getComputedStyle(el);

return (
el.getBoundingClientRect().width +
parseFloat(style.marginLeft) +
parseFloat(style.marginRight)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function getPosition(el: Element) {
const {top, left} = el.getBoundingClientRect();
const {marginTop, marginLeft} = getComputedStyle(el);
return {
top: top - parseInt(marginTop, 10),
left: left - parseInt(marginLeft, 10)
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function isHTMLElement(el: unknown): el is HTMLElement {
if (typeof HTMLElement !== 'object') {
throw new Error('Your browser does not support HTMLElement. Please use a newer browser.');
}
return el instanceof HTMLElement;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isVisible(el: HTMLElement) {
return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {isHTMLElement} from './isHTMLElement';
import {first} from './first';

export function selectHTMLElement(
selector: string,
context: Document | Element = document
): HTMLElement | null {
const el = first(selector, context);
return isHTMLElement(el) ? el : null;
}
4 changes: 4 additions & 0 deletions src/main/resources/assets/admin/common/js/dom/util/setData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function setData(el: Element, name: string, value: string) {
el.setAttribute('data-' + name, value);
return el;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function setInnerHeight(el: HTMLElement, value: string) {
el.style.height = value;
return el;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function setInnerHtml(el: Element, value: string) {
el.innerHTML = value;
return el;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function setOffset(el: HTMLElement, {top, left}: {top: number, left: number}) {
el.style.top = `${top}px`;
el.style.left = `${left}px`;
return el;
}
4 changes: 4 additions & 0 deletions src/main/resources/assets/admin/common/js/dom/util/show.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function show(el: HTMLElement) {
el.style.display = '';
return el;
}
Loading

0 comments on commit 82aa181

Please sign in to comment.