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, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
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.