jQTouchでswipeイベントを処理する

jQTouch を使って swipe イベント(iPhone のスワイプジェスチャー)を処理するには少し工夫が必要だったので、その方法を記載しておく。

環境は以下。

  • jQTouch 1.0 beta 2 r109

jQTouch では、touch系のイベントを処理する対象は内部変数の touchSelectors に設定されている必要があり、以下のようなものがデフォルトの処理対象として設定される。

  • input 要素
  • touchSelector
    • a 要素
    • touch クラス
  • backSelector
    • back クラス
    • cancel クラス
    • goback
  • submitSelector
    • submit クラス

ちなみに、クラスと書いているのは CSS のクラス設定の事。

これらのデフォルト設定は、$.jQTouch の初期化時に渡す options 変数で追加する事ができる模様。(例えば touchSelector に独自のクラスを指定すれば、そのクラスで touch イベントが発生するようになる)

ただし、今回は初期化時の変数設定は使わずに touch クラスを指定して、iPhone SMS/MMS アプリの「削除」ボタンのように、左方向への swipe で単一行の削除ボタン表示、右方向への swipe で削除ボタン非表示となるようなサンプルを作成してみた。

サンプルのソースは http://github.com/fits/fits-nmc

swipe イベント発生時の処理は、以下のように引数を2つ取る関数を swipe に渡すことで実装でき、swipe の方向はイベント処理関数の第2引数として渡される data 変数(変数名は任意)の direction で取得する。(left か right が取得できる、上下方向は今のところ無さそうだが、確認不足かも)

$(・・・).swipe(function(e, data) {
  ・・・
}

下記のサンプルでは、動的に追加した li 要素内の div 要素で touch クラスを設定し、swipe イベントが発生するようにし、swipe の方向によって DEL ボタンの表示・非表示を切り替える処理を実装している。

サンプル bookmark.html(一部抜粋)
<!DOCTYPE html>
<html>
<head>
  <title>Bookmark</title>
  <style type="text/css" media="screen">@import "js/jqtouch/jqtouch.min.css";</style>
  <style type="text/css" media="screen">@import "js/themes/apple/theme.min.css";</style>
  <style type="text/css">
    ・・・
    .delButton {
      position: static;
      display: none;
      margin-right: 5px;
    }
  </style>
  <script src="js/jqtouch/jquery.1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
  <script src="js/jqtouch/jqtouch.min.js" type="application/x-javascript" charset="utf-8"></script>
  <script type="text/javascript" charset="utf-8">
    $.jQTouch({
    });

    $(function() {
      var url = "service/bookmark";

      $("#bookmark_list").empty();

      $.get(url, null, function(res){
        if (res["error"]) {
          window.location.href = res["error"];
        }
        else {
          ・・・
          $.each(res, function() {
            addToList(this.id, this.title, this.artist);
            ・・・
          });

          readyDelButton();
          ・・・
        }
      }, "json");
    });
    ・・・
    //取得した JSON データをリストに動的表示
    function addToList(id, title, artist) {
      var liId = id + "_list";
      var delId = id + "_del";

      var content = "<li id='" + liId + "'>";
      // class に touch を設定し、div 要素を swipe イベントの発生対象に指定
      content += "<div class='touch'>";
      content += "<a class='button delButton' href='#' id='" + delId + "'>DEL</a>";
      content += title + " : " + artist;
      content += "</div>";
      ・・・
      content += "</li>";

      $("#bookmark_list").append(content);

      //DELボタンクリック時の処理
      $("#" + delId).click(function(e) {
        $.post("service/bookmark/del", {"id": id}, function(res) {
          if(res) {
            $("#" + liId).remove();
          }
        }, "json");
      });
    }

    //DELボタンのイベント処理や表示設定を実施
    function readyDelButton() {
      if ($.support.touch) {
        //iPhone の場合、swipe のイベント処理を設定
        $("div.touch").swipe(function(e, data) {
          //swipe の方向で DEL ボタンの表示・非表示を切り替え
          var displayStyle = (data.direction == "left")? "inline": "none";
          $(e.target).children(".delButton").css("display", displayStyle);
        });
      }
      else {
        //通常ブラウザの場合、DELボタンを常に表示
        $(".delButton").css("display", "inline");
      }
    }
  </script>
</head>
<body>
  <div id="bookmark" class="current">
    <div class="toolbar">
      ・・・
    </div>
    <ul id="bookmark_list" class="rounded"></ul>
  </div>
</body>
</html>