Swipeout (スワイプ可能なリスト)

Swipeoutは、リストビューの拡張機能であり、リスト要素をスワイプして、削除などのアクションを含む非表示のメニューを表示できます。

Swipeout レイアウト

リストビュー内のswipeout要素のレイアウト構造を見てみましょう。

<div class="list">
  <ul>
    <!-- Additional "swipeout" class on li -->
    <li class="swipeout">
      <!-- Usual list element wrapped with "swipeout-content" -->
      <div class="swipeout-content">
        <!-- Your list element here -->
        <div class="item-content">
          <div class="item-media">...</div>
          <div class="item-inner">...</div>
        </div>
      </div>
      <!-- Swipeout actions left -->
      <div class="swipeout-actions-left">
        <!-- Swipeout actions links/buttons -->
        <a href="#">Action 1</a>
        <a href="#">Action 2</a>
      </div>
      <!-- Swipeout actions right -->
      <div class="swipeout-actions-right">
        <!-- Swipeout actions links/buttons -->
        <a href="#" class="swipeout-close">Action 1</a>
        <a href="#" class="swipeout-delete">Delete</a>
      </div>
    </li>
    ...
  </ul>
</div>

ここで

swipeout-contentswipeout-actions-left/rightは、<li>の直接の子要素である必要があります。

"item-content"しかない場合は、「item-content」クラスを「swipeout-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」クラスをswipeoutアクションボタンに追加するだけです。

<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">
    <!-- Add this button and item will be deleted automatically -->
    <a href="#" class="swipeout-delete">Delete</a>
  </div>
</li>

ユーザーが「削除」ボタンをクリックしたときに確認モーダルを呼び出し、確認後にのみ要素を削除することもできます。確認時に削除するには、削除リンクに追加の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">
    <!-- We add data-confirm and data-confirm-title attributes -->
    <a href="#" class="swipeout-delete" data-confirm="Are you sure want to delete this item?" data-confirm-title="Delete?">Delete</a>
  </div>
</li>

オーバーズワイプ

Swipeoutは、「オーバーズワイプ」アクションもサポートしており、アクションをやりすぎると自動的にトリガーされます。この場合は、必要なアクションボタンに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>
  • オーバーズワイプは、右側のswipeoutアクションの最後のボタンと、左側のswipeoutアクションの最初のボタンでのみ使用できます。

  • オーバーズワイプを使用すると、スクリプトはオーバーズワイプボタンの「クリック」イベントを自動的にトリガーするため、このボタンに適切なイベントリスナーを追加する必要があります。

  • オーバーズワイプボタンは、オーバーズワイプ中に追加の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>

Swipeout アプリメソッド

Swipeoutには、swipeout要素を制御できる豊富なJavaScript APIもあります。適切なアプリのメソッドを見てみましょう。

app.swipeout.open(el, side, callback) - 指定された要素でswipeoutアクションを表示します。

  • el - HTMLElementまたは文字列(CSSセレクター付き)"swipeout"クラスを持つリスト(<li>)要素。必須です。
  • side - 文字列(「left」または「right」)。開くswipeoutアクション。アイテムに左右両方のswipeoutアクションがある場合は指定する必要があります。オプションです。
  • callback - 関数 - swipeout要素が開くアニメーションが完了した後、コールバック関数が実行されます。

app.swipeout.close(el, callback) - 指定された要素でswipeoutアクションを閉じます。

  • el - HTMLElementまたは文字列(CSSセレクター付き)"swipeout"クラスを持つリスト(<li>)要素。必須です。
  • callback - 関数 - swipeout要素が閉じるアニメーションが完了した後、コールバック関数が実行されます。

app.swipeout.delete(el, callback) - 指定されたswipeout要素を削除します。

  • el - HTMLElementまたは文字列(CSSセレクター付き)"swipeout"クラスを持つリスト(<li>)要素。必須です。
  • callback - 関数 - swipeout要素が削除アニメーションを完了した後、DOMから削除される直前にコールバック関数が実行されます。

app.swipeout.el - プロパティ。現在開いているswipeout HTMLElement。開いているswipeout要素がない場合はundefined

Swipeout アプリパラメーター

swipeoutプロパティの下にあるswipeout関連のパラメーターを渡すことで、アプリの初期化時にグローバルなswipeout動作を構成できます。

パラメータータイプデフォルト説明
noFollowブール値false古い/遅いデバイスでのパフォーマンス向上のためのフォールバックオプション。有効にすると、swipeoutアイテムはタッチ中に指に従わず、左/右にスワイプすると自動的に開閉されます。
removeElementsブール値ブール値true
無効にすると、フレームワークは「swipeout-delete」クリック時にDOMからswipeout要素を削除しません。VueやReactなどの別のライブラリを使用してswipeoutアイテムを管理(削除)する場合に有効です。ブール値falseremoveElementsWithTimeout
ブール値false0有効にすると、指定された遅延後に「swipeout-delete」クリック時にフレームワークがDOMからswipeout要素を削除します。
removeElementsTimeoutfalse1.2数値

removeElementsWithTimeoutが有効な場合、swipeoutアイテムを削除する遅延(ミリ秒)。

var app = new Framework7({
  swipeout: {
    noFollow: true,
    removeElements: false
  }
});

overswipeRatio

数値

1.2

オーバーズワイプをトリガーするために必要なスワイプの量/強さを定義します(デフォルトは1.2)。これらのパラメーターを変更するには、アプリの初期化時にswipeoutプロパティの下に渡す必要があります。例:説明
Swipeout イベントSwipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。DOM イベント
イベントSwipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。ターゲット
swipeoutSwipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。Swipeout 要素<li class="swipeout">
swipeout要素を移動中にトリガーされます。event.detailには、現在の開始進行状況のパーセンテージが含まれています。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:open
swipeout要素が開くアニメーションを開始したときにトリガーされます。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:opened
swipeout要素が開くアニメーションが完了したときにトリガーされます。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:close
swipeout要素が閉じるアニメーションを開始したときにトリガーされます。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:closed
swipeout要素が閉じるアニメーションが完了したときにトリガーされます。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:delete
swipeout要素が削除アニメーションを開始したときにトリガーされます。Swipeoutは、次のDOMイベントとアプリインスタンスのイベントを発生させます。swipeout:deleted

swipeout要素が削除アニメーションを完了した後、DOMから削除される直前にトリガーされます。

swipeout:overswipeenter

オーバーズワイプをトリガーするために必要なスワイプの量/強さを定義します(デフォルトは1.2)。これらのパラメーターを変更するには、アプリの初期化時にswipeoutプロパティの下に渡す必要があります。例:オーバーズワイプが有効になったときにトリガーされます。説明
Swipeout イベントswipeout:overswipeexitオーバーズワイプが無効になったときにトリガーされます。アプリインスタンスイベント
Swipeoutインスタンスは、アプリインスタンスでイベントを発生させます。swipeout:overswipeexit引数ターゲット
appswipeout:overswipeexit引数Swipeout 要素<li class="swipeout">
progressswipeout:overswipeexit引数swipeout:open
swipeout要素を移動中にトリガーされます。swipeout:overswipeexit引数swipeout:opened
swipeoutOpenswipeout:overswipeexit引数swipeout:close
swipeoutElswipeout:overswipeexit引数swipeout:closed
swipeoutOpenedswipeout:overswipeexit引数swipeout:delete
swipeoutCloseswipeout:overswipeexit引数swipeout:deleted

CSS変数

swipeoutClosed

:root {
  --f7-swipeout-delete-button-bg-color: #ff3b30;
  --f7-swipeout-button-text-color: #fff;
  --f7-swipeout-button-padding-vertical: 0px;
  --f7-swipeout-button-bg-color: rgba(0, 0, 0, 0.22);
}
:root .dark,
:root.dark {
  --f7-swipeout-button-bg-color: rgba(255, 255, 255, 0.55);
}
.ios {
  --f7-swipeout-button-padding-horizontal: 30px;
  --f7-swipeout-button-font-size: inherit;
  --f7-swipeout-button-font-weight: inherit;
}
.md {
  --f7-swipeout-button-padding-horizontal: 24px;
  --f7-swipeout-button-font-size: 14px;
  --f7-swipeout-button-font-weight: 500;
}
.md .dark,
.md.dark {
  --f7-swipeout-button-text-color: #000;
}

swipeoutDelete

swipeoutDeleted
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">Swipeout</div>
      </div>
    </div>
    <div class="page-content">
      <div class="block">
        <p>
          Swipe out actions on list elements is one of the most awesome F7 features. It allows you to call hidden menu
          for each list element where you can put default ready-to use delete button or any other buttons for some
          required actions.
        </p>
      </div>
      <div class="block-title">Swipe to delete with confirm modal</div>
      <div class="list list-strong list-outline-ios list-dividers-ios inset-md">
        <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 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 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 list-strong list-outline-ios list-dividers-ios inset-md">
        <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 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 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 list-strong list-outline-ios list-dividers-ios inset-md">
        <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 @click=${more}>More</a>
              <a 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 @click=${more}>More</a>
              <a 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 @click=${more}>More</a>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">With callback on remove</div>
      <div class="list list-strong list-outline-ios list-dividers-ios inset-md">
        <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 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 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 list-strong list-outline-ios list-dividers-ios inset-md">
        <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 class="color-green" @click=${reply}>Reply</a>
              <a 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 class="color-green" @click=${reply}>Reply</a>
              <a 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 list-strong list-outline-ios list-dividers-ios inset-md">
        <ul>
          <li class="swipeout">
            <div class="swipeout-content">
              <a 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.
                  </div>
                </div>
              </a>
            </div>
            <div class="swipeout-actions-left">
              <a class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
              <a class="color-blue" @click=${forward}>Forward</a>
            </div>
            <div class="swipeout-actions-right">
              <a @click=${more}>More</a>
              <a class="color-orange" @click=${mark}>Mark</a>
              <a 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 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.
                  </div>
                </div>
              </a>
            </div>
            <div class="swipeout-actions-left">
              <a class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
              <a class="color-blue" @click=${forward}>Forward</a>
            </div>
            <div class="swipeout-actions-right">
              <a @click=${more}>More</a>
              <a class="color-orange" @click=${mark}>Mark</a>
              <a 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 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.
                  </div>
                </div>
              </a>
            </div>
            <div class="swipeout-actions-left">
              <a class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
              <a class="color-blue" @click=${forward}>Forward</a>
            </div>
            <div class="swipeout-actions-right">
              <a @click=${more}>More</a>
              <a class="color-orange" @click=${mark}>Mark</a>
              <a 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 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.
                  </div>
                </div>
              </a>
            </div>
            <div class="swipeout-actions-left">
              <a class="color-green swipeout-overswipe" @click=${reply}>Reply</a>
              <a class="color-blue" @click=${forward}>Forward</a>
            </div>
            <div class="swipeout-actions-right">
              <a @click=${more}>More</a>
              <a class="color-orange" @click=${mark}>Mark</a>
              <a 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>
<script>
  export default (props, { $f7, $onMounted, $onBeforeUnmount }) => {
    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!');
    }

    $onBeforeUnmount(() => {
      actions.destroy();
    })

    $onMounted(() => {
      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',
              strong: true,
            }
          ]
        ],
      })
    })

    return $render;
  }
</script>