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; ?>