Skip to content

Commit

Permalink
Merge pull request #461 from sveltejs/gh-404-scroll
Browse files Browse the repository at this point in the history
window scroll bindings are bidirectional
  • Loading branch information
Rich-Harris authored Apr 11, 2017
2 parents 42c1096 + 783cd38 commit 229d9f0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 4 deletions.
53 changes: 49 additions & 4 deletions src/generators/dom/visitors/Element/meta/Window.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import flattenReference from '../../../../../utils/flattenReference.js';
import deindent from '../../../../../utils/deindent.js';
import CodeBuilder from '../../../../../utils/CodeBuilder.js';

const associatedEvents = {
innerWidth: 'resize',
Expand All @@ -13,6 +14,7 @@ const associatedEvents = {

export default function visitWindow ( generator, block, node ) {
const events = {};
const bindings = {};

node.attributes.forEach( attribute => {
if ( attribute.type === 'EventHandler' ) {
Expand Down Expand Up @@ -51,6 +53,8 @@ export default function visitWindow ( generator, block, node ) {
throw new Error( `Bindings on <:Window/> must be to top-level properties, e.g. '${parts.pop()}' rather than '${keypath}'` );
}

bindings[ attribute.name ] = attribute.value.name;

if ( !events[ associatedEvent ] ) events[ associatedEvent ] = [];
events[ associatedEvent ].push( `${attribute.value.name}: this.${attribute.name}` );

Expand All @@ -61,16 +65,31 @@ export default function visitWindow ( generator, block, node ) {
}
});

const lock = block.getUniqueName( `window_updating` );

Object.keys( events ).forEach( event => {
const handlerName = block.getUniqueName( `onwindow${event}` );

const props = events[ event ].join( ',\n' );

const handlerBody = new CodeBuilder();
if ( event === 'scroll' ) { // TODO other bidirectional bindings...
block.builders.create.addLine( `var ${lock} = false;` );
handlerBody.addLine( `${lock} = true;` );
}

handlerBody.addBlock( deindent`
component.set({
${props}
});
` );

if ( event === 'scroll' ) {
handlerBody.addLine( `${lock} = false;` );
}

block.builders.create.addBlock( deindent`
var ${handlerName} = function ( event ) {
component.set({
${props}
});
${handlerBody}
};
window.addEventListener( '${event}', ${handlerName} );
` );
Expand All @@ -79,4 +98,30 @@ export default function visitWindow ( generator, block, node ) {
window.removeEventListener( '${event}', ${handlerName} );
` );
});

// special case... might need to abstract this out if we add more special cases
if ( bindings.scrollX && bindings.scrollY ) {
const observerCallback = block.getUniqueName( `scrollobserver` );

block.builders.create.addBlock( deindent`
function ${observerCallback} () {
if ( ${lock} ) return;
var x = ${bindings.scrollX ? `component.get( '${bindings.scrollX}' )` : `window.scrollX`};
var y = ${bindings.scrollY ? `component.get( '${bindings.scrollY}' )` : `window.scrollY`};
window.scrollTo( x, y );
};
` );

if ( bindings.scrollX ) block.builders.create.addLine( `component.observe( '${bindings.scrollX}', ${observerCallback} );` );
if ( bindings.scrollY ) block.builders.create.addLine( `component.observe( '${bindings.scrollY}', ${observerCallback} );` );
} else if ( bindings.scrollX || bindings.scrollY ) {
const isX = !!bindings.scrollX;

block.builders.create.addBlock( deindent`
component.observe( '${bindings.scrollX || bindings.scrollY}', function ( ${isX ? 'x' : 'y'} ) {
if ( ${lock} ) return;
window.scrollTo( ${isX ? 'x, window.scrollY' : 'window.scrollX, y' } );
});
` );
}
}
12 changes: 12 additions & 0 deletions test/runtime/samples/window-bind-scroll-update/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default {
skip: true, // JSDOM

test ( assert, component, target, window ) {
assert.equal( window.scrollY, 0 );

component.set({ scrollY: 100 });
assert.equal( window.scrollY, 100 );

component.destroy();
}
};
3 changes: 3 additions & 0 deletions test/runtime/samples/window-bind-scroll-update/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<:Window bind:scrollY/>

<div style='width: 100%; height: 9999px;'></div>

0 comments on commit 229d9f0

Please sign in to comment.