ソート可能なリスト

ソート可能なリストは、リストビューの拡張機能であり、リストビュー要素をソートできます。

ソート可能なリストレイアウト

リストビューにおけるソート可能なリストのレイアウト構造を見てみましょう。

<!-- Additional "sortable" class on list block -->
<div class="list sortable">
    <li>
        <div class="item-content">
            <div class="item-media">...</div>
            <div class="item-inner">...</div>
        </div>
        <!-- Sortable handler element -->
        <div class="sortable-handler"></div>
    </li>
    ...
</div>

ここで

ご覧のように非常にシンプルで、リストブロックにsortableクラスを追加し、<div class="sortable-handler"></div><li>の子要素として配置するだけです。

ソートの無効化

特定のアイテムでソートを無効にする必要がある場合は、それらのアイテムにno-sortingまたはdisallow-sortingクラスを追加できます。

<!-- Additional "sortable" class on list block -->
<div class="list sortable">
    <!-- disable sorting for this item -->
    <li class="no-sorting">...</li>

    <!-- sortable items -->
    <li>...</li>
    <li>...</li>
</div>

これはリストの先頭または末尾のアイテムでのみ有効であり、中央のアイテムのソートを無効にすると正しく機能しません。

反対側のソート

ソートハンドラーを反対側に(LTR方向では左側に)レンダリングする必要がある場合は、ソート可能なリストにsortable-oppositeクラスを追加する必要があります。

<!-- Additional "sortable-opposite" class on sortable list -->
<div class="list sortable sortable-opposite">
  <li>
    <div class="item-content">
      <div class="item-media">...</div>
      <div class="item-inner">...</div>
    </div>
    <!-- Sortable handler element -->
    <div class="sortable-handler"></div>
  </li>
  ...
</div>

ソート可能なアプリメソッド

ソート可能なリストでソートモードを有効/無効にするには、次のアプリメソッドを使用する必要があります。

app.sortable.enable(listEl)- ソート可能なリストでソートモードを有効にする

  • listEl - HTMLElementまたはstring(CSSセレクター付き)。ソート可能なリストブロック要素。

app.sortable.disable(listEl)- ソート可能なリストでソートモードを無効にする

  • listEl - HTMLElementまたはstring(CSSセレクター付き)。ソート可能なリストブロック要素。

app.sortable.toggle(listEl)- ソート可能なリストでソートモードを切り替える

  • listEl - HTMLElementまたはstring(CSSセレクター付き)。ソート可能なリストブロック要素。

ソート可能なアプリパラメーター

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

パラメーターデフォルト説明
moveElementsbooleantrue

有効にすると、新しいソート順に従ってHTML要素を移動(並べ替え)します。ReactやVueなど、DOM操作に他のライブラリを使用する場合に無効にすることが有用です。

リスト要素にdata-sortable-move-elements="true"またはdata-sortable-move-elements="false"属性を追加することで、特定のリストに対してこの動作を上書きすることもできます。

これらのパラメーターを変更するには、例としてsortableプロパティの下でアプリの初期化時に渡す必要があります。

var app = new Framework7({
  sortable: {
    moveElements: false
  }
});

ソート可能なイベント

ソート可能なリストブロック要素で次のDOMイベント、およびアプリインスタンスでイベントが発生します。

DOMイベント

イベントターゲット説明
sortable:enableソート可能なリスト<div class="list sortable">ソートモードが有効になったときにトリガーされます。
sortable:disableソート可能なリスト<div class="list sortable">ソートモードが無効になったときにトリガーされます。
sortable:sortリスト要素<li>ユーザーが現在ソートしている要素を新しい位置で離した後にトリガーされます。event.detailには、ソートされたリストアイテムの開始/終了インデックス番号を示すfromおよびtoプロパティと、HTMLソート済み要素を示すelプロパティが含まれます。
sortable:moveリスト要素<li>ソート中にリストアイテムが移動するたびにトリガーされます。

アプリインスタンスイベント

ソート可能なインスタンスは、アプリインスタンスでイベントを発生させます。

イベントターゲット引数説明
sortableEnableapplistElソートモードが有効になったときにトリガーされます。
sortableDisableapplistElソートモードが無効になったときにトリガーされます。
sortableSortappitemEl, data, listElユーザーが現在ソートしている要素を新しい位置で離した後にトリガーされます。dataは、ソートされたリストアイテムの開始/終了インデックス番号を示すfromおよびtoプロパティと、HTMLソート済み要素を示すelプロパティを含むオブジェクトです。
sortableMoveappitemEl, listElソート中にリストアイテムが移動するたびにトリガーされます。

タップホールドでのソート

ソート可能な有効/無効のロジックをバイパスし、アイテムのタップアンドホールド(ロングプレス)でリストアイテムをソート可能にすることができます。これを実現するには、ソート可能なリストにsortable-tap-holdクラスを追加するだけです。

<!-- additional "sortable-tap-hold" class on sortable list -->
<div class="list sortable sortable-tap-hold">
  ...
</div>

この場合、アプリはカスタムtapholdイベントに依存します。正しく動作させるには、アプリパラメーターtouch.tapHold: trueも有効にしていることを確認してください。

特別なクラスとデータ属性をリンクで使用して、ソートモードを有効/無効にできます。

  • ソートモードを有効にするには、任意のHTML要素(リンクが推奨)にsortable-enableクラスを追加する必要があります。

  • ソートモードを無効にするには、任意のHTML要素(リンクが推奨)にsortable-disableクラスを追加する必要があります。

  • ソートモードを切り替えるには、任意のHTML要素(リンクが推奨)にsortable-toggleクラスを追加する必要があります。

  • アプリに複数のソート可能なリストがある場合、必要なソート可能なリストのCSSセレクターを含む追加のdata-sortable=".sortable"属性をこのHTML要素に指定する必要があります。

CSS変数

以下は、関連するCSS変数(CSSカスタムプロパティ)のリストです。

.ios {
  --f7-sortable-handler-width: 36px;
  --f7-sortable-sorting-item-box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.6);
  --f7-sortable-handler-color: rgba(0, 0, 0, 0.22);
  --f7-sortable-sorting-item-bg-color: rgba(255, 255, 255, 0.8);
}
.ios .dark,
.ios.dark {
  --f7-sortable-sorting-item-bg-color: rgba(50, 50, 50, 0.8);
  --f7-sortable-handler-color: rgba(255, 255, 255, 0.55);
}
.md {
  --f7-sortable-handler-width: 42px;
  --f7-sortable-sorting-item-box-shadow: none;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-sortable-handler-color: var(--f7-md-on-surface-variant);
  --f7-sortable-sorting-item-bg-color: var(--f7-md-surface-3);
}

sortable.html
<div class="page">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="title">Sortable List</div>
      <div class="right">
        <a class="link sortable-toggle" data-sortable=".sortable">Toggle</a>
      </div>
    </div>
  </div>
  <div class="page-content">
    <div class="block">
      <p>Just click "Toggle" button on navigation bar to enable sorting</p>
    </div>
    <div class="list list-strong-ios list-outline-ios list-dividers-ios sortable">
      <ul>
        <li>
          <div class="item-content">
            <div class="item-media"><i class="icon icon-f7"></i></div>
            <div class="item-inner">
              <div class="item-title">1 Jenna Smith</div>
              <div class="item-after">CEO</div>
            </div>
          </div>
          <div class="sortable-handler"></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">2 John Doe</div>
              <div class="item-after">Director</div>
            </div>
          </div>
          <div class="sortable-handler"></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">3 John Doe</div>
              <div class="item-after">Developer</div>
            </div>
          </div>
          <div class="sortable-handler"></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">4 Aaron Darling</div>
              <div class="item-after">Manager</div>
            </div>
          </div>
          <div class="sortable-handler"></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">5 Calvin Johnson</div>
              <div class="item-after">Accounter</div>
            </div>
          </div>
          <div class="sortable-handler"></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">6 John Smith</div>
              <div class="item-after">SEO</div>
            </div>
          </div>
          <div class="sortable-handler"></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">7 Chloe</div>
              <div class="item-after">Manager</div>
            </div>
          </div>
          <div class="sortable-handler"></div>
        </li>
      </ul>
    </div>

    <div class="list list-strong-ios list-outline-ios list-dividers-ios media-list sortable">
      <ul>
        <li>
          <div class="item-content">
            <div class="item-media"><img src="https://cdn.framework7.io/placeholder/people-160x160-1.jpg" width="80" />
            </div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">Yellow Submarine</div>
                <div class="item-after">$15</div>
              </div>
              <div class="item-subtitle">Beatles</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>
          </div>
          <div class="sortable-handler"></div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-media"><img src="https://cdn.framework7.io/placeholder/people-160x160-2.jpg" width="80" />
            </div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">Don't Stop Me Now</div>
                <div class="item-after">$22</div>
              </div>
              <div class="item-subtitle">Queen</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>
          </div>
          <div class="sortable-handler"></div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-media"><img src="https://cdn.framework7.io/placeholder/people-160x160-3.jpg" width="80" />
            </div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">Billie Jean</div>
                <div class="item-after">$16</div>
              </div>
              <div class="item-subtitle">Michael Jackson</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>
          </div>
          <div class="sortable-handler"></div>
        </li>
      </ul>
    </div>

    <div class="block-title">Opposite Side</div>
    <div class="list list-strong-ios list-outline-ios list-dividers-ios sortable sortable-opposite">
      <ul>
        <li>
          <div class="item-content">
            <div class="item-media"><i class="icon icon-f7"></i></div>
            <div class="item-inner">
              <div class="item-title">1 Jenna Smith</div>
              <div class="item-after">CEO</div>
            </div>
          </div>
          <div class="sortable-handler"></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">2 John Doe</div>
              <div class="item-after">Director</div>
            </div>
          </div>
          <div class="sortable-handler"></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">3 John Doe</div>
              <div class="item-after">Developer</div>
            </div>
          </div>
          <div class="sortable-handler"></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">4 Aaron Darling</div>
              <div class="item-after">Manager</div>
            </div>
          </div>
          <div class="sortable-handler"></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">5 Calvin Johnson</div>
              <div class="item-after">Accounter</div>
            </div>
          </div>
          <div class="sortable-handler"></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">6 John Smith</div>
              <div class="item-after">SEO</div>
            </div>
          </div>
          <div class="sortable-handler"></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">7 Chloe</div>
              <div class="item-after">Manager</div>
            </div>
          </div>
          <div class="sortable-handler"></div>
        </li>
      </ul>
    </div>
  </div>
</div>