Yahoo! UI を使った表示画面のソースコードを少し解説します

  • 21,36,51行目の<div>はダイアログ用のフォームです。通常のHTMLのフォームからsubmitボタンを削除しただけです。
  • 81〜95行目はテーブルに表示するJSON形式のデータ を作成する部分です。
  • 98〜103行目は上で作った表にイベントハンドラーを定義する部分です。
  • 105行目からは YUIコンポーネントの作成コードです。コンポーネントの大きさやボタン等の文字を定義しています。
    • 106〜123行目は テーブルの作成
    • 134〜162行目は ダイアログの作成
  • 179〜196行目はツールチップのデータ取り込みと、ツールチップの作成Callback関数。サーバーから表示用文字列が送られてきた際に実行されます。文字列を受け取り、ツールチップを表示しています。
  • 205〜220行目はツールチップ表示のイベントハンドラー。まだツールチップの表示文字列が取り込まれていなければ asyncRequest() を使ってサーバーに文字列のリクエストを送っています。
  • 222〜235行目は「感謝」などのダイアログ表示のイベントハンドラー。hiddenタグの値を書き換え、ダイアログを表示しています。
  • 240行目はテーブル表示エリア

こんな感じで、Yahoo! UI は案外かんたんに使えます :-)

     1	<style type="text/css">
     2	span.popup_base  {
     3	  color: #00f;
     4	}
     5	div.info_sw {
     6	  margin: 0 0 10px 10px;
     7	}
     8	.info_sw input {
     9	  margin: 0 5px 0 20px;
    10	}
    11	</style>
    12	
    13	<div class="info_sw">
    14	<input type="radio" name="info" checked /><span>新着情報</span>
    15	<input type="radio" name="info"/><span>検索結果</span>
    16	<input type="radio" name="info"/><span>履歴情報</span>
    17	<input type="radio" name="info"/><span>人気翻訳情報</span>
    18	<input type="radio" name="info"/><span>人気未翻訳情報</span>
    19	</div>
    20	
    21	<div id="reqDialog">
    22	  <div class="hd">翻訳リクエスト !!</div>
    23	  <div class="bd">
    24	    <form name="dlgForm" method="POST" action="/article/request_create">
    25	      <p><label>ニックネーム(オプション)</label>
    26		<input id="req_nickname" name="nickname" size="10" type="text" value="<%=@user.nickname%>" /></p>
    27	      
    28	      <p><label>メッセージ(オプション)</label>
    29		<input id="req_comment" name="comment" size="30" type="text" value="" /></p>
    30	      
    31	      <input id="req_article_id" name="article_id" type="hidden" value="1" />
    32	    </form>
    33	  </div>
    34	</div>
    35	
    36	<div id="apprDialog">
    37	  <div class="hd">感謝 ♪♪</div>
    38	  <div class="bd">
    39	    <form name="dlgForm" method="POST" action="/article/appreciate_create">
    40	      <p><label>ニックネーム(オプション)</label>
    41		<input id="appr_nickname" name="nickname" size="10" type="text" value="<%=@user.nickname%>" /></p>
    42	      
    43	      <p><label>メッセージ(オプション)</label>
    44		<input id="appr_comment" name="comment" size="30" type="text" value="" /></p>
    45	      
    46	      <input id="appr_translation_id" name="translation_id" type="hidden" value="1" />
    47	    </form>
    48	  </div>
    49	</div>
    50	
    51	<div id="transDialog">
    52	  <div class="hd">翻訳の登録</div>
    53	  <div class="bd">
    54	    <form name="dlgForm" action="/article/translate_create" method="post">
    55	      <p><label for="translation_url">翻訳形態(必須)</label>
    56		<select id="translation_kind" name="translation[kind]">
    57		  <option value="1">概訳</option>
    58		  <option value="2">意訳</option>
    59		  <option value="3">全訳</option></select></p>
    60	
    61	      <p><label for="translation_url">翻訳ページのURL(必須)</label>
    62		<input id="translation_url" name="translation[url]" size="40" type="text" /></p>
    63	
    64	      <p><label>ニックネーム(オプション)</label>
    65		<input id="nickname" name="nickname" size="10" type="text" value="<%=@user.nickname%>" /></p>
    66	      
    67	      <p><label>BlogのURL(オプション)</label>
    68		<input id="blog" name="blog" size="40" type="text" value="<%=@user.blog%>" /></p>
    69	      
    70	      <p><label for="article_title">メッセージ(オプション)</label>
    71		<input id="translation_comment" name="translation[comment]" size="30" type="text" /></p>
    72	      
    73	      <input id="trans_article_id" name="article_id" type="hidden" value="1" />
    74	    </form>
    75	  </div>
    76	</div>
    77	
    78	
    79	<script type="text/javascript">
    80	
    81	YAHOO.example.Data = {
    82	    bookorders: [
    83	<% for a in @articles %>
    84	   <% t = Translation.optimal_trans(a.translations) %>
    85	    {
    86	    req:'<span class="popup_base" onClick="popup_request(<%=a.id%>);" id="req<%=a.id%>" onmouseover="showReq(<%=a.id%>);"> &#8984; <%=star_mark(a.requests.size)%> </span>',
    87	    appr:'<% if t %><span class="popup_base" onClick="popup_appreciate(<%=t.id%>);" id="appr<%=t.id%>"> &#8984; <%=star_mark(t.appreciations.size)%> </span><% end %>',
    88	    trans:'<span class="popup_base" onClick="popup_translation(<%=a.id%>);">&#8984;</span> ' +
    89	       ' <% if t %><a href="<%=t.url%>"><%=translation_status(t.kind.to_i)%></a> <% end %>',
    90	    title:'<a href="<%= t ? t.url : a.link%>" id="title<%=a.id%>"><%=h a.title %></a>',
    91	    site:'<a href="<%=a.link%>"><%=h a.source %></a>',
    92	    date:'<%=short_date a.dc_date %>'
    93	    },
    94	<% end %>
    95	    ]
    96	}
    97	
    98	<% for a in @articles %>
    99	    <% t = Translation.optimal_trans(a.translations) %>
   100	    YAHOO.util.Event.addListener("req<%=a.id%>", "mouseover", showReq, "<%=a.id%>"); 
   101	    <% if t %>YAHOO.util.Event.addListener("appr<%=t.id%>", "mouseover", showAppr, "<%=t.id%>");<% end %>
   102	    YAHOO.util.Event.addListener("title<%=a.id%>", "mouseover", showDesc, "<%=a.id%>"); 
   103	<% end %>
   104	
   105	YAHOO.util.Event.addListener(window, "load", function() {
   106	    YAHOO.example.Basic = new function() {
   107	        var myColumnDefs = [
   108	            {key:"req", label:"訳して!", sortable:true, resizeable:true},
   109	            {key:"appr", label:"感謝", sortable:true, resizeable:true},
   110	            {key:"trans", label:"翻訳", sortable:true, resizeable:true},
   111	            {key:"title", label:"タイトル",  sortable:true, resizeable:true},
   112	            {key:"site", label:"サイト", sortable:true, resizeable:true},
   113	            {key:"date", label:"日付", sortable:true, resizeable:true}
   114	        ];
   115	
   116	        this.myDataSource = new YAHOO.util.DataSource(YAHOO.example.Data.bookorders);
   117	        this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
   118	        this.myDataSource.responseSchema = {
   119	            fields: ["trans","req","appr","title","site","date"]
   120	        };
   121	
   122	        this.myDataTable = new YAHOO.widget.DataTable("list_table", myColumnDefs,
   123	                this.myDataSource);
   124	
   125	        YAHOO.namespace("example.container");
   126	
   127	        var handleCancel = function() {
   128	            this.cancel();
   129	         };
   130	         var handleSubmit = function() {
   131	             this.submit();
   132	         };
   133	
   134	        YAHOO.example.container.dialogReq = new YAHOO.widget.Dialog("reqDialog",
   135	           { width : "300px",
   136	             modal : true,
   137	             visible : false, 
   138	             constraintoviewport : true,
   139	             buttons : [ { text:"訳して!", handler:handleSubmit, isDefault:true },
   140	                         { text:"Cancel", handler:handleCancel } ],
   141	             postmethod : "form"} );
   142		YAHOO.example.container.dialogReq.render();
   143	
   144	        YAHOO.example.container.dialogAppr = new YAHOO.widget.Dialog("apprDialog",
   145	           { width : "300px",
   146	             modal : true,
   147	             visible : false, 
   148	             constraintoviewport : true,
   149	             buttons : [ { text:"ありがとう!", handler:handleSubmit, isDefault:true },
   150	                         { text:"Cancel", handler:handleCancel } ],
   151	             postmethod : "form"} );
   152		YAHOO.example.container.dialogAppr.render();
   153	
   154	        YAHOO.example.container.dialogTrans = new YAHOO.widget.Dialog("transDialog",
   155	           { width : "400px",
   156	             modal : true,
   157	             visible : false, 
   158	             constraintoviewport : true,
   159	             buttons : [ { text:"登録 ", handler:handleSubmit, isDefault:true },
   160	                         { text:"Cancel", handler:handleCancel } ],
   161	             postmethod : "form"} );
   162		YAHOO.example.container.dialogTrans.render();
   163	
   164	    };
   165	});
   166	
   167	var tooltipHash = [];
   168	
   169	function makeTooptipAndShow(o, prefix, title) {
   170	    var m = o.responseText.match(/^([0-9]+);(.*)$/);
   171	    if (!m)  return;
   172	    var t = new YAHOO.widget.Tooltip(prefix + "Tooltip" + m[1], 
   173	               {context: prefix + m[1],  text: "<b>" + title + "</b><br/>" + m[2]});
   174	    tooltipHash[prefix + m[1]] = t;
   175	    t.onContextMouseMove(o.argument, t);
   176	    t.doShow(o.argument);
   177	}
   178	
   179	var callbackReq = {
   180	    success: function(o){ 
   181	        if (o.responseText !== undefined)  makeTooptipAndShow(o, "req", "翻訳リクエスト");
   182	    },
   183	    argument: []
   184	}; 	
   185	var callbackAppr = {
   186	    success: function(o){ 
   187	        if (o.responseText !== undefined)  makeTooptipAndShow(o, "appr", "感謝の言葉");
   188	    },
   189	    argument: []
   190	}; 	
   191	var callbackDesc = {
   192	    success: function(o){ 
   193	        if (o.responseText !== undefined)  makeTooptipAndShow(o, "title", "概要");
   194	    },
   195	    argument: []
   196	}; 	
   197	
   198	
   199	function clone_object(src) {
   200	    var dst = new Object;
   201	    for (var p in src)  dst[p] = src[p];
   202	    return dst;
   203	}
   204	
   205	function showReq(e, id) {
   206	    if (tooltipHash["req" + id]) return;
   207	    callbackReq.argument = clone_object(e);
   208	    var request = YAHOO.util.Connect.asyncRequest('GET', '/article/get_request/' + id, callbackReq); }
   209	
   210	function showAppr(e, id) {
   211	    if (tooltipHash["appr" + id]) return;
   212	    callbackAppr.argument = clone_object(e);
   213	    var request = YAHOO.util.Connect.asyncRequest('GET', '/article/get_appreciate/' + id, callbackAppr); 
   214	}
   215	
   216	function showDesc(e, id) {
   217	    if (tooltipHash["title" + id]) return;
   218	    callbackDesc.argument = clone_object(e);
   219	    var request = YAHOO.util.Connect.asyncRequest('GET', '/article/get_article/' + id, callbackDesc);
   220	}
   221	
   222	function popup_request(id) {
   223	    document.getElementById("req_article_id").value = id;
   224	    YAHOO.example.container.dialogReq.show();
   225	}
   226	
   227	function popup_appreciate(id) {
   228	    document.getElementById("appr_translation_id").value = id;
   229	    YAHOO.example.container.dialogAppr.show();
   230	}
   231	
   232	function popup_translation(id) {
   233	    document.getElementById("trans_article_id").value = id;
   234	    YAHOO.example.container.dialogTrans.show();
   235	}
   236	
   237	
   238	</script>
   239	
   240	<div id="list_table"></div>
   241	
   242	<br />
   243	<br />
   244	
   245	<%= link_to '情報登録', :action => 'new' %>