Skip to content

Instantly share code, notes, and snippets.

@DeveloperMarius
Created June 15, 2024 23:50
Show Gist options
  • Save DeveloperMarius/677adf6e692803036b3441ce41c6af78 to your computer and use it in GitHub Desktop.
Save DeveloperMarius/677adf6e692803036b3441ce41c6af78 to your computer and use it in GitHub Desktop.
This class extends dom Elements with some jQuery functions and other helpers.
/**
* This class extends dom Elements with some jQuery functions and other helpers.
*/
declare global {
interface String {
toHtmlElement(): DocumentFragment;
}
interface Element {
//jQuery helpers
offset(): { left: number; top: number };
find(selectors: string): HTMLElement | null;
findAll(selectors: string): NodeListOf<Element>;
parent(): HTMLElement | null;
width(): number;
height(): number;
text(text: string): Element;
text(): string | null;
data(key: string): string | null;
data(key: string, value: string): Element;
is(selector: string): boolean;
on(type: string, listener: (this: Element, ev: Event) => any): Element;
on(type: string, selector: string, listener: (this: Element, ev: Event) => any): Element;
hasClass(className: string): boolean;
addClass(className: string): Element;
removeClass(className: string): Element;
toggleClass(className: string, state?: boolean): Element;
html(html: string): Element;
html(): string;
css(key: string): string;
css(key: string, value: string | number): Element;
css(properties: { [key: string]: string | number }): Element;
toggle(state?: boolean): Element;
removeData(key: string): Element;
val(): string;
val(value: string | number): Element;
attr(attribute: string): string;
attr(attribute: string, value: string | boolean | number | null): Element;
prop(attribute: string): string;
prop(attribute: string, value: string | boolean | number): Element;
index(): number;
appendHtml(html: string): void;
clone(): Element;
}
interface Document {
on(type: string, listener: (this: Document, ev: Event) => any): Document;
on(type: string, selector: string, listener: (this: Document, ev: Event) => any): Document;
scrollTop(): number;
scrollLeft(): number;
}
}
export function initDomHelpers(): void {
Document.prototype.scrollTop = function (): number {
//https://stackoverflow.com/questions/50431891/how-can-i-detect-the-scrolltop-of-an-element-using-vanilla-javascript
return document.documentElement.scrollTop;
};
Document.prototype.scrollLeft = function (): number {
return document.documentElement.scrollLeft;
};
Element.prototype.val = function (parameter1?: any): any {
if (parameter1 !== undefined && this instanceof HTMLInputElement) {
this.value = parameter1;
return this;
}
if (this instanceof HTMLInputElement) return this.value;
return '';
};
Element.prototype.offset = function () {
let rect = this.getBoundingClientRect();
return {
top: rect.top + window.scrollY,
left: rect.left + window.scrollX
};
};
Element.prototype.find = function (selectors: string) {
return this.querySelector(selectors);
};
Element.prototype.findAll = function (selectors: string) {
return this.querySelectorAll(selectors);
};
Element.prototype.parent = function () {
return this.parentElement;
};
Element.prototype.width = function (): number {
return parseFloat(getComputedStyle(this).width);
};
Element.prototype.height = function (): number {
return parseFloat(getComputedStyle(this).height);
};
Element.prototype.hasClass = function (className: string): boolean {
return this.classList.contains(className);
};
Element.prototype.appendHtml = function (parameter1: string) {
this.appendChild(document.createRange().createContextualFragment(parameter1));
};
Element.prototype.text = function (prameter1?: any): any {
if (prameter1 && typeof prameter1 == 'string') {
this.textContent = prameter1;
return this;
} else {
return this.textContent;
}
};
Element.prototype.html = function (parameter1: any): any {
if (parameter1 && typeof parameter1 == 'string') {
this.innerHTML = parameter1;
return this;
}else{
return this.innerHTML;
}
};
Element.prototype.index = function (): number {
let parent = this.parentNode;
if (parent === null) return -1;
let children = parent.childNodes;
let num = 0;
for (let i = 0; i < children.length; i++) {
if (children[i] == this) return num;
if (children[i].nodeType == 1) num++;
}
return -1;
};
Element.prototype.is = function (selector: string): boolean {
return this.matches(selector);
};
Element.prototype.data = function (parameter1: any, parameter2?: any): any {
return this.attr('data-' + parameter1, parameter2);
};
Element.prototype.attr = function (parameter1: any, parameter2?: any): any {
if (
parameter1 &&
typeof parameter1 == 'string' &&
((parameter2 && (typeof parameter2 == 'string' || typeof parameter2 == 'number')) ||
parameter2 === '' ||
parameter2 === null)
) {
if (parameter2 === null || parameter2 === '' || parameter2 === false) {
this.removeAttribute(parameter1);
} else {
if (parameter2 === true) parameter2 = '';
this.setAttribute(parameter1, parameter2);
}
return this;
} else if (parameter1) {
return this.getAttribute(parameter1);
}
};
Element.prototype.prop = function (parameter1: any, parameter2?: any): any {
if (
parameter1 &&
typeof parameter1 == 'string' &&
((parameter2 && (typeof parameter2 == 'string' || typeof parameter2 == 'number')) ||
parameter2 === '' ||
parameter2 === null)
) {
if (parameter2 === null || parameter2 === '' || parameter2 === false) {
//@ts-ignore
this[parameter1] = null;
this.removeAttribute(parameter1);
} else {
if (parameter2 === true) parameter2 = '';
//@ts-ignore
this[parameter1] = parameter2;
}
return this;
} else if (parameter1) {
//@ts-ignore
return this[parameter1];
}
};
Element.prototype.removeData = function (key: string): Element {
this.removeAttribute(key);
return this;
};
Element.prototype.clone = function (): Element {
return this.cloneNode(true) as Element;
};
Element.prototype.addClass = function (className: string): Element {
className.split(' ').forEach((classNamePart) => {
this.classList.add(classNamePart);
});
return this;
};
Element.prototype.removeClass = function (className: string): Element {
className.split(' ').forEach((classNamePart) => {
this.classList.remove(classNamePart);
});
return this;
};
Element.prototype.toggleClass = function (className: string, state?: boolean): Element {
this.classList.toggle(className, state);
return this;
};
Element.prototype.on = function (parameter1: any, parameter2: any, parameter3?: any): any {
let _this = this;
if (
parameter1 &&
typeof parameter1 == 'string' &&
parameter2 &&
typeof parameter2 == 'string' &&
parameter3
) {
parameter1.split(',').forEach(function (eventName: string) {
_this.addEventListener(eventName, function (this: HTMLElement, e: Event) {
if (!(e.target instanceof Element)) return;
let originalTarget = e.target.closest(parameter2);
if (originalTarget === null) return;
parameter3.call(originalTarget, e);
});
});
} else if (parameter1 && typeof parameter1 == 'string' && parameter2) {
parameter1.split(',').forEach(function (eventName: string) {
_this.addEventListener(eventName, parameter2);
});
}
return _this;
};
Document.prototype.on = function (parameter1: any, parameter2: any, parameter3?: any): any {
let _this = this;
if (
parameter1 &&
typeof parameter1 == 'string' &&
parameter2 &&
typeof parameter2 == 'string' &&
parameter3 &&
parameter3 instanceof Function
) {
this.addEventListener(parameter1, function (this: Document, e: Event) {
if (e.target instanceof Element && e.target.matches(parameter2)) {
parameter3.call(_this, e);
}
});
} else if (
parameter1 &&
typeof parameter1 == 'string' &&
parameter2 &&
parameter2 instanceof Function
) {
parameter1.split(' ').forEach(function (eventName: string) {
_this.addEventListener(eventName, parameter2);
});
}
return _this;
};
Element.prototype.toggle = function (state?: boolean): any {
if (this instanceof HTMLElement) {
if (state === undefined) {
state = this.style.display === 'none';
}
this.style.display = state ? '' : 'none';
}
return this;
};
Element.prototype.css = function (parameter1?: any, parameter2?: any): any {
if (this instanceof HTMLElement) {
if (
parameter1 &&
typeof parameter1 == 'string' &&
parameter2 &&
(typeof parameter2 === 'string' || typeof parameter2 === 'number')
) {
parameter1 = parameter1
.replace(/\.?([A-Z])/g, function (x, y) {
return '-' + y.toLowerCase();
})
.replace(/^-(?!-)/, '');
// @ts-ignore
this.style.setProperty(parameter1, parameter2);
return this;
} else if (typeof parameter1 == 'object' && !parameter2) {
for (let [key, value] of Object.entries(parameter1)) {
if (typeof key == 'string' && (typeof value === 'string' || typeof value === 'number'))
this.css(key, value);
}
return this;
} else if (typeof parameter1 == 'string' && !parameter2) {
// @ts-ignore
return this.style[parameter1];
}
}
};
String.prototype.toHtmlElement = function (this: string): DocumentFragment {
return document.createRange().createContextualFragment(this);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment