Get Utility: Getting CSS Style Sheets

先の例で使ったYUIのGet Utilityには、cssをダイナミックにロードする機能がついてる。

今回は、そのサンプル(Getting CSS Style Sheets)を解析して、若干のmodifyを行う。

このExampleでは、CSSのダイナミックロードとともに、先の例と同様にGet.scriptを使って、YAHOO! News Search APIで提供されるWebServiceが利用されている。
YAHOO! News Search APIの仕様はこちら
この部分のJavascriptは、YUIのサーバー上にあるが(こちらからみえる)、先ほどの例にならって、module patternで実装してみた。
(結果的に、同じようなコードになったが。。。)

サンプルの初期画面は以下。YUIのサンプルでは、初期画面で「San Francisco」をキーにして検索が実行されるが、このサンプルでは、キーワードにイチローと入れるだけで、検索は「Search YAHOO! News」ボタンを押すまで、検索させないようにした。

検索は10レコードだけfetchするようにした(画面に入りきるようにするため)。以下が、検索を実行した画面である。

また、ダイナミックにロードするcssは、YUIのダウンロードファイルに含まれていないので、以下からダウンロードし、HTMLをおくディレクトリ下のscript/yui/get/assetに保管した。

  1. neutral.css
  2. border.css
  3. background.css
  4. text.css

ボタンを押したときの挙動は、YUIのExampleと同じである。
以下は、「Background CSS」ボタンを押したときのイメージ。

以下に、javascriptを含むソースの全文を示す。
今回の例は、app_id=YahooDemoで動かした。また、Inbound Linkの例と同様に、このAPIの利用にも、1つのIPアドレスあたり5000サーチ/日で、非商用であることが、APIドキュメントのRATE LIMITSに示されている。

CSSをダイナミックに変えられるということは、

  • スキンの選択
  • 簡易ズーム(フォントサイズ変更)

などが可能ということだ。

<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/button/assets/skins/sam/button.css" />

<!-- id="styleoverrides"を指定。Get.cssでinsertBeforeするため。 -->
<style type="text/css" id="styleoverrides">
#container .hd {
	background-image:url(http://us.i1.yimg.com/us.yimg.com/i/us/nt/ma/ma_nws_1.gif);
	background-position:top right;
	background-repeat:no-repeat;
	background-color:none;
} 
	
#container h2 {
	border:none;
	margin-top:0;
}

#container h3 {
	color:#999999;
}
	
#buttonContainer {
	padding-bottom:.5em;
}
	
#container .module {
	padding:.5em 1em 1em 1em;
	overflow:hidden;
}

</style>

<!-- 読み込むjs --> 
<script type="text/javascript" src="scripts/yui/yahoo/yahoo-min.js" >
</script> 
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js" >
</script> 
<script type="text/javascript" src="scripts/yui/utilities/utilities.js" >
</script> 
<script type="text/javascript" src="scripts/yui/button/button-min.js" >
</script> 

<script type="text/javascript">
YAHOO.namespace("EGP");

//関数オブジェクトBottunChangerの定義
//モジュールパターンで実装する。
YAHOO.EGP.BottunChanger = function() {

    // Alias
	var Button = YAHOO.widget.Button,
 	Event = YAHOO.util.Event,
 	Dom = YAHOO.util.Dom,
 	Get = YAHOO.util.Get,
 	elContainer,
 	borderButton, backgroundButton, textButton,
 	tIds = {};

        //
	// checkBottunのイベントハンドラーの定義
	// 
	// Checkbox buttonは、状態として"checked"と"unchecked"がある。
	// この状態が変わると、"onCheckedChange"イベントが発火する。
	// このイベントをトリガーにして、Get UtilityでCSSをloadしたり、unloadしたりする。
	var onCheckedChange = function() {
	    // thisはイベントのおこったBottunをあらわす。
	    // name属性で、イベントの起こったボタンを判別する。
 	    var name = this.get("name");

            // Bottunが、"checked"な状態であれば、必要なCSSをloadする。
 	    if(this.get("checked")) {
		// data パラメータを指定して、onSuccessハンドラーに渡す。	
		// dataには、CSS名を渡し、CSSを取り除くときのために格納しておく。
     	        //
     	        // insertBeforeプロパティーを指定する。
     	        // 値には、どのCSSの前に差し込むか、を指定する。
     	        // そのために、style タグにid(=styleoverrides)を指定する。
	        Get.css("scripts/yui/get/assets/" + name + ".css", {
 	            data:         name,
                    insertBefore: "styleoverrides",
                    onSuccess:    onSuccess
     	        });
 	    } else {
                // checkが外されたら、保管していた状態にもどす。
     	        tIds[this.get("name")].purge();
	
                // ある種のA-Grade Browserでは、purgeがうまくいかないので、
                // なにも書いてないCSSをGet.cssでloadする。
     	        Get.css("scripts/yui/get/assets/neutral.css");
 	   }
       };

	// Get UtilityのonSuccessハンドラー
	var onSuccess = function(o) {
		//alert("読み込み成功; " + o.data);
		// o.dataには、ボタン名が入ってる。purgeのときのために保管しておく。
		tIds[o.data] = o;
	};
	
	return{
            // DOMReadyで最初に呼ばれる初期化関数。
            init: function() {
   		// (注意)  	
     	        // DOMReady後でなければできない、メンバー変数の定義。
	    	elContainer = Dom.get("container"),
	    	
		// Bottunを動的に生成して、Containerに突っ込む。
	    	// Checkbox Buttonの定義
	    	borderButton = new Button({
	        	id: "borderButton",
	        	type: "checkbox",
	        	name: "border",
	        	label: "Border CSS",
	        	container: "buttonContainer" 
	    	});

	    	backgroundButton = new Button({
	        	id: "backgroundButton",
	        	type: "checkbox",
	        	name: "background",
	        	label: "Background CSS",
	        	container: "buttonContainer"
	    	});

	    	textButton = new Button({
	        	id: "textButton",
	        	type: "checkbox",
	        	name: "text",
	        	label: "Text CSS",
	        	container: "buttonContainer"
	    	});

	    	YAHOO.EGP.BottunChanger.buttons = 
	    		[borderButton, backgroundButton, textButton];

			// BottunのcheckedChangeイベントに、
			// onCheckedChangeハンドラーをsubscribeする。	
			borderButton.on("checkedChange", onCheckedChange);
			backgroundButton.on("checkedChange", onCheckedChange);
			textButton.on("checkedChange", onCheckedChange);
 	    }
      };
}();

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

//-------------------------------------------------------------
//
// YAHOO! NewsをとってくるScriptが書かれていないので、GetScriptで書いてみる。
// サンプルの本物は、
// http://developer.yahoo.com/yui/examples/get/assets/getNews.js
// を参照のこと。
// module patternで書くことにする。
YAHOO.EGP.NewsPicker = function() {

	var Event = YAHOO.util.Event,
    	Dom   = YAHOO.util.Dom,
    	Button = YAHOO.widget.Button,
    	Get    = YAHOO.util.Get,
    	elResults;

    var onNewsPickerSuccess = function(o) {
    }

    var onNewsPickerFailure = function(o) {
    	var html = "<h3>通信に失敗しました</h3>";
        elResults.innerHTML = html;
    }

	var getNewsPickerData = function() {
        
        elResults.innerHTML = "<h3>次のキーワードを検索しています。 " +
            Dom.get("searchString").value + ":</h3>" +
            "<img src='http://l.yimg.com/us.yimg.com/i/nt/ic/ut/bsc/busybar_1.gif' " +
            "alt='お待ちください...'>";
        
        // YAHOO! News APIを利用するURLを準備する。
        // V1の仕様は、http://developer.yahoo.com/search/news/V1/newsSearch.html
        // 面倒なので、outputはjson、リターンのリストは20個を指定する。
        var sURL = "http://search.yahooapis.com/NewsSearchService/V1/newsSearch" + 
        			"?appid=YahooDemo&output=json&results=10" +
        			"&callback=YAHOO.EGP.NewsPicker.callback" +
            		"&query=" + encodeURIComponent(Dom.get("searchString").value);
        
        // Get Utilityを使い、Web Serviceからデータを取得するcallbak定義。
        var transactionObj = Get.script(sURL, 
            {
            	onSuccess: onNewsPickerSuccess,
            	onFailure: onNewsPickerFailure,
                scope    : this
        	}
        );
        
	// ScriptメソッドはトランザクションIDを含む、single-fieldオブジェクトを戻す。
	// トランザクションIDを保管する。
        current = transactionObj.tId; 
    }
    // まず、無名関数を定義する。
	return {
        // DOMReadyで最初に呼ばれる初期化関数。
        init: function() {
      		// (注意)  	
        	// DOMReady後でなければできない、メンバー変数の定義。
    		elContainer = Dom.get("container");
        	elResults   = Dom.get("results"),
                //id=siteExplorerのsubmitイベントにハンドラーを仕掛ける。
                Event.on("newsSearch", "submit", 
            	    function(e) {
            		// submit formのデフォルトの動きを抑止する。
                	Event.preventDefault(e);
            		// WebServiceの呼び出しを実行する。
                	getNewsPickerData();
            	    }, 
            	    this, 
            	    true
               );
	      // input type=submit にbuttonをインスタンス化する。
              var oButton = new Button("getNewsData");
    	},

	// WebServiseのコールバック関数。 
	// (??) Get utilityの場合、レスポンスからのresultのとり方がわからない。
	// 以下のようにして、YAHOO Web ServiceのCallbackを使えば取れる。
	callback: function(results) {
    		
	    // 返却値から有用なフィールドを取得する。
            var aResults = results.ResultSet.Result;
            var totalLinks = results.ResultSet.totalResultsAvailable;
            var returnedLinkCount = results.ResultSet.totalResultsReturned;

            if(aResults) {
			// inbound linkがある場合;処理と表示をする。          
                var html = "<h4>" +
                    totalLinks + 
                    " のリンクが取得できた; 以下に最初の " + 
                    returnedLinkCount +
                    "リンクを表示</h4><ol>";
                
				// inboound linkの処理
                for (var i=0; i < aResults.length; i++) {
                    html += "<li><strong>" +
                        aResults[i].Title +
                        ":</strong> <a href='" +
                        aResults[i].Url +
                        "'>" + aResults[i].Url +
                        "</a></li>";
                }
                
				// inbound liskのlistの終端
                html += "</ol>";
            } else {
    			// inbound linkがない場合。          
            	var html = "<h3>リンクが見つかりませんでした。</h3>";
            }
            //insert string into DOM:
            elResults.innerHTML = html;
        }
    };
}();

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

</script>
</HEAD>

<!-- class=" yui-skin-sam"の指定はbuttunのskin適用に必要 -->
<BODY class=" yui-skin-sam">
<div id="container">

    <div id="buttonContainer">
        <!--  bottunインスタンスを動的に作成して、突っ込む。  -->
    </div>

    <div class="module">
        <div class="hd"><h2>In the News:</h2></div>

        <div class="bd" id="results">
            <!--News stories will be displayed here.-->
        </div>
        <div class="ft">        
            <div id="searchControls">
                <!--Use a real form that works without JavaScript:-->
                <form id="newsSearch" method="GET" action="xxx">            
                    <label for="searchString">Search Yahoo! News:</label> 
                    <input id="searchString" type="text" name="p"  value="イチロー" size="40">             
                    <input id="getNewsData" type="submit" value="Search Yahoo! News">  
                </form>            
            </div>

        </div>
    </div>
</div>

</BODY>
</HTML>