概要
各項目にソート機能を追加する
内容
各項目にソート機能を追加します。
Array#sort(comparetor)を利用しますが、ソート項目ごとに関数を書くのが嫌なので
evalを使ったメタプログラミングにして、DRYな実装にしてみました。
(comparator.js部)
comparator.js
var method_keys = ["TodoDateAsc", "TodoDateDesc", "SubjectAsc", "SubjectDesc", "SummaryAsc", "SummaryDesc", "EstimateAsc", "EstimateDesc", "StartAsc" , "StartDesc", "EndAsc", "EndDesc", "TotalAsc" , "TotalDesc"]; var attribute_keys = ["todo_date", "todo_date", "subject", "subject", "summary", "summary", "estimate", "estimate", "start", "start", "end", "end", "total" , "total"]; var large_ret_values = [1 , -1, 1, -1, 1 , -1, 1, -1, 1 , -1, 1, -1, 1 , -1,]; var less_ret_values = [-1 , 1, -1, 1, -1 , 1, -1, 1, -1 , 1, -1, 1, -1 , 1]; for (var i=0;i<method_keys.length;i++) { var func = (function () {/* function compareBy#{MethodKey}(one, other) { if (one.#{AttributeKey} < other.#{AttributeKey}) return #{LessValue}; if (one.#{AttributeKey} > other.#{AttributeKey}) return #{LargeValue}; return 0; } */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1]; func = func.replace("#{MethodKey}", method_keys[i]); func = func.replace(/#{AttributeKey}/g, attribute_keys[i]); func = func.replace(/#{LargeValue}/g, large_ret_values[i]); func = func.replace(/#{LessValue}/g, less_ret_values[i]); eval(func); }
studistory.html
<!doctype html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>studistory</title> <link rel="stylesheet" type="text/css" href="studistory.css" /> <script type="text/javascript" src="201308.js"></script> <script type="text/javascript" src="201309.js"></script> <script type="text/javascript" src="comparator.js"></script> <script type="text/javascript"> function search(sortKey, ascDesc) { ascDesc = ascDesc || "Asc"; enableMonths = ["201308", "201309"]; var tbody = document.getElementsByTagName("tbody")[0]; crearList(tbody); searchMonth = document.getElementById("month").value.replace("-", ""); if (!isValidMonths(searchMonth, enableMonths)) return; list = getList(searchMonth, sortKey, ascDesc); outputList(tbody, list); setMessage(searchMonth.slice(0,4) + "年" + searchMonth.slice(4,6) + "月" + "の検索実行が完了しました") } function crearList(tbody) { tbody.innerHTML = ''; } function isValidMonths(searchMonth, enableMonths) { if (enableMonths.indexOf(searchMonth) == -1) { setMessage("その日付の学習履歴は存在しません") return false; } return true; } function setMessage(message) { document.getElementById("message").innerText = message; } function getList(searchMonth, sortKey, ascDesc) { // ヒアドキュメントもどき const TEMPLATE = (function () {/* <tr id="#{id}"> <td id="tododate_#{id}">#{todo_date}</td> <td id="subject_#{id}">#{subject}</td> <td id="summary_#{id}">#{summary}</td> <td id="estimate_#{id}">#{estimate}</td> <td id="start_#{id}">#{start}</td> <td id="end_#{id}">#{end}</td> <td id="total_#{id}">#{total}</td> </tr> */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1]; var monthJsons = null; eval("monthJsons = eval(todos_" + searchMonth + ");"); comparator = eval("compareBy" + sortKey + ascDesc); monthJsons.sort(comparator); line_htmls = []; for (var i = 0;i < monthJsons.length; i++) { line = TEMPLATE; line = line.replace(/#{id}/g, monthJsons[i].id); line = line.replace("#{todo_date}", monthJsons[i].todo_date); line = line.replace("#{subject}", monthJsons[i].subject); line = line.replace("#{summary}", monthJsons[i].summary); line = line.replace("#{estimate}", monthJsons[i].estimate); line = line.replace("#{start}", monthJsons[i].start); line = line.replace("#{end}", monthJsons[i].end); line = line.replace("#{total}", monthJsons[i].total); line_htmls.push(line); } return line_htmls.join("\n"); } function outputList(tbody, list) { tbody.innerHTML = list; } </script> </head> <body> <header> <h1 id="title">studistory</h1> <p id="summary">学習履歴管理を行います</p> <p id="message" style="color:red;">検索を実行してください</p> </header> <section id="search"> <form name="studistoryform" id="studistoryform"> <p><input type="month" name="month" id="month" /></p> <p><input type="button" value="search" onclick="search('Start')"/></p> </form> </section> <section id="list"> <table id="list" border="1"> <thead> <tr> <th>todo date<span onclick="search('TodoDate')">↑</span> <span onclick="search('TodoDate', 'Desc')">↓</span></th> <th>subject<span onclick="search('Subject')">↑</span> <span onclick="search('Subject', 'Desc')">↓</span></th> <th>summary<span onclick="search('Summary')">↑</span> <span onclick="search('Summary', 'Desc')">↓</span></th> <th>estimate<span onclick="search('Estimate')">↑</span> <span onclick="search('Estimate', 'Desc')">↓</span></th> <th>start<span onclick="search('Start')">↑</span> <span onclick="search('Start', 'Desc')">↓</span></th> <th>end<span onclick="search('End')">↑</span> <span onclick="search('End', 'Desc')">↓</span></th> <th>total<span onclick="search('Total')">↑</span> <span onclick="search('Total', 'Desc')">↓</span></th> </tr> <tbody> </tbody> </thead> </table> </section> </body> </html>