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.