better tutorial for parameterised actions (#3930)

* better tutorial for parameterised actions

* update example alongside tutorial

* update thumbnail
pull/3932/head
Rich Harris 5 years ago committed by GitHub
parent 927fcbfc71
commit 054f409950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,70 +1,20 @@
<script>
let language = "english";
import { longpress } from './longpress.js';
const translations = {
english: {
tooltip: "Switch Languages",
},
latin: {
tooltip: "Itchsway Anguageslay",
}
};
function tooltip(node, text) {
const tooltip = document.createElement('div');
tooltip.textContent = text;
Object.assign(tooltip.style, {
position: 'absolute',
background: 'black',
color: 'white',
padding: '0.5em 1em',
fontSize: '12px',
pointerEvents: 'none',
transform: 'translate(5px, -50%)',
borderRadius: '2px',
transition: 'opacity 0.4s'
});
function position() {
const { top, right, bottom } = node.getBoundingClientRect();
tooltip.style.top = `${(top + bottom) / 2}px`;
tooltip.style.left = `${right}px`;
}
function append() {
document.body.appendChild(tooltip);
tooltip.style.opacity = 0;
setTimeout(() => tooltip.style.opacity = 1);
position();
}
function remove() {
tooltip.remove();
}
node.addEventListener('mouseenter', append);
node.addEventListener('mouseleave', remove);
return {
update(text) {
tooltip.textContent = text;
position();
},
let pressed = false;
let duration = 2000;
</script>
destroy() {
tooltip.remove();
node.removeEventListener('mouseenter', append);
node.removeEventListener('mouseleave', remove);
}
};
}
<label>
<input type=range bind:value={duration} max={2000} step={100}>
{duration}ms
</label>
function toggleLanguage() {
language = language === 'english' ? 'latin' : 'english'
}
</script>
<button use:longpress={duration}
on:longpress="{() => pressed = true}"
on:mouseout="{() => pressed = false}"
>press and hold</button>
<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}>
{language}
</button>
{#if pressed}
<p>congratulations, you pressed and held for {duration}ms</p>
{/if}

@ -0,0 +1,20 @@
export function longpress(node, duration) {
const handleMousedown = () => {
setTimeout(() => {
node.dispatchEvent(
new CustomEvent('longpress')
);
}, duration);
};
node.addEventListener('mousedown', handleMousedown);
return {
update(newDuration) {
duration = newDuration;
},
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
};
}

@ -1,70 +1,20 @@
<script>
let language = "english";
import { longpress } from './longpress.js';
const translations = {
english: {
tooltip: "Switch Languages",
},
latin: {
tooltip: "Itchsway Anguageslay",
}
};
function tooltip(node, text) {
const tooltip = document.createElement('div');
tooltip.textContent = text;
Object.assign(tooltip.style, {
position: 'absolute',
background: 'black',
color: 'white',
padding: '0.5em 1em',
fontSize: '12px',
pointerEvents: 'none',
transform: 'translate(5px, -50%)',
borderRadius: '2px',
transition: 'opacity 0.4s'
});
function position() {
const { top, right, bottom } = node.getBoundingClientRect();
tooltip.style.top = `${(top + bottom) / 2}px`;
tooltip.style.left = `${right}px`;
}
function append() {
document.body.appendChild(tooltip);
tooltip.style.opacity = 0;
setTimeout(() => tooltip.style.opacity = 1);
position();
}
function remove() {
tooltip.remove();
}
node.addEventListener('mouseenter', append);
node.addEventListener('mouseleave', remove);
return {
update(text) {
tooltip.textContent = text;
position();
},
let pressed = false;
let duration = 2000;
</script>
destroy() {
tooltip.remove();
node.removeEventListener('mouseenter', append);
node.removeEventListener('mouseleave', remove);
}
};
}
<label>
<input type=range bind:value={duration} max={2000} step={100}>
{duration}ms
</label>
function toggleLanguage() {
language = language === 'english' ? 'latin' : 'english'
}
</script>
<button use:longpress
on:longpress="{() => pressed = true}"
on:mouseout="{() => pressed = false}"
>press and hold</button>
<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}>
{language}
</button>
{#if pressed}
<p>congratulations, you pressed and held for {duration}ms</p>
{/if}

@ -0,0 +1,17 @@
export function longpress(node) {
const handleMousedown = () => {
setTimeout(() => {
node.dispatchEvent(
new CustomEvent('longpress')
);
}, 500);
};
node.addEventListener('mousedown', handleMousedown);
return {
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
};
}

@ -1,70 +1,20 @@
<script>
let language = "english";
import { longpress } from './longpress.js';
const translations = {
english: {
tooltip: "Switch Languages",
},
latin: {
tooltip: "Itchsway Anguageslay",
}
};
function tooltip(node, text) {
const tooltip = document.createElement('div');
tooltip.textContent = text;
Object.assign(tooltip.style, {
position: 'absolute',
background: 'black',
color: 'white',
padding: '0.5em 1em',
fontSize: '12px',
pointerEvents: 'none',
transform: 'translate(5px, -50%)',
borderRadius: '2px',
transition: 'opacity 0.4s'
});
function position() {
const { top, right, bottom } = node.getBoundingClientRect();
tooltip.style.top = `${(top + bottom) / 2}px`;
tooltip.style.left = `${right}px`;
}
function append() {
document.body.appendChild(tooltip);
tooltip.style.opacity = 0;
setTimeout(() => tooltip.style.opacity = 1);
position();
}
function remove() {
tooltip.remove();
}
node.addEventListener('mouseenter', append);
node.addEventListener('mouseleave', remove);
return {
update(text) {
tooltip.textContent = text;
position();
},
let pressed = false;
let duration = 2000;
</script>
destroy() {
tooltip.remove();
node.removeEventListener('mouseenter', append);
node.removeEventListener('mouseleave', remove);
}
};
}
<label>
<input type=range bind:value={duration} max={2000} step={100}>
{duration}ms
</label>
function toggleLanguage() {
language = language === 'english' ? 'latin' : 'english'
}
</script>
<button use:longpress={duration}
on:longpress="{() => pressed = true}"
on:mouseout="{() => pressed = false}"
>press and hold</button>
<button on:click={toggleLanguage} use:tooltip={translations[language].tooltip}>
{language}
</button>
{#if pressed}
<p>congratulations, you pressed and held for {duration}ms</p>
{/if}

@ -0,0 +1,20 @@
export function longpress(node, duration) {
const handleMousedown = () => {
setTimeout(() => {
node.dispatchEvent(
new CustomEvent('longpress')
);
}, duration);
};
node.addEventListener('mousedown', handleMousedown);
return {
update(newDuration) {
duration = newDuration;
},
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
};
}

@ -2,4 +2,45 @@
title: Adding parameters
---
TODO come up with a better example
Like transitions and animations, an action can take an argument, which the action function will be called with alongside the element it belongs to.
Here, we're using a `longpress` action that fires an event with the same name whenever the user presses and holds the button for a given duration. Right now, if you switch over to the `longpress.js` file, you'll see it's hardcoded to 500ms.
We can change the action function to accept a `duration` as a second argument, and pass that `duration` to the `setTimeout` call:
```js
export function longpress(node, duration) {
const handleMousedown = () => {
setTimeout(() => {
node.dispatchEvent(
new CustomEvent('longpress')
);
}, duration);
};
// ...
}
```
Back in `App.svelte`, we can pass the `duration` value to the action:
```html
<button use:longpress={duration}
```
This *almost* works — the event now only fires after 2 seconds. But if you slide the duration down, it will still take two seconds.
To change that, we can add an `update` method in `longpress.js`. This will be called whenever the argument changes:
```js
return {
update(newDuration) {
duration = newDuration;
},
destroy() {
node.removeEventListener('mousedown', handleMousedown);
}
};
```
> If you need to pass multiple arguments to an action, combine them into a single object, as in `use:longpress={{duration, spiciness}}`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Loading…
Cancel
Save