jQueryMobileを使って 簡単にRuby on RailsサイトをクールなiPhone対応サイトにしてみた

jQuery Mobile | jQuery Mobile を使って Ruby on Rails で作ったWebサイトを iPhoneなどのスマフォに対応したサイトに変更してみました。以下の画像は Ruby on Railsの Scaffold で作ったサイトをjQueryMobile対応した後の画面です。

クールなスマフォサイトになっています!

1. まずは普通にscaffold でアプリを作る

Railsはjavascript周りが大幅に強化された3.1を使っています。

% rails new jq_mobile
% cd jq_mobile
% rails g scaffold todo due:date task:string
% rake db:migration
% rails s

2. PC と iPhone でview(layout)を切り替える

jQueryMobile用のHTMLは通常のPCサイト用とは異なりますので、テンプレートファイルやlayoutを、PCとiPhoneからのアクセスで切り替えられようにしましょう。
これは Railsの機能で直ぐに出来ます。

config/initializers/mime_types.rb ファイルにコメントアウトされている以下の行を有効にすると :iphone というフォーマットが使えるようになりテンプレートは XXX.html.erb の他に XXX.iphone.erb が使えるようになります。

# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
Mime::Type.register_alias "text/html", :iphone

あとは、コントローラー (app/controllers/application_controller.rb)で user_agent を調べ、フォーマとやlayout を切り替えることにします。

class ApplicationController < ActionController::Base
  protect_from_forgery
  layout :set_layout
  before_filter :set_iphone_format

  def set_iphone_format
    request.format = :iphone if iphone_request?
  end
  
  def set_layout
    iphone_request? ? "iphone" : "application"
  end
  
  private
  
  def iphone_request?
    request.user_agent =~ /(Mobile.+Safari)/
  end
end

3. jQueryMobileのインストール

  • jQuery Mobileのjavascript, style sheetは CDN のものを使っても良いのですが、今回は ダウンロードし、Railsプロジェクトにコピーします。
% unizp jquery.mobile-1.0rc1.zip
% cd jquery.mobile-1.0rc1
% cp jquery.mobile-1.0rc1.js XXXX/jq_mobile/app/assets/javascripts
% cp jquery.mobile-1.0rc1.css XXXX/jq_mobile/app/assets/stylesheets
% cp -r images XXXX/jq_mobile/app/assets/stylesheets/images
  • app/assets/javascripts/application.jsはPC用するのでjQueryMobileが読み込まれないように以下の行を削除します(もっと良いやり方がある気がする・・・)。
 //= require_tree . 
  • app/assets/stylesheets/application.css はPC用するのでjQueryMobileが読み込まれないように以下の行を削除します(もっと良いやり方がある気がする・・・)。
 *= require_tree . 
  • app/assets/javascripts/mobile_application.js を追加
//= require jquery
//= require jquery_ujs
//= require jquery.mobile-1.0rc1
  • app/assets/stylesheets/mobile_application.css を追加
/*
 *= require_self
 *= require jquery.mobile-1.0rc1
*/

4. iPhone用view, layout を用意

iPhone用にviewportを定義し、jQueryMobileのページ用divを置きます

<html>
<head>
  <meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
  <title>iPhone</title>
  <%= stylesheet_link_tag    "mobile_application" %>
  <%= javascript_include_tag "mobile_application" %>
  <%= csrf_meta_tags %>
</head>
<body>
  <div data-role="page">

  <%= yield %>

  </div>
</body>
</html>
  • app/views/todos/index.iphone.erb の追加

例として、Todo一覧を表示するページを書いてみましょう。
ヘッダーにaddボタンを置いたり、一覧をjQueryMobileのテーブルと表示しています。

<div data-role="header">
  <h1>Listing todos</h1>
  <%= link_to 'Add', new_todo_path, "data-icon" => "plus", "class" => "ui-btn-right" %>
</div>

<div data-role="content">
  <ul data-role="listview">
  <% @todos.each do |todo| %>
    <li data-role="list-divider" style="padding: 0.1em 15px;"><%= todo.due %></li>
    <li><%= link_to todo.task ,todo %></li>
  <% end %>
  </ul>
</div>

他のページはGitHubの yuumi3/jQueryMobileRails に置きましたので参考にして下さい。

5. ajaxEnabled を false にする

4.までで、jQueryMobile対応のサイトが出来ます。
iPhoneシミュレータや ブラフザーのuser_agentを切り替えられるプラグインや開発機能を使ってアクセスしてみましょう。

動かしてみると少し動作がへんです。
Todo一覧からTodoを選択し、編集し一覧に戻ると、その行は編集出来ないなど不思議な動作をします・・・

実は、jQueryMobileは単純に HTMLを表示するだけではなく、ページをキャッシュしたり色々な管理を行っています。その為にRailsのコントロールから外れてしまうことが多々あります。
そこで設定で ajaxEnabled を false する必要があります。ただし、この設定は jQueryMobileのjsを読み込む前に行う必要があります。

  • app/assets/javascripts/jqm_setup.js を作り
$(document).bind("mobileinit", function(){
  $.extend( $.mobile, {
    ajaxEnabled: false
  });
});
  • app/assets/javascripts/mobile_application.js に追加します
//= require jquery
//= require jquery_ujs
//= require jqm_setup
//= require jquery.mobile-1.0rc1

これで、ちゃんと使えるようになります。

6. 日付設定用 jquery.mobile.datebox

Railsのdate_selectが作る年月日の3つのselectboxはjQueryMobileでも正しく動作しますが、どうもダサイです ^^;
そこで jQuery-Mobile-DateBoxを使ってみました。
_form.iphone.erbは以下の様にシンプルですが下の画像の様な日付入力が表示されます。

  <div data-role="fieldcontain">
    <%= f.label :due %>
    <%= f.text_field :due, "data-role"=>"datebox", "data-options"=>'{"mode": "flipbox"}' %>
  </div>

ただし、デフォルトは米国式表示なので、以下のような設定で日本式にできます。

jQuery.extend(jQuery.mobile.datebox.prototype.options, {
	titleDateDialogLabel: '日付設定',
	setDateButtonLabel: 'OK',
	dateFormat: 'YYYY-mm-dd',
  headerFormat: 'YYYY-mm-dd',
	dateFieldOrder: ['y', 'm', 'd'],
	monthsOfYear: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],
	monthsOfYearShort: ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"]
});


GitHubに プロジェクト全体を yuumi3/jQueryMobileRails に置きましたので参考にして下さい。