Button Control: Menu Buttons

Menu Buttonとは、ボタンを押すとリストボックスのようにMenuが展開されるボタンのこと(YUIのExampleのページへのリンクはこちら)。

サンプリングは以下の画面。(これまでのButtonの例と同じように)Markupから生成される場合と、YUIライブラリーからJavascriptで(動的に)作成される場合の2通りの方法がしめされている。

このMenu Button は、input+select+optionタグのコンビネーションと同様のものと考えてよいが、元となるmarkupによって挙動が微妙に違う。
たとえば、1番目の例(Menu Button 1)では、inputタグにtype=submitが指定されており、この場合には、メニューの選択と同時にsubmitイベントが発生する。

また、添付するhtmlファイルを見てもらうと分かるが、JavascriptでMenuButtonを生成する場合には、

  1. Menuを作成するのに非常に似た方法(Menuの内容である、オブジェクト・リテラルを利用する方法)
  2. もっとRadicalにOverlayインスタンスを利用する方法(Overlayオブジェクトは、Menuオブジェクトの祖先)

の2つが例示されている。
YUIのページによると、後者は、「calendarやColor pickerのようなオブジェクトをボタンに忍ばせることのできる方法」とかいてある。

以下に、Javascriptをふくむhtmlファイルの全文を示す。
この中で、ボタン5(JavascriptからMenuButtonを生成する後者の方法)のところに、

	        YAHOO.util.Event.onContentReady("menubuttonsfromjavascript", 
	    	        function () {
                        ....
                }

という、(やや不自然な)センテンスがある。
ここで指定されている、id=menubuttonsfromjavascriptのdivは、ボタン4と共有するコンテナであるが、ボタン4を生成するコードの直後に、ボタン5を生成するコードを書くと、ボタン5が先に来てしまう。これを防ぐために、このコンテナが準備完了になるのを待って(つまり、ボタン4の処理が終わるのを待って)、ボタン5を生成している。

<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" />
<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/element/element-beta-min.js"></script>
<script type="text/javascript" src="scripts/yui/button/button-min.js"></script>

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

/*
    Set the "zoom" property to "normal" since it is set to "1" by the 
   ".example-container .bd" rule in yui.css and this causes a Menu
    instance's width to expand to 100% of the browser viewport.
*/
    
div.yuimenu .bd {
	zoom: normal;
}

#button-example-form fieldset {
	border: 2px groove #ccc;
	margin: .5em;
	padding: .5em;
}

#menubutton3menu,
#menubutton5menu {
	position: absolute;
	visibility: hidden;
	border: solid 1px #000;
	padding: .5em;
	background-color: #ccc;
}

#button-example-form-postdata {
	border: dashed 1px #666;
	background-color: #ccc;
	padding: 1em;
}

#button-example-form-postdata h2 {
	margin: 0 0 .5em 0;
	padding: 0;
	border: none;
}

</style>

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

YAHOO.EGP.MenuButton = function() {

	var Dom = YAHOO.util.Dom;

    // MenuButton1は(input type="submit"から生成されるので)submitイベントを出す
    var onExampleSubmit = function (p_oEvent) {
        var bSubmit = window.confirm("Are you sure you want to submit this form?");
        if(!bSubmit) {
            YAHOO.util.Event.preventDefault(p_oEvent);
        }
    };
	
	return{
    	init: function() {

	// ---- buttonをタグから生成する。-----
		
            // Create a Button using an existing <input> element as a data source

        	// ----------- menu button1の処理 --------------------
		    // MenuButton1は(input type="submit"から生成されるので)submitイベントを出す
            var oMenuButton1 = new YAHOO.widget.Button("menubutton1", 
                    { 	type: "menu", 
                		menu: "menubutton1select" });

        	// ----------- menu button2の処理 --------------------
            var oMenuButton2 = new YAHOO.widget.Button("menubutton2", 
                    { 	type: "menu", 
                		menu: "menubutton2select" });

            // Create a Button using an existing <input> element and a YAHOO.widget.Overlay instance as its menu

        	// ----------- menu button3の処理 --------------------
            var oMenuButton3 = new YAHOO.widget.Button("menubutton3", 
                    { 	type: "menu", 
                		menu: "menubutton3menu" });

	// ---- buttonをmarkupなしで生成する。-----

        	/*
            Instantiate a Menu Button using the array of YAHOO.widget.MenuItem 
            configuration properties as the value for the "menu" configuration 
            attribute.
        	*/

        	// ----------- menu button4の処理 --------------------
			// MenuButton4のためのオブジェクトリテラル(Menuを定義するときと同じ)

			// MenuButton4のためのイベントハンドラ
		    function onMenuItemClick(p_sType, p_aArgs, p_oItem) {
		        oMenuButton4.set("label", p_oItem.cfg.getProperty("text"));
		    };

		    var aMenuButton4Menu = [
				{ text: "one", value: 1, onclick: { fn: onMenuItemClick } },
				{ text: "two", value: 2, onclick: { fn: onMenuItemClick } },
				{ text: "three", value: 3, onclick: { fn: onMenuItemClick } }
                ];

	        var oMenuButton4 = new YAHOO.widget.Button(
                { 	type: "menu", 
                    label: "one", 
                    name: "mymenubutton", 
                    menu: aMenuButton4Menu, 
                    container: "menubuttonsfromjavascript" 
                }
        	);

        	// ----------- menu button5の処理 --------------------
        	// 4の処理が終わったら動くようにする。
        	// 待たないと、4より前に表示されてしまう。
	        YAHOO.util.Event.onContentReady("menubuttonsfromjavascript", 
	    	        function () {
		        
				// Instantiate an Overlay instance
    	        var oOverlay = new YAHOO.widget.Overlay("menubutton5menu", 
        	            { visible: false }
            	);
            	// Menuの中身をセット(カレンダーやカラーピッカーなど入れられる)
            	oOverlay.setBody("Menu Button 5 Menu");
        
            	// Instantiate a Menu Button
            	var oMenuButton5 = new YAHOO.widget.Button(
                    { 	type: "menu", 
                        label: "Menu Button 5", 
                        menu: oOverlay 
                    }
            	);
            
            	/*
                 Append the Menu Button and Overlay to the element with the id 
                 of "menubuttonsfromjavascript"
            	*/
				var el = Dom.get('menubuttonsfromjavascript');
            	oMenuButton5.appendTo(el);
            	oOverlay.render(el);

	    	});
        	// ----------- menu button5の処理 (end)--------------------
	    	
            // MenuButton1は(input type="submit"から生成されるので)submitイベントを出す
            // (そのハンドラを仕込む)。
            YAHOO.util.Event.on("button-example-form", 
                    "submit", onExampleSubmit);
		}
	};
}();

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

</script>
</HEAD>

<BODY class="yui-skin-sam">
<div id="container">
<p>
Menu Buttonの作り方のサンプルです。
</p>
<form id="button-example-form" name="button-example-form" method="post">

    <fieldset id="menubuttons">
        <legend>Menu Buttons</legend>

        <fieldset id="menubuttonsfrommarkup">
            <legend>From Markup</legend>
            
            <!-- Menu1 -->
            <input type="submit" id="menubutton1" name="menubutton1_button" value="Menu Button 1">
            <select id="menubutton1select" name="menubutton1select">
                <option value="0">One</option>
                <option value="1">Two</option>
                <option value="2">Three</option>                
            </select>

            <!-- Menu2 -->
            <input type="button" id="menubutton2" name="menubutton2_button" value="Menu Button 2">
            <select id="menubutton2select" name="menubutton2select">
                <option value="0">One</option>
                <option value="1">Two</option>
                <option value="2">Three</option>                
            </select>

            <!-- Menu3 -->
            <input type="button" id="menubutton3" name="menubutton3_button" value="Menu Button 3">
            <div id="menubutton3menu" class="yui-overlay">
                <div class="bd">Menu Button 3 Menu</div>
            </div>
        </fieldset>

        <fieldset id="menubuttonsfromjavascript">
            <legend>From JavaScript</legend>
        </fieldset>
        
    </fieldset>
</form>

</div>
</BODY>		
</HTML>