Smart Communication Design Company
ホーム > ナレッジ > Blog > Web標準Blog > 2009年2月 > Graceful DegradationとProgressive Enhancementの実践

Graceful DegradationとProgressive Enhancementの実践

2009年2月20日
フロントエンド・エンジニア 矢倉

Chris Heilmanによる“Graceful degradation versus progressive enhancement”という記事について、前回は概要とその意義について紹介しました。今回は後半にあるの例をもとに、どのように実践していくのかを考えてみたいと思います。

「印刷する」というリンク

オンラインショッピングの決済画面には、印刷して手元に保管したいというニーズがあるからか「印刷する」といったリンクやボタンが設けられています。クリックしたときに印刷用ページが現れるものもありますが、記事では印刷ダイアログが現れる簡単なものを取り上げています。

このようなリンクは、JavaScriptにより実現されています。

<p id="printthis">
  <a href="javascript:windowprint()">Print this page</a>
</p>

しかしながら、JavaScriptが無効な環境では、リンクが機能せず全く意味がなくなってしまいます。というわけで、noscript要素を利用して、利用できない環境に向けたメッセージを記述することにしましょう。

ただ、「JavaScriptが有効になっていません」といったものはあまり意味がありません。「その機能が何で実装されているか」という情報を、ユーザーが直接求めているわけではないからです。なので、ここではブラウザーの印刷機能について書くことにしましょう。

<p id="printthis">
  <a href="javascript:windowprint()">Print this page</a>
</p>
<noscript>
  <p class="scriptwarning">
    Print a copy of your confirmation.
    Select the "Print" icon in your browser,
    or select "Print" from the "File" menu.
  </p>
</noscript>

「『印刷』アイコンまたは『ファイル』メニューより『印刷』を選択することで、印刷することができます。」といった文を書くことで、代替手段を直接提供はしないものの、ユーザーにその存在を伝えることができます。

起こってしまった問題への「対処」という側面が強いので、これはGraceful Degradation的なアプローチといえるでしょう。では、Progressive Enhancementでは、どのようなアプローチになるでしょうか。

Progressive Enhancementな印刷リンク

Progressive Enhancementは、最低限提供したい機能や目的を「ベースライン」として設定します。印刷リンクは「ページを印刷したいというユーザーのニーズに答える」ことが目的ですから、まず「ページの印刷について言及する」ことをベースラインとしましょう。

<p id="printthis">Thank you for your order.
 Please print this page for your records.</p>

まず「印刷して保管できます」ということを伝える文を書きます。もちろん、先ほどのように、ブラウザーの印刷手法について言及するのも悪くないでしょう。

さて、印刷リンクはどのように実装すればよいでしょうか。ここで登場するのが、「Unobtrusive JavaScript」という考え方です。「おせっかいではないJavaScript」という意味のこのキーワードですが、簡単に説明すると、不必要にUAやHTMLに干渉したり依存したりすることのないようにJavaScriptを書くことです。

「おせっかいなJavaScript」の例としては、リンク先を新規ウインドウやポップアップで開く、次のようなコードが該当します。

<a href="#" onclick="window.open('popup.html','_blank')">ポップアップ</a>

JavaScriptが無効な環境では、通常のページ遷移すら行われないため、情報にアクセスすることができなくなってしまいます。このようなおせっかいをせずに、印刷リンクを追加するコードを書くわけです。

記事の中で、Unobtrusive JavaScriptな印刷ボタンを追加するコードは、次のように実装されています(この例ではリンクではなく、ボタンになっています)。

(function(){
  if(document.getElementById){
    var pt = document.getElementById('printthis');
    if(pt && typeof window.print === 'function'){
      var but = document.createElement('input');
      but.setAttribute('type','button');
      but.setAttribute('value','Print this now');
      but.onclick = function(){
        window.print();
      };
      pt.appendChild(but);
    }
  }
})();

getElementByIdの存在や、window.print()が機能するかを確かめた上で、ボタンをDOMにより生成し、先ほどの段落に追加しています。

最終的なコードは、次のようになります。

<p id="printthis">Thank you for your order.
 Please print this page for your records.</p>
<script type="text/javascript">
(function(){
  if(document.getElementById){
    var pt = document.getElementById('printthis');
    if(pt && typeof window.print === 'function'){
      var but = document.createElement('input');
      but.setAttribute('type','button');
      but.setAttribute('value','Print this now');
      but.onclick = function(){
        window.print();
      };
      pt.appendChild(but);
    }
  }
})();
</script>

ブラウザーがJavaScriptコード中で必要な機能を満たすときのみ、印刷ボタンが現れます。

このやり方は、印刷リンク(ボタン)だけではなく、文字の拡大縮小インターフェースなどにも利用することができるでしょう。まずブラウザーの文字サイズ変更機能について言及し、インターフェースをあとからJavaScriptで組みこむのです。

今回の印刷ボタンは、window.print()というブラウザーのAPIにどうしても依存してしまうものなので、「実現したいもの」と「最低限必要なもの」の差が大きく開いている例です。次回は、漸進的なEnhancementの例をお見せしたいと思います。

コメント

前回の記事へのリンク先がこの記事になっているようです。
正しくは http://standards.mitsue.co.jp/archives/001387.html でしょうか。

Posted by: leva : 2009年2月21日 15:44

levaさま、ご指摘ありがとうございます。
リンクを修正し、エントリを更新しました。

Posted by: ミツエーリンクス : 2009年2月23日 08:49