インターン講義5日目「ユーザインターフェース,HTML5」

インターン生は、連日の講義と課題で大変そうですが、今日も講義が続きます。

本日は、id:nanto_viによる「ユーザインターフェース,HTML5」です。仕様書を隅々まで読んだ講師によるディープな講義内容となっています。今日も2時間の長丁場ですが、頑張って着いていきましょう!

ユーザーインターフェース、HTML5

ユーザーインターフェースで大切なこと、HTML5 及び関連 API で何ができるか

自己紹介

  • nanto_vi (外山真, TOYAMA Nao)
    • ブックマークチーム アプリケーションエンジニア
      • はてなブックマーク Firefox 拡張
      • はてなツールバー for Firefox
      • はてなブックマーク Twitter 投稿機能
    • はてなサマーインターン 2008
    • なんとなく Emacs
    • 富山県南砺市とはあまり関係なし

概略

  1. UI の評価・設計・実装の概略
  2. HTML についての概略、HTML5 とは何か
  3. HTML5 及び関連 API の機能をざっと紹介
  4. 「標準」に関して
  5. 課題

ユーザーインターフェース (UI)

interface
【名】

  1. 接合部分、接触面◆異質な物の間の
  2. 接点、仲立ち、連絡(係)、橋渡し(役)◆【同】liaison
  3. 《コ》インターフェース
  4. 《物理》界面
英辞郎 on the Web:スペースアルク
  • 機械と人間が情報をやり取りする接点
  • 優れた機能であっても、人とつながらなければ意味がない

Norman のデザイン原理

可視性
状態・機能が見て取れるように
フィードバック
反応を返すことで何をしているのかわかるように
制約
制限を加えることで誤操作を防ぐ
対応付け
制御とその結果に関係性を持たせる
一貫性
同じ機能は同じ操作で
アフォーダンス
操作の手がかりを与える

Design Principles
cf. 概念モデル

UI の評価

  • ヒューリスティック評価
    • ヒューリスティック (経験則) に沿って問題を発見していく
      • ユーザーが常に状態を把握できるか?
      • ユーザーにわかりやすい言葉を使っているか?
      • etc.
  • 認知的ウォークスルー
    • シナリオに沿ってユーザーの行動をシミュレート
      • ユーザー像 (ペルソナ) とタスクを設定
      • タスク達成に必要な操作系列を準備
    • 各操作を分析
      • 次に何を達成すればいいのかをユーザーはわかるか
      • 次にどう操作すればいいのかをユーザーはわかるか
      • 正しい操作だったかどうかをユーザーはわかるか
  • ユーザーテスト

ユーザビリティの評価手法 – U-Site

例: プロフィール画像変更

  • ユーザー像: 日常的に Web を使っている学生
  • タスク: はてなのプロフィール画像を変更する
  • 操作系列
    1. ユーザー設定ページに移動
    2. プロフィール画像設定ページに移動
    3. 現在のプロフィール画像を削除
    4. 新しいプロフィール画像を設定

UI の設計

  • ユーザーを想定する
    • ≠ ユーザーの言うがままにする

もし人々に何がほしいか尋ねていたら、彼らはより速い馬がほしいと答えていただろう。

ヘンリー・フォード
  • ユーザーの行動を観察する
    • cf. 「真心の想像力」
  • 既存の UI に学ぶ
    • ユーザーエクスペリエンスガイドライン
  • 検証・評価方法はある程度確立されている

例: ブックマーク追加時のオプション

  • 対象ユーザー
    • ブックマークはするが、オプション機能を使っていないユーザー
  • ユーザーにしてもらいたいこと
    • Twitter 連携機能の存在を知り、使ってもらう
    • 非公開ブックマーク機能 (はてなブックマークプラス) の存在を知り、使ってもらう

Web での UI の実装

  • いままで
    • HTML → HTML → HTML
  • 現在 (+ JavaScript)
    • インタラクティブ性の向上
      • HTML → Ajax によるデータ読み込み
    • その場で様々な情報を取得・表示
      • 動的な検索・RSS リーダー・地図アプリケーション
      • 短時間で効率よく情報にアクセス

はてなでの UI の実装

様々な場所に JS (+ Flash) が

  • はてなブックマーク
    • その場検索
    • キーバインド
  • 日記その場編集
  • お絵かきツール
  • フォトライフアップローダ

ハイブリット (JS と Flash の合わせ技) も使われている

HTML

  • HyperText Markup Language
  • Web を支える技術のひとつ
  • 文書構造を記述
  • ごく簡単なHTMLの説明 の「簡単なHTMLの説明」までは必読

HTML5 の誕生

  • HTML 4 / XHTML 1.0
    • 国際化、アクセシビリティ、マルチメディア
  • XHTML 1.1
    • モジュール化、拡張性 (他の仕様と組み合わせられるように)
  • XHTML 2.0
    • 「文書」の表現に特化
    • 「アプリケーション」の作成は XForms、XML Events、DOM、XFrames、SMIL、SVG、MathML、RDFa といった他の仕様と組み合わせて
  • HTML5
    • 大きく作り直すのではなく、既存のものの改良で
    • アプリケーションの作成も重視
      • 旧称 Web Applications 1.0
    • 機械アクセス可能なデータの記述

HTML5 仕様の範囲

  • HTML 4
    • 要素・属性・内容モデル、意味論を定義
    • 構文は SGML を利用
  • XHTML 1.x
    • 要素・属性・内容モデルを定義
    • 意味論は HTML 4 のものを流用
    • 構文は XML を利用
  • HTML5
    • 要素・属性・内容モデル、意味論、構文、API を定義
    • 構文は XML も利用可能
    • 従来の HTML 仕様に加えて、DOM HTML、基礎的な構文の範囲もカバー
  • 広義の HTML5
    • HTML5 仕様 + Web ブラウザ用の各種 API 仕様
    • いくつかの仕様はかつて HTML5 仕様に含まれていたもの
  • バズワードとしての HTML5
    • 最近のブラウザで実現できそうなありとあらゆること
    • CSS 3、独自拡張 CSS、SVG、ECMAScript 5

HTML5 の HTML 構文

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>こんにちは、世界 - お試しサイト</title>
</head>
<body>
  <h1>こんにちは、世界</h1>
  <p lang="en">Hello, world.</p>
  <p><a href="/so?me=th&amp;in=g">何か</a>いる。</p>
</body>
</html>

おすすめは、

  • 文書型宣言から始める
  • 属性値は二重引用符で囲む
  • 要素の開始タグと終了タグは省略しない
    • どんな場合に何を省略できるのかいちいち考えるのは面倒だし、見落としがあると危険
  • <>&" はそれぞれ &lt;&gt;&amp;&quot;
<script type="text/javascript" src="/js/foo.js"></script>
<script type="text/javascript">
  if (x && y)
    call('<script type="text/javascript"><\/script>');
</script>
  • script 要素の内容には、<!--</script を直接記述しなければ何でも書ける
    • <!-- を書いたら、対応する --> を書く必要あり
    • "</" はすべて "<\/" と書くのが安全

だいたい、XSS なんてのは「何が起きても常に valid な HTML を出力する」という誇りがありさえすれば、それだけで 9割方回避できるのです。ユーザが入力した < を文字参照に変換する処理は、誇りを守るための処理であって、セキュリティを意識したものではないのです。

H18年度ウェブアプリケーション開発者向けセキュリティ実装講座 | 水無月ばけらのえび日記

セクションとアウトライン

  • 章構造の明確化
    • ISO-HTML が目指し XHTML 2.0 が成そうとしたもの
  • sectionarticlenavaside などセクションを生成する要素の導入
  • 今までどおり h1 - h6 要素を使うだけでも、それなりに適切なアウトラインが生成される

HTML5についてのおさらい - W3G Blog Studies

canvas 要素

  • スクリプトからラスタ画像を描画
  • はてなではグラフ描画などに利用
<span id="my-graph">25日: 130 km/h, 30日: 160 km/h</span>
<script>
function drawGraph() {
  var canvas = document.createElement('canvas');
  if (!canvas.getContext) return;
  canvas.setAttribute('width', '300');
  canvas.setAttribute('height', '300');
  var placeholder = document.getElementById('my-graph');
  placeholder.parentNode.replaceChild(canvas, placeholder);
  var context = canvas.getContext('2d');
  context.strokeRect(...);
  ...
}
drawGraph();
</script>

Canvas チュートリアル - HTML | MDN

videoaudio 要素

  • フォールバック内容を持てる
<video width="300" height="300" control>
  <source src="video.ogv" type="video/ogg; codecs=&quot;theora, vorbis&quot;">
  <source src="video.mp4" type="video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;">
  <object data="video.swf" type="application/x-shockwave-flash" width="300" height="300">
    <param name="movie" value="video.swf">
    かくかくしかじかなビデオがあり、……
  </object>  
</video>

Using HTML5 audio and video - HTML | MDN

フォームコントロール

  • 新たな種類のコントロール
    • 未対応のブラウザではテキストフィールド
  • 新たな属性
  • input イベント
<input type="url">
<input type="date" required>
<input type="text" placeholder="チャンネル名を入力">
  • チェックボックス、ラジオボックスにはラベルを
<label for="my-check">
  <input id="my-check" type="checkbox">
  確認する
</label>

編集 API

  • contenteditable 属性
  • element.contentEditable
    • 特定要素を編集可能に
  • document.designMode
    • 文書全体を編集可能に
  • document.execCommand()
    • 特定の編集操作を実行

Drag and Drop API

  • draggable 属性
  • ドラッグ & ドロップ時に各種イベントが発生
  • 複雑

File API

  • <input type="file"> で選択したファイルを取得
    • 内容を読み込んで XMLHttpRequest で送信など
  • ブラウザ外からドラッグ & ドロップしてきたファイルも

Using files from web applications | MDN

Microdata

  • 機械認識可能なデータの記述方法
  • DOM API も定義
  • 既存の語彙を使えば共通の意味が保証される
<p itemscope>
  <span itemprop="name">nanto_vi</span> さんの
  <a href="http://b.hatena.ne.jp/nanto_vi/" itemprop="bookmarks">ブックマーク</a>
</p>

Microdata: A Primer

機械認識可能なデータ

  • データの記述
    • Microdata
    • microformats
    • aarealink 要素の rel 属性
  • Web の利用者は人間だけではない
    • Google
    • LDRize
  • 「今、私のため」ではなく「いつか、誰かのため」

カスタムデータ属性

  • 名前が data- から始まる属性
  • サイトにとって私的なデータ
  • 第三者が何らかの意味に解釈することはない
<ul data-eid="42">
  <li data-user="nanto_vi">nanto_vi said yes.</li>
  <li data-user="r_kurain">r_kurain said no.</li>
</ul>

URL と生成元

  • URL
    • URL ⊂ URI (RFC 3986)
      • ここでの URL は Uniform Resource Locator の略
    • URL ⊃ URI (HTML5)
  • 生成元 (origin)
    • スキーム、ホスト、ポートの組
    • http URL においてはパスより前の部分で表される
      • http://example.org/foo/bar の生成元は http://example.org
    • スクリプトからは異なる生成元の文書にアクセスできない

Web Storage

  • クライアント側でのデータ保存
  • キーと値のペア
  • 生成元ごとに独立
  • sessionStorage
    • ブラウザを終了するまで
    • ブラウザのタブ単位で独立
  • localStorage
    • ブラウザの終了後も保存される
if (window.localStorage) {
  localStorage.foo = 'bar';
  doSomething(localStorage.foo);
}

オフライン機能

  • アプリケーションキャッシュ
    • マニフェストに記載されたりソースをローカルにキャッシュ
  • onlineoffline イベント
window.addEventListener('offline', function (event) {
  alert('オフライン状態になりました');
}, false);

履歴管理

  • history.pushState()
    • ブラウザの戻る / 進む履歴に項目を追加
  • history.replaceState()
    • ブラウザの戻る / 進む履歴の項目を置換
  • hashchange イベント
    • URL のフラグメント部分 (# 以下) の変更時に発生

文書間メッセージング

  • 異なる文書 (の window) にメッセージを送信
  • 異なる生成元の文書間でも通信可能
<!-- http://example.org/foo -->
<iframe id="my-frame" src="http://example.com/bar"></iframe>
<script>
var frame = document.getElementById('my-frame');
// 生成元が http://example.com である
// 文書にメッセージ "hello" を送信
frame.contentWindow.postMessage('hello', 'http://example.com')
</script>
<!-- http://example.com/bar -->
<script>
window.addEventListener('message', function (event) {
  // http://example.org からのメッセージのみ処理
  if (event.origin !== 'http://example.org') return;
  alert(event.data); // "Hello"
  // メッセージを送り返す
  event.source.postMessage('world', event.origin);
}, false);
</script>

Cross-Origin XMLHttpRequest

  • XMLHttpRequest Level 2
    • 生成元が異なるリソースの取得
    • progress イベント
  • Cross-Origin Resource Sharing
    • HTTP ヘッダを基に異なる生成元からの要求を許可

WebSocket

  • 全二重双方向通信
  • WebSocket API
    • プログラミング言語から通信を扱う API
  • WebSocket Protocol
    • 実際の通信方式を定めたプロトコル

Server-Sent Events

  • サーバーからのプッシュ通信でイベント発生
var source = new EventSource('/event/source');
source.onmessage = function (event) {
  alert(event.data);
};

Web Workers

  • JavaScript を別スレッドで実行
  • 主文書とはメッセージ通信
  • ワーカー内では DOM に触れない
var worker = new Worker("fibonacci.js");
worker.onmessage = function (event) {
  document.getElementById("result").textContent = event.data;
};

Using web workers - Document Object Model (DOM) | MDN

Selectors API

  • スクリプトから CSS セレクタで要素を選択
  • node.querySelector('p')
    • 単一の要素
    • セレクタが複数要素にマッチする場合は文書順で最初の要素
    • マッチする要素がなければ null
  • node.querySelectorAll('#foo .bar')
    • ノードリスト (配列のようなオブジェクト)
    • マッチする要素がなければ空のノードリスト
  • DocumentFragment に対しても利用可能

WCAG 2.0

  • Web Content Accessibility Guideline 2.0
  • 誰でも情報にアクセスできるように
  • 4 原則
    • 知覚可能
    • 操作可能
    • 理解可能
    • 堅牢性

WAI-ARIA

  • Accessible Rich Internet Applications
  • 機械認識可能な UI 部品 (コントロール) の作成
<dl role="tablist">
  <dt id="a" role="tab" aria-selected="true" tabindex="0">A</dt>
  <dd role="tabpanel" aria-labelledby="a">...</dd>

  <dt id="b" role="tab" tabindex="0">B</dt>
  <dd role="tabpanel" aria-labelledby="b" aria-hidden="true">...</dd>
</dl>

Web IDL

  • 言語中立なインターフェースの記述
    • 各種 API 仕様を読むのに必須
  • JavaScript では attribute がプロパティに対応
  • 拡張属性 [...] で付加情報を記述
interface HTMLElement : Element {
  // DOM tree accessors
  NodeList getElementsByClassName(in DOMString classNames);

  // metadata attributes
           attribute DOMString id;
           attribute DOMString title;
           attribute DOMString className;
  readonly attribute DOMTokenList classList;
  readonly attribute DOMStringMap dataset;

  // microdata 
           attribute boolean itemScope;
           attribute DOMString itemType;
           attribute DOMString itemId;
  [PutForwards=value] readonly attribute DOMSettableTokenList itemRef;
  [PutForwards=value] readonly attribute DOMSettableTokenList itemProp;
  readonly attribute HTMLPropertiesCollection properties;
           attribute any itemValue;

  // user interaction
  void focus();
  void blur();
};

CSS

  • グラフィカルな UI の実現に必須
  • 現行仕様は CSS 2.1
  • 包含ブロック (containing block)
    • 多くの場合親要素の内容辺
    • 仕様を読む上で重要
<style>
.foo {
  background: #ffaa66 url("/images/bg.png");
  color: #ffffff;
}
#x li {
  border: 2px solid #f0e01f;
}
</style>
...
<div id="x">
  <ul class="foo bar">
    <li>...</li>
    <li>...</li>
  </ul>
</div>

以下の図は cho45 作






標準技術

  • 自分だけが使うなら標準化の必要はない
  • 相互運用性
  • アクセシビリティ

標準化団体

  • IETF
    • URI
    • HTTP
  • W3C
    • HTML
  • ISO
  • Ecma International
    • ECMAScript (JavaScript)

標準化への参加

  • メーリングリスト
  • IRC
  • バグ追跡ツール

まとめ

  • 標準技術重要
    • 誰もが情報にアクセスでき、操作できるようにするため
  • インターフェース重要
    • 誰が使うのかをよく考えて

課題 1

課題 2

  • ToDo 管理ツールで ToDo の追加・編集を画面遷移なしで行えるようにせよ
    • どんなユーザーが使用するのかを想定すること
  • 採点基準 (4 点)
    • 動作するか (1.5)
    • 想定ユーザーにとって適切な UI か (1.5)
    • プログラムの設計 (1.0)

課題 3

  • HTML5 及び関連 API を用いて ToDo 管理ツールを拡張せよ
    • 例: オフラインでも利用可能にする (Web Storage、オフラインイベント)
    • 例: 期限を基に ToDo を図示する (canvas 要素)
  • 採点基準 (3 点)
    • 動作するか (1.0)
    • プログラムの設計 (1.0)
    • その他感ずるところ (1.0)

ヒント: イベント、ちょっと詳しく

  • イベントバブリング
    • イベントは実際に発生したノードから親に向かって浮上 (バブル) していく
    • バブルしないイベントもある (submitfocusload、etc.)
    • event.stopPropagation() で浮上を停止

http://www.w3.org/TR/2009/WD-DOM-Level-3-Events-20090908/images/eventflow.png

Document Object Model (DOM) Level 3 Events Specification
<ol id="list">
  <li>最初の項目</li>
  <li>第二の項目</li>
</ol>
<script>
var list = document.getElementById('list');
list.addEventListener('click', function (event) {
  if (event.target.nodeName.toLowerCase() !== 'li') return;
  event.target.textContent += ' [checked]';
}, false);
</script>
  • デフォルトアクション
    • イベントに関連づいた挙動
      • リンクの click イベントならリンク先への移動
    • event.preventDefault() でデフォルトアクションを中止
      • 中止できないイベントもある (focusload、etc.)
<a href="...">def...</a>
<script>
a.addEventListener('click', function (event) {
  ...
  event.preventDefault();
  event.stopPropagation();
}, false);
</script>

おまけ: Firebug でのデバッグ

  • スクリプトパネルからブレークポイントを設定
  • ステップイン
    • 1 行実行
    • 関数呼び出し時は呼び出された関数の最初の行に移動
  • ステップオーバー
    • 1 行実行
    • 関数呼び出し時も現在の関数の次の行へ移動
  • ステップアウト
    • 現在の関数の最後まで実行

参考文献

  • 講義「ヒューマンインタフェース」石田亨
  • 『Webを支える技術 -HTTP、URI、HTML、そしてREST』山本陽平 (技術評論社)