mirror of https://github.com/sveltejs/svelte
add a <svelte:document> tag - #1484
parent
d1f35dfd85
commit
db37e3a84b
@ -0,0 +1,23 @@
|
||||
import Node from './shared/Node';
|
||||
import EventHandler from './EventHandler';
|
||||
|
||||
export default class Document extends Node {
|
||||
type: 'Document';
|
||||
handlers: EventHandler[];
|
||||
|
||||
constructor(component, parent, scope, info) {
|
||||
super(component, parent, scope, info);
|
||||
|
||||
this.handlers = [];
|
||||
|
||||
info.attributes.forEach(node => {
|
||||
if (node.type === 'EventHandler') {
|
||||
this.handlers.push(new EventHandler(component, this, scope, node));
|
||||
}
|
||||
|
||||
else {
|
||||
// TODO there shouldn't be anything else here...
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import Renderer from '../Renderer';
|
||||
import Block from '../Block';
|
||||
import Node from '../../nodes/shared/Node';
|
||||
import Wrapper from './shared/Wrapper';
|
||||
import deindent from '../../../utils/deindent';
|
||||
import Document from '../../nodes/Document';
|
||||
|
||||
export default class DocumentWrapper extends Wrapper {
|
||||
node: Document;
|
||||
|
||||
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) {
|
||||
super(renderer, block, parent, node);
|
||||
}
|
||||
|
||||
render(block: Block, parentNode: string, parentNodes: string) {
|
||||
const { renderer } = this;
|
||||
const { component } = renderer;
|
||||
|
||||
this.node.handlers.forEach(handler => {
|
||||
// TODO verify that it's a valid callee (i.e. built-in or declared method)
|
||||
component.addSourcemapLocations(handler.expression);
|
||||
|
||||
const isCustomEvent = component.events.has(handler.name);
|
||||
|
||||
let usesState = handler.dependencies.size > 0;
|
||||
|
||||
handler.render(component, block, 'document', false); // TODO hoist?
|
||||
|
||||
const handlerName = block.getUniqueName(`onwindow${handler.name}`);
|
||||
const handlerBody = deindent`
|
||||
${usesState && `var ctx = #component.get();`}
|
||||
${handler.snippet};
|
||||
`;
|
||||
|
||||
if (isCustomEvent) {
|
||||
// TODO dry this out
|
||||
block.addVariable(handlerName);
|
||||
|
||||
block.builders.hydrate.addBlock(deindent`
|
||||
${handlerName} = %events-${handler.name}.call(#component, document, function(event) {
|
||||
${handlerBody}
|
||||
});
|
||||
`);
|
||||
|
||||
block.builders.destroy.addLine(deindent`
|
||||
${handlerName}.destroy();
|
||||
`);
|
||||
} else {
|
||||
block.builders.init.addBlock(deindent`
|
||||
function ${handlerName}(event) {
|
||||
${handlerBody}
|
||||
}
|
||||
document.addEventListener("${handler.name}", ${handlerName});
|
||||
`);
|
||||
|
||||
block.builders.destroy.addBlock(deindent`
|
||||
document.removeEventListener("${handler.name}", ${handlerName});
|
||||
`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
export default {
|
||||
test(assert, component, target, window) {
|
||||
assert.equal(component.get().events.toString(), '');
|
||||
const event1 = new window.Event('mouseenter');
|
||||
window.document.dispatchEvent(event1);
|
||||
assert.equal(component.get().events.toString(), 'enter');
|
||||
const event2 = new window.Event('mouseleave');
|
||||
window.document.dispatchEvent(event2);
|
||||
assert.equal(component.get().events.toString(), 'enter,leave');
|
||||
},
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
<svelte:document on:mouseenter='log("enter")' on:mouseleave='log("leave")'/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({ events: [] }),
|
||||
methods: {
|
||||
log(event) {
|
||||
this.set({ events: this.get().events.concat(event) });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
Loading…
Reference in new issue