固定ポジションツールバー

CSSの position:fixed をサポートしているブラウザ(ほとんどのデスクトップブラウザ、iOS5以降、Android2.2以降、BlackBerry6など)では、“fixedtoolbar“プラグインが使われます。これにより、ヘッダやフッタとしてツールバーをページ上下に固定することが出来、コンテンツはその間を自由にスクロールさせられます。この固定機能をサポートしていないブラウザでは、バーの表示位置は固定されず、通常の配置と同様になります。

固定モードを有効にするには、ヘッダやフッタに data-position=“fixed” という属性を指定してやります。

<div data-role="header" data-position="fixed">
        <h1>Fixed toolbars</h1>
</div>

固定フッタであれば、次のようにします。

<div data-role="footer" data-position="fixed">
        <h1>Fixed Footer!</h1>
</div>

フルスクリーン・ツールバー

フルスクリーン・ポジションモードを使うと、固定ツールバー同様に上部にヘッダが固定表示されます。通常の固定ツールバーと異なるのは、機能をトグルした際に固定でない通常モードに切り替わらず、代わりに画面上から消えてしまう点です。フルスクリーン・ツールバーは、たとえばフォトビューワのような画面全部をコンテンツとして使いたいような場合に有用です。

フルスクリーン・モードを使用するには、固定ヘッダやフッタに data-fullscreen 属性を指定します。

<div data-role="header" data-position="fixed" data-fullscreen="true">
        <h1>Fixed Header!</h1>
</div>

ツールバー上のフォーム要素

固定ツールバー上にフォーム要素を配置した場合、jQuery Mobile 1.1以降は全て上手く動作することがテストされています。しかし、実際に固定ツールバーに限らず position:fixed を指定した要素内でフォーム要素を使う場合、より突っ込んだ動作確認をするようお勧めします。この構造は、たとえばAndroid2.2/2.3上で起きたような(後述)いくつかの予期しない問題を引き起こす可能性があります。

jQuery Mobile 1.1からの変更

バージョン1.1より前では、jQuery Mobileはツールバーをスクロール毎に動的な再配置を行うことで仮想的に固定ツールバーを実装していました。これは、ほんとうの意味での固定表示に必要な position:fixed CSSをサポートしているブラウザが極めて少なかったためです。そしてJavaScriptによるオーバーフロースクローリングの偽装は、ブラウザのサポート範囲を狭めるだけでなく操作性も不自然なものになってしまうプラットフォームもありました。こうした挙動は理想的なものとは言いがたく、jQuery Mobile 1.1では、より広範囲のブラウザに対応するためにも全く新しいアプローチでの実装に変更しました。現在は、多くの主流ブラウザで本当の意味での固定ツールバーを提供できるようになっており、またサポートしていなブラウザではシンプルに静的なツールバーに切り替わるようになっています。

古いブラウザでの対応

固定ツールバーは、CSSの position:fixed プロパティをサポートしていないiOS4.3のようなブラウザでは、自動的にデグレードします。もし、そうした環境下でも以前のバージョンのような仮想的な固定ツールバーを実装したければ、Filament Groupによって開発された拡張機能が利用できます。

実装するには、jQuery Mobileを参照した後に拡張機能のCSSとJSファイルを参照するだけです。iOS4.3などの上では、jQuery Mobile 1.0の時と同様の挙動をし、1.1の固定ツールバー同様のAPIで設定できます。

もし機能向上の提案などがあれば gist をフォークするなどして知らせて下さい!

固定ツールバー上にフォームコントロールを配置した場合の既知の問題

iOS5やAndroid上で、固定ポジションにした要素上にフォームコントロールを置いた状態で、プログラムからウインドウをスクロールさせた場合(たとえば window.scrollTo などを使って)に、再現性はハッキリしないものの選択状態にできなくなるという問題が報告されています。これはjQuery Mobile特有の問題ではないのですが、それ故にこちらでは解決困難です。jQuery Mobileで固定ツールバーを使い、更にフォームコントロールをそこに配置している場合、プログラムからのスクロールは行わないことをお勧めします。詳しくは Device Bugs Projectこのチケット で解説されています。

Android 2.2/2.3での既知の問題

Android 2.2/2.3における position:fixed の実装は、スタイルやマークアップのパターンとは無関係なものと思われる、おかしな挙動を引き起こします。特に、この position:fixed を指定した要素内に position:absolute の要素を配置した際に、おかしくなりがちです。この件について集中的に調査を行ったところ、カスタムスタイルを適用した際に問題が起こりやすいことが分かりました。

  • フォーム要素(特にセレクトメニュー)がページ上のどこかにあると、固定ポジション要素内に置いた中身が空のabsoluteポジション指定要素が操作できなくなる。更にAndroid 2.2上では稀に、ページ全体が操作不能になってしまう。この場合、absolute指定の要素内に、何か文字列を入れてやることで解決する場合があります。文字列は改行コードや、時にはスペースでも解決することがあります。
  • 上記問題は、時に固定ポジション要素内にabsolute指定の画像を置いた場合にも発生する。ただし、それはイメージのサイズ指定を画像本来の大きさ以外にした場合に限るようです。つまり、例えばCSSでheightやwidthの値を元画像のサイズ以外に指定した場合や、src属性に不正な参照があった場合(これはつまり、「元画像の大きさ」が存在しなくなってしまう)に、問題が発生します。たとえば50ピクセル四方のabsolute指定画像を固定ツールバーに置いても、サイズをそのままにしておけば、問題は起きないようです。
  • ページのどこかに position:fixed を指定した要素があると、多くの2D CSS トランスフォームが失敗します。不思議な事に translate だけは、この問題に当たらないようです。更に不思議なことに、こうした現象は、その親要素の opacity を .9 以下に指定すると、解決します。
  • 特に position:fixed と overflow 属性指定の組み合わせは、避けるべきです。これはAndroidの更に古いバージョンから、問題を引き起こすことで知られていました。
  • 固定ポジション要素上にスクリーンキーボードを呼び出す要素を置いた場合に、デフォルトのキーボード以外を設定していると入力できなくなります。これは Swype や XT9 など、通常のキーボードではない入力装置も含みます。

こうした諸問題を軽減するよう様々な工夫を入れていますが、現時点では固定ツールバーに複雑なスタイルを組み込んだり、フォーム要素を入れたりすることは、Android上での全バージョンテストをするのでない限り避けたほうが良いと思われます。

次のページは、固定ツールバー上のフォームテスト用のページです。 デモ , テキスト入力 , 検索ボックス , ラジオ , チェックボックス , スライダー , セレクト , ボタン


touchOverflowEnabledは、1.1.0から廃止になりました

jQuery Mobileは1.1より前のバージョンでは、真の固定ツールバーを実装するために overflow-scrolling:touch のCSSを使ってきました。しかし、現在のところこれをサポートしているのはiOS5のみです。そのためjQuery Mobile 1.1からは、この方法を一切止めることとしました。これらの機能は、既にフレームワークから削除されています。ただし、$.mobile オブジェクトだけは残されています。これは、既存のアプリケ>ーションが予期しないエラーを起こすことを防ぐためです。しかしこの値は設定しても機能せず、いずれはオブジェクトも削除される可能性があります。これは、今後使わないようお願いします。

オプション

visibleOnPageShow boolean

default: true

ページ表示時にツールバーを可視状態にするかどうかを指定します。この値はdata属性でも指定可能です: data-visible-on-page-show="false"

$("[data-role=header]").fixedtoolbar({ visibleOnPageShow: false });
disablePageZoom boolean

default: true

固定ツールバーを含んだページで、ユーザによるズームサイズ変更を許可するかどうかを指定します。この値はdata属性でも指定可能です: data-disable-page-zoom="false"

$("[data-role=header]").fixedtoolbar({ disablePageZoom: false });
transition string

default: "slide" (which ends up using slideup and slidedown)

固定ツールバーの表示/非表示が切り替わる際の効果を指定します。指定可能なのは "none", "fade", "slide"のいずれか、あるいはCSSで独自作成した切り替え効果です。この値はdata属性でも指定可能です: data-transition="fade"

$("[data-role=header]").fixedtoolbar({ transition: "fade" });
fullscreen boolean

default: false

フルスクリーンモードにすると通常の固定ツールバーとは異なり、表示状態にある限り常にコンテンツの最上部に表示されます。フルスクリーンにするとトグルされても静的ポジションにはならず、単に表示/非表示が切り替わるようになります。これは、たとえば画像ビューワのような画面全体を使うインターフェースに適しています。動作は、フルスクリーン・ポジションモードを参照してください。この値はdata属性でも指定可能です: data-fullscreen="true"

$("[data-role=header]").fixedtoolbar({ fullscreen: true });

注意: data属性のシンタックスは変わっていませんが、指定可能なのはツールバー要素そのものに対してのみとなりました。ページ要素への指定は出来ません。

tapToggle boolean

default: true

ツールバーの固定状態を、スクリーンのタップ(マウス環境であればクリック)によって切り替えます。この値はdata属性でも指定可能です: data-tap-toggle="true"

$("[data-role=header]").fixedtoolbar({ tapToggle: true });

注意: この挙動は、以前は次のような記述で指定できました。しかしバージョン1.1からは、サポートしていません:

     
$.mobile.fixedToolbars
   .setTouchToggleEnabled(false);
tapToggleBlacklist string

default: "a, .ui-header-fixed, .ui-footer-fixed"

タップしてもツールバーの固定状態切り替えとはならない要素をjQueryセレクタで指定します。

$("[data-role=header]").fixedtoolbar({ tapToggleBlacklist: "a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed" });
hideDuringFocus string

default: "input, select, textarea"

フォーカスが当たっている間、固定ツールバーが非表示になる要素をjQueryセレクタで指定します。ただし、固定ツールバー上にある要素は自動的に除外されます。

$("[data-role=header]").fixedtoolbar({ hideDuringFocus: "input, select, textarea" });
updatePagePadding boolean

default: true

ツールバーは、その中身によって高さが変わります。このオプションを有効にすると、固定ツールバーが静的なポジションに切り替えられて、なおかつページの最上部もしくは最下部にスクロールした際に充分なスペースを確保できるようにページが padding を取るようになります。しかし最適化のためにはこのオプションをfalseにして、CSSによりページ要素のpaddingをemで指定したツールバーの高さに揃えることをお薦めします。たとえば次のように指定します: .ui-page-header-fixed { padding-top: 4.5em; }. この値はdata属性でも指定可能です: data-update-page-paddinge="false"

$("[data-role=header]").fixedtoolbar({ updatePagePadding: false });
supportBlacklist function

default: function that returns a boolean value

CSSの position:fixed は、テストの非常に難しい属性です。実際バージョン1.1のリリースにあたっては、リーズナブルなブラウザの対応状況テスト方法は見つかりませんでした。このオプションは、この position:fixed に問題のあるブラウザが分かった際に、機能を無効にするためのブラックリストです。しばしば、これらのプラットフォームは postion:fixed をサポートしているにも関わらず、おかしな挙動をします。これは最初からサポートしていないよりもある意味で悪い状況で、機能を有効にすべきかどうかの判別が自動的に出来ません。そのため、ブラックリストに加えて識別させる機能が加えられました。この指定は mobileinit で行う必要があります。


$( document ).bind("mobileinit", function(){
  $.mobile.fixedtoolbar.prototype.options.supportBlacklist = function(){
    var result;
    // logic to determine whether result should be true or false
    return result;
  };
})
initSelector CSS selector string

default: ":jqmData(position='fixed')"

ここにセレクタ指定することで、自動的に固定ツールバーにする要素を設定できます。値を変更する場合は mobileinit で行う必要があります。

$( document ).bind( "mobileinit", function(){
        $.mobile.fixedtoolbar.prototype.options.initSelector = ".myselector";
});

メソッド

show ツールバーを表示する。

                    $("[data-position='fixed']").fixedtoolbar('show');
                                                

注意: バージョン1.1より前では、次の記述でツールバーを表示していました。しかし、これはもうサポートされていません。


$.mobile.fixedToolbars
   .show(true);
hide ツールバーを非表示にする(フルスクリーンモードで無い場合、通常ポジションへの変更)

$("[data-position='fixed']").fixedtoolbar('hide');
                                                
toggle 現在の表示状態によって、show/hideを呼び出す。

$("[data-position='fixed']").fixedtoolbar('toggle');
                                                
updatePagePadding ツールバーの高さに併せて、ページの上下paddingを更新する。

$("[data-position='fixed']").fixedtoolbar('updatePagePadding');
                                                

このメソッドは、ツールバーが再配置される updatelayout イベントでも用いることが出来ます。開発者はページ内のコンテンが動的にサイズを変えるようなプラグインを作る場合、手動で updatelayout イベントを呼び、コンポーネントが変更されたことを他のアプリケーションに通知することができます。このイベントは、たとえば開閉可能なブロックやリストビューのフィルタなどでも用いられているように、ツールバーに特定したものではなく、どのウィジェットでも相互にレイアウトの更新を通知できるイベントになっています。

destroy 固定ツールバーを、要素ごと削除する。

$("[data-position='fixed']").fixedtoolbar('destroy');
                                                

イベント

create 固定ツールバーが作成された際に発火。

$( ".selector" ).fixedtoolbar({
   create: function(event, ui) { ... }
});