TabView Control: Getting Content from an External Source

2009/6/5 tetsuya.odaka phpのバグを修正(なんで間違ったかな)。

=============================================
このExample(Exampleのページへのリンクはこちら)は、少し面倒なコードが示されている。

YAHOO.widget.Tabオブジェクトを生成する際、コンストラクタに食わせるオブジェクト・リテラル

  • dataSrc
  • cacheData

を設定する例である。

dataSrcは、その名の通り、データの取り出し先のことであるが、Connection Managerを経由してPHPプログラムを呼び出している。このPHPプログラム(news.php)はProxyをなって、YAHOO! News Serachからラベルに関係するニュースを取得している(YAHOO! News SearchのAPIドキュメントはこちら)。

以下がサンプリングした画面である。

dataSrcを指定すると、HTTPサーバーへGETで送られる。また、PHPからのレスポンスは、

<ul>
    <li><a href="xxxxxx">yyyyyyyyy</a><cite>zzzzzzz</cite></li><li><a href="xxxxxx">yyyyyyyyy</a><cite>zzzzzzz</cite></li>
</ul>

の形式になっている(Firebugで調べ)。したがって、PHPのproxyは、YAHOO! News Searchからのレスポンスをこの形式に変換して、レスポンスしなくてはならない。

以下が、Javascriptを含むHTMLの全文であるが、PHPに多くの処理を行わせているために、JavaScriptは非常にシンプルなものとなっている。
cacheData=trueの指定をした場合、一度データを取得すると、次に同じタブをActiveにした場合に(ブラウザキャッシュを利用するため)requestが発生しない(Firebugで調べ)。
これは、なかなかに面白い機能だな、と関心。
よく、タブを切り替え、元のタブに戻った時に新しいrequestとsessionがおきてしまって、使い勝手が悪くなってしまう(典型的には初期画面に戻るなど)アプリがあるからだ。この指定により、これが回避できる可能性がある。
Scriptのコードは、これまで通り、module patternで書いた。

<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>Ajax_Sampling</TITLE>
<style type="text/css">
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/tabview/assets/skins/sam/tabview.css" />
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="scripts/yui/element/element-beta-min.js"></script>
<script type="text/javascript" src="scripts/yui/tabview/tabview-min.js"></script>
<script type="text/javascript" src="scripts/yui/connection/connection-min.js""></script>

<style type="text/css" id="defaultstyle">
#container {
	margin: 2px;
	padding: 3px;
	width: 500px;
	height: auto;
	border:1px dashed #999999;
}
.yui-navset div.loading div {
    background:url(assets/loading.gif) no-repeat center center;
    height:8em; /* hold some space while loading */
}
#example-canvas h2 {padding: 0 0 .5em 0;}
</style>

<script type="text/javascript">
//モジュールパターンで実装する。
YAHOO.namespace("EGP");

YAHOO.EGP.DataSrcTab = function() {

	var tabView;

	return{
    	init: function() {
		    tabView = new YAHOO.widget.TabView();

		    tabView.addTab( new YAHOO.widget.Tab({
		        label: 'Opera',
		        dataSrc: 'ajax_yui_news.php?query=opera+browser',
		        // cacheData: true とすると、tabを変えたときに
		        // requestがでない。
		        cacheData: true,
		        active: true
		    }));
		    
		    tabView.addTab( new YAHOO.widget.Tab({
		        label: 'Firefox',
		        dataSrc: 'ajax_yui_news.php?query=firefox+browser',
		        cacheData: true
		    }));

		    tabView.addTab( new YAHOO.widget.Tab({
		        label: 'Explorer',
		        dataSrc: 'ajax_yui_news.php?query=microsoft+explorer+browser',
		        cacheData: true
		    }));

		    tabView.addTab( new YAHOO.widget.Tab({
		        label: 'Safari',
		        dataSrc: 'ajax_yui_news.php?query=apple+safari+browser',
		        cacheData: true
		    }));

		    tabView.appendTo('container');

    	}
	};
    
}();

//DOMが完全にloadされたら、サンプルを初期化する。
YAHOO.util.Event.onDOMReady(
		 //DomReadyイベントで発火するハンドラ
		YAHOO.EGP.DataSrcTab.init,
		//ハンドラに渡すオブジェクト(関数)
		YAHOO.EGP.DataSrcTab,
		//ハンドラは、上記のオブジェクトのスコープをもつ。   
		true
);

</script>
</HEAD>

<!-- class=" yui-skin-sam"の指定が必要 -->
<BODY class="yui-skin-sam">
<div id="container">
<p>
YAHOO! Newsからデータを取り出します。<br/>
</p>
<!-- TabViewが以下に追加される -->
</div>
</BODY>
</HTML>

YAHOOのExampleで実際に使われているnews.phpは、YUIダウンロードファイルのExample/Tabview/assets下にあるが、開発機のWindows環境では動かないので、作ってみた。

YAHOO!Webserviceには、一般にoutput形式の指定ができ、output=phpと指定するとシリアライズ化されたphpファイルでデータが取り出せる(Defaultはxml)。
YAHOO! Developers Networkにある「Using Serialized PHP with Yahoo! Web Services」というドキュメントを読むと、使いがってがよさそうなので使ってみた(news.phpでも利用している)。このページを見る限り、PHP以外の言語でも利用可能なようだ(未確認)。

以下にPHPプログラムの全文を示す。動作は開発環境(Windows XP SP3)にインストールしたApache2.2.9+PHP5.2.6で検証した。

<?php

$wkGET=$_GET["query"];

// spaceを+に置換 (opera+browserで送っても、opera browserで届いたとき)
$wkGET=str_replace(' ','+',$wkGET);

$queryString.='query='.$wkGET;

$url = 'http://search.yahooapis.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&output=php&'.$queryString; 

// データの取得
$phpserialized = file_get_contents($url);
// serializeされたデータをunserializeする。
$phparray = unserialize($phpserialized);

// レスポンスデータの準備
$res='<ul>';
foreach($phparray["ResultSet"]["Result"] as $record){
	$wkEl='<li><a href="'.$record["ClickUrl"].'">'.$record["Title"].'</a>'.
		'<cite>'.$record["NewsSource"].'</cite></li>';
	$res.=$wkEl;
}
$res.='</ul>';

// 結果の返却
echo $res;
?>