HTMLからの脱却
sample03ではコンテンツとなるHTMLを外部に分離し、sample04ではサイトの構造を表す設定を外部に分離しました。こうした作業は、プレゼンテーション技術としてのHTMLと、本質的なデータ部分を切り離そうという方向にあります。
しかし、最も重要なデータ元である記事の本文がHTMLで書かれていることは、やはり柔軟性において問題を残します。例えば、記事を挿入する雛型のHTML文書の構造と、記事のHTMLの相性が合わないということがあります。とにかく表示できればそれでいいというサイトならば問題はないかもしれませんが、XHTML 1.0 Strictに準拠することが要求される場合、使えない要素や使ってほしくない非推奨の要素などが発生する可能性があります。
こうした問題を踏まえ、XHTMLバージョンの変更やサイトのレイアウト、方針の変更に依存しないようにサイトを構築するには、記事をHTMLではなく、設定ファイルと同様にXMLで記述します。XMLで記述された記事をJavaScript+DOMでHTMLに変換して表示するという方法です。この方法であれば、プレゼンテーション(表示)とデータモデルを完全に分離することができ、高い柔軟性を確保することができます。
<?xml version=1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="jp"> <head> <title>test</title> <script type="text/javascript"> function createRequest() { var req = null; if ("XMLHttpRequest" in window) { req = new XMLHttpRequest(); } else if ("ActiveXObject" in window) { try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } return req; } var req; function requestArticle(url) { req = createRequest(); req.open("GET", url, true); req.onreadystatechange = req_readystatechange; req.send(null); } function req_readystatechange() { var divRightPanel = document.getElementById("rightPanel"); if (req.readyState == 4) { if (req.status == 200) { setArticle(req.responseXML); } else { divRightPanel.innerHTML = "システムエラー:読み込めませんでした"; } } } //要素内のテキストを抽出する function getElementText(element) { var nodes = element.childNodes; var result = ""; for(var i = 0 ; i < nodes.length ; i++) { var item = nodes.item(i); if (item.nodeType == 3) { result += item.nodeValue; } } return result; } //記事をrightPaneに出力する function setArticle(articleDoc) { var divRightPanel = document.getElementById("rightPanel"); var title; //タイトル(見出し) var author; //著者 var copyright; //著作権 //article要素の子要素を検出する var article = articleDoc.getElementsByTagName("article")[0]; for(var i = 0 ; i < article.childNodes.length ; i++) { var item = article.childNodes.item(i); if (item.nodeType == 1) { if (item.nodeName == "title") title = getElementText(item); else if (item.nodeName == "author") author = getElementText(item); else if (copyright == "copyright") copyright = getElementText(item); } } divRightPanel.innerHTML = "<h1>" + title + "</h1>"; //記事の本文を表すbody要素をHTMLに変換して出力 var body = article.getElementsByTagName("body")[0]; for(var i = 0 ; i < body.childNodes.length ; i++) { var item = body.childNodes.item(i); if (item.nodeType == 1) { if (item.nodeName == "p") { divRightPanel.innerHTML += "<p>" + getElementText(item) + "</p>"; } } } //著者、著作権者情報を出力 divRightPanel.innerHTML += "<p style=\"font-style:italic\">著者:" + author + "</p>"; divRightPanel.innerHTML += "<p style=\"font-style:bold\">Copyright (c) " + author + "</p>"; } </script> </head> <body> <table border="0"> <tr><td style="width:20%" valign="top"> <p><a href="javascript:requestText('ajax0.xml')">はじめに</a></p> </td> <td style="width:80%" valign="top"> <div id="rightPanel"></div> </td></tr> </table> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <article> <title>はじめに</title> <author>赤坂玲音</author> <copyright>赤坂玲音</copyright> <body> <p> ここ最近、Web 2.0という言葉と共に(略) </p> <p> では、Ajaxはそれほど敷居の高いものなのでしょうか。 質の高い開発集団や、高額な開発環境、またはサーバーなどの(略) </p> </body> </article>
sample05は、「ajax0.xml」をスクリプトで読み取り、XML文書を解析してHTMLに変換するというプログラムです。「test.html」を表示すると「はじめに」へのリンクが張られていますが、このリンクボタンを押すとrequestArticle()
関数を呼び出して「ajax0.xml」をダウンロードする仕組みになっています。基本的な処理はsample03と同じですが、取得するデータがHTMLが書かれたテキストファイルではなく、純粋なXMLファイルである点が異なります。
スクリプトからXMLHttpRequest
オブジェクトを通じてサーバーに要求を行い、結果をreq_readystatechange()
関数で受け取るとsetArticle()
関数を呼び出して取得した記事を出力します。記事はHTML形式ではなく、独自に定めたXML形式で表されています。そのため、setArticle()
関数の引数にはresponseXML
から取得したDocument
オブジェクトを渡しています。
setArticle()
関数はXMLの各要素を解析し、必要な値を受け取ってからHTMLとしてrightPanelに出力します。利用者にとっては、内部のデータ形式を意識する必要はなく、リンクを押したらコンテンツが表示されたように振る舞うことができます。
記事のデータは「ajax0.xml」にXML形式で格納しています。このXML形式は、このサンプルのために即席で用意したものです。article
要素をルート要素とし、article
要素の子要素には、主題を表すtitle
要素、著者を表すauthor
要素、著作権者を表すcopyright
要素、そして記事本文を表すbody
要素を指定することができます。
この方法であれば、コンテンツ本体だけではなく、コンテンツのメタデータなども柔軟に表現することができるようになります。記事には、短い文章で記事の要約を表すsummary
要素を加えても良いでしょうし、記事のキーワードを表すtag
要素などを加えても良いでしょう。それをどのように利用するかは、スクリプト側に委ねることができます。
重要なのは、こうした記事の論理的な構造(データ)と、この情報を画面に表示する方法(プレゼンテーション)が分離されていることです。このサンプルでは「test.html」のスクリプトがHTMLに変換して表示していますが、これとは別のスクリプトから「ajax0.xml」を参照して2次元ベクタグラフィックス情報を表すSVG形式に変換するなど、異なる媒体に変換することも可能です。
sample05のような規模になってくるとスクリプトでの処理が複雑になってきますが、XMLを別のデータに変換するXSLTなどの標準化された技術も存在しています。データの表現にXMLを用いることで、他の文書への変換や埋め込みが容易になり、または他のWebサイトとの相互運用も視野に入れることができるようになります。
最後に
Webサイト全体の設計をデータモデル、ビジネスロジック、プレゼンテーションに分離して…という話になってくると趣味で開発する規模を超えてしまいますが、sample05を見ると、XMLがデータ、JavaScriptによる変換処理がビジネスロジック、そしてHTMLがプレゼンテーションを担当していると考えることができます。
小規模な組織のWebサイトは、今も制限の強い共有レンタルサーバーを使っていることが多いと思います。データベースやサーバー側スクリプトを自由に使えない環境下で、データを抽象化し、ある程度の柔軟性や相互運用性を確保する手段として、前述したようなAjaxの応用があるのではないでしょうか。
また、Ajaxは背景に膨大な量のデータを必要とするメディアをWebで実現する方法としても有効です。必要なときに、必要な部分だけをダウンロードして表示できます。例えば、小説サイトやノベル形式のゲームなどで、ページ移動を行わずに次のページを表示するリッチな演出が可能となります。
Ajaxには複雑な一面もありますが、プロ集団でなければ作れないというものでもありません。本稿を通じて、学生の方や趣味で開発やWebサイト作りを楽しんでいる方に、Ajaxの実用について興味を持っていただければ幸いです。