2011年8月21日(日)に開催されたChrome+HTML5 Conferenceにて、id:nagayamaとid:nanto_viが講演を行ったので、その資料を公開します。「Webアプリの道も一歩から 〜はてなブックマークの場合〜」と題し、公式Chromeウェブアプリ はてなブックマークの開発フローや利用技術について解説しました。発表は2部構成で、ディレクターのid:nagayamaがはてなでのChromeウェブアプリの開発フローに関して、エンジニアのid:nanto_viがウェブアプリで活用しているHTML5関連技術に関して述べています。
Webアプリの道も一歩から 〜はてなブックマークの場合〜
View more presentations from nagayama
Web アプリの道も一歩から
- 実装について
- by nanto_vi
- スクリプトの設計
- 表示内容と URL の切り替え
- Flexbox レイアウト
- 新着エントリーの通知
- プレビュー
- タグ自動補完
- キーボードアクセス
- フォーカス管理
- 設定の記憶
- アプリケーションキャッシュ
- CSS3 による装飾
- CSS Transitions
- スクロールバー
スクリプトの設計
- MVC アーキテクチャを意識
- Model: サーバー側 API、データの取得・保存
- View: ユーザーへの表示、HTML の編集
- Controller (
Browsing
): ユーザーアクションに基づく内容の切り替え
- jQuery を採用
Events
: Observer パターンの実装、独自イベントDeferred
: リソースの非同期読み込み
// Model $([Model.Entry]).trigger('change'); $(this).trigger('load'); // View $([Model.Entry]).bind('change', onChange); $(model).bind('load', onLoad);
表示内容と URL の切り替え
- URL から各表示領域の内容を再現できるように
/viewer
/viewer/hot/social
- 「社会」カテゴリのエントリー一覧
/viewer?entry=http://example.org/
- エントリーのブックマーク一覧
- URL の切り替えは History API で
- 「戻る」「進む」にも対応
pushState()
、replaceState()
、onpopstate
- HTML5 で定義。WebKit、Mozilla、Opera が対応
<a href="/viewer/hot/social" data-link-target="viewer">社会</a>
$(document).delegate('a', 'click', function (e) { e.preventDefault(); browse(e.currentTarget.href); }); $(window).bind('popstate', function () { setup(document.URL); }); function browse(url) { history.pushState({}, document.title, url); setup(url) } function setup(url) { ... }
Flexbox レイアウト
- Mozilla の XUL レイアウト由来
- ボックスを縦または横に並べていく
- Flexbox: コンテナ
- Flexbox items: Flexbox の子要素。縦一列または横一列になる
- 固定長と可変長の組み合わせ
box-flex
に正整数を指定した flexbox item は可変長になる
CSS3 Flexible Box Layout Module
- Flexbox の標準化
display: flexbox
flex-flow
,flex-align
,flex-pack
...
新着エントリーの通知
- Notifications API
- 通知は即表示されるとは限らない
- 通知の消去も自分で制御
ondisplay
から 10 秒後にcancel()
var n = webkitNotifications.createHTMLNotification(url);
n.ondisplay = ...;
n.onclick = ...;
n.show();
プレビュー
iframe
要素で埋め込みsandbox
属性でフォーム送信、スクリプト実行等を禁止sandbox="allow-forms allow-scripts"
で個別許可も可能- HTML5 で定義。WebKit、IE 10 PP が対応
<iframe sandbox></iframe>
タグ自動補完
- ユーザーが入力するたびにタグ候補を表示
- ユーザーの入力は
input
イベントで監視 - HTML5 で定義。Mozilla、WebKit、Opera が対応
- DOM3 Events では
textinput
イベントが定義される
- ユーザーの入力は
キーボードアクセス
tabindex
属性でキーボードアクセス可能に- 「Enter で実行」は自前で実装
- IE 由来。HTML5 で定義。各ブラウザが対応
<span class="trigger" tabindex="0">実行</span>
.trigger { cursor: pointer; }
$(document).delegate('.trigger', { keypress: function (event) { if (event.which !== 13) return; $(event.currentTarget).click(); event.preventDefault(); event.stopPropagation(); }, mouseup: function (event) { event.currentTarget.blur(); }, });
フォーカス管理
- モーダルダイアログ表示は、モーダルダイアログのみにフォーカス
focusin
,focusout
イベントfocus
,blur
イベントと同じだが、バブルする- IE 由来。DOM3 Eventsで定義。
- jQuery は独自に模倣
設定の記憶
- 設定読み書き用オブジェクトを作成
- バックエンドに Web Storage を使用
- JSON にシリアライズして保存
- 名前空間を指定してキー名の競合を防ぐ
- Mozilla の preferences より
var storage = new Storage('my.namespace'); storage.set('foo', { bar: 42 }); // 実際の localStorage には、キー 'my.namespace.foo' に // 文字列値 '{"foo":42}' が保存される
アプリケーションキャッシュ
- HTML、CSS、JS、画像などをキャッシュ、オフラインで利用可能に
- HTML5で定義。Mozilla、WebKit、Opera が対応
- 今回は単に読み込み高速化のためだけに使用
- エントリー一覧、ブックマーク一覧をオンラインで取得するため
- サーバー側での表示出し分けはできなくなる
- ユーザー名表示などもクライアント側で生成
<html manifest="/viewer.appcache">
CACHE MANIFEST # <commit hash> CACHE: base.css viewer.js # マニフェストに記載のないリソースをオンラインで取得 NETWORK: *
CSS Transitions
- ツールチップを浮かび上がるように表示
- スクリプトで
class
名を切り替え visibility
も変化させないと、フォーカス移動の対象になったりしてしまう
- スクリプトで
.tooltip { visibility: hidden; opacity: 0; -webkit-transition: 0.2s ease-out; -webkit-transition-property: visibility, opacity; } .tooltip.shown { visibility: visible; opacity: 1; }