Menu Family: Multi-tiered Menu From JavaScript

このExampleは、複数階層のメニューを(Markupではなく)Scriptで作成する方法を示している(Exampleのページへのリンクはこちら)。

Scriptの場合も、Markupの場合(「Menu Family: Multi-tiered Menu From Markup」)と同様、一階層のメニューの生成方法(正確にいうと、MenuインスタンスにaddItemsメソッドでセットするオブジェクト・リテラル)をNestさせることで、これが可能となっている。

Nestのさせ方を見るにあたり、まずは、一階層の場合(「Menu Family: Basic Menu From JavaScriptComments」)を振り返ってみる。
一階層のメニューを作る場合、addItemsメソッドでセットするオブジェクト・リテラルは、

    { text: "Yahoo! Mail", url: "http://mail.yahoo.com" }

となっており、これがメニューの一項目となっている。
これらを、以下のように配列にして、addItemsメソッドの引数として、Menuインスタンスに加える。

[
    // オブジェクト・リテラル1
    { text: "Yahoo! Mail", url: "http://mail.yahoo.com" },
    
    // オブジェクト・リテラル2
    { text: "Yahoo! Address Book", url: "http://addressbook.yahoo.com" },
    
    // オブジェクト・リテラル3
    { text: "Yahoo! Calendar", url: "http://calendar.yahoo.com" },
]

複数階層のメニューの場合、上の配列が、トップレベルのメニュー項目となる。
この下位となるサブメニューは以下のように定義する。

    { text: "Yahoo! Mail", url: "http://mail.yahoo.com" , 
             submenu : {
                      id: "information", 
                      itemdata: [
                          { text: "Downloads", url: "http://downloads.yahoo.com" },
                      ]
             }
    }

すなわち、

  • オブジェクト・リテラルの属性としてsubmenu属性を追加する。
  • submenu属性は、それ自身の値がオブジェクト・リテラルであって、id属性、itemdata属性を持つ。
  • itemdata属性は配列であって、その要素が(1レベルの)オブジェクトリテラルとなる。

という構造になる。
上の例の場合、

Yahoo! Mail ===> Downloads

という階層のメニューができる。

サンプルの初期画面は以下。

メニューを展開したときのイメージは以下のようになる。

この場合も、親のメニュー要素として実在するURLを指定しまうと、クリック時にそのURLへ飛んでしまい、紛らわしい。親要素には、ダミーのセクション(#xxxxの形式)を指定し、サブメニューの集合として名前をタイトル(text属性)として与えるのが好ましいと思われる。

<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/menu/assets/skins/sam/menu.css" />
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="scripts/yui/container/container_core-min.js"></script>
<script type="text/javascript" src="scripts/yui/menu/menu-min.js"></script>

<style type="text/css" id="defaultstyle">
#container {
	margin: 2px;
	padding: 3px;
	width: 400px;
	height: auto;
	border:1px dashed #999999;
}
</style>

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

YAHOO.EGP.MarkupMenu = function() {

	var oMenu;
	var aItems = [
	      // (実体)MenuのTopレベルが1のオブジェクトとなった、オブジェクトリテラル4つの配列。
	      
	      // オブジェクト・リテラル1(Communication)
          {
           	text: "Communication", 
           	url: "#communication", 
			// オブジェクト・リテラルにsubmenu属性を追加
           	submenu: {
             	// submenu属性はidと配列のitemdataを持つ
                id: "communication", 
                itemdata: [ 
                     { text: "360", url: "http://360.yahoo.com" },
                     { text: "Alerts", url: "http://alerts.yahoo.com" },
                     { text: "Avatars", url: "http://avatars.yahoo.com" },
                     { text: "Groups", url: "http://groups.yahoo.com " },
                     { text: "Internet Access", url: "http://promo.yahoo.com/broadband" },
                     {
                       text: "PIM", 
                       url: "#pim", 
                       submenu: {
	                       id: "pim", 
	                       itemdata: [
                               { text: "Yahoo! Mail", url: "http://mail.yahoo.com" },
                               { text: "Yahoo! Address Book", url: "http://addressbook.yahoo.com" },
                               { text: "Yahoo! Calendar",  url: "http://calendar.yahoo.com" },
                               { text: "Yahoo! Notepad", url: "http://notepad.yahoo.com" }
	                                  ] 
	                              }
	                          
	                          }, 
                    { text: "Member Directory", url: "http://members.yahoo.com" },
                    { text: "Messenger", url: "http://messenger.yahoo.com" },
                    { text: "Mobile", url: "http://mobile.yahoo.com" },
                    { text: "Flickr Photo Sharing", url: "http://www.flickr.com" }
                         ] 
                  } 
              },

           // オブジェクト・リテラル2("Shopping")
           {
                  text: "Shopping", 
                  url: "http://shopping.yahoo.com", 
                  submenu: {
                      id: "shopping", 
                      itemdata: [
                         { text: "Auctions", url: "http://auctions.shopping.yahoo.com" },
                         { text: "Autos", url: "http://autos.yahoo.com" },
                         { text: "Classifieds", url: "http://classifieds.yahoo.com" },
                         { text: "Flowers & Gifts", url: "http://shopping.yahoo.com/b:Flowers%20%26%20Gifts:20146735" },
                         { text: "Real Estate", url: "http://realestate.yahoo.com" },
                         { text: "Travel", url: "http://travel.yahoo.com" },
                         { text: "Wallet", url: "http://wallet.yahoo.com" },
                         { text: "Yellow Pages", url: "http://yp.yahoo.com" }
	                      ] 
                  } 
              },

              // オブジェクト・リテラル3(Entertainment)
              {
                  text: "Entertainment", 
                  url: "http://entertainment.yahoo.com", 
                  submenu: { 
                      id: "entertainment", 
                      itemdata: [
                          { text: "Fantasy Sports", url: "http://fantasysports.yahoo.com" },
                          { text: "Games", url: "http://games.yahoo.com" },
                          { text: "Kids", url: "http://www.yahooligans.com" },
                          { text: "Music", url: "http://music.yahoo.com" },
                          { text: "Movies", url: "http://movies.yahoo.com" },
                          { text: "Radio", url: "http://music.yahoo.com/launchcast" },
                          { text: "Travel", url: "http://travel.yahoo.com" },
                          { text: "TV", url: "http://tv.yahoo.com" }              
                      ] 
                  } 
              },

              // オブジェクト・リテラル4(Information)
              {
                  text: "Information", 
                  url: "#information", 
                  submenu: {
                      id: "information", 
                      itemdata: [
                          { text: "Downloads", url: "http://downloads.yahoo.com" },
                          { text: "Finance", url: "http://finance.yahoo.com" },
                          { text: "Health", url: "http://health.yahoo.com" },
                          { text: "Local", url: "http://local.yahoo.com" },
                          { text: "Maps & Directions", url: "http://maps.yahoo.com" },
                          { text: "My Yahoo!", url: "http://my.yahoo.com" },
                          { text: "News", url: "http://news.yahoo.com" },
                          { text: "Search", url: "http://search.yahoo.com" },
                          { text: "Small Business", url: "http://smallbusiness.yahoo.com" },
                          { text: "Weather", url: "http://weather.yahoo.com" }
                      ]
                  } 
              }            
          ];                
	
	return{
    	init: function() {
		   // Muneのインスタンス生成
		   // コンストラクタの第1引数は、menuを構成するdivのid、
		   // 第2引数は、属性を表すオブジェクトリテラル
		   // 属性はMenuのAPIドキュメント
		   // http://developer.yahoo.com/yui/docs/YAHOO.widget.Menu.html
   		
	   		oMenu = new YAHOO.widget.Menu("menuwithgroups", 
   			   				{ xy: [300,45] }
						);

			oMenu.addItems(aItems);

			// YAHOO.widget.Menuのメソッドrenderを呼んで、レンダリング。
   			oMenu.render("rendertarget");

			// Bottunのクリックイベントにメニューの表示(show)を仕掛ける。
			// EventのAPIはhttp://developer.yahoo.com/yui/docs/YAHOO.util.Event.html
			// 第4引数は、ハンドラーへの引数、第5引数は実行scope.
   			YAHOO.util.Event.addListener(
   		   				"menubutton", 
   		   				"click", 
   		   				oMenu.show, 
   		   				null, 
   		   				oMenu
   		   			);
		}
	};
}();

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

</script>
</HEAD>

<!-- class=" yui-skin-sam"の指定が必要 -->
<BODY class="yui-skin-sam">
<div id="container">
<p>
Scriptで、複数階層のMenuを作成します。
</p>
<button id="menubutton" type="button">Menuを表示</button>
<!-- Menuを作るdiv -->
<div id="rendertarget"></div>
</div>
</BODY>
</HTML>