@web-atoms/core
Version:
263 lines (221 loc) • 6.79 kB
text/typescript
import { INameValues, IRect } from "../../core/types";
export class AncestorEnumerator {
public static find(e: HTMLElement, filter: (e: HTMLElement) => any) {
let start = e?.parentElement;
while (start) {
if(filter(start)) {
return start as HTMLElement;
}
start = start.parentElement;
}
}
/**
* Finds the parent element that matches given selector. It does not
* return element that contains the selector.
* @param e target Element
* @param selector selector to match
* @returns
*/
public static findSelector(e: HTMLElement, selector: string) {
let start = e?.parentElement;
while (start) {
const found = start.matches(selector);
if(found) {
return start as HTMLElement;
}
start = start.parentElement;
}
}
}
// refer http://youmightnotneedjquery.com/
export class ChildEnumerator {
public static find(e: HTMLElement, filter: (e: HTMLElement) => any) {
let item = e?.firstElementChild as HTMLElement;
while (item) {
const next = item.nextElementSibling as HTMLElement;
if (filter(item)) {
return item;
}
item = next;
}
}
public static *where(e: HTMLElement, filter: (e: HTMLElement) => any) {
let item = e?.firstElementChild as HTMLElement;
while (item) {
const next = item.nextElementSibling as HTMLElement;
if (filter(item)) {
yield item;
}
item = next;
}
}
public static *enumerate(e: HTMLElement) {
let item = e?.firstElementChild as HTMLElement;
while (item) {
const next = item.nextElementSibling as HTMLElement;
yield item;
item = next;
}
}
private item: HTMLElement;
public get current(): HTMLElement {
return this.item;
}
constructor(private e: HTMLElement) {
}
public next(): boolean {
if (!this.item) {
this.item = this.e?.firstElementChild as HTMLElement;
} else {
this.item = this.item.nextElementSibling as HTMLElement;
}
return this.item ? true : false;
}
}
/**
* Enumerate through all the descendents including self.
* @param e Element
*/
export function *descendentElementIterator(e: Element) {
const stack: Element[] = [];
const start = e;
if (start) {
stack.push(start);
}
while (stack.length) {
const pop = stack.pop();
const next = pop.nextElementSibling;
yield pop;
if (next) {
stack.push(next);
}
const child = pop.firstElementChild;
if (child) {
stack.push(child);
}
}
}
/**
* Enumerate through all the descendents including self.
* @param e Element
*/
export function *descendentIterator(e: Node) {
const stack: Node[] = [];
const start = e;
if (start) {
stack.push(start);
}
while (stack.length) {
const pop = stack.pop();
const next = pop.nextSibling;
yield pop;
if (next) {
stack.push(next);
}
const child = pop.firstChild;
if (child) {
stack.push(child);
}
}
}
export class AtomUI {
public static outerHeight(el: HTMLElement, margin: boolean = false): number {
let height = el.offsetHeight;
if (!margin) { return height; }
const style = getComputedStyle(el);
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
return height;
}
public static outerWidth(el: HTMLElement, margin: boolean = false): number {
let width = el.offsetWidth;
if (!margin) { return width; }
const style = getComputedStyle(el);
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
return width;
}
public static innerWidth(el: HTMLElement): number {
return el.clientWidth;
}
public static innerHeight(el: HTMLElement): number {
return el.clientHeight;
}
public static scrollTop(el: HTMLElement, y: number): any {
el.scrollTo(0, y);
}
public static screenOffset(e: HTMLElement): IRect {
const r = {
x: e.offsetLeft,
y: e.offsetTop,
width: e.offsetWidth,
height: e.offsetHeight
};
if (e.offsetParent) {
const p = this.screenOffset(e.offsetParent as HTMLElement);
r.x += p.x;
r.y += p.y;
}
return r;
}
public static parseUrl(url: string): INameValues {
const r: INameValues = {};
const plist: string[] = url.split("&");
for (const item of plist) {
const p: string[] = item.split("=");
const key: string = decodeURIComponent(p[0]);
if (!key) {
continue;
}
let val: string = p[1];
if (val) {
val = decodeURIComponent(val);
}
// val = AtomUI.parseValue(val);
r[key] = this.parseValue(val);
}
return r;
}
public static parseValue(val: string): (number|boolean|string) {
let n: number;
if (/^[0-9]+$/.test(val)) {
n = parseInt(val, 10);
if (!isNaN(n)) {
return n;
}
return val;
}
if (/^[0-9]+\.[0-9]+/gi.test(val)) {
n = parseFloat(val);
if (!isNaN(n)) {
return n;
}
return val;
}
if (val === "true") {
return true;
}
if (val === "false") {
return false;
}
return val;
}
public static assignID(element: HTMLElement): string {
if (!element.id) {
element.id = "__waID" + AtomUI.getNewIndex();
}
return element.id;
}
public static toNumber(text: string): number {
if (!text) {
return 0;
}
if (text.constructor === String) {
return parseFloat(text);
}
return 0;
}
public static getNewIndex(): number {
AtomUI.index = AtomUI.index + 1;
return AtomUI.index;
}
private static index: number = 1001;
}