Skip to content

Commit

Permalink
support dimension bindings in cross-origin mode
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkishi committed Jun 9, 2019
1 parent caebe0d commit cb5fddb
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 35 deletions.
11 changes: 2 additions & 9 deletions src/compiler/compile/render-dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,15 +481,8 @@ export default class ElementWrapper extends Wrapper {
group.events.forEach(name => {
if (name === 'resize') {
// special case
const resize_listener = block.get_unique_name(`${this.var}_resize_listener`);
block.add_variable(resize_listener);

block.builders.mount.add_line(
`${resize_listener} = @add_resize_listener(${this.var}, ${callee}.bind(${this.var}));`
);

block.builders.destroy.add_line(
`${resize_listener}.cancel();`
block.event_listeners.push(
`@listen_resize_with_iframe(${this.var}, ${callee}.bind(${this.var}))`
);
} else {
block.event_listeners.push(
Expand Down
66 changes: 44 additions & 22 deletions src/runtime/internal/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,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);
}
Expand Down Expand Up @@ -215,35 +215,57 @@ 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 it 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) {
try {
if (typeof window === 'undefined' || !window.parent || window.parent.document) {
crossorigin = false;
}
} 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.type = 'text/html';
return crossorigin;
}

let win;
export function listen_resize_with_iframe(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';
}

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};`
);

let unsubscribe: () => void;

if (/Trident/.test(navigator.userAgent)) {
element.appendChild(object);
object.data = 'about:blank';
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();
};
}

Expand Down
8 changes: 4 additions & 4 deletions test/js/samples/bind-width-height/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@
import {
SvelteComponent,
add_render_callback,
add_resize_listener,
detach,
element,
init,
insert,
listen_resize_with_iframe,
noop,
safe_not_equal
} from "svelte/internal";

function create_fragment(ctx) {
var div, div_resize_listener;
var div, dispose;

return {
c() {
div = element("div");
div.textContent = "some content";
add_render_callback(() => ctx.div_resize_handler.call(div));
dispose = listen_resize_with_iframe(div, ctx.div_resize_handler.bind(div));
},

m(target, anchor) {
insert(target, div, anchor);
div_resize_listener = add_resize_listener(div, ctx.div_resize_handler.bind(div));
},

p: noop,
Expand All @@ -35,7 +35,7 @@ function create_fragment(ctx) {
detach(div);
}

div_resize_listener.cancel();
dispose();
}
};
}
Expand Down

0 comments on commit cb5fddb

Please sign in to comment.