|
|
|
@ -57,7 +57,7 @@ export function empty() {
|
|
|
|
|
return text('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function listen(node: Node, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions) {
|
|
|
|
|
export function listen(node: EventTarget, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions) {
|
|
|
|
|
node.addEventListener(event, handler, options);
|
|
|
|
|
return () => node.removeEventListener(event, handler, options);
|
|
|
|
|
}
|
|
|
|
@ -234,37 +234,61 @@ export function select_multiple_value(select) {
|
|
|
|
|
return [].map.call(select.querySelectorAll(':checked'), option => option.__value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function add_resize_listener(element, fn) {
|
|
|
|
|
if (getComputedStyle(element).position === 'static') {
|
|
|
|
|
element.style.position = 'relative';
|
|
|
|
|
// unfortunately this can't be a constant as that wouldn't be tree-shakeable
|
|
|
|
|
// so we cache the result instead
|
|
|
|
|
let crossorigin: boolean;
|
|
|
|
|
|
|
|
|
|
export function is_crossorigin() {
|
|
|
|
|
if (crossorigin === undefined) {
|
|
|
|
|
crossorigin = false;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (typeof window !== 'undefined' && window.parent) {
|
|
|
|
|
void window.parent.document;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
crossorigin = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const object = document.createElement('object');
|
|
|
|
|
object.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
|
|
|
|
|
object.setAttribute('aria-hidden', 'true');
|
|
|
|
|
object.type = 'text/html';
|
|
|
|
|
object.tabIndex = -1;
|
|
|
|
|
return crossorigin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let win;
|
|
|
|
|
export function add_resize_listener(node: HTMLElement, fn: () => void) {
|
|
|
|
|
const computed_style = getComputedStyle(node);
|
|
|
|
|
const z_index = (parseInt(computed_style.zIndex) || 0) - 1;
|
|
|
|
|
|
|
|
|
|
object.onload = () => {
|
|
|
|
|
win = object.contentDocument.defaultView;
|
|
|
|
|
win.addEventListener('resize', fn);
|
|
|
|
|
};
|
|
|
|
|
if (computed_style.position === 'static') {
|
|
|
|
|
node.style.position = 'relative';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (/Trident/.test(navigator.userAgent)) {
|
|
|
|
|
element.appendChild(object);
|
|
|
|
|
object.data = 'about:blank';
|
|
|
|
|
const iframe = element('iframe');
|
|
|
|
|
iframe.setAttribute('style',
|
|
|
|
|
`display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ` +
|
|
|
|
|
`overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: ${z_index};`
|
|
|
|
|
);
|
|
|
|
|
iframe.setAttribute('aria-hidden', 'true');
|
|
|
|
|
iframe.tabIndex = -1;
|
|
|
|
|
|
|
|
|
|
let unsubscribe: () => void;
|
|
|
|
|
|
|
|
|
|
if (is_crossorigin()) {
|
|
|
|
|
iframe.src = `data:text/html,<script>onresize=function(){parent.postMessage(0,'*')}</script>`;
|
|
|
|
|
unsubscribe = listen(window, 'message', (event: MessageEvent) => {
|
|
|
|
|
if (event.source === iframe.contentWindow) fn();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
object.data = 'about:blank';
|
|
|
|
|
element.appendChild(object);
|
|
|
|
|
iframe.src = 'about:blank';
|
|
|
|
|
iframe.onload = () => {
|
|
|
|
|
unsubscribe = listen(iframe.contentWindow, 'resize', fn);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
cancel: () => {
|
|
|
|
|
win && win.removeEventListener && win.removeEventListener('resize', fn);
|
|
|
|
|
element.removeChild(object);
|
|
|
|
|
}
|
|
|
|
|
append(node, iframe);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
detach(iframe);
|
|
|
|
|
if (unsubscribe) unsubscribe();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|