JavaScript

ガイド:高橋 登史朗

Ajaxなど、何かと最近騒がれているJavaScriptの最新情報とその活用方法を解説します。

掲示板 取材依頼 問合せ

掲載日: 2006年 01月 28日

XMLHttpRequest風IFRAMEによるデータ通信1


XMLHttpRequest風IFAMEによるデータ通信1


XMLHttpRequestとの機能比較


今回作ったjsgt_JSONIframeReqestの機能は、ソースをみればわかりますが、一応、XMLHttpRequestとの簡単な比較をしてみました。 jsgt_JSONIframeReqestでは、HTTPクライアントの機能はブラウザまかせですので、 setRequestHeader()など、HTTPクライアント関連のメソッドやプロパティは存在しません。

その代わり、jsgt_JSONIframeReqestは、動作ブラウザが多く、XMLHttpRequestのようなブラウザ毎の動作の違いはありません。 さらに、レスポンスデータをオブジェクトで自由なタイミングで渡せるメリットがあります。

XMLHttpRequestjsgt_JSONIframeReqest
動作ブラウザ
win
n7m1e6o8
mac
n7m1e5o8s1.2s2
×
Linux
n7m1o8k3
win
n7m1e6o8
mac
n7m1e5o8s1.2s2
Linux
n7m1o8k3
インスタンス生成 new XMLHttpRequest()
new new ActiveXObject("Msxml2.XMLHTTP")
new ActiveXObject("Microsoft.XMLHTTP")
(* IE以外はnew XMLHttpRequest())
new jsgt_JSONIframeReqest()
(*対応ブラウザすべてで共通に使えます)
レスポンスデータ responseXML
responseText
(*文字列として渡します)
responseJson
(*オブジェクトとして渡します)
readyState(0,1,2,3,4) readyState
(*IEでは「3」で途中データを受け取れません)
readyState
(*対応ブラウザすべてで「3」で途中データを順次受け取れます。)
open open(method,url[,async[,user[,password]]]) open(object)
(*Objectリテラルで渡します。現在渡せるのはURLと強制ロード(sload)。object ={url:URL[,sload:true|false]})
send send(postData) send()
(*POSTは現在使えません。送信はGETでURLに付加してください。)
onload onload
(*IEではonloadを使えません)
onload
(*対応ブラウザすべてで共通に使えます)
onreadystatechange onreadystatechange
(*Opera8.0でイベントが2重発生)
onreadystatechange
(*対応ブラウザすべてで共通に使えます)
setRequestHeader() setRequestHeader() なし
getRequestHeader() getRequestHeader() なし
status status なし
statusText statusText なし
n=Netscape/m=Mozilla(Firefox)/e=IE/o=Opera/s=Safari/k=Konqueror


データフォーマット

iframe要素には、onloadとonreadystatechangeのイベントがありますが、すべてのブラウザに実装されているわけではありません。 そこで、今回は、データ側にコールバックの呼び出しを仕込むことで、すべてのブラウザで共通に動作するonloadとonreadystatechange を用意しました。

そのため、このjsgt_JSONIframeReqestを使うには、データ側の書き方を統一する必要があります。

今回は、データを乗せるコンテナとして HTMLファイルを利用し、その中のスクリプト要素内へJSON形式のデータを書いておく方法を採りました (注意:データ形式は、JavaScriptで渡せるなら何でも良いのですが、一応多少のフォーマット指針があった方があとで利用しやすいという理由で選びました)。

そして、iframeでそのHTMLファイルを呼び出すと、その中のJSONがJavaScriptのオブジェクトとして渡されるという仕組みになっています。

今回のサンプルで使ったデータは、たとえば、次のようになっています。

今回のサンプルでは、テーブルのヘッダ行とデータ行を「head」と「data」という二つのプロパティに分けて用意しました。この構造自体はXMLを書く場合と同様に 自由に使いやすい構造を決めて使えばよいと思います。

【eiggo.htm】
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" charset="utf-8"><!-- ///// // jsgt_JSONIframeReqestデータフォーマット // @syntax parent.jsgt_data.response({JSON...}); // @see http://jsgt.org/lib/jsoniframerequest/readme.htm // // responseする毎に、jsgt_JSONIframeReqestのonreadystatechangeイベントが // 発生しoj.responsJsonでJSONデータを渡します。データはpush追記されます。 // また、ページロード完了後にoj.onloadイベントが発生します。 // // Start data (OK chage here)/////////////////////////////////////////
parent.jsgt_JSONIframeReqest.response({url:location}, { "head" : [[ "名前" , "英語" ]], "data" : [ [ "田中" , "24" ] , [ "中山" , "68" ] , [ "山本" , "55" ] , [ "本井" , "18" ] , [ "井上" , "99" ] , [ "上山" , "26" ] ] });
// End data //////////////////////////////////////////////////////// //--></script> <!-- Start footer (Don't change)///////////////////////////////////--> <body onload=" parent.jsgt_JSONIframeReqest.onfileloaded({url:location}); "> <!-- End footer ///////////////////////////////////////////////////--> </body></html>


どうですか?出力されたテーブルと同じ構造のデータですから、わかりやすいでしょう?

このデータページがiframeへ読み込まれるたびに、データページ内の「...response(...)」が実行されます。

ページを読み終わったタイミングでbody要素のonloadに書いた 「...onfileloaded({url:location});」 が実行されて、jsgt_JSONIframeReqest側のoj.onloadイベントが発生します。この時、oj.readyState値は「4」に代わり、データが oj.responseJsonに渡ります。

JavaScriptでデータを取り出すときは、このサンプルなら、たとえば、oj.responseJson.head[0][1]で「英語」という文字列が取り出せます。 oj.responseJson.data[0][0]なら「田中」、oj.responseJson.data[0][1]なら「24」、 oj.responseJson.data[2][0]なら「山本」という具合です。

もし、データページ内のresponse()が複数あって、受信途中でデータを取り出したい場合は、oj.onreadystatechange毎に、oj.responseJson.part[0]、oj.responseJson.part[1]、oj.responseJson.part[2]、、、という具合に、各レスポンスがpart[oj.index]の下にコピーされていきます。

oj.indexは最初は0で、受信したデータ数だけカウントアップされます。

そして、ページを読み終わると、この最後のデータpart[oj.index]はoj.responseJson直下へコピーされます。

このようにして、oj.responseJson以下は受信した順番に、次のような構造を作っていきます。 この結果、「onreadystatechange==3」の時点での着信データによる、極め細かな制御なども可能になると思います。

oj.responseJson
  ├.part[0]
  │ └{ data1-1:...,data1-2:... } //最初の着信 
  ├.part[1]
  │ └{ data2-1:...,data2-2:... } //1番目の着信
  ├.part[3] 
  │ └{ data3-1:...,data3-2:... } //2番目の着信
  ├.part[4] 
  │ └{ data4-1:...,data4-2:... } //4番目の着信
  ├.part[5]
  │ └{ data5-1:...,data5-2:... } //最後の着信
  │
  │//以下最後の着信(.part[5])のコピー ( oj.onloadで取得 )
  ├.data5-1
  ├.data5-2
  ├.data5-3
  ├. :
  └.data5-n

ちなみに、第一引数の「url:location」は、リクエストとレスポンスを一意に結びつけるおまじないですので省略できません。
ガイドメールマガジン
携帯電話のメールアドレスでは登録できません

掲載の記事・写真・イラストなど、すべてのコンテンツの無断複写・転載・公衆送信等を禁じます。