001 : // 002 : // WeeklyAllViewer 003 : // 004 : // Created by M.Miyazaki [2013.11.26] 005 : // Modified by M.Miyazaki [2014.01.16] - 実装の方針を転換(Ajaxの利用) 006 : // Modified by M.Miyazaki [2014.01.18] - 不具合の修正とキーワード欄増減対応 007 : // 008 : 009 : //================== 010 : // Settings 011 : //================== 012 : 013 : /** 014 : * 作業ログのファイル 015 : */ 016 : var WORKLOG_FILE = "log_sample.txt"; 017 : 018 : 019 : //=================== 020 : // Constants 021 : //=================== 022 : 023 : /** 024 : * 本文と見出しを表示する(showLogs()の第二引数向け) 025 : */ 026 : var VISIBLE_DETAILS = true; 027 : 028 : /** 029 : * 本文を表示せず、見出しのみ表示する(showLogs()の第二引数向け) 030 : */ 031 : var INVISIBLE_DETAILS = false; 032 : 033 : /** 034 : * リクエストの状態(一連の動作が完了した) 035 : */ 036 : var DONE = 4; 037 : 038 : /** 039 : * キーワード入力欄のIDの接頭辞 040 : */ 041 : var KEYWORD_PREFIX = "keyword"; 042 : 043 : 044 : //=================== 045 : // Variables 046 : //=================== 047 : 048 : /** 049 : * 作業ログの配列 050 : */ 051 : var workLogs = null; 052 : 053 : 054 : //====================== 055 : // Main Routine 056 : //====================== 057 : 058 : /** 059 : * 作業ログを吸い出して、見出しのみ一覧表示する。 060 : * 061 : * Created by M.Miyazaki [2014.01.15] 062 : */ 063 : function loadWorkLogs() 064 : { 065 : 066 : var handle = new XMLHttpRequest(); 067 : 068 : handle.open("GET", WORKLOG_FILE); 069 : 070 : handle.onreadystatechange = function() 071 : { 072 : if (handle.readyState == DONE) 073 : { 074 : workLogs = getWorkLogs(handle.responseText); 075 : showLogs(workLogs, INVISIBLE_DETAILS); 076 : } 077 : } 078 : 079 : handle.send(); 080 : 081 : return; 082 : } 083 : 084 : /** 085 : * 検索を行って結果を表示する。 086 : * 087 : * Created by M.Miyazaki [2013.11.27] 088 : * Modified by M.Miyazaki [2014.01.15] 089 : */ 090 : function searchWorkLogs() 091 : { 092 : if (workLogs == null) { return; } 093 : 094 : var keywords = getKeywords(); 095 : 096 : var resultLogs = search(workLogs, keywords); 097 : 098 : showLogs(resultLogs, VISIBLE_DETAILS); 099 : 100 : return; 101 : } 102 : 103 : 104 : //====================== 105 : // Sub Routines 106 : //====================== 107 : 108 : /** 109 : * 作業ログのテキストを配列で応答する。 110 : * 111 : * Created by M.Miyazaki [2013.11.27] 112 : * Modified by M.Miyazaki [2013.11.28] 113 : * 114 : * @param logTextString 作業ログのテキスト 115 : * @return 作業ログの配列 116 : */ 117 : function getWorkLogs(logTextString) 118 : { 119 : if (logTextString == null) { return null; } 120 : 121 : var logArray = logTextString.split(/(■No\.[0-9]+ - [0-9]+\.[0-9]+\.[0-9]+\([^\)]+\)[=]{10,})/); 122 : 123 : var workLogs = new Array(); 124 : 125 : var numberOfLogs = (logArray.length - 1) / 2; 126 : 127 : for (var index = 0; index < numberOfLogs; index++) 128 : { 129 : var logString = logArray[index*2 + 1] + "" + logArray[index*2 + 2]; 130 : workLogs[index] = new WorkLog(logString); 131 : } 132 : 133 : return workLogs; 134 : } 135 : 136 : /** 137 : * 検索キーワードの配列を応答する。 138 : * 139 : * Created by M.Miyazaki [2014.01.18] 140 : * 141 : * @return 検索キーワードの配列 142 : */ 143 : function getKeywords() 144 : { 145 : var keywordElement; 146 : var index = 0; 147 : var keywords = new Array(); 148 : 149 : while ((keywordElement = document.getElementById(KEYWORD_PREFIX + (index + 1))) != null) 150 : { 151 : keywords.push(keywordElement.value); 152 : index++; 153 : } 154 : 155 : return keywords; 156 : } 157 : 158 : /** 159 : * 検索条件で絞り込む。 160 : * 161 : * Created by M.Miyazaki [2013.11.27] 162 : * Modified by M.Miyazaki [2014.01.16] 163 : * 164 : * @param workLogs 検索対象となる作業ログの配列 165 : * @param keywords 検索キーワードの配列 166 : * @return 検索で絞り込んだ作業ログの配列 167 : */ 168 : function search(workLogs, keywords) 169 : { 170 : if (keywords.length == 0) { return workLogs; } 171 : 172 : var resultLogs = new Array(); 173 : var keywordString = keywords.shift(); 174 : 175 : if (keywordString != "") 176 : { 177 : var regularExpression = new RegExp(keywordString, "g"); 178 : 179 : for (var index = 0; index < workLogs.length; index++) 180 : { 181 : var wordArray = workLogs[index].getWorkLogText().match(regularExpression); 182 : 183 : if (wordArray != null) 184 : { 185 : resultLogs.push(workLogs[index]); 186 : } 187 : } 188 : } 189 : else 190 : { 191 : resultLogs = workLogs; 192 : } 193 : 194 : return search(resultLogs, keywords); 195 : } 196 : 197 : /** 198 : * 作業ログを一覧表示する。 199 : * 200 : * Created by M.Miyazaki [2013.11.27] 201 : * Modified by M.Miyazaki [2013.11.29] 202 : * Modified by M.Miyazaki [2014.01.16] 203 : * 204 : * @param resultLogs 表示する作業ログの配列 205 : * @param visibleStatus 作業内容を表示するか否か(VISIBLE_DETAIL or INVISIBLE_DETAIL) 206 : */ 207 : function showLogs(resultLogs, visibleStatus) 208 : { 209 : var htmlString = ""; 210 : 211 : htmlString += "<ul>\n"; 212 : 213 : for (var index = 0; index < resultLogs.length; index++) 214 : { 215 : var log = resultLogs[index]; 216 : htmlString += "<li>"; 217 : htmlString += "<a href='#WorkLogNo." + sanitize(log.getWorkNumber()) + "'>"; 218 : htmlString += "No." + sanitize(log.getWorkNumber()) + ":" + sanitize(log.getWorkTitle()); 219 : htmlString += "</a>"; 220 : 221 : if (visibleStatus == VISIBLE_DETAILS) { 222 : htmlString += "<pre>" + sanitize(log.getWorkDetail()).replace(/\r\n|\r|\n/g, "<br>") + "</pre>"; 223 : } 224 : 225 : htmlString += "</li>\n"; 226 : } 227 : 228 : htmlString += "</ul>\n"; 229 : 230 : document.getElementById("searchResult").innerHTML = htmlString; 231 : 232 : return; 233 : } 234 : 235 : /** 236 : * 文字列をサニタイズ(無害化)する。 237 : * 238 : * Created by M.Miyazaki [2014.01.16] 239 : * 240 : * @param inputString サニタイズ対象の文字列 241 : * @return サニタイズ後の文字列 242 : */ 243 : function sanitize(inputString) 244 : { 245 : return inputString.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">"); 246 : } 247 : 248 : /** 249 : * 検索キーワード入力欄を増やす。 250 : * 251 : * Created by M.Miyazaki [2014.01.18] 252 : */ 253 : function addKeywordField() 254 : { 255 : var index = 2; 256 : while (document.getElementById(KEYWORD_PREFIX + index) != null) { index++; } 257 : 258 : var deleteButton = document.getElementById("deleteKeywordFieldButton"); 259 : 260 : if (index == 2) 261 : { 262 : deleteButton.style.display = ""; // visible! 263 : } 264 : 265 : var newBreak = document.createElement("br"); 266 : newBreak.id = KEYWORD_PREFIX + "Br" + index; 267 : deleteButton.parentNode.insertBefore(newBreak, deleteButton); 268 : 269 : var newField = document.getElementById(KEYWORD_PREFIX + "1").cloneNode(); 270 : newField.id = KEYWORD_PREFIX + index; 271 : deleteButton.parentNode.insertBefore(newField, deleteButton); 272 : 273 : return; 274 : } 275 : 276 : /** 277 : * 検索キーワード入力欄を減らす。 278 : * 279 : * Created by M.Miyazaki [2014.01.18] 280 : */ 281 : function deleteKeywordField() 282 : { 283 : var index = 2; 284 : while (document.getElementById(KEYWORD_PREFIX + index) != null) { index++; } 285 : 286 : index--; 287 : 288 : if (index == 1) { return; } 289 : if (index == 2) 290 : { 291 : document.getElementById("deleteKeywordFieldButton").style.display = "none"; // invisible! 292 : } 293 : 294 : var oldBreak = document.getElementById(KEYWORD_PREFIX + "Br" + index); 295 : oldBreak.parentNode.removeChild(oldBreak); 296 : 297 : var oldField = document.getElementById(KEYWORD_PREFIX + index); 298 : oldField.parentNode.removeChild(oldField); 299 : 300 : return; 301 : } 302 : 303 : 304 : //================= 305 : // Objects 306 : //================= 307 : 308 : /** 309 : * 作業ログのオブジェクト。 310 : * 311 : * Created by M.Miyazaki [2013.11.27] 312 : * Modified by M.Miyazaki [2013.11.28] 313 : * 314 : * @param logText 原本データ(作業ログ) 315 : */ 316 : function WorkLog(logText) 317 : { 318 : //===== Properties ===== 319 : 320 : /** 321 : * 作業ナンバー 322 : */ 323 : this.workNumber = null; 324 : 325 : /** 326 : * 日付 327 : */ 328 : this.workDate = null; 329 : 330 : /** 331 : * 作業タイトル 332 : */ 333 : this.workTitle = null; 334 : 335 : /** 336 : * 作業内容 337 : */ 338 : this.workDetail = null; 339 : 340 : /** 341 : * 原本データ(作業ログ) 342 : */ 343 : this.workLogText = logText; 344 : 345 : 346 : //===== Methods ===== 347 : 348 : /** 349 : * 原本データに含まれる各プロパティの値を解析する。 350 : */ 351 : this.parse = function() 352 : { 353 : var regularExpression = /^■No\.([0-9]+) - ([0-9]+)\.([0-9]+)\.([0-9]+)\([^\)]+\)[=]{10,}(?:\r\n|\n){2}【([^】]*)】(?:\r\n|\n)([\d\D]*)$/; 354 : 355 : var resultArray = this.workLogText.match(regularExpression); 356 : if (resultArray == null) return; 357 : 358 : // 作業ナンバー 359 : this.workNumber = resultArray[1]; 360 : 361 : // 日付 362 : var year = resultArray[2]; 363 : var month = resultArray[3]; 364 : var day = resultArray[4]; 365 : this.workDate = new Date(year, month - 1, day); 366 : 367 : // 作業タイトル 368 : this.workTitle = resultArray[5]; 369 : 370 : // 作業内容 371 : this.workDetail = resultArray[6].trim(); 372 : 373 : return; 374 : } 375 : 376 : 377 : //===== Accessor ===== 378 : 379 : /** 380 : * 作業ナンバーを応答する。 381 : * 382 : * @return 作業ナンバー 383 : */ 384 : this.getWorkNumber = function() 385 : { 386 : if (this.workNumber == null) this.parse(); 387 : 388 : return this.workNumber; 389 : } 390 : 391 : /** 392 : * 日付を応答する。 393 : * 394 : * @return 日付 395 : */ 396 : this.getWorkDate = function() 397 : { 398 : if (this.workDate == null) this.parse(); 399 : 400 : return this.workDate; 401 : } 402 : 403 : /** 404 : * 作業タイトルを応答する。 405 : * 406 : * @return 作業タイトル 407 : */ 408 : this.getWorkTitle = function() 409 : { 410 : if (this.workTitle == null) this.parse(); 411 : 412 : return this.workTitle; 413 : } 414 : 415 : /** 416 : * 作業内容を応答する。 417 : * 418 : * @return 作業内容 419 : */ 420 : this.getWorkDetail = function() 421 : { 422 : if (this.workDetail == null) this.parse(); 423 : 424 : return this.workDetail; 425 : } 426 : 427 : /** 428 : * 原本データ(作業ログ)を応答する。 429 : * 430 : * @return 作業内容 431 : */ 432 : this.getWorkLogText = function() 433 : { 434 : return this.workLogText; 435 : } 436 : 437 : } 438 : 439 : 440 : //==================== 441 : // Extensions 442 : //==================== 443 : 444 : /** 445 : * 文字列にtrimメソッドを追加する。 446 : * 447 : * Quoted from https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/trim 448 : */ 449 : if (!String.prototype.trim) 450 : { 451 : String.prototype.trim = function() 452 : { 453 : return this.replace(/^\s+|\s+$/g, ""); 454 : } 455 : } 456 : 457 : /** 458 : * 非同期通信用オブジェクトを設定する。(Windowsへの対応) 459 : * 460 : * Quoted from http://itpro.nikkeibp.co.jp/article/COLUMN/20070613/274683/ 461 : */ 462 : if (window.ActiveXObject) 463 : { 464 : window.XMLHttpRequest = function() 465 : { 466 : try 467 : { 468 : return (new ActiveXObject("Microsoft.XMLHTTP")); 469 : } 470 : catch (ignore) {} 471 : 472 : return null; 473 : } 474 : } 475 :
This document was generated by NanigashiBiyori on 2014/01/19 at 01:18:58.