[[iPhone関連]] > [[iPhoneサイト構築]] > jQuery Mobile を使用してスマホサイト構築 * jQuery Mobile を使用してスマホサイト構築 [#h0e44747] #setlinebreak(on); &color(red){※TODO:書きかけの記事}; 基本的な使い方は、以下のサイトを参照して構築するものとして、 当ページでは、特にデザインなどのカスタマイズ方法と、カスタマイズに必要な最低限の情報についてのみ記載する。 #html(<div style="padding-left:10px">) http://jquerymobile.com/ http://dev.screw-axis.com/doc/jquery_mobile/ #html(</div>) 《目次》 #contents ** ページの基本構成 [#q7c60242] #html(<div style="padding-left:10px;">) デザイン面で重要になるのは、data-role などの data 属性 jQuery Mobile は指定された data-role などの属性を読み取り、各要素にCSSセレクタの付与などを行い、ページの体裁を整える。 また data-role="page" の要素は1ページ内に複数持つ事ができ、非同期通信による部分読み込みによって、 1枚のHTMLを複数ページであるかのように見せる事ができる。 #html(</div>) <html> <body> <div id="page1" data-role="page"> <div data-role="header"> ヘッダ領域 </div> <div data-role="navbar"> ナビゲーションバー領域 </div> <div data-role="content"> コンテンツ領域 </div> <div data-role="footer"> フッタ </div> </div> <div id="page2" data-role="page"> <div data-role="header"> ヘッダ領域 </div> <div data-role="navbar"> ナビゲーションバー領域 </div> <div data-role="content"> コンテンツ領域 </div> <div data-role="footer"> フッタ </div> </div> </body> </html> ** 主なdata-role [#gdb886e0] #html(<div style="padding-left:10px;">) ナビゲーションバーやフッター、ボタンやリストなどにもそれぞれ data-roleが用意されており、追加したい箇所に 対象のdata-role属性をもつ要素を追加する事で簡単にそれっぽいページを作る事ができる。 |data-role|内容|h |page|ページ全体用| |header|ヘッダ領域用| |content|コンテンツ領域用| |navbar|ナビゲーションバー用| |footer|フッター用| |slider|フリップスイッチ(selectタグに指定するとフリップスイッチとして表示される)| |button|| |controlgroup|| |fieldcontain|| |collapsible|開閉式コンテンツ| |collapsible-set|アコーディオン式コンテンツ(開閉式コンテンツ)| #html(</div>) ** その他の data属性 [#h9721b49] #html(<div style="padding-left:10px;">) また、data-role の他にも、体裁を整えたり、挙動を変える為の data-* 属性が用意されている。 |data-corners|| |data-icon|home or delete or plus or arrow-u or arrow-d or check or gear or grid or star or custom or arrow-r or arrow-l or minus or refresh or forward or back or alert or info or search| |data-iconpos|left or right or top or bottom or notext| |data-iconshadow|true or false| |data-inline|true or false| |data-shadow|true or false| |data-theme|swatch letter (a-z)| |data-type|horizontal or | |data-id|| |data-position|| |data-title|| |data-inline|| |data-mini|| |data-shadow|| |data-theme|| |data-content-theme|| |data-ajax|true or false| |data-dom-cache|true or false| |data-prefetch|true or false| |data-rel|slide or slideup or slidedown or pop or fade or flip| #html(</div>) ** CSSクラス [#ecf0c3b0] ** jQuery Mobile によるHTML装飾 [#g5f9f926] #html(<div style="padding-left:10px;">) ui-grid #html(</div>) jQuery Mobile が自動的に追加・変更する CSSセレクタや装飾後のHTMLを把握する事で、より細かなカスタマイズを行う事ができる。 ** デザインのカスタマイズ方法 [#bae3e3de] #html(<div style="padding-left:10px;">) [data-role=header] { xxxx } などのように、data-role名をCSSセレクタとしてデザインをカスタマイズする事も可能だが、 jQuery Mobile が動的に追加・変更する CSSセレクタなどを把握する事で、より細かなカスタマイズを行う事ができる。 #html(</div>) 例えば、テキストボックスの場合は、以下のように自動装飾される。 #html(<div style="padding-left:20px">) 各領域には、以下のように自動的にclassなどが追加される。 *** data-role=header [#wa24ff7e] 素の記述 #mycode{{ <div data-role="header" class="ui-header ui-bar-a" role="banner"> ヘッダ領域 </div> <input type="text" id="text1" name="text1" value="" > }} *** data-role=navbar [#te57761a] jQueryMobileによる自動装飾後 #mycode{{ <div data-role="navbar" class="ui-navbar ui-mini" role="navigation"> ナビゲーション領域 <div class="ui-input-text ui-shadow-inset ui-corner-all ui-btn-shadow ui-body-c"> <input type="text" id="text1" name="text1" value="" class="ui-input-text ui-body-c"> </div> }} ※その他の自動装飾の例は [[jQuery Mobileによる自動装飾後のHTML]] を参照。 *** data-role=content [#ca862f6f] ここで、テキストボックスが無駄に多く取る余白(margin)を小さくしたい場合、 #mycode{{ <div data-role="content" class="ui-content" role="main"> コンテンツ領域 </div> #text1 { margin : 0px !important; } }} などを記述しても、余白は小さくならない。 余白(margin)が設定されているのは、実際のテキストボックスではなく、.ui-input-text だから。 *** data-role=footer [#le16119a] テキストボックスの余白を無くすには、以下のように記述する。 #mycode{{ <div data-role="footer" class="ui-footer ui-bar-a" role="contentinfo"> フッター </div> .ui-input-text { margin : 0px !important;} }} *** Aタグ [#yc4ce0c8] 特定のテキストボックスの余白だけ調整したい場合は、以下のようにdiv等で括って、 その配下の .ui-input-text に対して余白を指定する。など一手間かける必要がある。 #mycode{{ <a href="test.html" class="ui-link">link1</a> }} <style> #text1_area .ui-input-text { margin : 0px !important;} </style> *** input type="button" [#l86acaf7] #mycode{{ <div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c" data-disabled="false" class="ui-btn ui-btn-up-c ui-shadow ui-btn-corner-all" aria-disabled="false"> <span class="ui-btn-inner"><span class="ui-btn-text">button1</span></span> <input type="button" value="button1" class="ui-btn-hidden" data-disabled="false"> <div id="text1_area"> <input type="text" id="text1" name="text1" value="" > </div> }} *** input type="text" [#a39ebd80] #mycode{{ <div class="ui-input-text ui-shadow-inset ui-corner-all ui-btn-shadow ui-body-c"> <input type="text" name="text1" value="" class="ui-input-text ui-body-c"> </div> }} このように、自動装飾後のHTMLがどうなっているかを把握しておかないと、余白調整すらままならない。 *** input type="submit" [#vf2817c0] #mycode{{ <div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="c" data-disabled="false" class="ui-submit ui-btn ui-shadow ui-btn-corner-all ui-btn-up-c" aria-disabled="false"> <span class="ui-btn-inner"><span class="ui-btn-text">button1</span></span> <input type="submit" value="button1" class="ui-btn-hidden" data-disabled="false"> </div> }} ◆解決方法 とはいえ、fieldset で括った場合や、data属性を足した場合など、全ての装飾結果を把握する事は困難。 そこで、google chrome を利用する。 chrome に表示されたページ上で対象の要素を右クリック→ [要素の検証] を選択すると、 素のHTMLではなく、javaScriptによる変更が反映された状態のHTMLが確認できる。 *** select [#a6dd7663] #mycode{{ <div class="ui-select"> <div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-icon="arrow-d" data-iconpos="right" data-theme="c" class="ui-btn ui-shadow ui-btn-corner-all ui-btn-icon-right ui-btn-up-c"> <span class="ui-btn-inner"> <span class="ui-btn-text"><span>value1</span></span> <span class="ui-icon ui-icon-arrow-d ui-icon-shadow"> </span> </span> <select name="select1"> <option value="value1">value1</option> <option value="value2">value2</option> </select> </div> </div> }} *** input type="checkbox" [#ea72ffac] #mycode{{ <div class="ui-checkbox"> <label for="checkbox1" data-corners="true" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="checkbox-off" data-theme="c" data-mini="false" class="ui-checkbox-off ui-btn ui-btn-corner-all ui-fullsize ui-btn-icon-left ui-btn-up-c"> <span class="ui-btn-inner"> <span class="ui-btn-text">checkbox1</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow">&nbsp;</span> </span> </label> <input type="checkbox" id="checkbox1" name="checkbox1" value="1"> </div> }} ※チェックボックスがON状態になった時は、data-icon=checkbox-onに、classが ui-checkbox-on、ui-icon-checkbox-on に変わる。 *** input type="radio" [#r5b7aeb5] #html(</div>) ** イベント処理 [#d3fb87c1] #html(<div style="padding-left:20px">) *** 用意されているイベント [#mdd60218] 様々なイベントが用意されているが、とりあえず以下の3つさえおさえておけば大抵の事はできる。 様々なイベントが用意されているが、とりあえず以下をおさえておけば大抵の事はできる。 |イベント名|説明|補足|h |pageinit|そのページが最初に読み込まれた時に実行されるイベント。|| |pageshow|ページを表示する際に実行されるイベント。|基本的にページ表示時には毎回実行されるが、data-ajax=falseなボタンで遷移した後に戻るで戻った場合等は実行されない。| |pagebeforecreate|そのページがDOMツリーに組み込まれ、jQueryMobileによるHTML装飾が行われる前に起こるイベント。|このタイミングで動的にHTML要素を追加・編集すれば、jQueryMobileによるHTML装飾も行われる。| |pageinit&br;pagecreate|そのページが最初に読み込まれた時に実行されるイベント。|| |pagebeforeshow|ページを表示する前に実行されるイベント。|基本的にページ表示時には毎回実行される。[戻る](data-rel=backなボタン)で戻った場合や、ダイアログを閉じてメインページに制御が戻った際にも実行される為、注意が必要。| |pageshow|ページを表示する際に実行されるイベント。|~| |pagehide|ページ遷移を行う時に、実行されるイベント。|data-ajax=falseのリンクやボタンをクリックした場合は実行されない。| |pageremove|ページがDOMツリーから削除される時に起こるイベント。| DOMツリーに残しておきたいページ等は event.preventDefault() でremoveをキャンセルする事ができる。| *** イベントの捕捉方法 [#ycfa2c4e] data-ajax=falseでない限り、headタグ内に記述したJavaScriptは一度しか読み込まれないので、全ページで同じものを記述する。 ページ毎に異なる処理を記述する場合は、ページのidなどを指定するか、data-role=page 配下に処理を記述する。 ただし、data-role=page配下に記述する場合、onでなくbindを使用して記述する。(後述を参照) %%ページ毎に異なる処理を記述する場合は、ページのidなどを指定するか、data-role=page 配下に処理を記述する。%% %%ただし、data-role=page配下に記述する場合、onでなくbindを使用して記述する。(後述を参照)%% ページ毎に異なる処理を記述する場合は、ページのidなどを指定してheadタグ内に記述する。 ※data-role=page 配下にも書けるが初期化に限っては headタグ内の方が良さげ。(後述の注意点を参照。) #mycode{{ <head> <script> $(document).on("pageshow", function(){ // 全ページで行う初期表示処理 }); $(document).on("pageshow", "#page1", function(){ // page1 のみで行う初期表示処理 }); </script> </head> <body> <div id="page1" data-role="page"> <script> $(document).bind("pagehide", "#page1", function(){ // page1 のみで行うページ遷移前処理 }); </script> </div> </body> }} *** イベントの捕捉時の注意点 [#ycfa2c4e] headタグ内にイベント捕捉を記述した場合は、onによる捕捉でもbindによる捕捉でも 同一イベントに対する記述がある場合は、それら全てが実行される。 例えば、以下の例では 2回alertが表示される。 #mycode{{ <head> <script> $(document).on("pageshow", function(){ alert("test1"); }); $(document).on("pageshow", function(){ alert("test2"); }); </script> <head> }} data-role=page 配下にイベント捕捉を記述した場合、 bindによるイベント捕捉は上書きされるが、on によるイベント捕捉は上書きされずに追加される。 例えば以下の例では、このページを何度表示しても「bindによる捕捉」は一回しか表示されないが、 「onによる捕捉」はページにアクセスする度に表示回数が増えていく。 #mycode{{ <div id="page1" data-role="page"> <script> $(document).on("pageshow", "#page1", function(){ alert("onによる捕捉"); }); $(document).bind("pageshow", "#page1", function(){ alert("bindによる捕捉"); }); </script> <div> }} *** ボタン押下時のイベント [#l997b64e] jQuery 1.7b1 以降は bind や live、delegate で書いていた所は全て on で書けるので(onが推奨らしい) headタグ内で 対象ページのIDを指定して on でイベント捕捉するのが良いと思われる。 ※jQuery 1.9 になると liveは無くなっているので、liveで書いていた所は全て on で記述するように変更する必要がある。 #mycode{{ <head> <script> $(document).on("pageshow", "#page1", function(){ // この書き方は live と等価 // page1の初期処理 }); </script> <head> }} *** 動的に追加したHTMLに対して装飾を行う [#p8dc96f3] 動的に追加した要素は、jQueryMobileによるHTML装飾が行われない為、自分で装飾を指示する必要がある。 ※ただし pagebeforecreate 時に追加した要素は装飾されるので、個別に装飾指示をしなくても良い。 #mycode{{ <div id="#myDiv1"></div> <script> $(document).on("pageshow", "#page1", function(){ // 追加/変更した要素の親要素に対してcreateを実行する var btn = "<input type=\"button\" value=\"動的に追加したボタン\" />"; $("#myDiv1").html(btn).trigger("create"); //$("#myDiv1").append(btn).trigger("create"); }); </script> }} #html(</div>)