@pivoto/core
Version:

217 lines (190 loc) • 5.81 kB
text/typescript
const SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
const MOZ_HACK_REGEXP = /^moz([A-Z])/;
const ieVersion = Number((document as any).documentMode);
function trim(string: string): string {
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
}
function camelCase(name: string): string {
return name.replace(SPECIAL_CHARS_REGEXP, function (_, separator, letter, offset) {
return offset ? letter.toUpperCase() : letter;
}).replace(MOZ_HACK_REGEXP, 'Moz$1');
}
export const on = (function () {
if (document.addEventListener) {
return function (element: Node, event: any, handler: (this: Node, e: any) => any) {
if (element && event && handler) {
element.addEventListener(event, handler, false);
}
};
} else {
return function (element: Node, event: any, handler: (this: Node, e: any) => any) {
if (element && event && handler) {
// @ts-ignore
element.attachEvent('on' + event, handler);
}
};
}
})()
export const off = (function () {
if (document.removeEventListener) {
return function (element: Node, event: any, handler: (this: Node, e: any) => any) {
if (element && event) {
element.removeEventListener(event, handler, false);
}
};
} else {
return function (element: Node, event: any, handler: (this: Node, e: any) => any) {
if (element && event) {
// @ts-ignore
element.detachEvent('on' + event, handler);
}
};
}
})()
export const once = function (el: Node, event: any, fn: (this: Node, e: any) => any) {
let listener = function () {
if (fn) {
fn.apply(this, arguments);
}
off(el, event, listener);
};
on(el, event, listener);
}
export function hasClass(el: Element, cls: string): boolean {
if (!el || !cls) return false;
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
if (el.classList) {
return el.classList.contains(cls);
} else {
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
}
export function addClass(el: Element, cls: string): void {
if (!el) return;
let curClass = el.className;
let classes = (cls || '').split(' ');
for (let i = 0, j = classes.length; i < j; i++) {
let clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.add(clsName);
} else if (!hasClass(el, clsName)) {
curClass += ' ' + clsName;
}
}
if (!el.classList) {
el.setAttribute('class', curClass);
}
}
export function removeClass(el: Element, cls: string): void {
if (!el || !cls) return;
let classes = cls.split(' ');
let curClass = ' ' + el.className + ' ';
for (let i = 0, j = classes.length; i < j; i++) {
let clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.remove(clsName);
} else if (hasClass(el, clsName)) {
curClass = curClass.replace(' ' + clsName + ' ', ' ');
}
}
if (!el.classList) {
el.setAttribute('class', trim(curClass));
}
}
function getStyleCompatible(element: HTMLElement, styleName: string): any {
if (!element || !styleName) return null;
styleName = camelCase(styleName);
if (styleName === 'float') {
styleName = 'styleFloat';
}
try {
switch (styleName) {
case 'opacity':
try {
// @ts-ignore
return element.filters.item('alpha').opacity / 100;
} catch (e) {
return 1.0;
}
default:
// @ts-ignore
return (element.style[styleName] || element.currentStyle ? element.currentStyle[styleName] : null);
}
} catch (e) {
return element.style[styleName];
}
}
function getStyleStd(element: HTMLElement, styleName: string): any {
if (!element || !styleName) return null;
styleName = camelCase(styleName);
if (styleName === 'float') {
styleName = 'cssFloat';
}
try {
let computed = document.defaultView.getComputedStyle(element, '');
return element.style[styleName] || computed ? computed[styleName] : null;
} catch (e) {
return element.style[styleName];
}
}
export const getStyle = ieVersion < 9 ? getStyleCompatible : getStyleStd
export function setStyle(element: HTMLElement, styleName: string | object, value: any) {
if (!element || !styleName) return;
if (typeof styleName === 'object') {
for (let prop in styleName) {
if (styleName.hasOwnProperty(prop)) {
setStyle(element, prop, styleName[prop]);
}
}
} else {
styleName = camelCase(styleName);
if (styleName === 'opacity' && ieVersion < 9) {
element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')';
} else {
element.style[styleName] = value;
}
}
}
export const isScroll: (el: HTMLElement, vertical?: any) => boolean = (el, vertical) => {
const determinedDirection = vertical !== null && vertical !== undefined;
const overflow = determinedDirection
? vertical
? getStyle(el, 'overflow-y')
: getStyle(el, 'overflow-x')
: getStyle(el, 'overflow');
return overflow.match(/(scroll|auto|overlay)/);
}
export const getScrollContainer = (el: HTMLElement, vertical?: any) => {
let parent: Node = el;
while (parent) {
if ([window, document, document.documentElement].includes(parent as any)) {
return window;
}
if (isScroll(parent as HTMLElement, vertical)) {
return parent;
}
parent = parent.parentNode;
}
return parent;
}
export const isInContainer = (el: HTMLElement, container: HTMLElement): boolean => {
if (!el || !container) return false;
const elRect = el.getBoundingClientRect();
let containerRect;
if ([window, document, document.documentElement, null, undefined].includes(container)) {
containerRect = {
top: 0,
right: window.innerWidth,
bottom: window.innerHeight,
left: 0
};
} else {
containerRect = container.getBoundingClientRect();
}
return elRect.top < containerRect.bottom &&
elRect.bottom > containerRect.top &&
elRect.right > containerRect.left &&
elRect.left < containerRect.right;
}