amis
Version:
一种MIS页面生成工具
161 lines (141 loc) • 4.53 kB
text/typescript
/**
* @file resize-sensor.js.
* @author fex
*/
class EventQueue {
q: Array<Function> = [];
add(cb: Function) {
this.q.push(cb);
}
call(...args: Array<any>) {
this.q.forEach(fn => {
fn(...args);
});
}
}
export function getComputedStyle(element: HTMLElement, prop: string) {
if ((element as any).currentStyle) {
return (element as any).currentStyle[prop];
} else if (window.getComputedStyle) {
const style = window.getComputedStyle(element, undefined);
return style ? style.getPropertyValue(prop) : undefined;
} else {
return element.style[prop as any];
}
}
function attachResizeEvent(element: HTMLElement, resized: Function) {
if (!(element as any).resizedAttached) {
(element as any).resizedAttached = new EventQueue();
(element as any).resizedAttached.add(resized);
} else if ((element as any).resizedAttached) {
(element as any).resizedAttached.add(resized);
return;
}
const resizeSensor = ((element as any).resizeSensor = document.createElement(
'div'
));
resizeSensor.className = 'resize-sensor';
let style =
'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;';
let styleChild = 'position: absolute; left: 0; top: 0;';
resizeSensor.style.cssText = style;
resizeSensor.innerHTML = `
<div class="resize-sensor-expand" style="${style}">
<div style="${styleChild}"></div>
</div>
<div class="resize-sensor-shrink" style="${style}">
<div style="${styleChild} width: 200%; height: 200%"></div>
</div>
<div class="resize-sensor-appear" style="${style}animation-name: apearSensor; animation-duration: 0.2s;"></div>`;
// 要定义 resizeSensor 这个动画,靠这个监听出现。
element.appendChild(resizeSensor);
(element as any).hasInlineStyle = element.hasAttribute('style');
const position = ((element as any).originPosition = getComputedStyle(
element,
'position'
));
if (!~['fixed', 'absolute'].indexOf(position)) {
element.style.position = 'relative';
}
const expand = resizeSensor.children[0] as HTMLElement;
const expandChild = expand.children[0] as HTMLElement;
const shrink = resizeSensor.children[1] as HTMLElement;
// let shrinkChild = shrink.children[0] as HTMLElement;
const appear = resizeSensor.children[2] as HTMLElement;
let lastWidth: number, lastHeight: number;
const reset = function () {
expandChild.style.width = expand.offsetWidth + 10 + 'px';
expandChild.style.height = expand.offsetHeight + 10 + 'px';
expand.scrollLeft = expand.scrollWidth;
expand.scrollTop = expand.scrollHeight;
shrink.scrollLeft = shrink.scrollWidth;
shrink.scrollTop = shrink.scrollHeight;
lastWidth = element.offsetWidth;
lastHeight = element.offsetHeight;
};
reset();
let changed = function () {
if ((element as any).resizedAttached) {
(element as any).resizedAttached.call();
}
};
let addEvent = function (el: HTMLElement, name: string, cb: Function) {
if ((el as any).attachEvent) {
(el as any).attachEvent('on' + name, cb);
} else {
el.addEventListener(name, cb as any);
}
};
let onScroll = function (e: Event) {
if (
element.offsetWidth != lastWidth ||
element.offsetHeight != lastHeight
) {
changed();
}
reset();
};
addEvent(expand, 'scroll', onScroll);
addEvent(shrink, 'scroll', onScroll);
addEvent(appear, 'animationstart', reset);
}
function detach(element: HTMLElement) {
if ((element as any).resizeSensor) {
if ((element as any).hasInlineStyle) {
element.style.position = (element as any).originPosition;
} else {
element.removeAttribute('style');
}
try {
element.removeChild((element as any).resizeSensor);
} catch (e) {}
delete (element as any).resizeSensor;
delete (element as any).resizedAttached;
delete (element as any).hasInlineStyle;
delete (element as any).originPosition;
}
}
export function resizeSensor(
element: HTMLElement,
callback: Function
): () => void;
export function resizeSensor(
element: HTMLElement,
callback: Function,
once: boolean = false
) {
if (once) {
attachResizeEvent(element, function (this: any) {
callback.apply(this, arguments);
detach(element);
});
return;
}
attachResizeEvent(element, callback);
let detached = false;
return function () {
if (detached) return;
detached = true;
detach(element);
};
}