Menu Family: Website Top Nav Using Animation With Submenus From JavaScript

このExampleは、先の「Menu Family: Website Top Nav Using Animation With Submenus Built From Markup」のサンプルをScriptで記述したものである。(YUIのExampleページへのリンクはこちら

したがって、画面とその動作は、「Menu Family: Website Top Nav Using Animation With Submenus Built From Markup」のサンプルとまったく変わりがない。

また、MarkupからScriptへのコードの変更は、「Menu Family: Website Top Nav With Submenus Built From Markup」から「Menu Family: Website Top Nav With Submenus From JavaScript」への変更とまったく同じ方法をとっている。
先の「Menu Family: Website Top Nav Using Animation With Submenus Built From Markup」のサンプルは、(UserAgentごとの調整など)面倒なコードを含んでいたが、MarkupからScriptに変更することでも、このあたりの改善はなされないようである。
また、画面にトレースされるログにも変わりがない。

以下のJavascriptを含む、htmlの全体を示す。

<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" />
-->
<!-- ヘッダー部、本文(コンテンツ部、メニュー部)、フッター部を分けるグリッド表示のCSS -->
<link rel="stylesheet" type="text/css" href="scripts/yui/reset-fonts-grids/reset-fonts-grids.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>
<script type="text/javascript" src="scripts/yui/animation/animation.js"></script>

<style type="text/css" id="defaultstyle">

div.yui-b p {
    margin: 0 0 .5em 0;
    color: #999;
}
            
div.yui-b p strong {
    font-weight: bold;
    color: #000;
}
            
div.yui-b p em {
    color: #000;
}            

h1 {
   font-weight: bold;
   margin: 0 0 1em 0;
   padding: .25em .5em;
   background-color: #ccc;
}

/* メニューのbottom marginを設定 */
#productsandservices {
   margin: 0 0 10px 0;
}

</style>

<script type="text/javascript">

//モジュールパターンで実装する。
YAHOO.namespace("EGP");

YAHOO.EGP.MarkupMenu = function() {

	var oMenu;
        var ua = YAHOO.env.ua,
    	oAnim;  // Animation instance
		Dom = YAHOO.util.Dom;
	    var aSubmenuData = [
	                        {
	                            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", 
	                                    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" },
	                            ]
	                        },

	                        {
	                            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" }                    
	                            ]    
	                        },
	                        
	                        {
	                            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" }              
	                            ] 
	                        },
	                        
	                        {
	                            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" }
	                            ]
	                        }                    
	                    ];

	/*
    	SubMenuが開く前のイベントのハンドラ; 
		thisは<ul>エレメント。
    	サブメニューがAnimationされる前のスタイルの調整を行う。
		<ul>エレメント(サブメニュー)のアニメーションを動かす。
	*/

	var onSubmenuBeforeShow = function (p_sType, p_sArgs) {

   		var oBody,
       		oElement,
     		oShadow,
       		oUL;

   		
		//ログの表示
		if(this instanceof YAHOO.widget.MenuBarItem){
			var nInst = 'YAHOO.widget.MenuBarItem';
		} else if(this instanceof YAHOO.widget.MenuItem){
			nInst = 'YAHOO.widget.MenuItem';
		} else {
			nInst = 'unknown';
		}
               var log = '<hr/><font color="red"> owner: ' + this.cfg.toString() + 
			' instance of :' + nInst + 
        		' (in onSubmenuBeforeShow) ' +  '</font><br/>';
		Dom.get('log').innerHTML += log;
		
   		if (this.parent) {
			// subメニュー(ul以下のDOM)の保管
   			oElement = this.element;

	       	/*
    	        Get a reference to the Menu's shadow element and 
        	    set its "height" property to "0px" to syncronize 
            	it with the height of the Menu instance.
       		*/

			// これで陰影が取得できる??
       		oShadow = oElement.lastChild;
       		// 陰影を隠す。
       		oShadow.style.height = "0px";
       
	       /*
    	       Stop the Animation instance if it is currently 
        	   animating a Menu.
       		*/ 
   
       		if (oAnim && oAnim.isAnimated()) {
           		oAnim.stop();
           		oAnim = null;
       		}

	       /*
    	       Set the body element's "overflow" property to 
        	   "hidden" to clip the display of its negatively 
           		positioned <ul> element.
       		*/ 
			// class="bd" を保存
       		oBody = this.body;


           //  Check if the menu is a submenu of a submenu.
	       //  Submenu の SubMenuの時の処理(User Agentのごとの調整)
    	   if (this.parent && 
        	   !(this.parent instanceof YAHOO.widget.MenuBarItem)) {

           		/*
               There is a bug in gecko-based browsers and Opera where 
               an element whose "position" property is set to 
               "absolute" and "overflow" property is set to 
               "hidden" will not render at the correct width when
               its offsetParent's "position" property is also 
               set to "absolute."  It is possible to work around 
               this bug by specifying a value for the width 
               property in addition to overflow.
           		*/

		        if (ua.gecko || ua.opera) {
        	 		oBody.style.width = oBody.clientWidth + "px";
           		}
           
		        /*
        	    Set a width on the submenu to prevent its 
            	width from growing when the animation 
               	is complete.
           		*/
           		if (ua.ie == 7) {
               		oElement.style.width = oElement.clientWidth + "px";
           		}
	       }
			// class="bd" のスタイル
       		oBody.style.overflow = "hidden";

       		/*
           		Set the <ul> element's "marginTop" property 
           		to a negative value so that the Menu's height
           		collapses.
       		*/
       		
			// class="bd" 内のulをとる。
       		oUL = oBody.getElementsByTagName("ul")[0];
           	// marginTopをマイナスにしてサブメニューを隠してしまう。(※)
       		oUL.style.marginTop = ("-" + oUL.offsetHeight + "px");
   		}

	}

	/*
	Anmationの間の処理;
		ieのときしか動かない。
	*/
	var onTween = function (p_sType, p_aArgs, p_oShadow) {

		//ログの表示
		if(this instanceof YAHOO.widget.MenuBarItem){
			var nInst = 'YAHOO.widget.MenuBarItem';
		} else if(this instanceof YAHOO.widget.MenuItem){
			nInst = 'YAHOO.widget.MenuItem';
		} else {
			nInst = 'unknown';
		}
		var log = 	'<hr/><font color="blue"> owner: ' + this.cfg.toString() +
		' instance of :' + nInst + 
		' (in onTween) ' +  '</font><br/>';
		Dom.get('log').innerHTML += log;

		if (this.cfg.getProperty("iframe")) {
    		this.syncIframe();
		}

		if (p_oShadow) {
    		p_oShadow.style.height = this.element.offsetHeight + "px";
		}
	}

	/*
	SubMenuが開くときのイベントのハンドラ; 
		thisは<ul>エレメント。
		<ul>エレメント(サブメニュー)のアニメーションを動かす。
	*/

	var onSubmenuShow = function (p_sType, p_sArgs) {

		var oElement,
   		 	oShadow,
   			oUL;
		var	obj = this;

		//ログの表示
		if(obj instanceof YAHOO.widget.MenuBarItem){
			var nInst = 'YAHOO.widget.MenuBarItem';
		} else if(obj instanceof YAHOO.widget.MenuItem){
			nInst = 'YAHOO.widget.MenuItem';
		} else {
			nInst = 'unknown';
		}

		obj = this.parent;
		if(obj instanceof YAHOO.widget.MenuBarItem){
			var pInst = 'YAHOO.widget.MenuBarItem';
		} else if(obj instanceof YAHOO.widget.MenuItem){
			pInst = 'YAHOO.widget.MenuItem';
		} else {
			pInst = 'unknown';
		}
		
        var log = 	'<hr/> owner: ' + this.cfg.toString() + 
		' instance of :' + nInst + 
		' instance(parent) of :' + pInst + 
        ' (in onSubmenuShow) ' +  '<br/>';
		Dom.get('log').innerHTML += log;

		if (this.parent) {
   			oElement = this.element;
   			oShadow = oElement.lastChild;
			// class=bdの取得。
   			oUL = this.body.getElementsByTagName("ul")[0];

           	// marginTopをマイナスにして隠してしまったもの0に戻すことで、現れる。
   			oAnim = new YAHOO.util.Anim(oUL, 
       					{ marginTop: { to: 0 } },
       					.5, YAHOO.util.Easing.easeOut);

			// フレームの陰影の高さを100%にする。
        	oAnim.onStart.subscribe(function () {
    	   			oShadow.style.height = "100%";
   			});
   			oAnim.animate();

   			/*
       			Subscribe to the Anim instance's "tween" event for 
       			IE to syncronize the size and position of a 
       			submenu's shadow and iframe shim (if it exists)  
       			with its changing height.
   			*/

   			if (YAHOO.env.ua.ie) {
       			oShadow.style.height = oElement.offsetHeight + "px";
       			/*
           			Subscribe to the Anim instance's "tween"
           			event, passing a reference Menu's shadow 
           			element and making the scope of the event 
           			listener the Menu instance.
       			*/
       			oAnim.onTween.subscribe(onTween, oShadow, this);
   			}

   			/*
       			Subscribe to the Anim instance's "complete" event,
       			passing a reference Menu's shadow element and making 
       			the scope of the event listener the Menu instance.
   			*/
   			oAnim.onComplete.subscribe(onAnimationComplete, 
   		   				oShadow, this);
   		}

	}

	return{
    	init: function() {
            /*
		    Menuのインスタンス化;第1引数はMenu部を意味するDivのid.
		          第2引数はConfigプロパティー。
	        */
           oMenuBar = new YAHOO.widget.MenuBar("productsandservices", 
					// Menuのコンフィグのためのオブジェクトリテラル
                   { 
                    // MouseOverでsubmenuが展開される。
                    autosubmenudisplay: true, 
                    // Menuが消えるまでの時間(msec)
                    hidedelay:  750,
                    // 表示するときまで、レンダリングを待つ。
                    lazyload: true 
                    }
           );

           oMenuBar.subscribe("beforeRender", function () {
               // ここで取れるthisは、oMenu(発火するインスタンス)
               if (this.getRoot() == this) {

                   this.getItem(0).cfg.setProperty("submenu", aSubmenuData[0]);
                   this.getItem(1).cfg.setProperty("submenu", aSubmenuData[1]);
                   this.getItem(2).cfg.setProperty("submenu", aSubmenuData[2]);
                   this.getItem(3).cfg.setProperty("submenu", aSubmenuData[3]);
               }
           });

           // subMenuが開く直前に発火
           oMenuBar.subscribe("beforeShow", onSubmenuBeforeShow);
           // subMenuが開く際に発火
           oMenuBar.subscribe("show", onSubmenuShow);
           

           //renderだけで、showはいらない
           oMenuBar.render();            
   		
		}
	};
}();

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

</script>
</HEAD>
<body class="yui-skin-sam">
   <div id="doc" class="yui-t1">
      <div>
          <!-- start: your content here -->
          <p>ヘッダー:ここがヘッダーです。</p>
          <h1>Example: Website Top Nav Using Animation With Submenus From JavaScript (YUI Library)</h1>
          <!-- end: your content here -->
      </div>

      <div id="bd">
         <div id="yui-main">
			<!-- 1コラム目のスタート(メニューバー、とコンテンツ) -->
             <div class="yui-b">
                <!-- start: stack grids here -->
				<!-- メニュー部 -->
          		<div id="productsandservices" class="yuimenubar yuimenubarnav">
              		<div class="bd">
                 	  <ul>
                     	<li class="yuimenubaritem"><a href="#communication">Communication</a>
                     	</li>
                     	<li class="yuimenubaritem"><a href="http://shopping.yahoo.com">Shopping</a>
                     	</li>
                     	<li class="yuimenubaritem"><a href="http://entertainment.yahoo.com">Entertainment</a>
                     	</li>
                     	<li class="yuimenubaritem"><a href="#">Information</a>                      
                     	</li>
                      </ul>            
             		</div>
         		</div>
                        
				<!-- コンテンツ部 -->
                <p id="note"><strong>NOTE:</strong> <em>This example demonstrates how to add animation effects to a menu bar with submenus built using JavaScript.</em></p>

                    <form name="example">
                       <select name="test">
                         <option value="one">One</option>
                         <option value="two">Two</option>
                         <option value="three">Three</option>                                
                       </select>
                    </form>
		    <p>ここにログを出しちゃおう。</p> 
		    <div id='log'></div>
                <!-- end: stack grids here -->
          </div>
       </div>
                <!-- 1コラム目の終わり -->

                <!-- 2コラム目 -->
                <div class="yui-b">
                    <p>左ペインです。</p>
                </div>
                <!-- 2コラム目の終わり -->
            </div>

            <div>
                <p>フッター:ここがフッターです。</p>
            </div>
        </div>
    </body>