diff --git a/site/content/tutorial/12-actions/01-actions/app-a/App.svelte b/site/content/tutorial/12-actions/01-actions/app-a/App.svelte index feacc44c52..2131fbf732 100644 --- a/site/content/tutorial/12-actions/01-actions/app-a/App.svelte +++ b/site/content/tutorial/12-actions/01-actions/app-a/App.svelte @@ -1,26 +1,10 @@ @@ -35,15 +19,15 @@ top: calc(50% - var(--height) / 2); border-radius: 4px; background-color: #ff3e00; - cursor: move; + color: #fff; + text-align: center; + font-style: bold; } -
\ No newline at end of file + +{#if showModal} +
+ Click outside me! +
+{/if} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/01-actions/app-a/pannable.js b/site/content/tutorial/12-actions/01-actions/app-a/pannable.js index 332cd3e147..b9812fb50b 100644 --- a/site/content/tutorial/12-actions/01-actions/app-a/pannable.js +++ b/site/content/tutorial/12-actions/01-actions/app-a/pannable.js @@ -1,9 +1,9 @@ -export function pannable(node) { +export function clickOutside(node) { // setup work goes here... return { destroy() { // ...cleanup goes here - } + }, }; -} \ No newline at end of file +}; diff --git a/site/content/tutorial/12-actions/01-actions/app-b/App.svelte b/site/content/tutorial/12-actions/01-actions/app-b/App.svelte index 171f82762c..7c4eb3e2e8 100644 --- a/site/content/tutorial/12-actions/01-actions/app-b/App.svelte +++ b/site/content/tutorial/12-actions/01-actions/app-b/App.svelte @@ -1,27 +1,10 @@ @@ -36,16 +19,15 @@ top: calc(50% - var(--height) / 2); border-radius: 4px; background-color: #ff3e00; - cursor: move; + color: #fff; + text-align: center; + font-style: bold; } -
\ No newline at end of file + +{#if showModal} +
+ Click outside me! +
+{/if} \ No newline at end of file diff --git a/site/content/tutorial/12-actions/01-actions/app-b/pannable.js b/site/content/tutorial/12-actions/01-actions/app-b/pannable.js index f7d15328be..f275a0d001 100644 --- a/site/content/tutorial/12-actions/01-actions/app-b/pannable.js +++ b/site/content/tutorial/12-actions/01-actions/app-b/pannable.js @@ -1,47 +1,15 @@ -export function pannable(node) { - let x; - let y; - - function handleMousedown(event) { - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panstart', { - detail: { x, y } - })); - - window.addEventListener('mousemove', handleMousemove); - window.addEventListener('mouseup', handleMouseup); - } - - function handleMousemove(event) { - const dx = event.clientX - x; - const dy = event.clientY - y; - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panmove', { - detail: { x, y, dx, dy } - })); - } - - function handleMouseup(event) { - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panend', { - detail: { x, y } - })); - - window.removeEventListener('mousemove', handleMousemove); - window.removeEventListener('mouseup', handleMouseup); - } +export function clickOutside(node) { + const handleClick = (event) => { + if (!node.contains(event.target)) { + node.dispatchEvent(new CustomEvent("outclick")); + } + }; - node.addEventListener('mousedown', handleMousedown); + document.addEventListener("click", handleClick, true); return { destroy() { - node.removeEventListener('mousedown', handleMousedown); - } + document.removeEventListener("click", handleClick, true); + }, }; -} \ No newline at end of file +}; diff --git a/site/content/tutorial/12-actions/01-actions/text.md b/site/content/tutorial/12-actions/01-actions/text.md index 3706b31e7c..d22ad74d54 100644 --- a/site/content/tutorial/12-actions/01-actions/text.md +++ b/site/content/tutorial/12-actions/01-actions/text.md @@ -4,85 +4,45 @@ title: The use directive Actions are essentially element-level lifecycle functions. They're useful for things like: -* interfacing with third-party libraries -* lazy-loaded images -* tooltips -* adding custom event handlers +- interfacing with third-party libraries +- lazy-loaded images +- tooltips +- adding custom event handlers -In this app, we want to make the orange box 'pannable'. It has event handlers for the `panstart`, `panmove` and `panend` events, but these aren't native DOM events. We have to dispatch them ourselves. First, import the `pannable` function... +In this app, we want to make the orange modal close when the user clicks outside it. It has an event handler for the `outclick` event, but it isn't a native DOM event. We have to dispatch it ourselves. First, import the `clickOutside` function... ```js -import { pannable } from './pannable.js'; +import { clickOutside } from "./pannable.js"; ``` ...then use it with the element: ```html -
+
+ Click outside me! +
``` -Open the `pannable.js` file. Like transition functions, an action function receives a `node` and some optional parameters, and returns an action object. That object can have a `destroy` function, which is called when the element is unmounted. +Open the `click_outside.js` file. Like transition functions, an action function receives a `node` (which is the element that the action is applied to) and some optional parameters, and returns an action object. That object can have a `destroy` function, which is called when the element is unmounted. -We want to fire `panstart` event when the user mouses down on the element, `panmove` events (with `dx` and `dy` properties showing how far the mouse moved) when they drag it, and `panend` events when they mouse up. One possible implementation looks like this: +We want to fire the `outclick` event when the user clicks outside the orange box. One possible implementation looks like this: ```js -export function pannable(node) { - let x; - let y; - - function handleMousedown(event) { - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panstart', { - detail: { x, y } - })); - - window.addEventListener('mousemove', handleMousemove); - window.addEventListener('mouseup', handleMouseup); - } - - function handleMousemove(event) { - const dx = event.clientX - x; - const dy = event.clientY - y; - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panmove', { - detail: { x, y, dx, dy } - })); - } - - function handleMouseup(event) { - x = event.clientX; - y = event.clientY; - - node.dispatchEvent(new CustomEvent('panend', { - detail: { x, y } - })); - - window.removeEventListener('mousemove', handleMousemove); - window.removeEventListener('mouseup', handleMouseup); - } +export function clickOutside(node) { + const handleClick = (event) => { + if (!node.contains(event.target)) { + node.dispatchEvent(new CustomEvent("outclick")); + } + }; - node.addEventListener('mousedown', handleMousedown); + document.addEventListener("click", handleClick, true); return { destroy() { - node.removeEventListener('mousedown', handleMousedown); - } + document.removeEventListener("click", handleClick, true); + }, }; } ``` -Update the `pannable` function and try moving the box around. - -> This implementation is for demonstration purposes — a more complete one would also consider touch events. +Update the `clickOutside` function, click the button to show the modal and then click outside it to close it.