Hatena::ブログ(Diary)

放浪するエンジニアの覚え書き このページをアンテナに追加 RSSフィード

2008-12-05

DataTable Control: JSON Data Over XHR

| 18:14 |  DataTable Control: JSON Data Over XHR - 放浪するエンジニアの覚え書き のブックマークコメント

このExampleでは、DataSourceとして「サーバーにあるPHPプログラムを指定」して、JSONデータの取得を行い、テーブルを作成している。

この部分は

        // Connection Managerに任せるRequestは待ち行列に入れる。
        myDataSource.connXhrMode = "queueRequests";
        myDataSource.responseSchema = {
	// Jsonデータとして使うルート(要素)を指定
          resultsList: "ResultSet.Result",
	// AverageRatingは、Rating下なので、Rating.AverageRating。
            fields: ["Title","Phone","City","Rating.AverageRating","ClickUrl"]
        };
 
	// 初期リクエストを発行して、テーブルデータを作成する。
        var myDataTable = new YAHOO.widget.DataTable("json", myColumnDefs,
                myDataSource, {initialRequest:"query=pizza&zip=96815-3289&results=10&output=json"});

というコードとなっていて、Connection Managerを経由してデータを取得するRequestの出し方、結果の取得方法をDataSourceに設定し、DataTableのインスタンスを生成する際の初期データとして、initialRequestを発行してデータを取得している。initialRequest属性に指定しているのは、phpプログラムへ渡す引数である(初期データ取得時には、「Loading...」という文言が表示される。)。

PHPプログラム側では、YAHOO! Local SearchのWeb Service APIをつかって、データをJSON形式で取得している(PHPプログラムがProxyとして機能するようになっている)。

サンプルでは、このPHPプログラムへ計3回のリクエストを発行し、コールバックのハンドラによって、DataTableに戻り値を追加する。

以下は、このようにして作成されたテーブルである。

f:id:tetsuya_odaka:20081201205759p:image

以下に、Javascriptを含むHTMLの全文と、PHPプログラムを示す。

YUIのサンプルではSunnydaleのzip(郵便番号)が指定されていたが、遊びでHawaii WaikikiのHyatt Regencyのzipを指定してみた(Hyatt Regency Waikiki Beach Resort and SpaのHPへのリンク)。

また、YAHOO Local SerachはV2が用いられていたが、これがdeprecatedになっている(2009/1にサービス停止)ので、V3に変更した。PHPCurlを用いないようにしている。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
<title>JSON Data Over XHR</title> 
 
<style type="text/css"> 
/*margin and padding on body element
  can introduce errors in determining
  element position and are not recommended;
  we turn them off as a foundation for YUI
  CSS treatments. */
body {
	margin:0;
	padding:0;
}
</style> 
 
<link rel="stylesheet" type="text/css" href="scripts/yui/fonts/fonts-min.css" /> 
<link rel="stylesheet" type="text/css" href="scripts/yui/datatable/assets/skins/sam/datatable.css" /> 
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript" src="scripts/yui/connection/connection-min.js"></script> 
<script type="text/javascript" src="scripts/yui/build/json/json-min.js"></script> 
<script type="text/javascript" src="scripts/yui/element/element-beta-min.js"></script> 
<script type="text/javascript" src="scripts/yui/datasource/datasource-min.js"></script> 
<script type="text/javascript" src="scripts/yui/datatable/datatable-min.js"></script> 

<style type="text/css" id="defaultstyle">
#main {
	margin: 2px;
	padding: 3px;
}
  
</style>

<script type="text/javascript"> 
YAHOO.util.Event.addListener(window, "load", function() {
    YAHOO.example.XHR_JSON = function() {

    	// カスタムフォーマッターの定義
    	// elCell; td、oRecord; レコードオブジェクト、sData: ※1でkey定義した変数値
        var formatUrl = function(elCell, oRecord, oColumn, sData) {
            elCell.innerHTML = "<a href='" + oRecord.getData("ClickUrl") + "' target='_blank'>" + sData + "</a>";
        };
 
    	// 列の定義
        var myColumnDefs = [
            // ※1
            {key:"Title", label:"Name", sortable:true, formatter:formatUrl},
            {key:"Phone"},
            {key:"City"},
            {key:"Rating.AverageRating", label:"Rating", formatter:YAHOO.widget.DataTable.formatNumber, sortable:true}
			// ClickUrlはデータとしてとってくるが、カスタムフォーマッターに使うだけで、列定義しない。
       	];
 
		// データソースとして、サーバープログラムを定義する。
    	var myDataSource = new YAHOO.util.DataSource("ajax_yui_datatable_json_over_XHR.Proxy.php?");
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;

        // Connection Managerに任せるRequestは待ち行列に入れる。
        myDataSource.connXhrMode = "queueRequests";
        myDataSource.responseSchema = {
			// Jsonデータとして使うルート(要素)を指定
        	resultsList: "ResultSet.Result",
			// AverageRatingは、Rating下なので、Rating.AverageRating。
            fields: ["Title","Phone","City","Rating.AverageRating","ClickUrl"]
        };
 
		// 初期リクエストを発行して、テーブルデータを作成する。
        var myDataTable = new YAHOO.widget.DataTable("json", myColumnDefs,
                myDataSource, {initialRequest:"query=pizza&zip=96815-3289&results=10&output=json"});
 
		// コールバック・ハンドラー(success);thisはmyDataTable
		var mySuccessHandler = function() {
            // myDataTableに、コールバックデータ(arguments)をappendする。
            this.onDataReturnAppendRows.apply(this,arguments);
        };
        
		// コールバック・ハンドラー(failure);thisはmyDataTable
        var myFailureHandler = function() {
            this.showTableMessage(YAHOO.widget.DataTable.MSG_ERROR, YAHOO.widget.DataTable.CLASS_ERROR);
            // myDataTableに、コールバックデータ(arguments)をappendする。
            this.onDataReturnAppendRows.apply(this,arguments);
        };

        // Connection Managerのコールバック・オブジェクト
        var callbackObj = {
            success : mySuccessHandler,
            failure : myFailureHandler,
			// call backハンドラーにはmyDataTableを渡す。
            scope : myDataTable
        };
        
	// 非同期にConnection Managerの待ち行列にリクエストを入れる。これらは、次々とテーブルにAppendされる。
        myDataSource.sendRequest("query=mexican&zip=96815-3289&results=10&output=json",
                callbackObj);
 
	// 非同期にConnection Managerの待ち行列にリクエストを入れる。これらは、次々とテーブルにAppendされる。
        myDataSource.sendRequest("query=chinese&zip=96815-3289&results=10&output=json",
                callbackObj);
                
        return {
            oDS: myDataSource,
            oDT: myDataTable
        };
    }();
});
</script>
</head> 
 
<body class=" yui-skin-sam">
<div id="main">
<p>Yahoo! Local Searchからjsonデータを取得して、テーブルに表示します。</p>
<div id="json"></div> 
</div>
</body> 
</html>

以下は、PHPプログラム(ajax_yui_datatable_json_over_XHR.Proxy.php)。

<?php

// http://developer.yahoo.com/search/local/V3/localSearch.html
define ('PATH', 'http://local.yahooapis.com/LocalSearchService/V3/localSearch');

$type = "text/xml";

// Get all query params
$query = "?";
foreach ($_GET as $key => $value) {
    if(($key == "output") && ($value == "json")) {
        $type = "application/json";
    }
    $query .= urlencode($key)."=".urlencode($value)."&";
}

foreach ($_POST as $key => $value) {
    if(($key == "output") && ($value == "json")) {
        $type = "application/json";
    }
    $query .= $key."=".$value."&";
}
$query .= "appid=YahooDemo";
$url = PATH.$query;


$response = file_get_contents($url);

header("Content-Type: ".$type);
echo $response;

?>