YUI2.7.0+PHP5で画面のヘルプ機能を自作する。
漠然としたタイトルだが、要するに「アプリを作ったとき、画面それぞれにヘルプをつけたい」というためのプログラムのこと。
先日のログで作成した、(ログインユーザーのロールに応じた)メニュー機能を転用し、以下の仕様とした。
- ヘルプの文面はMarkupで記述し、サーバーのhelpディレクトリ下におく。
- ヘルプを記述したファイルの、ファイル名は、(対応する画面の)ファイル名+'.txt'とする。
- アプリでは、画面のどこかに「?」を記述し、そこをクリックすると、YUIのパネルに差し込まれたヘルプを表示する。
- パネルはドラッグ・アンド・ドロップ可能なウィンドウとする。
具体的なイメージを見てしまった方が早い。以下は、初期画面のスクリーンショット。
上の「?」のリンクをクリックすると、下のようなヘルプを記述したウィンドウが表示される。
ウィンドウに差し込んだマークアップは、以下(help/test_help1.html.txtという変な名前)。
画面idに対応したヘルプ画面を表示するサンプルです。<br> helpディレクトリ下に、 <ul> <li> 画面のファイル名+".txt" </ul> でファイルを作成してください。<br> このテキストのファイル名は<strong>test_help1.html.txt</strong> です。
このために作成したプログラムは以下。
XHRを通じて送信された画面のファイル名から、対応するヘルプをフィードする | getHelp1.php |
ヘルプ文書の要求とパネルの生成などおこなうHTML | test_help1.html |
以下が、getHelp1.php。helpディレクトリ下のファイルをピックアップするために、以前に作成した、TextPickup.class.phpを利用している。メニュー機能のときと同様に、helpディレクトリ下にdefault.txtというMarkup文書を作成しておけば、要求に該当する文書が見つからなかった場合に、代わりにレスポンスされる。
<?php /* * ヘルプの取得を行う * ヘルプは、help/下にユーザーロール別に存在する前提です。 * * author ; t.odaka * date ; 2009/5/8 */ require_once("TextPickup.class.php"); require_once("../Myznala/MyConverter.class.php"); // リクエストデータの取り出し switch($_SERVER['REQUEST_METHOD']) { case 'GET' : $rMethod = &$_GET; break; case 'POST' : $rMethod = &$_POST; break; default: } // パラメータをサニタイズして配列に入れる。 $cObj = new MyConverter(); $reqParm = array(); foreach ($rMethod as $key => $value) { $key =$cObj->sanitize($key,'UTF-8'); $value =$cObj->sanitize($value,'UTF-8'); $m_log->debug($key.'; '.$value); // Debugログ $reqParm[$key]=$value; } // 取り出すメニューの名称 $_help = 'help/'.$reqParm["fname"].'.txt'; if(!file_exists($_help)) $_help = 'help/default.txt'; // テキストの取り出し $ret = null; $tObj = new TextPickup(); $tObj->setFileName($_help); $fp = $tObj->fileOpen('r'); $ret = $tObj->pickupText($fp); $tObj->fileClose($fp,'r'); // 出力 header("Content-Type:text/html"); echo($ret); return; ?>
以下が、Javascriptを含むHTMLの全文(test_help1.html)。比較的シンプルになっている。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache"> <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT"> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>Menu</title> <link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/fonts/fonts-min.css" /> <link rel="stylesheet" type="text/css" href="../scripts/lib/yui/build/container/assets/skins/sam/container.css" /> <script type="text/javascript" src="../scripts/lib/yui/build/yahoo-dom-event/yahoo-dom-event.js"></script> <script type="text/javascript" src="../scripts/lib/yui/build/connection/connection-min.js" ></script> <script type="text/javascript" src="../scripts/lib/yui/build/dragdrop/dragdrop-min.js" ></script> <script type="text/javascript" src="../scripts/lib/yui/build/container/container-min.js" ></script> <style type="text/css" id="defaultstyle"> #main { margin: 2px; padding: 3px; } .ez_error { /* red(エラー用) */ color:#ff0000; } #res { visibility: hidden; } </style> <script type="text/javascript"> DisplayHelp = function() { var Event = YAHOO.util.Event; var Dom = YAHOO.util.Dom; var Connect = YAHOO.util.Connect; var Panel = YAHOO.widget.Panel; var helpPanel; /* * メニューリンクをクリックしたときのハンドラ */ var helpClickHdlr = function(_evt){ Event.preventDefault(_evt); // メッセージのクリア Dom.get('msg').innerHTML = ''; Dom.get('helpDiv').innerHTML = ''; var _url = 'getHelp1.php'; var _arg ={ 'errId' : 'msg', 'resId' : 'helpDiv' }; helpCallback.argument = _arg; var _parm = 'fname=' + Dom.get('pagename').innerHTML; // ajaxで検証 YAHOO.util.Connect.asyncRequest('POST',_url, helpCallback, _parm); } /* * ヘルプ取得時のコールバック */ var helpCallback = { success : function(_obj) { var _resId = _obj.argument.resId; var _errId = _obj.argument.errId; // XHRの戻り値の取得(メニュー文字列) var _ret = _obj.responseText; // メニューの表示 if(_ret.length > 0){ //Panelのインスタンス化: helpPanel = new Panel("hpanel", { width:"320px", visible:true, draggable:true, close:true, constraintoviewport:true } ); helpPanel.setHeader("Help"); helpPanel.setBody(_ret); helpPanel.setFooter(Dom.get('pagename').innerHTML); // id=panel1のMarkupが存在しないので、 // renderingする場所(div)を指定 // div id=helpDivにappendされる。 helpPanel.render("helpDiv"); } else { // エラーのハンドル(皆さん適当に) Dom.get(_errId).innerHTML = 'メニューの取得に失敗しました.'; } }, failure : function(_obj) { var _errId = _obj.argument.errId; var _ret = 'ステータス: ' + _obj.status + 'ステータステキスト: ' + _obj.statusText + ' メニューの取得に失敗しました。'; // エラーのハンドル(皆さん適当に) Dom.get(_errId).innerHTML = _ret; } }; return{ init: function() { // ヘルプ画面のハンドラー Event.on('lnk1', 'click', helpClickHdlr); }, // initの終わり }; }(); //DOMが完全にloadされたら、サンプルを初期化する。 YAHOO.util.Event.onDOMReady( //DomReadyイベントで発火するハンドラ DisplayHelp.init, //ハンドラに渡すオブジェクト DisplayHelp, //ハンドラは、上記のオブジェクトのスコープをもつ。 true ); </script> </HEAD> <BODY class="yui-skin-sam"> <div id="pagename">test_help1.html</div> <br> <div id="container"> <p> 画面ヘルプのサンプルです。<br/> </p> <a id="lnk1" href="#" class="lnk">?</a> <div id="msg" class=".ez_error"></div> <div id="res"></div> <!-- ヘルプ表示のためのマークアップ --> <div id = 'helpDiv'></div> </div> </BODY> </HTML>