From 3e962b9c900eddff75ff635577e9c709e942f621 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 17 Nov 2018 09:29:27 -0500 Subject: [PATCH] basic events --- index.js | 4 ++-- src/compile/render-dom/wrappers/Element/index.ts | 3 --- .../render-dom/wrappers/InlineComponent/index.ts | 12 ++++++------ src/compile/render-dom/wrappers/Window.ts | 2 +- src/internal/SvelteComponent.js | 11 ++++++++++- src/internal/lifecycle.js | 15 +++++++++++++++ 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/index.js b/index.js index 63d1731698..4691d20dee 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,3 @@ -import { onprops, onmount, onupdate, ondestroy } from './internal.js'; +import { onprops, onmount, onupdate, ondestroy, createEventDispatcher } from './internal.js'; -export { onprops, onmount, onupdate, ondestroy }; \ No newline at end of file +export { onprops, onmount, onupdate, ondestroy, createEventDispatcher }; \ No newline at end of file diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts index 8cfb224416..9f9e9893a9 100644 --- a/src/compile/render-dom/wrappers/Element/index.ts +++ b/src/compile/render-dom/wrappers/Element/index.ts @@ -174,9 +174,6 @@ export default class ElementWrapper extends Wrapper { }); if (this.parent) { - // console.log(`has intro ${!!node.intro}`); - // console.log(`has outro ${!!node.outro}`); - if (node.actions.length > 0) this.parent.cannotUseInnerHTML(); if (node.animation) this.parent.cannotUseInnerHTML(); if (node.bindings.length > 0) this.parent.cannotUseInnerHTML(); diff --git a/src/compile/render-dom/wrappers/InlineComponent/index.ts b/src/compile/render-dom/wrappers/InlineComponent/index.ts index fb789c5710..30339e2d50 100644 --- a/src/compile/render-dom/wrappers/InlineComponent/index.ts +++ b/src/compile/render-dom/wrappers/InlineComponent/index.ts @@ -278,7 +278,7 @@ export default class InlineComponentWrapper extends Wrapper { hasStoreBindings && 'newStoreState = {}', ].filter(Boolean).join(', '); - // TODO use component.on('state', ...) instead of _bind + // TODO use component.$on('state', ...) instead of _bind componentInitProperties.push(deindent` _bind(changed, childState) { var ${initialisers}; @@ -327,10 +327,10 @@ export default class InlineComponentWrapper extends Wrapper { ${this.node.handlers.map(handler => deindent` function ${handler.var}(event) { - ${handler.snippet || `#component.fire("${handler.name}", event);`} + (${handler.snippet || `() => { throw new Error('TODO shorthand events'); }`})(event); } - if (${name}) ${name}.on("${handler.name}", ${handler.var}); + if (${name}) ${name}.$on("${handler.name}", ${handler.var}); `)} `); @@ -389,7 +389,7 @@ export default class InlineComponentWrapper extends Wrapper { ${name}.$$mount(${updateMountNode}, ${anchor}); ${this.node.handlers.map(handler => deindent` - ${name}.on("${handler.name}", ${handler.var}); + ${name}.$on("${handler.name}", ${handler.var}); `)} ${this.node.ref && `#component.$$refs.${this.node.ref.name} = ${name};`} @@ -429,8 +429,8 @@ export default class InlineComponentWrapper extends Wrapper { ${beforecreate} ${this.node.handlers.map(handler => deindent` - ${name}.on("${handler.name}", function(event) { - ${handler.snippet || `#component.fire("${handler.name}", event);`} + ${name}.$on("${handler.name}", function(event) { + (${handler.snippet || `() => { throw new Error('TODO shorthand events'); }`})(event); }); `)} diff --git a/src/compile/render-dom/wrappers/Window.ts b/src/compile/render-dom/wrappers/Window.ts index 00cbd93379..11914bce9e 100644 --- a/src/compile/render-dom/wrappers/Window.ts +++ b/src/compile/render-dom/wrappers/Window.ts @@ -168,7 +168,7 @@ export default class WindowWrapper extends Wrapper { // special case... might need to abstract this out if we add more special cases if (bindings.scrollX || bindings.scrollY) { block.builders.init.addBlock(deindent` - #component.on("state", ({ changed, current }) => { + #component.$on("state", ({ changed, current }) => { if (${ [bindings.scrollX, bindings.scrollY].map( binding => binding && `changed["${binding}"]` diff --git a/src/internal/SvelteComponent.js b/src/internal/SvelteComponent.js index 9e6d64db26..43788e3413 100644 --- a/src/internal/SvelteComponent.js +++ b/src/internal/SvelteComponent.js @@ -1,6 +1,7 @@ import { schedule_update, flush } from './scheduler.js'; import { set_current_component } from './lifecycle.js' import { run_all } from '../shared/utils.js'; +import { blankObject } from './utils.js'; export class SvelteComponent { constructor(options) { @@ -9,6 +10,8 @@ export class SvelteComponent { this.$$onupdate = []; this.$$ondestroy = []; + this.$$callbacks = blankObject(); + this.$$slotted = options.slots; set_current_component(this); @@ -35,8 +38,14 @@ export class SvelteComponent { } } - $on(eventName, callback) { + $on(type, callback) { + const callbacks = (this.$$callbacks[type] || (this.$$callbacks[type] = [])); + callbacks.push(callback); + return () => { + const index = callbacks.indexOf(callback); + if (index !== -1) callbacks.splice(index, 1); + }; } $destroy() { diff --git a/src/internal/lifecycle.js b/src/internal/lifecycle.js index 0d733608b0..0232ef9c3d 100644 --- a/src/internal/lifecycle.js +++ b/src/internal/lifecycle.js @@ -18,4 +18,19 @@ export function onupdate(fn) { export function ondestroy(fn) { current_component.$$ondestroy.push(fn); +} + +export function createEventDispatcher() { + const component = current_component; + + return (type, detail) => { + const callbacks = component.$$callbacks[type]; + + if (callbacks) { + // TODO are there situations where events could be dispatched + // in a server (non-DOM) environment? + const event = new window.CustomEvent(type, { detail }); + callbacks.slice().forEach(fn => fn(event)); + } + }; } \ No newline at end of file