From 9e9a078d5c58d630affc51091dcdac9f7b7168c1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 29 Apr 2018 13:02:33 -0400 Subject: [PATCH] set window scroll from bindings on initialisation - fixes #938 --- src/compile/dom/index.ts | 4 +- src/compile/nodes/Window.ts | 40 ++++++++++++++----- .../computed-collapsed-if/expected-bundle.js | 1 + .../samples/computed-collapsed-if/expected.js | 1 + .../expected-bundle.js | 1 + .../expected.js | 1 + .../window-binding-scroll/expected-bundle.js | 4 ++ .../samples/window-binding-scroll/expected.js | 4 ++ 8 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/compile/dom/index.ts b/src/compile/dom/index.ts index e43d64e3f2..bcf9949ffb 100644 --- a/src/compile/dom/index.ts +++ b/src/compile/dom/index.ts @@ -18,7 +18,7 @@ import { Ast, CompileOptions, Node } from '../../interfaces'; export class DomTarget { blocks: (Block|string)[]; readonly: Set; - metaBindings: string[]; + metaBindings: CodeBuilder; hasIntroTransitions: boolean; hasOutroTransitions: boolean; @@ -29,7 +29,7 @@ export class DomTarget { this.readonly = new Set(); // initial values for e.g. window.innerWidth, if there's a meta tag - this.metaBindings = []; + this.metaBindings = new CodeBuilder(); } } diff --git a/src/compile/nodes/Window.ts b/src/compile/nodes/Window.ts index 6651fce854..31d342a10e 100644 --- a/src/compile/nodes/Window.ts +++ b/src/compile/nodes/Window.ts @@ -121,14 +121,10 @@ export default class Window extends Node { const property = properties[binding.name] || binding.name; if (!events[associatedEvent]) events[associatedEvent] = []; - events[associatedEvent].push( - `${binding.value.node.name}: this.${property}` - ); - - // add initial value - compiler.target.metaBindings.push( - `this._state.${binding.value.node.name} = window.${property};` - ); + events[associatedEvent].push({ + name: binding.value.node.name, + value: property + }); }); const lock = block.getUniqueName(`window_updating`); @@ -137,13 +133,37 @@ export default class Window extends Node { Object.keys(events).forEach(event => { const handlerName = block.getUniqueName(`onwindow${event}`); - const props = events[event].join(',\n'); + const props = events[event]; if (event === 'scroll') { // TODO other bidirectional bindings... block.addVariable(lock, 'false'); block.addVariable(clear, `function() { ${lock} = false; }`); block.addVariable(timeout); + + const condition = [ + bindings.scrollX && `"${bindings.scrollX}" in this._state`, + bindings.scrollY && `"${bindings.scrollY}" in this._state` + ].filter(Boolean).join(' || '); + + const x = bindings.scrollX && `this._state.${bindings.scrollX}`; + const y = bindings.scrollY && `this._state.${bindings.scrollY}`; + + compiler.target.metaBindings.addBlock(deindent` + if (${condition}) { + window.scrollTo(${x || 'window.pageXOffset'}, ${y || 'window.pageYOffset'}); + } + + ${x && `${x} = window.pageXOffset;`} + + ${y && `${y} = window.pageYOffset;`} + `); + } else { + props.forEach(prop => { + compiler.target.metaBindings.addLine( + `this._state.${prop.name} = window.${prop.value};` + ); + }); } const handlerBody = deindent` @@ -154,7 +174,7 @@ export default class Window extends Node { ${compiler.options.dev && `component._updatingReadonlyProperty = true;`} #component.set({ - ${props} + ${props.map(prop => `${prop.name}: this.${prop.value}`)} }); ${compiler.options.dev && `component._updatingReadonlyProperty = false;`} diff --git a/test/js/samples/computed-collapsed-if/expected-bundle.js b/test/js/samples/computed-collapsed-if/expected-bundle.js index 0ea5200f7d..c2a8bb251e 100644 --- a/test/js/samples/computed-collapsed-if/expected-bundle.js +++ b/test/js/samples/computed-collapsed-if/expected-bundle.js @@ -149,6 +149,7 @@ function create_main_fragment(component, ctx) { function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); + this._recompute({ x: 1 }, this._state); this._fragment = create_main_fragment(this, this._state); diff --git a/test/js/samples/computed-collapsed-if/expected.js b/test/js/samples/computed-collapsed-if/expected.js index 5c248bf515..5106a4fd87 100644 --- a/test/js/samples/computed-collapsed-if/expected.js +++ b/test/js/samples/computed-collapsed-if/expected.js @@ -27,6 +27,7 @@ function create_main_fragment(component, ctx) { function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); + this._recompute({ x: 1 }, this._state); this._fragment = create_main_fragment(this, this._state); diff --git a/test/js/samples/dev-warning-missing-data-computed/expected-bundle.js b/test/js/samples/dev-warning-missing-data-computed/expected-bundle.js index bea4d272db..b942565727 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected-bundle.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected-bundle.js @@ -206,6 +206,7 @@ function SvelteComponent(options) { if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option"); init(this, options); this._state = assign({ Math : Math }, options.data); + this._recompute({ foo: 1 }, this._state); if (!('foo' in this._state)) console.warn(" was created without expected data property 'foo'"); diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js index 93be0ba0c1..a61b8ee01c 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -46,6 +46,7 @@ function SvelteComponent(options) { if (!options || (!options.target && !options.root)) throw new Error("'target' is a required option"); init(this, options); this._state = assign({ Math : Math }, options.data); + this._recompute({ foo: 1 }, this._state); if (!('foo' in this._state)) console.warn(" was created without expected data property 'foo'"); diff --git a/test/js/samples/window-binding-scroll/expected-bundle.js b/test/js/samples/window-binding-scroll/expected-bundle.js index ffc59dacc5..d23cbbf2bd 100644 --- a/test/js/samples/window-binding-scroll/expected-bundle.js +++ b/test/js/samples/window-binding-scroll/expected-bundle.js @@ -198,6 +198,10 @@ function create_main_fragment(component, ctx) { function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); + if ("y" in this._state) { + window.scrollTo(window.pageXOffset, this._state.y); + } + this._state.y = window.pageYOffset; this._fragment = create_main_fragment(this, this._state); diff --git a/test/js/samples/window-binding-scroll/expected.js b/test/js/samples/window-binding-scroll/expected.js index d3f6718dd6..800b624875 100644 --- a/test/js/samples/window-binding-scroll/expected.js +++ b/test/js/samples/window-binding-scroll/expected.js @@ -56,6 +56,10 @@ function create_main_fragment(component, ctx) { function SvelteComponent(options) { init(this, options); this._state = assign({}, options.data); + if ("y" in this._state) { + window.scrollTo(window.pageXOffset, this._state.y); + } + this._state.y = window.pageYOffset; this._fragment = create_main_fragment(this, this._state);