From 38ae43f6d71cb0f3b21c6aecbac0320d926a8523 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 10 Apr 2017 16:31:44 -0400 Subject: [PATCH] add bind:online to <:Window/> (#404) --- .../dom/visitors/Element/meta/Window.js | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/generators/dom/visitors/Element/meta/Window.js b/src/generators/dom/visitors/Element/meta/Window.js index 837578ef69..8030d68090 100644 --- a/src/generators/dom/visitors/Element/meta/Window.js +++ b/src/generators/dom/visitors/Element/meta/Window.js @@ -42,12 +42,6 @@ export default function visitWindow ( generator, block, node ) { } if ( attribute.type === 'Binding' ) { - const associatedEvent = associatedEvents[ attribute.name ]; - - if ( !associatedEvent ) { - throw new Error( `Cannot bind to ${attribute.name} on <:Window>` ); - } - if ( attribute.value.type !== 'Identifier' ) { const { parts, keypath } = flattenReference( attribute.value ); throw new Error( `Bindings on <:Window/> must be to top-level properties, e.g. '${parts.pop()}' rather than '${keypath}'` ); @@ -55,6 +49,15 @@ export default function visitWindow ( generator, block, node ) { bindings[ attribute.name ] = attribute.value.name; + // bind:online is a special case, we need to listen for two separate events + if ( attribute.name === 'online' ) return; + + const associatedEvent = associatedEvents[ attribute.name ]; + + if ( !associatedEvent ) { + throw new Error( `Cannot bind to ${attribute.name} on <:Window>` ); + } + if ( !events[ associatedEvent ] ) events[ associatedEvent ] = []; events[ associatedEvent ].push( `${attribute.value.name}: this.${attribute.name}` ); @@ -88,7 +91,7 @@ export default function visitWindow ( generator, block, node ) { } block.builders.create.addBlock( deindent` - var ${handlerName} = function ( event ) { + function ${handlerName} ( event ) { ${handlerBody} }; window.addEventListener( '${event}', ${handlerName} ); @@ -124,4 +127,26 @@ export default function visitWindow ( generator, block, node ) { }); ` ); } + + // another special case. (I'm starting to think these are all special cases.) + if ( bindings.online ) { + const handlerName = block.getUniqueName( `onlinestatuschanged` ); + block.builders.create.addBlock( deindent` + function ${handlerName} ( event ) { + component.set({ ${bindings.online}: navigator.onLine }); + }; + window.addEventListener( 'online', ${handlerName} ); + window.addEventListener( 'offline', ${handlerName} ); + ` ); + + // add initial value + generator.builders.metaBindings.addLine( + `this._state.${bindings.online} = navigator.onLine;` + ); + + block.builders.destroy.addBlock( deindent` + window.removeEventListener( 'online', ${handlerName} ); + window.removeEventListener( 'offline', ${handlerName} ); + ` ); + } } \ No newline at end of file