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 : //  Modified by M.Miyazaki [2014.05.31] - 作業タイトル押下によるトグル表示、ボタン配置変更、検索結果のリスト表示対応
008 : //  Modified by M.Miyazaki [2014.06.01] - 作業ナンバーのリンク化、否定検索対応
009 : //
010 : 
011 : //==================
012 : //     Settings
013 : //==================
014 : 
015 : /**
016 :  * 作業ログのファイル
017 :  */
018 : var WORKLOG_FILE = "log_sample.txt";
019 : 
020 : 
021 : //===================
022 : //     Constants
023 : //===================
024 : 
025 : /**
026 :  * 本文と見出しを表示する
027 :  */
028 : var VISIBLE_DETAIL = 1;
029 : 
030 : /**
031 :  * 本文を表示せず、見出しのみ表示する
032 :  */
033 : var INVISIBLE_DETAIL = 2;
034 : 
035 : /**
036 :  * 本文も見出しも表示しない(非表示の画面要素)
037 :  */
038 : var INVISIBLE_LOG = 3;
039 : 
040 : /**
041 :  * リクエストの状態(一連の動作が完了した)
042 :  * 4で固定。
043 :  */
044 : var DONE = 4;
045 : 
046 : /**
047 :  * キーワード入力欄のIDの接頭辞
048 :  */
049 : var KEYWORD_PREFIX = "keyword";
050 : 
051 : /**
052 :  * preタグのID接頭辞
053 :  */
054 : var PRE_PREFIX = "pre";
055 : 
056 : /**
057 :  * liタグのID接頭辞
058 :  */
059 : var LI_PREFIX = "li";
060 : 
061 : 
062 : 
063 : //===================
064 : //     Variables
065 : //===================
066 : 
067 : /**
068 :  * 作業ログの配列
069 :  */
070 : var workLogs = null;
071 : 
072 : 
073 : //======================
074 : //     Main Routine
075 : //======================
076 : 
077 : /**
078 :  * 作業ログを吸い出して、見出しのみ一覧表示する。
079 :  *
080 :  * Created by M.Miyazaki [2014.01.15]
081 :  */
082 : function loadWorkLogs()
083 : {
084 :     var handle = new XMLHttpRequest();
085 :     
086 :     handle.open("GET", WORKLOG_FILE);
087 :     
088 :     handle.onreadystatechange = function()
089 :     {
090 :         if (handle.readyState == DONE)
091 :         {
092 :             workLogs = getWorkLogs(handle.responseText);
093 :             showLogs(workLogs, INVISIBLE_DETAIL);
094 :         }
095 :     }
096 :     
097 :     handle.send();
098 :     
099 :     return;
100 : }
101 : 
102 : /**
103 :  * 検索を行って結果を表示する。
104 :  * 
105 :  * Created by M.Miyazaki [2013.11.27]
106 :  * Modified by M.Miyazaki [2014.01.15]
107 :  * Modified by M.Miyazaki [2014.06.01]
108 :  */
109 : function searchWorkLogs()
110 : {
111 :     searchWorkLogsWithVisibleStatus(VISIBLE_DETAIL);
112 :     
113 :     return;
114 : }
115 : 
116 : /**
117 :  * 検索を行って結果のリストを表示する。
118 :  * 
119 :  * Created by M.Miyazaki [2014.06.01]
120 :  */
121 : function searchWorkLogsList()
122 : {
123 :     searchWorkLogsWithVisibleStatus(INVISIBLE_DETAIL);
124 :     
125 :     return;
126 : }
127 : 
128 : 
129 : //======================
130 : //     Sub Routines
131 : //======================
132 : 
133 : /**
134 :  * 検索を行って結果を表示する。
135 :  * 
136 :  * Created by M.Miyazaki [2014.06.01]
137 :  *
138 :  * @param visibleStatus 作業内容を表示するか否か
139 :  */
140 : function searchWorkLogsWithVisibleStatus(visibleStatus)
141 : {
142 :     if (workLogs == null) { return; }
143 :     
144 :     resetVisibleStatus(workLogs);
145 :     
146 :     var keywords = getKeywords();
147 :     
148 :     var resultLogs = search(workLogs, keywords);
149 :     
150 :     showLogs(resultLogs, visibleStatus);
151 :     
152 :     return;
153 : }
154 : 
155 : /**
156 :  * 作業ログのテキストを配列で応答する。
157 :  *
158 :  * Created by M.Miyazaki [2013.11.27]
159 :  * Modified by M.Miyazaki [2013.11.28]
160 :  *
161 :  * @param logTextString 作業ログのテキスト
162 :  * @return 作業ログの配列
163 :  */
164 : function getWorkLogs(logTextString)
165 : {
166 :     if (logTextString == null) { return null; }
167 :     
168 :     var logArray = logTextString.split(/(■No\.[0-9]+ - [0-9]+\.[0-9]+\.[0-9]+\([^\)]+\)[=]{10,})/);
169 :     
170 :     var workLogs = new Array();
171 :     
172 :     var numberOfLogs = (logArray.length - 1) / 2;
173 :     
174 :     for (var index = 0; index < numberOfLogs; index++)
175 :     {
176 :         var logString = logArray[index*2 + 1] + "" + logArray[index*2 + 2];
177 :         workLogs[index] = new WorkLog(logString);
178 :     }
179 :     
180 :     return workLogs;
181 : }
182 : 
183 : /**
184 :  * 検索キーワードの配列を応答する。
185 :  *
186 :  * Created by M.Miyazaki [2014.01.18]
187 :  *
188 :  * @return 検索キーワードの配列
189 :  */
190 : function getKeywords()
191 : {
192 :     var keywordElement;
193 :     var index = 0;
194 :     var keywords = new Array();
195 :     
196 :     while ((keywordElement = document.getElementById(KEYWORD_PREFIX + (index + 1))) != null)
197 :     {
198 :         var keywordText = keywordElement.value;
199 :         var isNegative = ("negativeKeywordField" == keywordElement.className) ? true : false;
200 :         var keyword = new Keyword(keywordText, isNegative);
201 :         
202 :         keywords.push(keyword);
203 :         index++;
204 :     }
205 :     
206 :     return keywords;
207 : }
208 : 
209 : /**
210 :  * 作業ログの可視性をリセットする。
211 :  * 
212 :  * Created by M.Miyazaki [2014.06.01]
213 :  *
214 :  * @param workLogs 可視性をリセットする作業ログの配列
215 :  */
216 : function resetVisibleStatus(workLogs)
217 : {
218 :     for (var index = 0; index < workLogs.length; index++)
219 :     {
220 :         workLogs[index].isVisible = true;
221 :     }
222 :     
223 :     return;
224 : }
225 : 
226 : /**
227 :  * 検索条件で絞り込む。
228 :  * 
229 :  * Created by M.Miyazaki [2013.11.27]
230 :  * Modified by M.Miyazaki [2014.01.16]
231 :  * Modified by M.Miyazaki [2014.06.01] - 否定検索処理追加
232 :  *
233 :  * @param workLogs 検索対象となる作業ログの配列
234 :  * @param keywords 検索キーワードの配列
235 :  * @return 検索で絞り込んだ作業ログの配列
236 :  */
237 : function search(workLogs, keywords)
238 : {
239 :     if (keywords.length == 0) { return workLogs; }
240 :     
241 :     var resultLogs = new Array();
242 :     var keyword = keywords.shift();
243 :     
244 :     var keywordText = keyword.getKeywordText();
245 :     var isNegative = keyword.isNegative();
246 :     
247 :     if (keywordText != "")
248 :     {
249 :         var regularExpression = new RegExp(keywordText, "g");
250 :         
251 :         for (var index = 0; index < workLogs.length; index++)
252 :         {
253 :             if (true == workLogs[index].isVisible)
254 :             {
255 :                 var wordArray = workLogs[index].getWorkLogText().match(regularExpression);
256 :                 
257 :                 if (isNegative == false)
258 :                 {
259 :                     workLogs[index].isVisible = ((wordArray != null) ? true : false);
260 :                 }
261 :                 else
262 :                 {
263 :                     workLogs[index].isVisible = ((wordArray == null) ? true : false);
264 :                 }
265 :             }
266 :             
267 :             resultLogs.push(workLogs[index]);
268 :         }
269 :     }
270 :     else
271 :     {
272 :         resultLogs = workLogs;
273 :     }
274 :     
275 :     return search(resultLogs, keywords);
276 : }
277 : 
278 : /**
279 :  * 作業ログを一覧表示する。
280 :  * 
281 :  * Created by M.Miyazaki [2013.11.27]
282 :  * Modified by M.Miyazaki [2013.11.29]
283 :  * Modified by M.Miyazaki [2014.01.16]
284 :  * Modified by M.Miyazaki [2014.05.31]
285 :  * Modified by M.Miyazaki [2014.06.01]
286 :  *
287 :  * @param resultLogs 表示する作業ログの配列
288 :  * @param visibleStatus 作業内容を表示するか否か(VISIBLE_DETAIL or INVISIBLE_DETAIL)
289 :  */
290 : function showLogs(resultLogs, visibleStatus)
291 : {
292 :     if (visibleStatus == INVISIBLE_LOG)
293 :     {
294 :         // INVISIBLE_LOG is unexpected visibleStatus!
295 :         visibleStatus = VISIBLE_DETAIL;
296 :     }
297 :     
298 :     var htmlString = "";
299 :     
300 :     htmlString += "<ul>\n";
301 :     
302 :     for (var index = 0; index < resultLogs.length; index++)
303 :     {
304 :         var log = resultLogs[index];
305 :         var workLogId = 'WorkLogNo.' + sanitize(log.getWorkNumber());
306 :         
307 :         if (log.isVisible == true)
308 :         {
309 :             htmlString += "<li id='" + LI_PREFIX + workLogId + "' style='display:;'>";
310 :         }
311 :         else
312 :         {
313 :             htmlString += "<li id='" + LI_PREFIX + workLogId + "' style='display:none;'>";
314 :         }
315 :         
316 :         htmlString += "<a name='" + workLogId + "' onclick='toggleLog(\"" + workLogId + "\");'>";
317 :         htmlString += "No." + sanitize(log.getWorkNumber()) + ":" + sanitize(log.getWorkTitle());
318 :         htmlString += "</a>";
319 :         
320 :         if (visibleStatus == VISIBLE_DETAIL)
321 :         {
322 :             htmlString += "<pre id='" + PRE_PREFIX + workLogId + "' style='display:;'>";
323 :         }
324 :         else
325 :         {
326 :             htmlString += "<pre id='" + PRE_PREFIX + workLogId + "' style='display:none;'>";
327 :         }
328 :         
329 :         var workDetail = sanitize(log.getWorkDetail()).replace(/\r\n|\r|\n/g, "<br>");
330 :         workDetail = convertNumberToLink(workDetail);
331 :         
332 :         htmlString += workDetail;
333 :         htmlString += "</pre>";
334 :         htmlString += "</li>\n";
335 :     }
336 :     
337 :     htmlString += "</ul>\n";
338 :     
339 :     document.getElementById("searchResult").innerHTML = htmlString;
340 :     
341 :     return;
342 : }
343 : 
344 : /**
345 :  *
346 :  * 作業ログの表示形式(タイトルのみor詳細)をトグルする。
347 :  * 
348 :  * Created by M.Miyazaki [2014.05.31]
349 :  * 
350 :  * @param workLogId トグル対象の作業ログのID
351 :  */
352 : function toggleLog(workLogId)
353 : {
354 :     var isVisible = ("" == document.getElementById(PRE_PREFIX + workLogId).style.display);
355 :     var visibleStatus = isVisible ? INVISIBLE_DETAIL : VISIBLE_DETAIL;
356 :     
357 :     setVisibleStatus(workLogId, visibleStatus);
358 :     
359 :     return;
360 : }
361 : 
362 : /**
363 :  *
364 :  * 作業ログの表示形式(タイトルのみor詳細or非表示)を設定する。
365 :  * 
366 :  * Created by M.Miyazaki [2014.05.31]
367 :  * Modified by M.Miyazaki [2014.06.01]
368 :  * 
369 :  * @param workLogId 対象の作業ログのID
370 :  * @param visibleStatus 作業ログの表示形式(VISIBLE_DETAIL or INVISIBLE_DETAIL or INVISIBLE_LOG)
371 :  */
372 : function setVisibleStatus(workLogId, visibleStatus)
373 : {
374 :     if (visibleStatus == VISIBLE_DETAIL)
375 :     {
376 :         document.getElementById(LI_PREFIX + workLogId).style.display = "";
377 :         document.getElementById(PRE_PREFIX + workLogId).style.display = "";
378 :     }
379 :     else if (visibleStatus == INVISIBLE_DETAIL)
380 :     {
381 :         document.getElementById(LI_PREFIX + workLogId).style.display = "";
382 :         document.getElementById(PRE_PREFIX + workLogId).style.display = "none";
383 :     }
384 :     else if (visibleStatus == INVISIBLE_LOG)
385 :     {
386 :         document.getElementById(LI_PREFIX + workLogId).style.display = "none";
387 :     }
388 :     else
389 :     {
390 :         // Unexpected visibleStatus...
391 :     }
392 :     
393 :     return;
394 : }
395 : 
396 : /**
397 :  * 文字列をサニタイズ(無害化)する。
398 :  *
399 :  * Created by M.Miyazaki [2014.01.16]
400 :  *
401 :  * @param inputString サニタイズ対象の文字列
402 :  * @return サニタイズ後の文字列
403 :  */
404 : function sanitize(inputString)
405 : {
406 :     if (null == inputString) { return ""; }
407 :     
408 :     return inputString.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
409 : }
410 : 
411 : /**
412 :  * 作業ログのナンバリング「No.XXX」をリンク化する。
413 :  *
414 :  * Created by M.Miyazaki [2014.06.01]
415 :  *
416 :  * @param inputString リンク化対象の文字列
417 :  * @return リンク化した文字列
418 :  */
419 : function convertNumberToLink(inputString)
420 : {
421 :     if (null == inputString) { return ""; }
422 :     
423 :     var regularExpression = new RegExp("(No\.[0-9]+)", "g");
424 :     var replacement = "<a href='#WorkLog$1' onclick='setVisibleStatus(\"WorkLog$1\", VISIBLE_DETAIL);'>$1</a>";
425 :     var outputString = inputString.replace(regularExpression, replacement);
426 :     
427 :     return outputString;
428 : }
429 : 
430 : /**
431 :  * キーワード種別(肯定or否定)をトグルする。
432 :  *
433 :  * Created by M.Miyazaki [2014.06.01]
434 :  *
435 :  * @param keywordId 種別変更対象のキーワード欄のID
436 :  * @return リンク化した文字列
437 :  */
438 : function toggleKeywordType(keywordId)
439 : {
440 :     var keywordField = document.getElementById(keywordId);
441 :     
442 :     if ("negativeKeywordField" == keywordField.className)
443 :     {
444 :         keywordField.className = "keywordField";
445 :     }
446 :     else
447 :     {
448 :         keywordField.className = "negativeKeywordField";
449 :     }
450 :     
451 :     return;
452 : }
453 : 
454 : /**
455 :  * 検索キーワード入力欄を増やす。
456 :  *
457 :  * Created by M.Miyazaki [2014.01.18]
458 :  * Modified by M.Miyazaki [2014.05.20]
459 :  * Modified by M.Miyazaki [2014.05.31]
460 :  * Modified by M.Miyazaki [2014.06.01]
461 :  */
462 : function addKeywordField()
463 : {
464 :     var index = 2;
465 :     while (document.getElementById(KEYWORD_PREFIX + index) != null) { index++; }
466 :     
467 :     //if (index == 2)
468 :     //{
469 :     //    document.getElementById("deleteKeywordFieldButton").style.display = "";   // visible!
470 :     //}
471 :     
472 :     var bottomOfKeywords = document.getElementById("bottomOfKeywords");
473 :     
474 :     var newBreak = document.createElement("br");
475 :     newBreak.id = KEYWORD_PREFIX + "Br" + index;
476 :     bottomOfKeywords.parentNode.insertBefore(newBreak, bottomOfKeywords);
477 :     
478 :     var newField = document.getElementById(KEYWORD_PREFIX + "1").cloneNode();
479 :     newField.id = KEYWORD_PREFIX + index;
480 :     newField.ondblclick = new Function("toggleKeywordType('" + KEYWORD_PREFIX + index + "');");
481 :     bottomOfKeywords.parentNode.insertBefore(newField, bottomOfKeywords);
482 :     
483 :     // Initialize textfield
484 :     newField.value = "";
485 :     newField.className = "keywordField";
486 :     
487 :     return;
488 : }
489 : 
490 : /**
491 :  * 検索キーワード入力欄を減らす。
492 :  *
493 :  * Created by M.Miyazaki [2014.01.18]
494 :  * Modified by M.Miyazaki [2014.05.31]
495 :  */
496 : function deleteKeywordField()
497 : {
498 :     var index = 2;
499 :     while (document.getElementById(KEYWORD_PREFIX + index) != null) { index++; }
500 :     
501 :     index--;
502 :     
503 :     if (index == 1) { return; }
504 :     //if (index == 2)
505 :     //{
506 :     //    document.getElementById("deleteKeywordFieldButton").style.display = "none";   // invisible!
507 :     //}
508 :     
509 :     var oldBreak = document.getElementById(KEYWORD_PREFIX + "Br" + index);
510 :     oldBreak.parentNode.removeChild(oldBreak);
511 :     
512 :     var oldField = document.getElementById(KEYWORD_PREFIX + index);
513 :     oldField.parentNode.removeChild(oldField);
514 :     
515 :     return;
516 : }
517 : 
518 : 
519 : //=================
520 : //     Objects
521 : //=================
522 : 
523 : /**
524 :  * 作業ログのオブジェクト。
525 :  * 
526 :  * Created by M.Miyazaki [2013.11.27]
527 :  * Modified by M.Miyazaki [2013.11.28]
528 :  * Modified by M.Miyazaki [2014.06.01]
529 :  *
530 :  * @param logText 原本データ(作業ログ)
531 :  */
532 : function WorkLog(logText)
533 : {
534 :     
535 :     //===== Properties =====
536 :     
537 :     /**
538 :      * 作業ナンバー
539 :      */
540 :     this.workNumber = null;
541 :     
542 :     /**
543 :      * 日付
544 :      */
545 :     this.workDate = null;
546 :     
547 :     /**
548 :      * 作業タイトル
549 :      */
550 :     this.workTitle = null;
551 :     
552 :     /**
553 :      * 作業内容
554 :      */
555 :     this.workDetail = null;
556 :     
557 :     /**
558 :      * 表示対象か否か
559 :      */
560 :     this.isVisible = true;
561 :     
562 :     /**
563 :      * 原本データ(作業ログ)
564 :      */
565 :     this.workLogText = logText;
566 :     
567 :     
568 :     //===== Methods =====
569 :     
570 :     /**
571 :      * 原本データに含まれる各プロパティの値を解析する。
572 :      */
573 :     this.parse = function()
574 :     {
575 :         var regularExpression = /^■No\.([0-9]+) - ([0-9]+)\.([0-9]+)\.([0-9]+)\([^\)]+\)[=]{10,}(?:\r\n|\n){2}【([^】]*)】(?:\r\n|\n)([\d\D]*)$/;
576 :         
577 :         var resultArray = this.workLogText.match(regularExpression);
578 :         if (resultArray == null) return;
579 :         
580 :         // 作業ナンバー
581 :         this.workNumber = resultArray[1];
582 :         
583 :         // 日付
584 :         var year  = resultArray[2];
585 :         var month = resultArray[3];
586 :         var day   = resultArray[4];
587 :         this.workDate = new Date(year, month - 1, day);
588 :         
589 :         // 作業タイトル
590 :         this.workTitle = resultArray[5];
591 :         
592 :         // 作業内容
593 :         this.workDetail = resultArray[6].trim();
594 :         
595 :         return;
596 :     }
597 :     
598 :     /**
599 :      * 自分自身を文字列で表現して応答する。
600 :      */
601 :     this.toString = function()
602 :     {
603 :         var aString = "";
604 :         
605 :         aString += "WorkLog(";
606 :         aString += this.workNumber;
607 :         aString += ",'";
608 :         aString += this.workTitle;
609 :         aString += "')";
610 :         
611 :         return aString;
612 :     }
613 :     
614 :     
615 :     //===== Accessor =====
616 :     
617 :     /**
618 :      * 作業ナンバーを応答する。
619 :      *
620 :      * @return 作業ナンバー
621 :      */
622 :     this.getWorkNumber = function()
623 :     {
624 :         if (this.workNumber == null) this.parse();
625 :         
626 :         return this.workNumber;
627 :     }
628 :     
629 :     /**
630 :      * 日付を応答する。
631 :      *
632 :      * @return 日付
633 :      */
634 :     this.getWorkDate = function()
635 :     {
636 :         if (this.workDate == null) this.parse();
637 :         
638 :         return this.workDate;
639 :     }
640 :     
641 :     /**
642 :      * 作業タイトルを応答する。
643 :      *
644 :      * @return 作業タイトル
645 :      */
646 :     this.getWorkTitle = function()
647 :     {
648 :         if (this.workTitle == null) this.parse();
649 :         
650 :         return this.workTitle;
651 :     }
652 :     
653 :     /**
654 :      * 作業内容を応答する。
655 :      *
656 :      * @return 作業内容
657 :      */
658 :     this.getWorkDetail = function()
659 :     {
660 :         if (this.workDetail == null) this.parse();
661 :         
662 :         return this.workDetail;
663 :     }
664 :     
665 :     /**
666 :      * 原本データ(作業ログ)を応答する。
667 :      *
668 :      * @return 作業内容
669 :      */
670 :     this.getWorkLogText = function()
671 :     {
672 :         return this.workLogText;
673 :     }
674 :     
675 : }
676 : 
677 : /**
678 :  * 検索キーワードのオブジェクト。
679 :  * 
680 :  * Created by M.Miyazaki [2014.06.01]
681 :  *
682 :  * @param keywordText 検索キーワード
683 :  * @param isNegative 否定検索キーワードか否かの真偽値
684 :  */
685 : function Keyword(keywordText, isNegative)
686 : {
687 :     
688 :     //===== Properties =====
689 :     
690 :     /**
691 :      * 検索キーワード
692 :      */
693 :     this.keywordText = keywordText;
694 :     
695 :     /**
696 :      * 否定検索キーワードか否かの真偽値
697 :      */
698 :     this.isNegativeKeyword = isNegative;
699 :     
700 :     
701 :     //===== Methods =====
702 :     
703 :     /**
704 :      * 自分自身を文字列で表現して応答する。
705 :      */
706 :     this.toString = function()
707 :     {
708 :         var aString = "";
709 :         
710 :         aString += "Keyword('";
711 :         aString += this.keywordText;
712 :         aString += "',";
713 :         aString += (this.isNegativeKeyword) ? "negative=true" : "negative=false";
714 :         aString += ")";
715 :         
716 :         return aString;
717 :     }
718 :     
719 :     
720 :     //===== Accessor =====
721 :     
722 :     /**
723 :      * 検索キーワードを応答する。
724 :      *
725 :      * @return 検索キーワード
726 :      */
727 :     this.getKeywordText = function()
728 :     {
729 :         return this.keywordText;
730 :     }
731 :     
732 :     /**
733 :      * 否定検索キーワードか否かの真偽値を応答する。
734 :      * 
735 :      * @return 否定検索キーワードか否かの真偽値
736 :      */
737 :     this.isNegative = function()
738 :     {
739 :         return this.isNegativeKeyword;
740 :     }
741 :     
742 : }
743 : 
744 : 
745 : //====================
746 : //     Extensions
747 : //====================
748 : 
749 : /**
750 :  * 文字列にtrimメソッドを追加する。
751 :  *
752 :  * Quoted from https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/trim
753 :  */
754 : if (!String.prototype.trim)
755 : {
756 :     String.prototype.trim = function()
757 :     {
758 :         return this.replace(/^\s+|\s+$/g, "");
759 :     }
760 : }
761 : 
762 : /**
763 :  * 非同期通信用オブジェクトを設定する。(Windowsへの対応)
764 :  *
765 :  * Quoted from http://itpro.nikkeibp.co.jp/article/COLUMN/20070613/274683/
766 :  */
767 : if (window.ActiveXObject)
768 : {
769 :     window.XMLHttpRequest = function()
770 :     {
771 :         try
772 :         {
773 :             return (new ActiveXObject("Microsoft.XMLHTTP"));
774 :         }
775 :         catch (ignore) {}
776 :         
777 :         return null;
778 :     }
779 : }
780 : 

This document was generated by NanigashiBiyori on 2014/06/02 at 00:25:56.