diff --git a/src/compiler/compile/nodes/Body.ts b/src/compiler/compile/nodes/Body.ts index bd68c51290..fc350ca3cd 100644 --- a/src/compiler/compile/nodes/Body.ts +++ b/src/compiler/compile/nodes/Body.ts @@ -1,21 +1,23 @@ import Node from './shared/Node'; import EventHandler from './EventHandler'; +import Action from './Action'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; -import { TemplateNode } from '../../interfaces'; +import { Element } from '../../interfaces'; export default class Body extends Node { type: 'Body'; - handlers: EventHandler[]; + handlers: EventHandler[] = []; + actions: Action[] = []; - constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { + constructor(component: Component, parent: Node, scope: TemplateScope, info: Element) { super(component, parent, scope, info); - this.handlers = []; - - info.attributes.forEach((node: Node) => { + info.attributes.forEach((node) => { if (node.type === 'EventHandler') { this.handlers.push(new EventHandler(component, this, scope, node)); + } else if (node.type === 'Action') { + this.actions.push(new Action(component, this, scope, node)); } else { // TODO there shouldn't be anything else here... } diff --git a/src/compiler/compile/render_dom/wrappers/Body.ts b/src/compiler/compile/render_dom/wrappers/Body.ts index d80ef6c4a0..0e82fca79f 100644 --- a/src/compiler/compile/render_dom/wrappers/Body.ts +++ b/src/compiler/compile/render_dom/wrappers/Body.ts @@ -7,6 +7,7 @@ import EventHandler from './Element/EventHandler'; import add_event_handlers from './shared/add_event_handlers'; import { TemplateNode } from '../../../interfaces'; import Renderer from '../Renderer'; +import add_actions from './shared/add_actions'; export default class BodyWrapper extends Wrapper { node: Body; @@ -19,5 +20,6 @@ export default class BodyWrapper extends Wrapper { render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) { add_event_handlers(block, x`@_document.body`, this.handlers); + add_actions(block, x`@_document.body`, this.node.actions); } } diff --git a/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts b/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts index b57820beb3..6429f18928 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/add_actions.ts @@ -1,17 +1,18 @@ import { b, x } from 'code-red'; import Block from '../../Block'; import Action from '../../../nodes/Action'; +import { Expression } from 'estree'; import is_contextual from '../../../nodes/shared/is_contextual'; export default function add_actions( block: Block, - target: string, + target: string | Expression, actions: Action[] ) { actions.forEach(action => add_action(block, target, action)); } -export function add_action(block: Block, target: string, action: Action) { +export function add_action(block: Block, target: string | Expression, action: Action) { const { expression, template_scope } = action; let snippet; let dependencies; diff --git a/src/compiler/interfaces.ts b/src/compiler/interfaces.ts index 73be74bef9..7446c4c14b 100644 --- a/src/compiler/interfaces.ts +++ b/src/compiler/interfaces.ts @@ -46,6 +46,23 @@ interface BaseDirective extends BaseNode { modifiers: string[]; } +export interface Element extends BaseNode { + type: 'InlineComponent' | 'SlotTemplate' | 'Title' | 'Slot' | 'Element' | 'Head' | 'Options' | 'Window' | 'Body'; + attributes: Array; + name: string; +} + +export interface Attribute extends BaseNode { + type: 'Attribute'; + name: string; + value: any[]; +} + +export interface SpreadAttribute extends BaseNode { + type: 'Spread'; + expression: Node; +} + export interface Transition extends BaseDirective { type: 'Transition'; intro: boolean; @@ -57,6 +74,9 @@ export type Directive = BaseDirective | Transition; export type TemplateNode = Text | MustacheTag | BaseNode +| Element +| Attribute +| SpreadAttribute | Directive | Transition | Comment; diff --git a/test/runtime/samples/action-body/_config.js b/test/runtime/samples/action-body/_config.js new file mode 100644 index 0000000000..c882499e0e --- /dev/null +++ b/test/runtime/samples/action-body/_config.js @@ -0,0 +1,18 @@ +export default { + html: '
', + + async test({ assert, target, window }) { + const enter = new window.MouseEvent('mouseenter'); + const leave = new window.MouseEvent('mouseleave'); + + await window.document.body.dispatchEvent(enter); + assert.htmlEqual(target.innerHTML, ` +
+
Perform an Action
+
+ `); + + await window.document.body.dispatchEvent(leave); + assert.htmlEqual(target.innerHTML, '
'); + } +}; diff --git a/test/runtime/samples/action-body/main.svelte b/test/runtime/samples/action-body/main.svelte new file mode 100644 index 0000000000..dd57116577 --- /dev/null +++ b/test/runtime/samples/action-body/main.svelte @@ -0,0 +1,32 @@ + + + +
\ No newline at end of file