Container Family: Creating a Resizable Panel

Reasizable Panel(Resizable Windowsともいう)とは、文字とおり、大きさの変えられるPanel(Window)のことを指す。

YUIのExampleのページを見ると、この機能が実装されたのは、YUIのバージョン2.5.0と比較的最近のことだったようだ。
そのためだと思われるが、Resizable Panelを生成するには、YAHOO.widget.PanelのインスタンスとYAHOO.util.Resizeのインスタンスを、同一のエレメントID(もしくは、同一HTMLエレメント)に対して生成するような手順を踏む。

Resizeには、

  1. (リサイズするためにドラッグする)ハンドル(つまみ)
  2. ドラッグに関連したイベント
  3. エレメントを一定の範囲までリサイズする

といった機能が備わっている。(詳細については、ResizeのAPIドキュメントを参照)

Panelについては、これまでのサンプルと同様のコンフィグパラメータを設定すればよいが、このExampleでは、autofillheightという属性をbodyに設定している(デフォルト値)。このパラメータをheaderなどのデフォルト以外の値に設定すると、bodyのコンテンツのボリュームに応じた高さのPanelが生成されてしまう。

以下が、サンプルのResizable Panelを開いたときの画面。
Panelのインスタンス生成時に、

パラメータ
draggable true
width "500px"
height "150px"
autofillheight "body"(Default)
constraintoviewport true

とパラメータを指定したので、高さが150pixのDgarrableなPanelとなっており、画面の表示範囲内にDragが制約される。

以下にJavascriptを含むHTMLの全体を示す。
Resizeイベントの発生時に、PanelのMaxwidth、Maixheightを再計算させているところに注意。

<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/container/assets/skins/sam/container.css" />
<link rel="stylesheet" type="text/css" href="scripts/yui/resize/assets/skins/sam/resize.css" />
<script type="text/javascript" src="scripts/yui/utilities/utilities.js"></script>
<script type="text/javascript" src="scripts/yui/container/container-min.js"></script>
<script type="text/javascript" src="scripts/yui/resize/resize.js"></script>

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

/* 初期表示で初めて表示するようにする */
#resizablepanel {
	visibility:hidden;
	height:0;
}

#resizablepanel .bd {
    overflow:auto;
    background-color:#fff;
    padding:10px;
}

#resizablepanel .ft {
    height:15px;
    padding:0;
}

/* Resizeするためのハンドルをbrにする */
#resizablepanel .yui-resize-handle-br {
    right:0;
    bottom:0;
    height: 8px;
    width: 8px;
    position:absolute;
}

/* 以下は、MacOS上のGeckoブラウザー(たとえば、FireFox)のための配慮 */
/*
	MacOS上のGeckoブラウザーで、Resizable PanelがHiddenになった際に
	スクロールバーが見えたままになることを防止するための配慮。
	詳細は、"container-core.css"のコメントを参照。
*/
#resizablepanel_c.hide-scrollbars .yui-resize .bd {
    overflow: hidden;
}

#resizablepanel_c.show-scrollbars .yui-resize .bd {
    overflow: auto;
}

/*
	以下もMacOS上のGeckoブラウザーについての配慮。
*/
#resizablepanel_c.show-scrollbars .underlay {
    overflow: visible;
}

</style>

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

// YAHOO.example.containerにModalPanelを追加する。
YAHOO.example.container.resizablePanel = function() {
	var Event = YAHOO.util.Event;
	var Dom = YAHOO.util.Dom;
	var panel,resize;

	//panelインスタンスは1回だけ生成
	var clickHandler = function(){

		if(!panel){
			// まずはPanelを生成する。
			panel = new YAHOO.widget.Panel("resizablepanel", {
        			draggable: true,
        			width: "500px",
        			height: "150px",
        			// コンテンツのボリュームに関わらずPanelのbodyの高さを一定に保つ。
        			autofillheight: "body", 
		        	constraintoviewport:true,
		        	// showbtnにくっつけて表示する。
        			context: ["showbtn", "tl", "bl"]
    		});
    		
    		panel.render();

		// resizeインスタンスを生成し、上でつくったPanelにくっつける。
    		resize = new YAHOO.util.Resize("resizablepanel", {
		    // resizeするハンドルを右下(bottom-right)にする。
    		    handles: ["br"],
    	    	    autoRatio: false,
		    // resizeした時の幅の最小値
        	    minWidth: 300,
		    // resizeした時の高さの最小値
        	    minHeight: 100,
        	    status: false 
    		});
		}

		// Show the Panel
		panel.show();
	
	    // resizeイベント発生時に、panelのmaxWidth、maxHeightをきめる。
	    resize.on("startResize", function(args) {

			if (this.cfg.getProperty("constraintoviewport")) {
				// resizeイベントで、panelのmaxWidth、maxHeightをきめる
				var D = YAHOO.util.Dom;

				var clientRegion = D.getClientRegion();
				var elRegion = D.getRegion(this.element);

				resize.set("maxWidth", clientRegion.right - elRegion.left - YAHOO.widget.Overlay.VIEWPORT_OFFSET);
				resize.set("maxHeight", clientRegion.bottom - elRegion.top - YAHOO.widget.Overlay.VIEWPORT_OFFSET);
			} else {
				resize.set("maxWidth", null);
				resize.set("maxHeight", null);
			}

    		}, 
    		panel, 
    		true);

	    // resizeイベントで、panelの高さをきめる
	    resize.on("resize", function(args) {
    	    var panelHeight = args.height;
        	this.cfg.setProperty("height", panelHeight + "px");
    		}, 
    		panel, 
    		true);
	};
	
	return{
    	init: function() {
    		Event.on("showbtn", 
	    		"click", 
	    	       	clickHandler);
		}
	};
}();

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

</script>
</HEAD>

<BODY class="yui-skin-sam">
<div id="container">
<p>
Resizable Panelのサンプルです。<br/>
「Show Resizable Panel」でパネルが表示されます。
右下にフォーカスしてドラッグすることで、resizeできます。
</p>
    <div id="examplecontainer">
        <button id="showbtn">Show Resizable Panel</button>

        <div id="resizablepanel">
            <div class="hd">Resizable Panel</div>
            <div class="bd">
                <p>
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                	あいうえおあいうえおあいうえおあいうえお
                </p>
            </div>
            <div class="ft"></div>
        </div>
    </div>
</div>
</BODY>
</HTML>