diff --git a/src/generators/nodes/Window.ts b/src/generators/nodes/Window.ts index 6396577003..c8b044bb2d 100644 --- a/src/generators/nodes/Window.ts +++ b/src/generators/nodes/Window.ts @@ -1,3 +1,4 @@ +import CodeBuilder from '../../utils/CodeBuilder'; import deindent from '../../utils/deindent'; import { stringify } from '../../utils/stringify'; import flattenReference from '../../utils/flattenReference'; @@ -106,6 +107,8 @@ export default class Window extends Node { }); const lock = block.getUniqueName(`window_updating`); + const clear = block.getUniqueName(`clear_window_updating`); + const timeout = block.getUniqueName(`window_updating_timeout`); Object.keys(events).forEach(event => { const handlerName = block.getUniqueName(`onwindow${event}`); @@ -114,10 +117,15 @@ export default class Window extends Node { if (event === 'scroll') { // TODO other bidirectional bindings... block.addVariable(lock, 'false'); + block.addVariable(clear, `function() { ${lock} = false; }`); + block.addVariable(timeout); } const handlerBody = deindent` - ${event === 'scroll' && `${lock} = true;`} + ${event === 'scroll' && deindent` + if (${lock}) return; + ${lock} = true; + `} ${generator.options.dev && `component._updatingReadonlyProperty = true;`} #component.set({ @@ -146,7 +154,8 @@ export default class Window extends Node { block.builders.init.addBlock(deindent` function ${observerCallback}() { - if (${lock}) return; + ${lock} = true; + clearTimeout(${timeout}); var x = ${bindings.scrollX ? `#component.get("${bindings.scrollX}")` : `window.scrollX`}; @@ -154,6 +163,7 @@ export default class Window extends Node { ? `#component.get("${bindings.scrollY}")` : `window.scrollY`}; window.scrollTo(x, y); + ${timeout} = setTimeout(${clear}, 100); } `); @@ -170,8 +180,10 @@ export default class Window extends Node { block.builders.init.addBlock(deindent` #component.observe("${bindings.scrollX || bindings.scrollY}", function(${isX ? 'x' : 'y'}) { - if (${lock}) return; + ${lock} = true; + clearTimeout(${timeout}); window.scrollTo(${isX ? 'x, window.scrollY' : 'window.scrollX, y'}); + ${timeout} = setTimeout(${clear}, 100); }); `); } diff --git a/test/js/samples/window-binding-scroll/expected-bundle.js b/test/js/samples/window-binding-scroll/expected-bundle.js index b3dbd98a57..43760c21f0 100644 --- a/test/js/samples/window-binding-scroll/expected-bundle.js +++ b/test/js/samples/window-binding-scroll/expected-bundle.js @@ -190,9 +190,10 @@ var proto = { /* generated by Svelte vX.Y.Z */ function create_main_fragment(state, component) { - var window_updating = false, p, text, text_1; + var window_updating = false, clear_window_updating = function() { window_updating = false; }, window_updating_timeout, p, text, text_1; function onwindowscroll(event) { + if (window_updating) return; window_updating = true; component.set({ @@ -203,8 +204,10 @@ function create_main_fragment(state, component) { window.addEventListener("scroll", onwindowscroll); component.observe("y", function(y) { - if (window_updating) return; + window_updating = true; + clearTimeout(window_updating_timeout); window.scrollTo(window.scrollX, y); + window_updating_timeout = setTimeout(clear_window_updating, 100); }); return { diff --git a/test/js/samples/window-binding-scroll/expected.js b/test/js/samples/window-binding-scroll/expected.js index 0387b24a05..70eae003d7 100644 --- a/test/js/samples/window-binding-scroll/expected.js +++ b/test/js/samples/window-binding-scroll/expected.js @@ -2,9 +2,10 @@ import { appendNode, assign, createElement, createText, detachNode, init, insertNode, proto } from "svelte/shared.js"; function create_main_fragment(state, component) { - var window_updating = false, p, text, text_1; + var window_updating = false, clear_window_updating = function() { window_updating = false; }, window_updating_timeout, p, text, text_1; function onwindowscroll(event) { + if (window_updating) return; window_updating = true; component.set({ @@ -15,8 +16,10 @@ function create_main_fragment(state, component) { window.addEventListener("scroll", onwindowscroll); component.observe("y", function(y) { - if (window_updating) return; + window_updating = true; + clearTimeout(window_updating_timeout); window.scrollTo(window.scrollX, y); + window_updating_timeout = setTimeout(clear_window_updating, 100); }); return {