fix scroll bindings

pull/1890/head
Rich Harris 7 years ago
parent e23822b5d8
commit 6a398b0b51

@ -1,3 +1,7 @@
<script>
let sy;
</script>
<!-- this binds `sy` to the current value of `window.scrollY` -->
<svelte:window bind:scrollY={sy}/>

@ -112,7 +112,7 @@
<title>Svelte • The magical disappearing UI framework</title>
</svelte:head>
<!-- <svelte:window bind:scrollY={sy}/> -->
<svelte:window bind:scrollY={sy}/>
<img alt="Svelte logo" class="logo" src="logo.svg" style="transform: translate(0,{sy * 0.2}px)">

@ -21,7 +21,8 @@ self.addEventListener('message', async event => {
});
const commonCompilerOptions = {
dev: false
dev: false,
css: false
};
function compile({ source, options, entry }) {

@ -68,9 +68,9 @@ export default class WindowWrapper extends Wrapper {
});
});
const lock = block.getUniqueName(`window_updating`);
const clear = block.getUniqueName(`clear_window_updating`);
const timeout = block.getUniqueName(`window_updating_timeout`);
const scrolling = block.getUniqueName(`scrolling`);
const clear_scrolling = block.getUniqueName(`clear_scrolling`);
const scrolling_timeout = block.getUniqueName(`scrolling_timeout`);
Object.keys(events).forEach(event => {
const handler_name = block.getUniqueName(`onwindow${event}`);
@ -78,9 +78,9 @@ export default class WindowWrapper extends Wrapper {
if (event === 'scroll') {
// TODO other bidirectional bindings...
block.addVariable(lock, 'false');
block.addVariable(clear, `function() { ${lock} = false; }`);
block.addVariable(timeout);
block.addVariable(scrolling, 'false');
block.addVariable(clear_scrolling, `() => { ${scrolling} = false }`);
block.addVariable(scrolling_timeout);
const condition = [
bindings.scrollX && `"${bindings.scrollX}" in this._state`,
@ -97,58 +97,61 @@ export default class WindowWrapper extends Wrapper {
${x && `${x} = window.pageXOffset;`}
${y && `${y} = window.pageYOffset;`}
`);
block.event_listeners.push(deindent`
@addListener(window, "${event}", () => {
${scrolling} = true;
clearTimeout(${scrolling_timeout});
${scrolling_timeout} = setTimeout(${clear_scrolling}, 100);
ctx.${handler_name}();
})
`);
} else {
props.forEach(prop => {
renderer.metaBindings.addLine(
`this._state.${prop.name} = window.${prop.value};`
);
});
block.event_listeners.push(deindent`
@addListener(window, "${event}", ctx.${handler_name});
`);
}
component.declarations.push(handler_name);
component.template_references.add(handler_name);
component.partly_hoisted.push(deindent`
function ${handler_name}() {
${event === 'scroll' && deindent`
if (${lock}) return;
${lock} = true;
`}
${props.map(prop => `${prop.name} = window.${prop.value}; $$make_dirty('${prop.name}');`)}
${event === 'scroll' && `${lock} = false;`}
}
`);
block.builders.init.addBlock(deindent`
window.addEventListener("${event}", ctx.${handler_name});
@add_render_callback(ctx.${handler_name});
`);
block.builders.destroy.addBlock(deindent`
window.removeEventListener("${event}", ctx.${handler_name});
`);
component.has_reactive_assignments = true;
});
// special case... might need to abstract this out if we add more special cases
if (bindings.scrollX || bindings.scrollY) {
block.builders.init.addBlock(deindent`
#component.$on("state", ({ changed, current }) => {
block.builders.update.addBlock(deindent`
if (${
[bindings.scrollX, bindings.scrollY].map(
binding => binding && `changed["${binding}"]`
).filter(Boolean).join(' || ')
} && !${lock}) {
${lock} = true;
clearTimeout(${timeout});
[bindings.scrollX, bindings.scrollY].filter(Boolean).map(
b => `changed.${b}`
).join(' || ')
} && !${scrolling}) {
${scrolling} = true;
clearTimeout(${scrolling_timeout});
window.scrollTo(${
bindings.scrollX ? `current["${bindings.scrollX}"]` : `window.pageXOffset`
}, ${
bindings.scrollY ? `current["${bindings.scrollY}"]` : `window.pageYOffset`
});
${timeout} = setTimeout(${clear}, 100);
${scrolling_timeout} = setTimeout(${clear_scrolling}, 100);
}
});
`);
}

@ -1,26 +1,22 @@
/* generated by Svelte vX.Y.Z */
import { SvelteComponent as SvelteComponent_1, add_render_callback, append, createElement, createText, detachNode, flush, init, insert, run, safe_not_equal, setData } from "svelte/internal";
import { SvelteComponent as SvelteComponent_1, addListener, add_render_callback, append, createElement, createText, detachNode, flush, init, insert, run, safe_not_equal, setData } from "svelte/internal";
function create_fragment(component, ctx) {
var window_updating = false, clear_window_updating = function() { window_updating = false; }, window_updating_timeout, p, text0, text1, current;
var scrolling = false, clear_scrolling = () => { scrolling = false }, scrolling_timeout, p, text0, text1, current, dispose;
window.addEventListener("scroll", ctx.onwindowscroll);
add_render_callback(ctx.onwindowscroll);
component.$on("state", ({ changed, current }) => {
if (changed["y"] && !window_updating) {
window_updating = true;
clearTimeout(window_updating_timeout);
window.scrollTo(window.pageXOffset, current["y"]);
window_updating_timeout = setTimeout(clear_window_updating, 100);
}
});
return {
c() {
p = createElement("p");
text0 = createText("scrolled to ");
text1 = createText(ctx.y);
dispose = addListener(window, "scroll", () => {
scrolling = true;
clearTimeout(scrolling_timeout);
scrolling_timeout = setTimeout(clear_scrolling, 100);
ctx.onwindowscroll();
});
},
m(target, anchor) {
@ -31,6 +27,13 @@ function create_fragment(component, ctx) {
},
p(changed, ctx) {
if (changed.y && !scrolling) {
scrolling = true;
clearTimeout(scrolling_timeout);
window.scrollTo(window.pageXOffset, current["y"]);
scrolling_timeout = setTimeout(clear_scrolling, 100);
}
if (changed.y) {
setData(text1, ctx.y);
}
@ -44,11 +47,11 @@ function create_fragment(component, ctx) {
o: run,
d(detach) {
window.removeEventListener("scroll", ctx.onwindowscroll);
if (detach) {
detachNode(p);
}
dispose();
}
};
}
@ -57,10 +60,7 @@ function define($$self, $$props, $$make_dirty) {
let { y } = $$props;
function onwindowscroll() {
if (window_updating) return;
window_updating = true;
y = window.pageYOffset; $$make_dirty('y');
window_updating = false;
}
$$self.$$.get = () => ({ y, onwindowscroll });

Loading…
Cancel
Save