Yahoo! UI Library: TreeViewで今風(いまふう)のメニューをつくるには
先の「Yahoo! UI Library: TreeViewの基本(その3)」では、自HTTPサーバー配下に、DOMファイルを置き、それをXHRで一気に取得して、TreeViewを構成してみた。
ここでは、図にのって、今風のメニューを作るための基本機能について実装してみたい。
今風というのは、
- メニューを必要に応じて表示/非表示する。
- メニューの内容をダイナミックに変える。
- メニューの表示にアニメーションを取り入れる。
- メニューによる画面の切り替えの際に、画面をリロードしない。
というのを念頭においている。
突然、「メニュー」という言葉が登場したが、これは、ここまでのTreeViewと同義である。
なぜなら、TreeViewがアンカー(aタグ)のリストから生成できることから、(target=_selfで)異なったサイトの呼び出しができることが自明だからである。
メニューをダイナミックに切り替えることで、利用ユーザごとのメニューの切り替えが可能となる。
また、話は飛ぶが、これにCSSの動的な切り替え(「Get Utility: Getting CSS Style Sheets」を参照)を加えることで、利用ユーザーごとのスキンの切り替えも可能になるだろう。
ここで示すサンプルは、これらの機能を全て実装してるわけではないが、コードを読んでみれば、このコードをカスタマイズすることで、それが可能であることがわかるはずだ。
サンプルの初期画面は以下である。
<閑話休題>
背景の写真は、植物の写真ばかりUpしてある私のFlickrのサイトからのリンクである。
ちなみに、花の名前はコブクザクラ。晩秋から春かけて咲く桜。
さて、上の画面の「メニュー」をクリックすると、XHRでDOMファイルを取得して、透明度を上げながらメニュー(tree)が表示される(下の図)。
ここのメニュー中にあるGoogleは、前のサンプル同様にtarget=_blankで開くようになっているが、このクリックイベントに、defaultの動きを抑止して(EventオブジェクトのpreventDefaultメソッドを使えばいい)、写真を表示しているDivにiframeを差し込むようにすることで、画面の切り替えができるはずだ(この目的で、下のHTMLでは、z-indexとpositionをいじっている)。
また、カスタムアプリケーションであれば、出力結果をこのdivに差し込めばよい。
画面の「閉じる」をクリックすることで、メニューは消えて、上の画面に戻る。
以下に、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" /> <link rel="stylesheet" type="text/css" href="scripts/yui/treeview/assets/skins/sam/treeview.css" /> <style type="text/css" id="defaultstyle"> #container { margin: 2px; padding: 3px; } #treeDiv1 { margin: 5px; position: relative; width: 350px; height: auto; opacity: 0; background: #C0FF3E; padding:1em; z-index: 2; visibility: hidden; } #contents { top: 0px; left: 0pix; position: absolute; border:1px dashed #999999; z-index: 1; } /*擬似リンク(メニュー)*/ #lnk1.lnk { top: 0px; left: 0pix; position: absolute; margin: 2px; padding: 3px; width: 100px; color: blue; background: #7FFF00; text-decoration: underline; cursor: pointer; z-index: 3; visibility: visible; } /*擬似リンク(閉じる)*/ #lnk2.lnk { top: 0px; left: 0pix; position: absolute; margin: 2px; padding: 3px; width: 100px; color: blue; background: #7FFF00; text-decoration: underline; cursor: pointer; z-index: 3; visibility: hidden; } </style> <!-- 読み込むjs --> <script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js" > </script> <script type="text/javascript" src="scripts/yui/treeview/treeview-min.js" > </script> <script type="text/javascript" src="scripts/yui/connection/connection-min.js" > </script> <script type="text/javascript" src="scripts/yui/animation/animation-min.js" > </script> <script type="text/javascript"> var Event = YAHOO.util.Event, Get = YAHOO.util.Get, Dom = YAHOO.util.Dom, tree; //module patternではうまくかけなかった。(スコープの問題??) ajaxHandlers = { // 受信成功時の処理 responseSuccess:function(oj){ var menu = eval(oj.responseText); if(menu) { Dom.get('treeDiv1').innerHTML = menu; } else { alert("メニューが取得できませんでした。"); } YAHOO.util.Event.onAvailable('treeDiv1', function(){ //Treeのインスタンス化: tree = new YAHOO.widget.TreeView('treeDiv1'); tree.draw(); } ); // Animation Dom.setStyle('lnk1','visibility','hidden'); var attributes = { opacity: { to: 0.9 } }; // Animオブジェクトのインスタンス化 var anim = new YAHOO.util.Anim('treeDiv1', attributes, 1,YAHOO.util.Easing.backIn); anim.animate(); Dom.setStyle('treeDiv1','visibility','visible'); Dom.setStyle('lnk2','visibility','visible'); }, // 受信失敗時の処理 responseFailure:function(oj){ alert("failure"); alert("メニューが取得できませんでした(2)。"); }, // テキストを読み込む startRequest :function(url){ YAHOO.util.Connect.asyncRequest('GET', url, ajaxCallback, null); }, // ツリーを閉じる closeTree :function(){ // Animation Dom.setStyle('lnk1','visibility','visible'); Dom.setStyle('lnk2','visibility','hidden'); var attributes = { opacity: { to: 0 } }; // Animオブジェクトのインスタンス化 var anim = new YAHOO.util.Anim('treeDiv1', attributes, 1,YAHOO.util.Easing.backIn); anim.animate(); } }; // コールバック成功/失敗時の振り分け ajaxCallback = { success:ajaxHandlers.responseSuccess, failure:ajaxHandlers.responseFailure, // cache: falseのしないと、HttpServerがajax_test2.xml // の内容をcacheしてしまう。 cache: false, scope: ajaxHandlers }; // 擬似リンクの処理(ツリーを作る) // ハンドラを定義 lnkHandlers = { click:function(){ ajaxHandlers.startRequest('data/ajax_menu1.txt') } } //擬似リンクにイベントを仕掛ける。lnk1がAvailableになってからだよ。 YAHOO.util.Event.onAvailable('lnk1', function() { YAHOO.util.Event.on('lnk1','click', lnkHandlers.click); } ); // 擬似リンクの処理(ツリーを閉じる) // ハンドラを定義 lnkHandlers2 = { click:function(){ ajaxHandlers.closeTree() } } //擬似リンクにイベントを仕掛ける。lnk2がAvailableになってからだよ。 YAHOO.util.Event.onAvailable('lnk2', function() { YAHOO.util.Event.on('lnk2','click', lnkHandlers2.click); } ); </script> </HEAD> <!-- class=" yui-skin-sam"の指定が必要 --> <BODY class=" yui-skin-sam"> <div id="container"> <div id='lnk1' class="lnk">メニュー</div> <div id='lnk2' class="lnk">閉じる</div> <div id='treeDiv1'></div> <div id='contents'> <img src="http://farm3.static.flickr.com/2269/2095697595_efdc8f723c.jpg?v=0" /> </div> </div> </BODY> </HTML>