mirror of https://github.com/sveltejs/svelte
commit
9988749b74
@ -0,0 +1,84 @@
|
||||
import flattenReference from '../../../../utils/flattenReference.js';
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
|
||||
const associatedEvents = {
|
||||
innerWidth: 'resize',
|
||||
innerHeight: 'resize',
|
||||
outerWidth: 'resize',
|
||||
outerHeight: 'resize',
|
||||
|
||||
scrollX: 'scroll',
|
||||
scrollY: 'scroll'
|
||||
};
|
||||
|
||||
export default {
|
||||
enter ( generator, node ) {
|
||||
const events = {};
|
||||
|
||||
node.attributes.forEach( attribute => {
|
||||
if ( attribute.type === 'EventHandler' ) {
|
||||
// TODO verify that it's a valid callee (i.e. built-in or declared method)
|
||||
generator.addSourcemapLocations( attribute.expression );
|
||||
|
||||
const flattened = flattenReference( attribute.expression.callee );
|
||||
if ( flattened.name !== 'event' && flattened.name !== 'this' ) {
|
||||
// allow event.stopPropagation(), this.select() etc
|
||||
generator.code.prependRight( attribute.expression.start, 'component.' );
|
||||
}
|
||||
|
||||
const handlerName = generator.current.getUniqueName( `onwindow${attribute.name}` );
|
||||
|
||||
generator.current.builders.init.addBlock( deindent`
|
||||
var ${handlerName} = function ( event ) {
|
||||
[✂${attribute.expression.start}-${attribute.expression.end}✂];
|
||||
};
|
||||
window.addEventListener( '${attribute.name}', ${handlerName} );
|
||||
` );
|
||||
|
||||
generator.current.builders.teardown.addBlock( deindent`
|
||||
window.removeEventListener( '${attribute.name}', ${handlerName} );
|
||||
` );
|
||||
}
|
||||
|
||||
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}'` );
|
||||
}
|
||||
|
||||
if ( !events[ associatedEvent ] ) events[ associatedEvent ] = [];
|
||||
events[ associatedEvent ].push( `${attribute.value.name}: this.${attribute.name}` );
|
||||
|
||||
// add initial value
|
||||
generator.builders.metaBindings.addLine(
|
||||
`this._state.${attribute.value.name} = window.${attribute.name};`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys( events ).forEach( event => {
|
||||
const handlerName = generator.current.getUniqueName( `onwindow${event}` );
|
||||
|
||||
const props = events[ event ].join( ',\n' );
|
||||
|
||||
generator.current.builders.init.addBlock( deindent`
|
||||
var ${handlerName} = function ( event ) {
|
||||
component.set({
|
||||
${props}
|
||||
});
|
||||
};
|
||||
window.addEventListener( '${event}', ${handlerName} );
|
||||
` );
|
||||
|
||||
generator.current.builders.teardown.addBlock( deindent`
|
||||
window.removeEventListener( '${event}', ${handlerName} );
|
||||
` );
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
export default {
|
||||
enter () {
|
||||
// noop
|
||||
},
|
||||
|
||||
leave () {
|
||||
// noop
|
||||
}
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
export default {
|
||||
html: `<div>1024x768</div>`,
|
||||
|
||||
skip: /^v4/.test( process.version ), // node 4 apparently does some dumb stuff
|
||||
'skip-ssr': true, // there's some kind of weird bug with this test... it compiles with the wrong require.extensions hook for some bizarre reason
|
||||
|
||||
test ( assert, component, target, window ) {
|
||||
const event = new window.Event( 'resize' );
|
||||
|
||||
// JSDOM executes window event listeners with `global` rather than
|
||||
// `window` (bug?) so we need to do this
|
||||
Object.defineProperties( global, {
|
||||
innerWidth: {
|
||||
value: 567,
|
||||
configurable: true
|
||||
},
|
||||
innerHeight: {
|
||||
value: 456,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent( event );
|
||||
|
||||
assert.htmlEqual( target.innerHTML, `
|
||||
<div>567x456</div>
|
||||
`);
|
||||
}
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
<:Window bind:innerWidth='width' bind:innerHeight='height'/>
|
||||
|
||||
<div>{{width}}x{{height}}</div>
|
@ -0,0 +1,29 @@
|
||||
export default {
|
||||
html: `<div>undefinedxundefined</div>`,
|
||||
|
||||
skip: /^v4/.test( process.version ), // node 4 apparently does some dumb stuff
|
||||
'skip-ssr': true, // there's some kind of weird bug with this test... it compiles with the wrong require.extensions hook for some bizarre reason
|
||||
|
||||
test ( assert, component, target, window ) {
|
||||
const event = new window.Event( 'resize' );
|
||||
|
||||
// JSDOM executes window event listeners with `global` rather than
|
||||
// `window` (bug?) so we need to do this
|
||||
Object.defineProperties( global, {
|
||||
innerWidth: {
|
||||
value: 567,
|
||||
configurable: true
|
||||
},
|
||||
innerHeight: {
|
||||
value: 456,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent( event );
|
||||
|
||||
assert.htmlEqual( target.innerHTML, `
|
||||
<div>567x456</div>
|
||||
`);
|
||||
}
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
<:Window on:resize='set({ width: this.innerWidth, height: this.innerHeight })'/>
|
||||
|
||||
<div>{{width}}x{{height}}</div>
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"message": "<:Window> cannot have children",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"pos": 9
|
||||
}
|
@ -0,0 +1 @@
|
||||
<:Window>contents</:Window>
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"message": "A component can only have one <:Window> tag",
|
||||
"loc": {
|
||||
"line": 2,
|
||||
"column": 0
|
||||
},
|
||||
"pos": 11
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
<:Window/>
|
||||
<:Window/>
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"message": "<:Window> tags cannot be inside elements or blocks",
|
||||
"loc": {
|
||||
"line": 2,
|
||||
"column": 1
|
||||
},
|
||||
"pos": 13
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{{#if foo}}
|
||||
<:Window/>
|
||||
{{/if}}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"message": "<:Window> tags cannot be inside elements or blocks",
|
||||
"loc": {
|
||||
"line": 2,
|
||||
"column": 1
|
||||
},
|
||||
"pos": 7
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<:Window/>
|
||||
</div>>
|
Loading…
Reference in new issue