ラベル jQuery Mobile の投稿を表示しています。 すべての投稿を表示
ラベル jQuery Mobile の投稿を表示しています。 すべての投稿を表示

2012/07/03

"header"や"footer"を再利用する方法|jQuery Mobile

ヘッダーとかフッターをjQuery Mobile利用のサイト内で再利用する方法。


jQuery Mobile(jqm)ではAjaxを利用したページ遷移が基準となっている。

さらに、スマートフォン向けにUIを最適化までしてくれるため、
単純に外部ページの要素を読込むだけでは表示が上手くいかない。

ページ遷移については初期設定により通常リンクに変更することができるけれど、
UI最適化まで無効にしてしまったらjqmを使う意味がなくなってしまう。


そこでjqmの機能を最大限に活かしつつ部品(フッターなど)を外部ページから取り込む方法を考えてみた。


"部品"を集めたページを用意する|module.html

とりあえず読込まれる側のページを用意する。

このページから必要な部品を取り出して、jQueryのprepend()append()を利用して必要なページに埋め込む。

<!DOCTYPE html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <section data-role="page">
   <header data-role="header">
    <h1>module header</h1>
   </header>
   <footer data-role="footer" data-theme="e" class="ui-bar">
    <h3>module footer</h3>
   </footer>
  </section>
 </body>
</html>

上記の例ではリンクを含んでないけれど、メニュー表示などの<a href="***"></a>を含む場合は、絶対URLで指定する。


"部品"を読込むためのスクリプト|module.js

スクリプトでしたいことは3つ。

  • 外部ページから"部品"を読込むこと
  • 読込んだ"部品"を埋め込んだ後にUI最適化すること(ランディング時や更新時用)
  • 最適化された"部品"を次のページに埋め込むこと(ページ遷移時用)
function module() {
 var head = $('#module :jqmData(role="header")').clone();
 var foot = $('#module :jqmData(role="footer")').clone();
 $(':jqmData(role="header"),:jqmData(role="footer")').remove();
 $(':jqmData(role="page")').prepend(head).append(foot).page().trigger('pagecreate');
}

$(function(){
 $('body').append('
'); $('#module').load('module.html div:jqmData(role="page")',function(){ $($(this).html()).replaceAll(this).attr('id','module'); module(); }); $(':jqmData(role="page")').live('pageinit',module); });

jqmは新たなページを読込むときに、だいたい次のようにページ遷移を表現する。

  1. 次のページを読込む(pageloadイベント)
  2. 次のページの表示を最適化する(pagecreatepageinitializeイベント)
  3. 前のページを隠す(pagehideイベント)
  4. 次のページを表示する(pageshowイベント)

例えば、2.の後に"部品"を埋め込んでもキレイには表示されない。

とはいっても、javascriptについてはjQueryとjqmが少し扱える程度の理解しかないので、
試行錯誤を繰り返した結果、たまたま上手くいったスクリプト。

ちゃんと理解している人が作ったらもっとスマートなものになるんだろう。


ちなみに

この方法を使うと、階層化リストの2階層以降で表示されるリストにもヘッダーとフッターを埋め込むことができる。

階層化リストではフッターを表示や指定することが出来ないので、フッターのモジュール化は応用ができそう。

ただ、ヘッダーに関してはモジュール化する必要性はあまり感じない。


あ、ダイアログへの埋め込みはについては考えてなかった。。。
$(':jqmData(role="dialog")')とかを上手に使えば上手くいくのかな?




2012/06/20

"ui-icon-alt"を使う2つの方法|jQuery Mobile

jQuery Mobileのデザインを作ることができるThemeRollerでダウンロードしたCSSの中に .ui-icon-alt というセレクタを見つけた。

/* Alt icon color
-------------------------------------*/
.ui-icon-alt {
 background: #fff;
 background: rgba(255,255,255,.3);
 background-image: url(images/icons-18-black.png);
 background-repeat: no-repeat;
}

どうやら色違いのアイコンを設定できるようだ。

jQuery MobileのDocs内にはアイコンの切替(Alt icon color)についての記述はないようなので、
ThemeRoller独自に拡張されたものなのだろうか。
ui-icon-alt」などで検索してみたけれども、それらしき情報も見つからない。

ということで、実装する方法をいろいろ試してみた結果、応用が効きそうな2つをご紹介。
ただし、一部のフォーム要素には非対応


個別の要素ごとに Alt icon color を設定する方法



アイコンを設定する時は、対象の要素にdata-icon="***"を指定する。
jQuery Mobileはアイコンを描写するために、指定された要素の内部に新たな要素を生成し、
"ui-icon-***"をクラスとして(class="ui-icon-***"を)追加する。

そこでdata-icon="aaa bbb"と半角スペースを挟んで2つの文字列を指定してあげると、
生成される要素にはclass="ui-icon-aaa bbb"が付与され、2つのクラスを追加する事ができる。

つまり、半角スペースの後を ui-icon-alt にしてアイコンを指定すると、
生成される要素に ui-icon-alt のクラスを付与させることができる。

ただ、なんかちょっとずるい感じがするな。。。

sample1:個別の要素ごとにアイコンの色を設定
右側のボタンに『data-icon="*** ui-icon-alt"』を設定

<div class="ui-grid-a">
 <div class="ui-block-a">
  <h3>Normal</h3>
  <a data-role="button" data-icon="check">check</a>
  <a data-role="button" data-icon="gear">grid</a>
  <a data-role="button" data-icon="refresh">refresh</a>
  <a data-role="button" data-icon="grid">grid</a>
  <a data-role="button" data-icon="star">star</a>
 </div>
 <div class="ui-block-b">
  <h3>Icon-Alt</h3>
  <a data-role="button" data-icon="check ui-icon-alt">check</a>
  <a data-role="button" data-icon="gear ui-icon-alt">grid</a>
  <a data-role="button" data-icon="refresh ui-icon-alt">refresh</a>
  <a data-role="button" data-icon="grid ui-icon-alt">grid</a>
  <a data-role="button" data-icon="star ui-icon-alt">star</a>
 </div>
</div>


テーマごとに Alt icon color を設定する方法



アイコンの背景を透明にした場合、テーマによってはアイコンが見えづらくなってしまう。
任意のテーマ内全てのアイコンに対して個別の設定をするのは結構大変。
jQueryを使いテーマを指定して内部のアイコンを一括で設定してしまおう。

sanple2.jsだけでは、Ajaxで読込んだページには適用されないので、
本当は$('div:jqmData(role="page")')の pageinit イベントなんかにバインドしてあげたほうがよい。

sample2:テーマごとにアイコンの色を設定
明度の高いc、d、eのテーマに黒いアイコンを設定

$(function(){
 var $alttheme = new Array( "c", "d", "e" ); //ここでテーマを指定
 var at = new Array();
 for( t in $alttheme ){
  at.push(':jqmData(theme="' + alttheme[t] + '"):jqmData(icon) > span > span');
 }
 $(at.join()).addClass('ui-icon-alt');
});
<div data-role="header" data-theme="a">
 <h1>theme a</h1>
 <a data-icon="arrow-l">button a</a>
 <a data-theme="b" data-icon="arrow-r" data-iconpos="right">button b</a>
</div> 
<div data-role="header" data-theme="b">
 <h1>theme b</h1>
 <a data-icon="arrow-l">button b</a>
 <a data-theme="c" data-icon="arrow-r" data-iconpos="right">button c</a>
</div> 
<div data-role="header" data-theme="c">
 <h1>theme c</h1>
 <a data-icon="arrow-l">button c</a>
 <a data-theme="d" data-icon="arrow-r" data-iconpos="right">button d</a>
</div> 
<div data-role="header" data-theme="d">
 <h1>theme d</h1>
 <a data-icon="arrow-l">button d</a>
 <a data-theme="e" data-icon="arrow-r" data-iconpos="right">button e</a>
</div> 
<div data-role="header" data-theme="e">
 <h1>theme e</h1>
 <a data-icon="arrow-l">button e</a>
 <a data-theme="a" data-icon="arrow-r" data-iconpos="right">button a</a>
</div> 



※ 一部フォーム要素には非対応



jQuery Mobileはsample3-1.htmlのようなマークアップからsample3-2.htmlを生成する。
<a href="#" data-role="button" data-icon="check">sample<a>
<a href="#" data-role="button" data-icon="check" class="ui-btn ui-btn-icon-left">
 <span class="ui-btn-inner ui-btn-corner-all">
  <span class="ui-btn-text">sample</span>
  <span class="ui-icon ui-icon-check ui-icon-shadow"> </span>
 </span>
</a>


上記の2つの方法はこの生成されるマークアップ構造を利用して Alt icon color を実装している。
そのためアイコンを描写するマークアップが異なる次の3つのフォーム要素は非対応となってしまう。

  • <input type="radio" />
  • <input type="checkbox" />
  • <input type="search" /> ※入力内容削除ボタンには有効


ラジオボタン・チェックボックスがON時に表示されるアイコンの色は、ThemeRoller内でも白固定で指定することができない。
全テーマ共通の設定になるので、アクティブカラーをある程度明度の低い色にしておけば特に問題はないだろう。

ただし、検索タイプのインプットに関しては、アイコンの背景を透明にした場合に致命的な問題が起こる。
jQuery Mobileが「ここは検索タイプ」と分かりやすいようにしてくれているのに、
虫眼鏡アイコンが外側の要素の背景に溶け込んでしまいほとんど見えなくなってしまう。

CSSを修正とjavascript追加で解決できなくはないんだけど、
CSSはいじらないで実装したいので、もうちょっと勉強してきます!