@serenity-is/corelib
Version:
Serenity Core Library
168 lines (141 loc) • 4.43 kB
text/typescript
import { isArrayLike } from "../base";
export { };
interface LayoutTimerReg {
handler: () => void;
element: () => HTMLElement;
width: boolean;
height: boolean;
storedWidth?: number;
storedHeight?: number;
}
export namespace LayoutTimer {
var timeout: number;
var nextKey: number = 0;
var regCount: number = 0;
var regs: { [key: number]: LayoutTimerReg; } = {};
function startTimer() {
if (timeout == null && regCount > 0) {
timeout = window.setTimeout(onTimeout, 100);
}
}
function clearTimer() {
if (timeout != null) {
clearTimeout(timeout);
timeout = null;
}
}
function onTimeout() {
for (var key in regs) {
var reg = regs[key];
try {
var el = reg.element();
if (!el)
continue;
var w = el.offsetWidth;
var h = el.offsetHeight;
try {
if ((reg.width && reg.storedWidth !== w) ||
(reg.height && reg.storedHeight !== h) ||
(!reg.width && !reg.height && (!w !== !reg.storedWidth || !h !== !reg.storedHeight))) {
if (w > 0 && h > 0) {
try {
reg.handler();
}
finally {
w = el.offsetWidth;
h = el.offsetHeight;
}
}
}
}
finally {
reg.storedWidth = w;
reg.storedHeight = h;
}
}
catch (e) {
console.log(e);
}
}
clearTimer();
startTimer();
}
export function store(key: number) {
var reg = regs[key];
if (!reg)
return;
var el = reg.element();
if (!el)
return;
reg.storedWidth = el.offsetWidth;
reg.storedHeight = el.offsetHeight;
}
export function trigger(key: number) {
var reg = regs[key];
if (!reg)
return;
store(key);
if (reg.storedWidth >= 0 &&
reg.storedHeight >= 0) {
reg.handler();
}
store(key);
}
export function onSizeChange(element: () => HTMLElement, handler: () => void, width?: boolean, height?: boolean): number {
if (handler == null)
throw "Layout handler can't be null!";
regs[++nextKey] = {
element: element,
handler: handler,
width: width !== false,
height: height !== false
}
regCount++;
store(nextKey)
startTimer();
return nextKey;
}
export function onWidthChange(element: () => HTMLElement, handler: () => void) {
return onSizeChange(element, handler, true, false);
}
export function onHeightChange(element: () => HTMLElement, handler: () => void) {
return onSizeChange(element, handler, false, true);
}
export function onShown(element: () => HTMLElement, handler: () => void) {
return onSizeChange(element, handler, false, false);
}
export function off(key: number): number {
var reg = regs[key];
if (!reg)
return 0;
delete regs[key];
regCount--;
if (regCount <= 0)
clearTimer();
return 0;
}
}
export function executeOnceWhenVisible(el: HTMLElement | ArrayLike<HTMLElement>, callback: Function): void {
el = isArrayLike(el) ? el[0] : el;
if (!el)
return;
if (el.offsetWidth > 0 && el.offsetHeight > 0) {
callback();
return;
}
var timer = LayoutTimer.onShown(() => el as HTMLElement, () => {
LayoutTimer.off(timer);
callback();
});
}
export function executeEverytimeWhenVisible(el: HTMLElement | ArrayLike<HTMLElement>, callback: Function, callNowIfVisible: boolean): void {
el = isArrayLike(el) ? el[0] : el;
if (!el)
return;
if (callNowIfVisible && el.offsetWidth > 0 && el.offsetHeight > 0) {
callback();
}
LayoutTimer.onShown(() => el as HTMLElement, () => {
callback();
});
}