From a5ee77786052f9f22ac89279f98c6b26e0c3bf8b Mon Sep 17 00:00:00 2001 From: Florian Bouillon Date: Wed, 2 Sep 2020 12:50:47 +0200 Subject: [PATCH] Added DomManager Signed-off-by: Florian Bouillon --- packages/dom-manager/.babelrc | 5 + packages/dom-manager/.gitignore | 1 + packages/dom-manager/.npmignore | 8 + packages/dom-manager/package.json | 30 ++++ packages/dom-manager/src/DOMElement.ts | 164 ++++++++++++++++++++ packages/dom-manager/src/DOMFleetManager.ts | 41 +++++ packages/dom-manager/src/browser.ts | 6 + packages/dom-manager/src/index.ts | 7 + packages/dom-manager/tsconfig.json | 11 ++ packages/dom-manager/webpack.config.js | 17 ++ 10 files changed, 290 insertions(+) create mode 100644 packages/dom-manager/.babelrc create mode 100644 packages/dom-manager/.gitignore create mode 100644 packages/dom-manager/.npmignore create mode 100644 packages/dom-manager/package.json create mode 100644 packages/dom-manager/src/DOMElement.ts create mode 100644 packages/dom-manager/src/DOMFleetManager.ts create mode 100644 packages/dom-manager/src/browser.ts create mode 100644 packages/dom-manager/src/index.ts create mode 100644 packages/dom-manager/tsconfig.json create mode 100644 packages/dom-manager/webpack.config.js diff --git a/packages/dom-manager/.babelrc b/packages/dom-manager/.babelrc new file mode 100644 index 0000000..867a790 --- /dev/null +++ b/packages/dom-manager/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + "@babel/preset-env" + ] +} diff --git a/packages/dom-manager/.gitignore b/packages/dom-manager/.gitignore new file mode 100644 index 0000000..178135c --- /dev/null +++ b/packages/dom-manager/.gitignore @@ -0,0 +1 @@ +/dist/ diff --git a/packages/dom-manager/.npmignore b/packages/dom-manager/.npmignore new file mode 100644 index 0000000..11a09b5 --- /dev/null +++ b/packages/dom-manager/.npmignore @@ -0,0 +1,8 @@ +node_modules +src +.babelrc +.gitignore +.npmignore +tsconfig.* +webpack.config.js +yarn-error.log diff --git a/packages/dom-manager/package.json b/packages/dom-manager/package.json new file mode 100644 index 0000000..04bc149 --- /dev/null +++ b/packages/dom-manager/package.json @@ -0,0 +1,30 @@ +{ + "name": "@dzeio/dom-manager", + "version": "0.0.1", + "description": "JQuery but lighter", + "repository": { + "type": "git", + "url": "https://github.com/dzeiocom/libs.git", + "directory": "packages/dom-manager" + }, + "author": "Aviortheking", + "license": "MIT", + "main": "./dist/index.js", + "browser": "./dist/browser.js", + "types": "./dist/index.d.ts", + "devDependencies": { + "@babel/core": "^7.11.4", + "@babel/preset-env": "^7.11.0", + "babel-loader": "^8.1.0", + "ts-loader": "^8.0.3", + "ts-node": "^9.0.0", + "typescript": "^4.0.2", + "webpack": "^4.44.1", + "webpack-cli": "^3.3.12" + }, + "scripts": { + "prepublishOnly": "yarn build", + "build": "webpack --mode=\"production\" && tsc", + "test": "jest --coverage && codecov -f coverage/coverage-final.json" + } +} diff --git a/packages/dom-manager/src/DOMElement.ts b/packages/dom-manager/src/DOMElement.ts new file mode 100644 index 0000000..d4a2a5f --- /dev/null +++ b/packages/dom-manager/src/DOMElement.ts @@ -0,0 +1,164 @@ +type Tags = keyof HTMLElementTagNameMap + +export default class DOMElement { + + public item: T + + public static create(tagName: K, options?: ElementCreationOptions): DOMElement; + public static create(tagName: string, options?: ElementCreationOptions): DOMElement { + return new DOMElement(tagName as Tags, options) + } + + public constructor(tagName: Tags | T, options?: ElementCreationOptions) { + if (tagName instanceof HTMLElement) { + this.item = tagName + return + } + this.item = document.createElement(tagName, options) as any + } + + public static get(query: string | T, source?: HTMLElement): DOMElement | undefined { + if (!(query instanceof HTMLElement)) { + const tmp = (source || document).querySelector(query) + if (!tmp) { + return undefined + } + return new DOMElement(tmp) + } + return new DOMElement(query) + } + + public on(type: K, listener: (this: T, ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): this + public on(type: string, listener: (this: T, ev: Event) => void, options?: boolean | AddEventListenerOptions): this + public on(type: string, listener: (this: T, ev: Event) => void, options?: boolean | AddEventListenerOptions) { + this.item.addEventListener(type, listener, options) + return this + } + + public off(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => void) { + this.item.removeEventListener(type, listener) + return this + } + + public text(): string + public text(val: string): this + public text(val?: string) { + if (val) { + this.item.innerText = val + return this + } + return this.item.innerText + } + + public html(): string + public html(val: string): this + public html(val?: string) { + if (val) { + this.item.innerHTML = val + return this + } + return this.item.innerText + } + + public addClass(...classes: Array) { + this.item.classList.add(...classes) + return this + } + + public setClass(...classes: Array) { + this.item.classList.forEach((cls) => { + if (!classes.includes(cls)) { + this.item.classList.remove(cls) + } + }) + this.addClass(...classes) + return this + } + + public classList(...classes: Array): this + public classList(): Array + public classList(...classes: Array) { + if (!classes) { + const res: Array = [] + this.item.classList.forEach((el) => res.push(el)) + return res + } + return this.setClass(...classes) + } + + public toggleClass(...classes: Array) { + for (const classe of classes) { + this.item.classList.toggle(classe) + } + return this + } + + public removeClass(...classes: Array) { + this.item.classList.remove(...classes) + return this + } + + public placeBefore(item: DOMElement | HTMLElement) { + if (item instanceof DOMElement) { + item = item.item + } + const parent = item.parentElement + if (!parent) { + throw new Error('can\'t place DOMElement before item because it has no parent') + } + parent.insertBefore(this.item, item) + return this + } + + public emit(event: E): this + public emit(event: string): this + public emit(event: string): this { + if (event in this.item) { + ;(this.item as any)[event]() + return this + } + this.item.dispatchEvent(new Event(event)) + return this + } + + public attr(key: string): string | null + public attr(key: string, value: string): this + public attr(key: keyof T, value: boolean): this + public attr(key: string, value: null): this + public attr(key: string | keyof T, value?: string | boolean | null): this | string | null { + if (!value) { + return this.item.getAttribute(key as string) + } + if (value === null) { + this.item.removeAttribute(key as string) + return this + } + if (typeof value === 'boolean') { + this.item[key as 'draggable'] = value + return this + } + this.item.setAttribute(key as string, value) + return this + } + + + public data(key: string): string | null + public data(key: string, value: string): this + public data(key: string, value: null): this + public data(key: string, value?: string | null): this | string | null { + // @ts-ignore + return this.attr(`data-${key}`, value) + } + + public style(key: string, value?: string | number) { + if (typeof value === 'undefined') { + return this.item.style[key as any] + } + this.item.style[key as any] = value as string + return this + } + + public exist() { + return !!this.item + } +} diff --git a/packages/dom-manager/src/DOMFleetManager.ts b/packages/dom-manager/src/DOMFleetManager.ts new file mode 100644 index 0000000..f26c27d --- /dev/null +++ b/packages/dom-manager/src/DOMFleetManager.ts @@ -0,0 +1,41 @@ +import { DOMElement } from "." + +export default class DOMFleetManager { + public items: Array> = [] + + public constructor( + private query: string, + private source?: HTMLElement + ) { + this.refresh() + } + + public each(fn: (item: DOMElement, index: number) => void) { + this.items.forEach((el, index) => fn(el, index)) + } + + public on(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions) { + this.each((item) => item.on(type, listener, options)) + } + + public off(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => void) { + this.each((item) => item.off(type, listener)) + } + + public refresh() { + this.items = [] + ;(this.source || document).querySelectorAll(this.query).forEach((item) => { + const element = DOMElement.get(item) + if (!element) { + return + } + this.items.push( + element + ) + }) + } + + public [Symbol.iterator]() { + return this.items + } +} diff --git a/packages/dom-manager/src/browser.ts b/packages/dom-manager/src/browser.ts new file mode 100644 index 0000000..d3b141b --- /dev/null +++ b/packages/dom-manager/src/browser.ts @@ -0,0 +1,6 @@ +import { DOMFleetManager, DOMElement} from "."; + +// @ts-expect-error +window.DOMElement = DOMElement +// @ts-expect-error +window.DOMFleetManager = DOMFleetManager diff --git a/packages/dom-manager/src/index.ts b/packages/dom-manager/src/index.ts new file mode 100644 index 0000000..3c5c066 --- /dev/null +++ b/packages/dom-manager/src/index.ts @@ -0,0 +1,7 @@ +import DOMElement from './DOMElement' +import DOMFleetManager from './DOMFleetManager' + +export { + DOMElement, + DOMFleetManager +} diff --git a/packages/dom-manager/tsconfig.json b/packages/dom-manager/tsconfig.json new file mode 100644 index 0000000..679b23a --- /dev/null +++ b/packages/dom-manager/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist" + }, + "files": [ + "src/DOMElement.ts", + "src/DOMFleetManager.ts", + "src/index.ts" + ] +} diff --git a/packages/dom-manager/webpack.config.js b/packages/dom-manager/webpack.config.js new file mode 100644 index 0000000..6273b45 --- /dev/null +++ b/packages/dom-manager/webpack.config.js @@ -0,0 +1,17 @@ +module.exports = { + entry: './src/index', + output: { + path: __dirname, + filename: './dist/browser.js', + }, + resolve: { + extensions: ['.js', '.ts'], + }, + module: { + rules: [ + { + test: /\.ts$/, use: ['babel-loader', 'ts-loader'], exclude: /node_modules/ + } + ] + } +}