連載:jQuery Mobile入門(最終回)

第6回 jQuery Mobile APIでもっとJavaScriptプログラミング

山田 祥寛
2012/06/14
Page1 Page2

 本連載の初回では、jQuery Mobileは(jQueryのモバイル版というよりも)jQuery UIのモバイル版である、と述べた。実際、jQuery Mobileでは標準であまたのウィジェットを提供しており、マークアップのみでネイティブ・アプリ・ライクなスマホ・アプリを開発できてしまう。もっとも、その特長が故に、ともすると、jQuery Mobileではあらかじめ用意された範囲でしかアプリを開発できないと思われがちだ。

 そのようなことはない。jQuery Mobileでは、豊富な独自のJavaScript APIを提供しており、これらを呼び出すことで、固有の仕組みをアプリに簡単に組み込める。そうした自由度の高さも、jQuery Mobileの特長なのだ。

 前回は、jQuery MobileでJavaScriptプログラミングを行う中でも、特に基本となる「グローバル設定」と「イベント」について解説した。これを受けて、最終回となる今回は、個別のメソッド/プロパティについて、具体例を挙げながら解説していく。

JavaScriptからウィジェットを操作する

 まず前半では、フォーム関連の話題を中心に、JavaScriptコードからウィジェットを操作する方法について解説する。

フォーム要素のオプションをスクリプトから指定する

 第2回では、フォーム要素の体裁をdata-xxxxx属性で指定する方法について紹介した。余計なスクリプトを記述しなくてよいという意味で、これは便利であるが、ページ(サイト)に同じ要素が何度も登場すると、コードも冗長になるし、何といっても変更時の修正が面倒だ。

 そのような場合には、

$.mobile.<ウィジェット名>.prototype.options.<オプション名> = 設定値;

の形式で、ウィジェットのオプションを一律に設定することも可能だ。

 例えば以下は、カスタム・メニューの表示をスクリプトから指定した例である。

$(document).bind('mobileinit', function() {
  $.mobile.selectmenu.prototype.options.corners = false;
  $.mobile.selectmenu.prototype.options.icon = 'info';
  $.mobile.selectmenu.prototype.options.iconpos = 'left';
});
カスタム・メニューの体裁をスクリプトから操作するJavaScriptコード(custom.html)

スクリプトでの指定がカスタム・メニューに反映された

 前回も述べたように、アプリ全体にかかわるグローバル設定は、mobileinitイベント・リスナで定義するのが基本だ。以下に、ウィジェットごとの主なオプションをまとめておく。

分類(ウィジェット名) オプション名 概要 デフォルト値
共通 mini 要素を小さめにレイアウト false
theme 適用するテーマ (親要素を継承)
ボタン(button) corners 角丸効果 true
icon 表示するアイコン null
iconpos アイコンの表示位置 left
iconshadow アイコンを影付きにするか true
inline ボタンをインライン表示するか false
shadow ボタンを影付きにするか true
テキストボックス(textinput) preventFocusZoom フォーカス時にズーム機能を無効化 true(iOSのみ)
検索ボックス(textinput) clearSearchButtonText 文字入力時の[×]アイコンに付与するツール・ヒント clear text
ラジオボタン/チェックボックス(checkboxradio)
セレクト・メニュー/カスタム・メニュー(selectmenu) corners 角丸効果を適用するか true
icon 表示するアイコン arrow-down
iconpos アイコンの表示位置 right
iconshadow アイコンを影付きにするか true
inline メニューをインライン表示するか false
nativeMenu ネイティブな選択メニューを表示するか true
shadow 影付きにするか true
スライダ/フリップ・スイッチ(slider) trackTheme トラック部分のテーマ (親要素を継承)
trackTheme トラック部分のテーマ (親要素を継承)
フォーム要素の主なオプション

自動初期化の対象となるフォーム要素を変更する ― initSelectorプロパティ

 第2回で触れたように、jQuery Mobileはネイティブなフォーム要素に対して、自動的にウィジェットを適用する。これはとても便利なことであるが、jQuery Mobile以外のプラグイン(ライブラリ)も併用しているような場合には、jQuery Mobileによる初期化が邪魔になるケースもあるだろう。

 そのような場合には、$.mobile.<ウィジェット名>.prototype.options.initSelectorプロパティ*1を指定すればよい。jQuery Mobileでは、initSelectorプロパティで指定されたセレクタに合致した要素だけを自動初期化の対象として処理する。

 例えば以下は、「class="jqmtext"」属性の付いた要素だけにtextinputウィジェット(テキストボックス/テキストエリア)を適用する例である。

*1 ウィジェット名と実際のフォーム要素の対応関係は、前項の表を参照してほしい。

<script>
$(document).bind('mobileinit', function() {
  // textinputウィジェットによる初期化対象を限定する
  $.mobile.textinput.prototype.options.initSelector = '.jqmtext';
});
</script>
……中略……
<input id="basic1" name="basic1" type="text" value="" />
<input id="basic2" name="basic2" type="text" class="jqmtext" value="" />
<textarea id="basic3" name="basic3"></textarea>
「class="jqmtext"」属性の付いた要素だけにtextinputウィジェットを適用するコード(init.html)

「class="jqmtext"」属性のない要素は自動初期化されない

 以下には、ウィジェットごとのinitSelectorプロパティの初期値をまとめておく。

ウィジェット名 初期値
button button, [type='button'], [type='submit'], [type='reset'], [type='image']
textinput input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input:not([type])
slider input[type='range'], :jqmData(type='range'), :jqmData(role='slider')
selectmenu select:not(:jqmData(role='slider'))
initSelectorプロパティの初期値

特定のフォーム要素のみを自動初期化の対象とする ― keepNativeプロパティ

 自動初期化の対象を決めるinitSelectorプロパティに対して、自動初期化を適用しない要素を決めるのはkeepNativeプロパティの役割だ。特定の要素を自動初期化の対象外とするならば、一から初期化対象を指定するinitSelectorプロパティよりも、keepNativeプロパティを利用した方がシンプルだろう。

 例えば以下は、「jqmNone」というクラスを持つ要素を自動初期化の対象外とする例である。

<script>
$(document).bind('mobileinit', function() {
  $.mobile.page.prototype.options.keepNative = '.jqmNone';
});
</script>
……中略……
<input id="basic_name" name="basic_name" type="text"
  value="" class="jqmNone" />
「class="jqmNone"」である要素を自動初期化の対象外とするコード(native.html)

テキストボックスがネイティブなままで表示されている

フォーム要素への変更はウィジェットに通知する ― refreshメソッド

 JavaScriptコードからウィジェットを操作した場合には、refreshメソッドで変更を通知しなければならない。

 例えば、以下はスライダの現在値をJavaScriptコードから変更した例である。まずは、refreshメソッドを呼び出さなかった例から見てみよう。

<script>
$(document).bind('pageinit', function() {
  $('#sl').val(80);
});
</script>
……中略……
<input id="sl" name="sl" type="range" min="0" max="100" value="10" />
JavaScriptコードからスライダの値を操作するコード(slider.html)

スライダに現在値が反映されない(数値入力ボックスにのみ反映)

 ネイティブな要素を操作しただけでは、ウィジェットが値の変化を知ることができないのだ。上の例でも、数値入力ボックスにのみ値が反映されて、スライダは初期値のままという中途半端な状態になっている。

 では、ウィジェットを操作した後、refreshメソッドを呼び出すようにしてみよう。

<script>
$(document).bind('pageinit', function() {
  $('#sl').val(80).slider('refresh');
});
</script>
……中略……
<input id="sl" name="sl" type="range" min="0" max="100" value="10" />
操作後、ウィジェットに対して変更を通知するコード(slider2.html)

スライダ/数値入力ボックスいずれにも値が反映される

 今度は、スライダ/数値入力ボックスいずれにもJavaScriptコードから設定した値が反映されていることが確認できる。ウィジェットを操作した後はrefreshメソッドで通知――しっかり覚えておこう。

要素を動的に追加するには? ― createイベント

 すでに何度か述べているように、jQuery Mobileではページ・ロード時にウィジェットなどの初期化処理を自動的に実施する。そのため、開発者はとりたてて「ウィジェットを適用する」という行為を意識しなくてもよかったわけだ。

 しかし、自動初期化の後でJavaScriptコードから要素を追加した場合には要注意だ。

 例えば、以下はJavaScriptコードでテキストボックスを追加した例だ。

$(document).bind('pageinit', function() {
  var tag_str = '<div data-role="fieldcontain"><label for="basic_name">氏名:</label><input id="basic_name" name="basic_name" type="text" value="" /></div>';
  $(tag_str).appendTo('#basic_body');
});
JavaScriptコードからテキストボックスを追加するコード(create.html)

テキストボックスがネイティブな状態で表示されてしまう

 jQuery Mobileが自動初期化を終えた後に追加された要素には、そのままではウィジェットが適用されないのだ(当然といえば当然だ)。

 このようなケースでは、triggerメソッドでcreateイベントを発生させなければならない。createイベントは、ウィジェットが生成される際に発生するイベントで、jQuery Mobileに初期化処理を促す働きを持つ。これによって、動的に生成された要素に対してもウィジェットが適用されるわけだ。

 以下はコードを修正した例と、実行結果である。

$(document).bind('pageinit', function() {
  var tag_str = '<div data-role="fieldcontain"><label for="basic_name">氏名:</label><input id="basic_name" name="basic_name" type="text" value="" /></div>';
  $(tag_str).appendTo('#basic_body').trigger('create');
});
テキストボックスを動的に生成した後、createイベントを発生させるコード(create2.html)

テキストボックスに正しくウィジェットが適用された

フォーム要素を有効/無効化する ― enable/disableメソッド

 要素を有効/無効化するには、ほとんどのフォーム系ウィジェット*2に備わっているenable/disableメソッドを利用すればよい。例えば、以下はスライダを無効化する例だ。

*2 具体的には、textinput、checkboxradio、selectmenu、slider、button。

$(document).bind('pageinit', function() {
  $('#sl').slider('disable');
});
……中略……
<input id="sl" name="sl" type="range" min="0" max="100" value="10" />
スライダをJavaScriptコードから無効化する例(disable.html)

スライダが無効化された

 ただし、アンカー・タグ(=<a>タグ)で生成したリンク・ボタンだけはenable/disableメソッドが利用できないので注意されたい*3。そもそも有効/無効を切り替えるようなボタンについては、<input>/<button>要素を優先して利用するのが望ましいが、それが叶わないときには、以下のように「class="ui-disabled"」属性をaddClass/removeClass属性で着脱しなければならない。

*3 内部的には、ボタンは2種類に分類される。<input>/<button>要素によるボタンはbuttonウィジェットが適用されるが、アンカー・タグによるボタンはbuttomMarkupウィジェットが適用されている。

$(document).bind('pageinit', function() {
  $('#top').addClass('ui-disabled');
});
……中略……
<a id="top" href="http://www.wings.msn.to" data-role="button">トップ</a>
リンク・ボタンの有効/無効を切り替えるコード(disable2.html)

リンク・ボタンが無効化された

[参考]テーマ・クラス

 jQuery Mobileでテーマ(スウォッチ)を変更するには、まずdata-theme属性(または、派生するdata-xxxxx-theme属性)を指定するのが基本だ。ただし、それは唯一の方法ではなく、あまた用意されているテーマ・クラス(スタイル・クラス)を直接要素に指定することも可能だ。テーマ・クラスを利用することで、独自のレイアウトに対してもjQuery Mobile標準のテーマを適用することが可能となる。

分類 クラス 概要
標準 ui-bar/ui-bar-x ツールバー(構造と色)
ui-body/ui-body-x コンテンツ領域(構造と色)
ui-disabled 無効(使用不可)状態
ボタン ui-btn-up-x ボタン(標準)
ui-btn-hover-x ボタン(マウス・ホバー時)
ui-btn-down-x ボタン(押下時)
効果 ui-corner-all テーマ全体の角丸
ui-corner-xxx 特定箇所の角丸(xxxはtl:左上、top:上、left:左など)
ui-btn-corner-all ボタン用の角丸
ui-shadow 影付き効果
主なテーマ・クラス(「x」はスウォッチを表す「a」〜「z」の値)

 本文で利用した「ui-disabled」もまた、テーマ・クラスの一種であったわけだ。

リスト・ビューの検索機能をカスタマイズする

 リスト・ビューのフィルタ機能は、大文字・小文字を区別しない部分一致検索がデフォルトの挙動だ。もっとも、用途によっては「大文字・小文字を厳密に区別したい」「前方一致に制限したい」などのニーズもあるだろう。

 そのようなケースでは、$.mobile.listview.prototype.options.filterCallbackプロパティに、自作の検索コールバック関数を設定すればよい。検索コールバック関数とは、リスト・ビューの検索ボックスで検索キーワードが入力されたときに呼び出される関数のこと。デフォルトでは、以下のようなコールバック関数が設定されている。

function( text, searchValue ){
  return text.toLowerCase().indexOf( searchValue ) === -1;
};
デフォルトで設定されている検索コールバック関数

 コールバック関数のルールは、以下のとおりだ。

  • 引数として、「リスト項目の文字列(text)」「入力された検索キーワード(searchValue)」を受け取る
  • 戻り値として「true」を返した場合はリスト項目を除外、「false」を返した場合は残す

 上の例であれば、リスト項目(text)をindexOfメソッドで検索キーワード(searchValue)により比較し、戻り値が「-1」である(=テキストが含まれない)場合は「true」を返している(=項目を除外する)わけだ。

 toLowerCaseメソッドを呼び出しているのは、比較するテキストをいったん小文字にすることで大文字・小文字を区別しない検索を行っている(引数「searchValue」はリスト・ビューの側で小文字変換されているので、コールバック関数での変換は不要)。

 以上を念頭に置いて、コールバック関数をカスタマイズしてみよう。以下は、リスト項目を前方一致検索で検索する例だ。

$(document).bind('mobileinit', function(){
  $.mobile.listview.prototype.options.filterCallback = function(text, searchValue){
    return text.toLowerCase().indexOf(searchValue) !== 0;
  };
});
リスト項目を前方一致検索で絞り込むための設定(list.html)

前方一致したリスト項目だけが表示される

 デフォルトのコールバック関数からの変更点は、実に太字の箇所だけだ。「戻り値が0でない」とは、文字列「text」が部分文字列「searchValue」で始まらない(または、そもそも含まれない)ことを表している。

 続いて次のページからは、jQuery Mobile APIを使って簡単なスマホ・アプリを作成する。


 INDEX
  [連載]jQuery Mobile入門(最終回)
  第6回 jQuery Mobile APIでもっとJavaScriptプログラミング
  1.JavaScriptからウィジェットを操作する
    2.jQuery Mobile APIでカンタン・アプリ開発

インデックス・ページヘ  「連載:jQuery Mobile入門」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH