読者です 読者をやめる 読者になる 読者になる

@thorikiriのてょりっき

@thorikiriがWebとかAndroidとかの技術ネタや本を読んだブログです

jQueryMobileでiPad向けの2カラムのWebページをデザインする その5

jQuery mobile iPad

前回はメニューの画面遷移を実装しました。しかしながら遷移しただけで戻れないと言う致命的な欠陥がありますので、戻るボタンを実装しようと思います。
jQueryMobileでは画面遷移をURLのハッシュで管理していますね。でも2カラムだとどうしようもないので、独自に実装します。
location.historyも利用出来ないので、Stackとして保持するようにしましょう。

画面遷移の履歴を管理する

画面遷移の履歴を保持しましょう。JavaScriptで実装していきます。今回はメニュー部分の履歴ですが、コンテンツ部分も同様です。

var app = {};
// スタックを保持する
app.menuBackStack = [];
// スタックが空の状態に返すものを定義する
app.backStackConfig = {
	main: {
		title: 'content',
		hash: '#main'
	},
	menu: {
		title: 'menu',
		hash: '#menu'
	}
};
// バックスタックに登録する
app.pushMenuBackStack = (function() {
	return function(page) {
		app.menuBackStack.push(page);
	};
})();
// バックスタックから取り出す
app.popMenuBackStack = (function() {
	return function() {
		if (app.menuBackStack.length === 0) {
			return app.backStackConfig.menu;
		}
		return app.menuBackStack.pop();
	};
})();
// バックスタックの最後に登録されているものを返す
app.getMenuBackStack = (function() {
	return function() {
		if (app.menuBackStack.length === 0) {
			return {
				hash: '#',
				title: ''
			};
		}
		return app.menuBackStack[app.menuBackStack.length - 1];
	};
})();
// バックスタックをクリアする
app.clearMenuBackStack = (function() {
	return function() {
		return function() {
			app.menuBackStack = [];
		}
	};
})();

これでひと通り管理出来るようになったかなと思います。

画面遷移時にバックスタックに登録する

バックスタックとは別に、現在いる画面を覚えておく必要もありますね。なので、初期表示される画面のsectionタグに必要なデータを追加しておきます。

  • sample.html
<section data-role="page" id="index" data-mainpage="#main" data-mainpagetitle="content" data-menupage="#menu" data-menupagetitle="menu">
<!-- 中身は以前と同じ -->
</section>

data-mainpage, data-mainpagetitle, data-menupage, data-menupagetitleを定義しました。こちらに現在の状況を保持しておくことにしましょう。
そして前回作った、app.loadMenuBody()を変更しようと思います。

app.loadMenuBody = (function() {
	return function(title, page) {
		var html = $(page).find('div[class=ipad-menu-body]').html();
		$('#menuBody').html(html);
		$('#menuHeader h1').text(title);
		// ここから追加
		// 遷移後の状況を保持する
		$('#index').data('mainpage', page.hash).data('mainpagetitle', page.title);
		// すでにある戻るボタンを消す
		$('#contentHeader').find('a').remove();
		// 登録されている最新のバックスタックを取得(取り出さない)
		var back = app.getContentBackStack();
		// バックスタックが存在する場合は戻るボタンを作る
		if (page && page.hash !== app.backStackConfig.main.hash) {
			$('#contentHeader').append($('<a></a>').data('icon', 'back').data('rel', 'back').attr('href', back.hash).text('Back'));
		}
		// ここまで追加
		$('#index').page('destroy').page();
	};
})();

戻る時に画面を復元する

戻るボタンが押されたら画面を元に戻さないといけないですね。
ヘッダ部分のリンクが押された場合に、それが戻るボタンならバックスタックから前の画面を取り出して、差し替えて上げる処理を呼び出しましょう。
この時、普通にloadMenuBodyを呼び出してしまうとまたバックスタックに入ってしまうので、別の関数を作ります。

  • sample.js
app.backMenuBody = (function() {
	return function(page) {
		var html = $(page.hash).find('div[class=ipad-menu-body]').html();
		$('#menuBody').html(html);
		$('#menuHeader h1').text(page.title);
		$('#index').data('menupage', page.hash).data('menupagetitle', page.title);
		$('#menuHeader').find('a').remove();
		var back = app.getMenuBackStack();
		if (page && page.hash !== app.backStackConfig.menu.hash) {
			$('#menuHeader').append($('<a></a>').data('icon', 'back').data('rel', 'back').attr('href', back.hash).text('Back'));
		}
		$('#index').page('destroy').page();
	};
})();
$('#menuHeader a').live('click', function(ev) {
	var target = $(this);
	var rel = target.data('rel');
	// 戻るボタンの場合だけ戻る処理を呼び出す
	if (rel === 'back') {
		app.backMenuBody(app.popMenuBackStack());
		return false;
	}
});

こんな感じで実装出来ました。
メニュー部分の上部に戻るボタンが配置され、それを押すと実際に戻る事が出来ましたね。
次回はコンテンツ部分に対しても同じような処理を書いて行こうと思います。