WEBアプリ開発記

~備忘録としてね~

webでのシングルページアプリケーション作成に役立つ(はず)軽量ライブラリを作った

モバイル向けのwebアプリを作成していると、画面が狭いのであまりたくさんのコンテンツを表示できませんね。
その場合、複数のhtmlを用意して、リンクを張って、、っていうのも良いんですが、ページロードが遅くてイライラする。。

まぁそんな要望を叶える1つの考え方が、シングルページアプリケーション(SPA)なのですが、それを上手くやるjavascriptのライブラリを作ったので、紹介してみようとか思って、切り出してみました。

名をば、「single-page-manager」ってことにしておきます。

ダウンロードはこちら→single-page-managerのダウンロード

使い方は、

1.まず、jQueryが必要なんですね。読み込みます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>sample</title>
<script src="jquery/jquery-2.1.3.min.js"></script>
</head>


2.次に、single-page-manager-1.0.jsとsingle-page-manager-1.0.cssを読み込みます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>sample</title>
<script src="jquery/jquery-2.1.3.min.js"></script>
<script src="lib/single-page-manager-1.0.js"></script>
<link rel="stylesheet" href="lib/single-page-manager-1.0.css" />
</head>


3.ホームとなるページを普通にbody以下に書きます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>sample</title>
<script src="jquery/jquery-2.1.3.min.js"></script>
<script src="lib/single-page-manager-1.0.js"></script>
<link rel="stylesheet" href="lib/single-page-manager-1.0.css" />
</head>
<body>
	<!-- home view-->
	<h1>ほーむだよ</h1>
</body>
</html>


4.重ねるレイヤーとなるページをdiv要素を使って以下のように書きます。
必要なページ数分だけ書きましょう。
※styleやcssで対象をdisplay:none;にしておけば、画面描画時のちらつきが防げます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>sample</title>
<script src="jquery/jquery-2.1.3.min.js"></script>
<script src="lib/single-page-manager-1.0.js"></script>
<link rel="stylesheet" href="lib/single-page-manager-1.0.css" />
</head>
<body>
	<!-- home view-->
	<h1>ほーむだよ</h1>

	<div id="layer-1" style="display: none;">
		<div class="sbro-layer-header">layer1</div>
		レイヤー1だよ
	</div>
	<div id="layer-2" style="display: none;">
		<div class="sbro-layer-header">layer2</div>
		レイヤー2だよ
	</div>
</body>
</html>


5.bodyの最後で(documentが読み終わった時点で)、以下のようにLayerManagerを生成します。
toLayerメソッドを使って、レイヤー化したい要素のセレクタを渡せば良いわけです。

<script>
	var layerManager = new sbro.LayerManager();
	layerManager.toLayer("#layer-1");
	layerManager.toLayer("#layer-2");
</script>


6.レイヤー化したページを開くには、layerManagerのopenメソッドを使います。
適当なボタンを作って、バインドしてみましょう。

<body>
	<!-- home view-->
	<h1>ほーむだよ</h1>
	<button id="open-layer-1">レイヤー1を開く</button>

	<div id="layer-1" style="display: none;">
		<div class="sbro-layer-header">layer1</div>
		レイヤー1だよ
		<br>
		<br>
		<button id="open-layer-2">レイヤー2を開く</button>
	</div>
	<div id="layer-2" style="display: none;">
		<div class="sbro-layer-header">layer2</div>
		レイヤー2だよ
	</div>
</body>
<script>
	var layerManager = new sbro.LayerManager();
	layerManager.toLayer("#layer-1");
	layerManager.toLayer("#layer-2");

	$('#open-layer-1').on('click', function() {
		layerManager.open("#layer-1");
	});
	$('#open-layer-2').on('click', function() {
		layerManager.open("#layer-2");
	});
</script>


以上で、ボタンをクリックした際にページが画面いっぱいに開きます!
homeボタンを押せば、管理されているすべてのレイヤーが閉じて一気にホームに戻れる感じです。


他にも、ボタンのキャプション変えられたり、ページ遷移にアニメーション付けたり(要animate.css)できます。
詳しくは、サンプルソースを参照してみてね♪
ダウンロードはこちら→single-page-managerのダウンロード


最後に、全サンプルソースを載せておきます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>sample</title>
<script src="jquery/jquery-2.1.3.min.js"></script>
<script src="lib/single-page-manager-1.0.js"></script>
<link rel="stylesheet" href="lib/single-page-manager-1.0.css" />
</head>
<body>
	<!-- home view-->
	<h1>ほーむだよ</h1>
	<button id="open-layer-1">レイヤー1を開く</button>

	<div id="layer-1" style="display: none;">
		<div class="sbro-layer-header">layer1</div>
		レイヤー1だよ
		<br>
		<br>
		<button id="open-layer-2">レイヤー2を開く</button>
	</div>
	<div id="layer-2" style="display: none;">
		<div class="sbro-layer-header">layer2</div>
		レイヤー2だよ
	</div>
</body>
<script>
	var layerManager = new sbro.LayerManager();
	layerManager.toLayer("#layer-1");
	layerManager.toLayer("#layer-2");

	$('#open-layer-1').on('click', function() {
		layerManager.open("#layer-1");
	});
	$('#open-layer-2').on('click', function() {
		layerManager.open("#layer-2");
	});
</script>
</html>


別のhtmlファイルをテンプレートとしてロード~レイヤー化させる機能も欲しかったのですが、かったりーのでやめました
誰か、「そんなの楽勝だぜぃ」という心から素敵な方、修正お待ちしております笑

アプリ紹介 : ワンタップ日記~過去の検索が楽々!非公開無料日記アプリ!~

最近リリースしたアプリの紹介です!

「 ワンタップ日記~過去の検索が楽々!非公開無料日記アプリ!~」ってアプリです。
web日記サービスとして、ブラウザからも利用できますよ!


ワンタップ日記~過去の検索が楽々!非公開無料日記アプリ!~ - Google Play の Android アプリ

f:id:jazzmaster0601:20150515234604p:plain f:id:jazzmaster0601:20150325213649p:plain
基本的には至ってシンプルな日記アプリなのですが、無料で使えることに加え、以下のような機能を付けてみました。


[ワンタップ機能でスマホから素早く記録しよう]
いつも書き込む単語はラベルを用意しておいてタップするだけで時刻と一緒に記録できます!
今いる場所もワンタップで記録可能!
地図とマーカーでいつどこにいたかも即時で表示!
せわしない移動中でもタップだけでOK!

f:id:jazzmaster0601:20150325213652p:plain f:id:jazzmaster0601:20150325213657p:plain


[天気は自動で取得しよう]
現在地の天気をワンタップで登録できます!
手動で登録してもOKです!


複数の日記帳を作ろう]
日記帳は何冊でも作成可能なので、普段の日記帳とは別に夢日記なんかも書けちゃう!
日記帳のテーマカラーは5色から選べます!

f:id:jazzmaster0601:20150325213703p:plain f:id:jazzmaster0601:20150325213659p:plain


[写真も毎日登録しよう]
写真だってカメラからさくっと登録できます!
枚数の制限もないのでどんどん登録しましょう!

f:id:jazzmaster0601:20150325213705p:plain


[過去の日記を検索ワードで検索しよう]
また過去の日記は単語で検索可能なので、最後に美容室に行った日とかも簡単に分かります!

f:id:jazzmaster0601:20150325213709p:plain


[ブラウザからもどうぞ!↓↓↓]
web日記サービスとして、ブラウザからも利用できます!
https://remembertheday61.appspot.com
出先でさらっと記録しておいて、それを見ながら自宅ではPCの大きな画面から丁寧に書き直すといった使い方がオススメです!

ワンタップ日記~過去の検索が楽々!非公開無料日記アプリ!~ - Google Play の Android アプリ

詳細な紹介ページは以下!

http://cosbroths.com/remembertheday/cosbroths.com

是非使ってみてくださいm(__)m

iPhoneで位置情報の許可を元に戻す方法

iPhone使ってるとたまに「位置情報を利用します。よろしいですか?」とか出て来て、「うぉ、あんなことやこんなことまでバレるのやだこわい」って、勢いで許可しないってなりますね。

f:id:jazzmaster0601:20150325155011j:plain
fig1:「やだこわい」の図


でもアプリやら何やらで、そんな位置情報を利用しないと使えないような便利な機能をいざ使おうとなっても、かつて「許可しない」にしてしまったもんだから使えないでショゲルケースがよくあったのでメモします。


iPhone > 設定 > 一般 > リセット > 位置情報とプライバシーをリセット


これでOK!

アプリ紹介 : お買い物リスト~共有機能付きお買い物メモ~

以前から作っていたアプリの紹介です。

「お買い物リスト~共有機能付きお買い物メモ~」ってアプリです。


お買い物リスト~共有機能付きお買い物メモ~ - Google Play の Android アプリ


簡単に言うと普段の買い忘れを防ぐためのメモアプリなのですが、写真メモやURLメモができたり、メモ一覧を家族と共有できたり、その辺が一応ウリです。

f:id:jazzmaster0601:20150323210030p:plain


こんな感じでリストを作っていきます。

f:id:jazzmaster0601:20150323210059p:plain


グループでの共有リストはこんな感じ。

f:id:jazzmaster0601:20150323210225p:plain


詳細な紹介ページは以下!

cosbroths.com

是非使ってみてくださいm(__)m

SpringMVC × jQuery Ajax × iOS Chromeでエラーになる件の解決方法

他のブラウザでは問題ないのだけれども、iOSChromeだけでjQueryajaxがエラーになる件で苦しんだのでメモ。

記事をいろいろ漁っても大体「iOSChromeは捨てろ」なんてことが書かれており、個人的にiPhoneでもChrome使いたい自分にとってとても困った。

まず、クライアント側のajaxソースコードとしては以下のように単純。

var param = {
	type : 'POST',
	url : 'hoge/put-hoge',
	contentType : 'application/json; charset=utf-8',
	data : JSON.stringify({
		param1 : 'aaa',
		param2 : 'bbb',
	}),
};
$.ajax(param).done(function(receiveData, textStatus, jqXHR) {
	console.log(receiveData);
}).fail(function(jqXHR, textStatus, errorThrown) {
	var message = 'status"=' + jqXHR.status + '", textStatus="' + textStatus + '", errorThrown="' + errorThrown + '"';
	alert(message);
});

そして、サーバーサイドのメソッドは以下のように

@RequestMapping(value = "hoge/put-hoge", method = RequestMethod.POST)
@ResponseBody
public String putHoge(@RequestBody Map<String, String> param) {
	String param1 = param.get("param1");
	String param2 = param.get("param2");

	// この辺でパラメータ使ってDBに書き込み

	return "success";
}

とまぁこちらも簡単にDBにこにょこにょして、文字列を返すだけなのだが、これがiOSChromeだけ上手くいかない。。
エラーの内容も、

status="0", textStatus="error", errorThrown=""

と、もう「何かしら起こりましたが何かしらダメです。何かは教えません。」て感じでクソ。
サーバーサイドではエラーは起こっていない。平然と「仕事しましたが何か?」って感じでこちらもクソ。

他のiOSSafariAndroidChromeでは全然行けるのに。。


問題は、サーバーサイドのメソッドアノテーションの記載が足りなかったことだった!
つまり、上記サーバーサイドのコードを

@RequestMapping(value = "hoge/put-hoge", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)

と、produceを追記してやればOK。
殆どのブラウザがレスポンスのメディアタイプを自動判別してくれてたってことなのかね。
記述が長くなるが、つけといた方がいいってことで了解しました。

windowsマシンでのpythonGAE開発環境が遅くて仕事にならない件の解決法

ちょっとソースを変更して実験しようとすると、全然pythonのサーバー側が応答せず、トライアンドエラーのサイクルが全くスムーズに行かない。。

原因はどうやら、開発環境のAPサーバーがIPv6に対応してないことのようだ。windowsの最近のマシンはデフォルトでIPv6を優先するような設定になっている。

 

localhostに接続すると、IPv6でアクセスして、タイムアウトを待ち、続いてようやくIPv4でアクセスするため、その待ち時間のせいで遅かったようだ。

 

解決方法は以下リンク


Google AppEngineのdev_appserver高速化 - Firespeed

 

要するに、localhost127.0.0.1にアクセスするようにすればいいようだ。

GitHubでのIssue管理及びPullRequestの流れ

1.まず、作業するリポジトリGitHub上で開きます。

画面左側の「Issue」ボタンを押します。

f:id:jazzmaster0601:20141208184425p:plain

 

2.画面左上の「New issue」を押します。

f:id:jazzmaster0601:20141208184645p:plain

 

3.タイトルと内容を記入して、「Submit new issue」を押します。

f:id:jazzmaster0601:20141208185122p:plain

 

4.Issue番号が発行されました。これを覚えておきます。後で作成するブランチ名をこのIssue番号にするからです。

f:id:jazzmaster0601:20141208185305p:plain

 

5.eclipseの「Git リポジトリー」タブにて、新規ブランチを作成します。

ブランチ名は何でも良いのですが、慣習的にIsuue番号と同じにしましょう。

※後々ぱっと見で分かりやすいので。

f:id:jazzmaster0601:20141208190023p:plain

f:id:jazzmaster0601:20141208190137p:plain

 

6.新規ブランチとして「#6」というブランチが作成されました。

このブランチを編集していきましょう。

f:id:jazzmaster0601:20141208190420p:plain

 

7.編集が完了したら、コミットしてリモートリポジトリにこのブランチをプッシュします。

この時、コミットコメントに「#6」とIssue番号を書くことを絶対に忘れないでください

このコミットコメントを以て、このコミットとIssueが紐づくわけです。

(自動でブランチ名をコミットコメントに追加するプラグインでもあれば忘れにくくなるでしょう。要調査)

f:id:jazzmaster0601:20141208191319p:plain

f:id:jazzmaster0601:20141208191618p:plain

 

8.以下のような画面が出てきたら、ソース参照から現在のブランチを選択し、「仕様の追加」を押します。「完了」ボタンを押すことで、#6のブランチがリモートリポジトリにプッシュされます。

f:id:jazzmaster0601:20141208192024p:plain

f:id:jazzmaster0601:20141208192030p:plain

f:id:jazzmaster0601:20141208192132p:plain

 

9.GitHubに戻ると、「Compare & pull rquest」というボタンが表示されています。

このボタンから、管理者(※1)に「ちゃんとしたソースだったらmasterブランチ(本番環境)(※2)にマージしてくださいな♪」というお願いを出します。

次の画面でコメントを入力し、「Create pull request」を押します。

f:id:jazzmaster0601:20141208192922p:plain

f:id:jazzmaster0601:20141208193120p:plain

 

10.管理者(※1)でGitHubリポジトリを開くと、Pull requestが届いています。

リンクから変更点なども見れます。実際にローカルに落としたりして動作確認します。

f:id:jazzmaster0601:20141208193439p:plain

f:id:jazzmaster0601:20141208193533p:plain

 

11.ソースの修正に問題がなければ、「Merge pull request」ボタンを押して、#6のブランチをmasterブランチにマージします。

f:id:jazzmaster0601:20141208193936p:plain

 

12.masterブランチにマージされました。pull requestも自動でcloseされました。

f:id:jazzmaster0601:20141208194127p:plain

 

13.Issueは自動でcloseされないようです(※3)。Isuueをcloseしましょう。

リポジトリトップ画面からIsuue -> #6のIsuueを選択し、開きます。

(尚、先ほどのコミットコメントがこのIssueに紐づいていることもこの画面で確認できます)

close用コメントを入力し、closeします。

f:id:jazzmaster0601:20141208194732p:plain

 

14.次に、不要になったブランチも削除します。こちらも自動でremoveされないようです(※4)

リポジトリトップ画面のbranchを押します。

次の画面で、#6のブランチのゴミ箱アイコンを押すことで、このリモートリポジトリから#6のブランチを消すことができます。

f:id:jazzmaster0601:20141208195048p:plain

f:id:jazzmaster0601:20141208195445p:plain

 

15.最後にローカルの開発環境を整理します。リモートの変更をローカルはまだ知りません。以下の画面のようにリモートブランチが残っています。

f:id:jazzmaster0601:20141208195717p:plain

 

16.ローカルの該当リポジトリにて「git remote prune origin」コマンドを実行します。

これで、ローカルにもリモートの変更が同期されます。

f:id:jazzmaster0601:20141208200050p:plain

 

17.残った#6ブランチは名前を変えて、リベースすれば、また次の作業ブランチとして使えます。

f:id:jazzmaster0601:20141208200516p:plain

f:id:jazzmaster0601:20141208200533p:plain

f:id:jazzmaster0601:20141208200725p:plain

 

(※1)管理者って?

→おそらくリポジトリのownerだと思われるが調査不足。複数アカウントで実際にやってみないと分からない。また、ソースレビュアとして複数人をpull requestの受信者(マージ権限者)に設定することができるかも調査不足。

 

(※2) masterブランチにマージするのか?developブランチなど別ブランチではないのか?

GitHubFlowでは、今までのGitFlowのようにいろいろなブランチを作らず、masterと作業用のブランチという2種類のみにすることで、GitFlowを簡略化する目的があるそうです。

 Gitブランチを使いこなすgit-flow/GitHub Flow入門(終):プルリクエスト/レビューを取り込んだ、よりシンプルなGitHub Flowの運用を図解する (1/2) - @IT

 

(※3)Issueの自動closeはできないのか?

調べていたら、コミットコメントでできるかもって感じでした。

できました。

但し、これもコミットに書き忘れると不要Issueが残りまくる可能性もあると思います。

【Github, Gitlab】コミットメッセージにissueクローズを書き忘れたときの対処法 - Qiita

 

(※4)マージした不要ブランチは自動で削除されないのか?

されません。が、上記12の画面(マージ完了画面)で「Delete branch」ってボタンがありました。これを押せばすぐに該当ブランチは消えます。