スワイプアウト (スワイプ可能なリスト)
Swipeoutは、リストビューの拡張機能で、リスト要素の上をスワイプすると、スワイプ→削除などのアクションが可能な隠しメニューが表示されます。
スワイプアウトのレイアウト
リストビューのスワイプアウト要素のレイアウト構造を見てみましょう。
<div class="list">
<ul>
<!-- liに "swipeout "クラスを追加 -->
<li class="swipeout">
<!-- 通常のリスト要素には "swipeout-content "を付加しています。 -->
<div class="swipeout-content">
<!-- あなたのリスト要素の場合 -->
<div class="item-content">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</div>
</div>
<!-- 左のスワイプアウト・アクション -->
<div class="swipeout-actions-left">
<!-- スワイプアウト・アクションのリンク/ボタン -->
<a href="#">Action 1</a>
<a href="#">Action 2</a>
</div>
<!-- スワイプアウト機能(右 -->
<div class="swipeout-actions-right">
<!-- スワイプアウト・アクションのリンク/ボタン -->
<a href="#" class="swipeout-close">Action 1</a>
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
...
</ul>
</div>
構造
swipeout-content
- リスト要素のラッパーです。このコンテナは、リストアイテムの上をスワイプすると動きます。swipeout-actions-left
- 左スワイプアウトアクションのボタンやリンクを含むコンテナです。swipeout-actions-right
- 右スワイプアウトのアクションボタン/リンクを持つコンテナです。swipeout-close
- スワイプアウトのリンクに追加されるクラスで、このリンクをクリックするとスワイプアウト要素が閉じられます。swipeout-delete
- スワイプアウトのリンクに追加されるクラスで、このリンクをクリックすると、スワイプアウトのリストアイテムを削除します。
swipeout-content と
swipeout-actions-left/right` は、 <li> の直接の子でなければならないことに注意してください。
item-content "しかない場合は、"swipeout-content "に "item-content "クラスを追加することで、レイアウトを簡単にすることができます。
<li class="swipeout">
<div class="swipeout-content item-content">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</div>
<div class="swipeout-actions-right">
<a href="#">Action 1</a>
<a href="#">Action 2</a>
</div>
</li>
リンクアイテムを使うと、以下のようなレイアウトになります。
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-content item-link">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</a>
</div>
<div class="swipeout-actions-right">
<a href="#">Action 1</a>
<a href="#">Action 2</a>
</div>
</li>
スワイプで削除
Framework7では、頻繁に使われるこの機能を、JavaScriptを一行も書かずにサポートしています。必要なのは、スワイプアウトのアクションボタンに swipeout-delete
クラスを追加するだけです。
<li class="swipeout">
<div class="swipeout-content item-content">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</div>
<div class="swipeout-actions-right">
<!-- このボタンを追加すると、アイテムが自動的に削除されます -->
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
また、ユーザーが「Delete」ボタンをクリックしたときに「Confirm」モーダルを呼び出し、確認後に要素が削除されるようにすることも可能です。確認後に削除するには、削除リンクに追加のdata-confirm
とdata-confirm-title
(オプション)属性を追加する必要があります。
<li class="swipeout">
<div class="swipeout-content item-content">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</div>
<div class="swipeout-actions-right">
<!-- data-confirm属性とdata-confirm-title属性を追加します。 -->
<a href="#" class="swipeout-delete" data-confirm="Are you sure want to delete this item?" data-confirm-title="Delete?">Delete</a>
</div>
</li>
オーバーワイプ
スワイプアウトは「オーバースワイプ」アクションもサポートしており、アクションをスワイプしすぎると自動的にトリガーされます。この場合、必要なアクションボタンに swipeout-overswipe
クラスを追加する必要があります。
<li class="swipeout">
<div class="swipeout-content item-content">
<div class="item-media">...</div>
<div class="item-inner">...</div>
</div>
<div class="swipeout-actions-right">
<a href="#">More</a>
<a href="#" class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</div>
</li>
overswipeは、右スワイプアウトのアクションでは最後のボタンにのみ、左スワイプアウトのアクションでは最初のボタンにのみ使用できます。
オーバースワイプでは、スクリプトが自動的にオーバースワイプボタンの「クリック」イベントをトリガーするので、このボタンに適切なイベントリスナーを追加する必要があります。
オーバースワイプボタンは、オーバースワイプ中に追加の
swipeout-overswipe-active
クラスを持ち、その状態の追加スタイリングに使用できます。
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-content item-link">
...
</a>
</div>
<div class="swipeout-actions-left">
<a href="#" class="swipeout-overswipe bg-green reply">Reply</a>
<a href="#" class="bg-blue forward">Forward</a>
</div>
<div class="swipeout-actions-right">
<a href="#" class="mark bg-orange">Mark</a>
<a href="#" class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</li>
スワイプアウトアプリのメソッド
スワイプアウトには、スワイプアウト要素を制御するための豊富な JavaScript API も用意されています。ここでは、アプリのメソッドについて説明します。
app.swipeout.open(el, side, callback) - reveal swipeout actions on specified element
- el - HTMLElementまたはstring (with CSS Selector)のリスト(<li>)要素に「swipeout」クラスを指定します。必須
- side - string ("left "または "right "の可能性あり)開くためのスワイプアウト・アクション。アイテムに左右両方のスワイプアウト操作がある場合に指定します。任意
- callback - function - スワイプアウト要素が開くアニメーションが完了した後に実行されるコールバック関数です。
app.swipeout.close(el, callback) - close swipeout actions on specified element
- el - HTMLElementまたはstring(CSSセレクタ付き)のリスト(<li>)要素で、クラスが "swipeout "であるもの。必須
- callback - function - スワイプアウト要素が閉じるアニメーションを完了した後に実行されるコールバック関数。
app.swipeout.delete(el, callback) - delete specified swipeout element
- el - HTMLElementまたはstring(CSSセレクタ付き)で、swipeoutクラスを持つリスト(<li>)要素。必須
- callback - function - スワイプアウト要素の削除アニメーションが完了した後、DOMから削除される直前に実行されるコールバック関数です。
app.swipeout.el - property. Currently opened swipeout HTMLElement. Or undefined
if there is no opened swipeout element
スワイプアウトアプリのパラメーター
swipeout`プロパティにスワイプアウト関連のパラメータを渡すことで、アプリの初期化時にグローバルなスワイプアウトの動作を設定することができます。
Parameter | Type | Default | Description |
---|---|---|---|
noFollow | boolean | false | 古いデバイスや低速なデバイスでのパフォーマンスを向上させるためのフォールバックオプションです。このオプションを有効にすると、スワイプアウトされたアイテムはタッチ時に指を追わず、左/右のスワイプで自動的に開閉されます。 |
removeElements | boolean | true | 無効にすると、フレームワークは「スワイプアウト・削除」のクリック時にスワイプアウト要素をDOMから削除しません。VueやReactなどの他のライブラリを使ってスワイプアウトのアイテムを管理(削除)する場合に有効にすると便利です。 |
removeElementsWithTimeout | boolean | false | 有効にすると、"swipeout-delete "がクリックされたときに、指定した遅延時間後にフレームワークがスワイプアウト要素をDOMから削除します。 |
removeElementsTimeout | number | 0 | removeElementsWithTimeout` が有効な場合、スワイプアウトアイテムを削除するための遅延時間を ms 単位で指定します。 |
overswipeRatio | number | 1.2 | オーバースワイプのトリガーとなるスワイプの量や強さを定義します (デフォルトは 1.2) |
これらのパラメータを変更するには、アプリの起動時に swipeout
プロパティで渡す必要があります。
var app = new Framework7({
swipeout: {
noFollow: true,
removeElements: false
}
});
スワイプアウトのイベント
Swipeout は、以下の DOM イベントとアプリのインスタンス上のイベントを発生させます。
DOMイベント
Event | Target | Description |
---|---|---|
swipeout | Swipeout Element<li class="swipeout"> | イベントは、スワイプアウトの要素を動かしたときに発生します。event.detail` には、現在の開封率が含まれます。 |
swipeout:open | Swipeout Element<li class="swipeout"> | イベントは、スワイプアウト要素がオープニングアニメーションを開始するときにトリガーされます。 |
swipeout:opened | Swipeout Element<li class="swipeout"> | イベントは、スワイプアウト要素がオープニングアニメーションを完了した後に発生します。 |
swipeout:close | Swipeout Element<li class="swipeout"> | スワイプアウト要素が閉じるアニメーションを開始すると、イベントが発生します。 |
swipeout:closed | Swipeout Element<li class="swipeout"> | イベントはスワイプアウト要素が閉じるアニメーションを完了した後にトリガされます。 |
swipeout:delete | Swipeout Element<li class="swipeout"> | スワイプアウト要素が削除アニメーションを開始すると、イベントが発生します。 |
swipeout:deleted | Swipeout Element<li class="swipeout"> | イベントは、swipeout 要素が DOM から削除される直前に削除アニメーションを完了した後に発生します。 |
swipeout:overswipeenter | Swipeout Element<li class="swipeout"> | オーバーワイプが有効になるとイベントが発生する |
swipeout:overswipeexit | Swipeout Element<li class="swipeout"> | オーバースワイプが無効になると、イベントが発生する |
アプリのインスタンスのイベント
スワイプアウトのインスタンスは、アプリのインスタンス上でイベントを発行します。
Event | Target | Arguments | Description |
---|---|---|---|
swipeout | app | progress | スワイプアウトの要素を動かしたときにイベントが発生する |
swipeoutOpen | app | swipeoutEl | スワイプアウト要素がオープニングアニメーションを開始するとイベントが発生します。 |
swipeoutOpened | app | swipeoutEl | スワイプアウト要素のオープニングアニメーションが完了するとイベントが発生します。 |
swipeoutClose | app | swipeoutEl | スワイプアウト要素が閉じるアニメーションを開始すると、イベントが発生します。 |
swipeoutClosed | app | swipeoutEl | スワイプアウト要素が閉じるアニメーションを完了すると、イベントが発生します。 |
swipeoutDelete | app | swipeoutEl | スワイプアウト要素が削除アニメーションを開始すると、イベントが発生します。 |
swipeoutDeleted | app | swipeoutEl | イベントは、swipeout 要素が DOM から削除される直前に削除アニメーションを完了した後に発生します。 |
swipeoutOverswipeEnter | app | swipeoutEl | オーバーワイプが有効になるとイベントが発生する |
swipeoutOverswipeExit | app | swipeoutEl | オーバースワイプが無効になるとイベントが発生する |
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
:root {
--f7-swipeout-button-text-color: #fff;
--f7-swipeout-delete-button-bg-color: #ff3b30;
--f7-swipeout-button-font-size: inherit;
--f7-swipeout-button-font-weight: inherit;
--f7-swipeout-button-padding-vertical: 0px;
--f7-swipeout-button-bg-color: rgba(0, 0, 0, 0.22);
}
:root .theme-dark,
:root.theme-dark {
--f7-swipeout-button-bg-color: rgba(255, 255, 255, 0.55);
}
.ios {
--f7-swipeout-button-padding-horizontal: 30px;
}
.md {
--f7-swipeout-button-padding-horizontal: 24px;
}
.aurora {
--f7-swipeout-button-padding-horizontal: 24px;
--f7-swipeout-button-font-weight: 500;
}
Examples
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Swipeout</div>
</div>
</div>
<div class="page-content">
<div class="block-title">Swipe to delete with confirm modal</div>
<div class="list">
<ul>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media"><i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe left on me please</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media"> <i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe left on me too</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete">Delete</a>
</div>
</li>
<li>
<div class="item-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">I am not removable</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Swipe to delete without confirm</div>
<div class="list">
<ul>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-inner">
<div class="item-title">Swipe left on me please</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-inner">
<div class="item-title">Swipe left on me too</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li>
<div class="item-content">
<div class="item-inner">
<div class="item-title">I am not removable</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">Swipe for actions</div>
<div class="list">
<ul>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe left on me please</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe left on me too</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">You can't delete me</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
</div>
</li>
</ul>
</div>
<div class="block-title">With callback on remove</div>
<div class="list">
<ul>
<li class="swipeout" @swipeout:deleted=${onDeleted}>
<div class="item-content swipeout-content">
<div class="item-inner">
<div class="item-title">Swipe left on me please</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li class="swipeout" @swipeout:deleted=${onDeleted}>
<div class="item-content swipeout-content">
<div class="item-inner">
<div class="item-title">Swipe left on me too</div>
</div>
</div>
<div class="swipeout-actions-right">
<a href="#" class="swipeout-delete">Delete</a>
</div>
</li>
<li>
<div class="item-content">
<div class="item-inner">
<div class="item-title">I am not removable</div>
</div>
</div>
</li>
</ul>
</div>
<div class="block-title">With actions on left side (swipe to right)</div>
<div class="list">
<ul>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe right on me please</div>
</div>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
</li>
<li class="swipeout">
<div class="item-content swipeout-content">
<div class="item-media">
<i class="icon icon-f7"></i>
</div>
<div class="item-inner">
<div class="item-title">Swipe right on me too</div>
</div>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
</li>
</ul>
</div>
<div class="block-title">On both sides with overswipes</div>
<div class="list media-list">
<ul>
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">Facebook</div>
<div class="item-after">17:14</div>
</div>
<div class="item-subtitle">New messages from John Doe</div>
<div class="item-text">
<Lorem>ipsum dolor sit amet, consectetur adipiscing elit. Nulla sagittis tellus ut turpis
condimentum, ut dignissim lacus tincidunt. Cras dolor metus, ultrices condimentum sodales sit
amet, pharetra sodales eros. Phasellus vel felis tellus. Mauris rutrum ligula nec dapibus
feugiat. In vel dui laoreet, commodo augue id, pulvinar lacus.</Lorem>
</div>
</div>
</a>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="color-orange" @click=${mark}>Mark</a>
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">John Doe (via Twitter)</div>
<div class="item-after">17:11</div>
</div>
<div class="item-subtitle">John Doe (@_johndoe) mentioned you on Twitter!</div>
<div class="item-text">
<Lorem>ipsum dolor sit amet, consectetur adipiscing elit. Nulla sagittis tellus ut turpis
condimentum, ut dignissim lacus tincidunt. Cras dolor metus, ultrices condimentum sodales sit
amet, pharetra sodales eros. Phasellus vel felis tellus. Mauris rutrum ligula nec dapibus
feugiat. In vel dui laoreet, commodo augue id, pulvinar lacus.</Lorem>
</div>
</div>
</a>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="color-orange" @click=${mark}>Mark</a>
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">Facebook</div>
<div class="item-after">16:48</div>
</div>
<div class="item-subtitle">New messages from John Doe</div>
<div class="item-text">
<Lorem>ipsum dolor sit amet, consectetur adipiscing elit. Nulla sagittis tellus ut turpis
condimentum, ut dignissim lacus tincidunt. Cras dolor metus, ultrices condimentum sodales sit
amet, pharetra sodales eros. Phasellus vel felis tellus. Mauris rutrum ligula nec dapibus
feugiat. In vel dui laoreet, commodo augue id, pulvinar lacus.</Lorem>
</div>
</div>
</a>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="color-orange" @click=${mark}>Mark</a>
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</li>
<li class="swipeout">
<div class="swipeout-content">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">John Doe (via Twitter)</div>
<div class="item-after">15:32</div>
</div>
<div class="item-subtitle">John Doe (@_johndoe) mentioned you on Twitter!</div>
<div class="item-text">
<Lorem>ipsum dolor sit amet, consectetur adipiscing elit. Nulla sagittis tellus ut turpis
condimentum, ut dignissim lacus tincidunt. Cras dolor metus, ultrices condimentum sodales sit
amet, pharetra sodales eros. Phasellus vel felis tellus. Mauris rutrum ligula nec dapibus
feugiat. In vel dui laoreet, commodo augue id, pulvinar lacus.</Lorem>
</div>
</div>
</a>
</div>
<div class="swipeout-actions-left">
<a href="#" class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
<a href="#" class="color-blue" @click=${forward}>Forward</a>
</div>
<div class="swipeout-actions-right">
<a href="#" @click=${more}>More</a>
<a href="#" class="color-orange" @click=${mark}>Mark</a>
<a href="#" data-confirm="Are you sure you want to delete this item?"
class="swipeout-delete swipeout-overswipe">Delete</a>
</div>
</li>
</ul>
</div>
</div>
</div>
</template>
<style>
.icon-f7 {
background: #EE350F;
color: #fff !important;
border-radius: 50%;
text-align: center;
}
.icon-f7:before {
content: '7';
}
.ios .icon-f7 {
width: 29px;
height: 29px;
line-height: 29px;
}
.md .icon-f7,
.aurora .icon-f7 {
width: 24px;
height: 24px;
line-height: 24px;
}
</style>
<script>
export default (props, { $f7, $on }) => {
let actions;
const more = () => {
actions.open();
}
const mark = () => {
$f7.dialog.alert('Mark');
}
const reply = () => {
$f7.dialog.alert('Reply');
}
const forward = () => {
$f7.dialog.alert('Forward');
}
const onDeleted = () => {
$f7.dialog.alert('Thanks, item removed!');
}
$on('pageInit', () => {
actions = $f7.actions.create({
buttons: [
[
{
text: 'Here comes some optional description or warning for actions below',
label: true,
},
{
text: 'Action 1',
},
{
text: 'Action 2',
},
],
[
{
text: 'Cancel',
bold: true,
}
]
],
})
})
return $render;
}
</script>