      1 ﻿
      2 /**
      3  * @name	CeL log function
      4  * @fileoverview
      5  * 本檔案包含了記錄用 functions。
      6  * @since	2009/11/17
      7  * @see
      8  * <a href="http://getfirebug.com/lite.html" accessdate="2010/1/1 14:54">Firebug Lite</a>,
      9  * <a href="http://www.mozilla.org/projects/venkman/" accessdate="2010/1/1 16:43">Venkman JavaScript Debugger project page</a>
     10  */
     11
     12 //	http://blogs.msdn.com/b/webdevtools/archive/2007/03/02/jscript-intellisense-in-orcas.aspx
     13 ///	<reference path="../ce.js"/>
     14
     15 /*
     16 TODO:
     17 emergency/urgent situation alert
     18 會盡量以網頁上方/頂部黄色的導航條/警告條展示
     19 「不再顯示」功能
     20 .format()
     21 	將 div format 成 log panel。
     22 分群, http://developer.yahoo.com/yui/examples/uploader/uploader-simple-button.html
     23 */
     24
     25
     26
     27 //WScript.Echo(this.Class);
     28
     29 //	若 library base 尚未 load 或本 module 已經 loaded 則跳過。
     30 if (typeof CeL === 'function')
     31 (function(){
     32
     33 /**
     34  * 本 module 之 name(id)，<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。
     35  * @type	String
     36  * @constant
     37  * @inner
     38  * @ignore
     39  */
     40 var module_name = 'application.debug.log';
     41
     42 //var do_before_including = function() {};
     43
     44 /*	to include:
     45 	include code_for_including
     46 	<div id="debug_panel"></div>
     47 	var SL=new Debug.log('debug_panel'),sl=function(){SL.log.apply(SL,arguments);},err=function(){SL.err.apply(SL,arguments);},warn=function(){SL.warn.apply(SL,arguments);};
     48
     49 	http://www.comsharp.com/GetKnowledge/zh-CN/TeamBlogTimothyPage_K742.aspx
     50
     51 	if possible, use Firebug Lite instead.
     52 	http://benalman.com/projects/javascript-debug-console-log/
     53 */
     54
     55
     56 //	===================================================
     57 /**
     58  * 若欲 include 整個 module 時，需囊括之 code。通常即 CeL。
     59  * @type	Function
     60  * @param	{Function} library_namespace	namespace of library
     61  * @param	load_arguments	呼叫時之 argument(s)
     62  * @return
     63  * @constant
     64  * @inner
     65  * @ignore
     66  */
     67 var code_for_including = function(library_namespace, load_arguments) {
     68 //WScript.Echo(this);
     69
     70 var
     71
     72 //	class private	-----------------------------------
     73
     74 //	class name, 需要用到這個都不是好方法。
     75 //cn='Debug.log',
     76
     77 /**
     78  * private storage pool
     79  * @ignore
     80  */
     81 p=[],
     82
     83 log_data = function(m, l) {
     84 	this.m = m;
     85 	this.l = l;
     86 	return this;
     87 },
     88
     89 /**
     90  * default write/show log function
     91  * @ignore
     92  * @param	{string} id	element id
     93  */
     94 w = function(id) {
     95 	var o, m, c, _p = p[id], _t = _p.instance,
     96 	/**
     97 	 * buffer
     98 	 * @inner
     99 	 * @ignore
    100 	 */
    101 	b = _p.buf,
    102 	B = _p.board, F = _p.do_function, level;
    103
    104 	if (_p.clean)
    105 		_t.clear(), _p.clean = 0;
    106
    107 	if (!B && !F)
    108 		return;
    109
    110 	while (b.length){
    111 		// 預防 MP 時重複顯示
    112 		m = b.shift();
    113
    114 		if (F)
    115 			F(m);
    116
    117 		//	IE8: 'constructor' 是 null 或不是一個物件
    118 		try {
    119 			c = m.constructor;
    120 			// alert((m.constructor === log_data) + '\n' + m.constructor + '\n' + m);
    121 		} catch (e) {
    122 		}
    123 		if (c === log_data) {
    124 			if (!isNaN(m.l) && m.l < library_namespace.set_debug())
    125 				continue;
    126 			c = m.l in _t.className_set ? m.l : 0;
    127 			m = m.m;
    128 			if (c in _t.message_prefix)
    129 				m = _t.message_prefix[c] + m;
    130 			c = _t.className_set[c];
    131 		} else {
    132 			//	add default style set
    133 			if (c = _t.message_prefix.log)
    134 				m = c + m;
    135 			c = _t.className_set.log || 0;
    136 		}
    137 		_p.lbuf.push(m);
    138
    139 		if (B) { // && typeof document==='object'
    140 			o = _p.instance.log_tag;
    141 			if (o) {
    142 				o = document.createElement(o);
    143 				if (c)
    144 					o.className = c;
    145
    146 				o.innerHTML = typeof m === 'string' ?
    147 						// for character (null)
    148 						m.replace(/\x00/g,
    149 						'<span class="control_character">\\x00</span>')
    150 						//	'' (hyphen) 這符號(連字符)可以自動斷行，並在斷行時自動加上個橫槓。在顯示長整數時較有用。
    151 						.replace(/(\d{20})/g,'$1')
    152 						: m;
    153 			} else
    154 				o = document.createTextNode(m);
    155 			B.appendChild(o);
    156 		}
    157 	}
    158
    159 	//if(_t.auto_hide)B.style.display=B.innerHTML?'block':'none';
    160 	if (B && _t.auto_scroll)
    161 		B.scrollTop = B.scrollHeight - B.clientHeight;
    162 },
    163
    164
    165 /**
    166  * save log
    167  * @ignore
    168  * @param	m	message
    169  * @param	{string} id	element id
    170  * @param	force	force to clean the message area
    171  */
    172 s = function(m, id, force) {
    173 	var _p = p[id], _t = _p.instance, f = _p.logF, s = _t.save_log;
    174 	if (!s || typeof s === 'function' && !s(m, l))
    175 		return;
    176
    177 	if (m)
    178 		_p.sbuf.push(m = (_t.save_date && typeof gDate == 'function' ? _t.save_new_line
    179 				+ gDate() + _t.save_new_line
    180 				: '')
    181 				+ m);
    182
    183 	if (force || _t.flush || _p.sbufL > _t.save_limit)
    184 		try {
    185 			if (f
    186 					|| _t.log_file
    187 					&& (f = _p.logF = fso.OpenTextFile(_t.log_file,
    188 							8/* ForAppending */, true/* create */,
    189 							_t.log_encoding)))
    190 				f.Write(_p.sbuf.join(_t.save_new_line)), _p.sbuf = [],
    191 						_p.sbufL = 0, _t.error_message = 0;
    192 		} catch (e) {
    193 			_t.error_message = e;// err(e);
    194 		}
    195 	else if (m)
    196 		_p.sbufL += m.length;
    197 },
    198
    199 //	instance constructor	---------------------------
    200 //	(document object)
    201 /*
    202
    203 _=this
    204
    205
    206 TODO:
    207 set class in each input
    208 input array
    209 show file path & directory functional	可從 FSO operation.hta 移植
    210 增加 group 以便在多次輸入時亦可 toggle 或排版
    211
    212 count
    213 c.f.: GLog
    214
    215 dependency:
    216
    217 */
    218 /**
    219  * initial a log tool's instance/object
    220  * @class	log function
    221  * @see	usage: <a href="#.extend">CeL.application.debug.log.extend</a>
    222  * @since	2008/8/20 23:9:48
    223  * @requires	gDate(),NewLine,fso
    224
    225  * @constructor
    226  * @name	CeL.application.debug.log
    227  * @param	{String|object HTMLElement} obj	log target: message area element or id
    228  * @param	{Object} [className_set]	class name set
    229  */
    230 _tmp;CeL.application.debug.log
    231 = function(obj, className_set) {
    232 	// Initial instance object. You can set it yourself.
    233 	/**
    234 	 * log 時 warning/error message 之 className
    235 	 * @name	CeL.application.debug.log.prototype.className_set
    236 	 */
    237 	this.className_set = className_set || {
    238 			/**
    239 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.log} 時使用的 className, DEFAULT className.
    240 			 * @name	CeL.application.debug.log.prototype.className_set.log
    241 			 */
    242 			log : 'debug_log',
    243 			/**
    244 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.warn} 時使用的 className
    245 			 * @name	CeL.application.debug.log.prototype.className_set.warn
    246 			 */
    247 			warn : 'debug_warn',
    248 			/**
    249 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.err} 時使用的 className
    250 			 * @name	CeL.application.debug.log.prototype.className_set.err
    251 			 */
    252 			err : 'debug_err',
    253 			/**
    254 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.set_board} 時設定 log panel 使用的 className
    255 			 * @name	CeL.application.debug.log.prototype.className_set.panel
    256 			 */
    257 			panel : 'debug_panel'
    258 	};
    259
    260 	/**
    261 	 * log 時 warning/error message 之 prefix
    262 	 * @name	CeL.application.debug.log.prototype.message_prefix
    263 	 */
    264 	this.message_prefix = {
    265 			/**
    266 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.log} 時使用的 prefix, DEFAULT prefix.
    267 			 * @name	CeL.application.debug.log.prototype.message_prefix.log
    268 			 */
    269 			log : '',
    270 			/**
    271 			 * @description	當呼叫 {@link CeL.application.debug.log.prototype.warn} 時使用的 prefix
    272 			 * @name	CeL.application.debug.log.prototype.message_prefix.warn
    273 			 */
    274 			warn : '',
    275 			/**
    276 			 * @description	表示當呼叫 {@link CeL.application.debug.log.prototype.err}, 是錯誤 error message 時使用的 prefix
    277 			 * @name	CeL.application.debug.log.prototype.message_prefix.err
    278 			 */
    279 			err : '<em>!! Error !!</em> '
    280 	};
    281
    282 	this.id = p.length;
    283 	p.push( {
    284 		instance : this,
    285 		/**
    286 		 * write buffer
    287 		 */
    288 		buf : [],
    289 		/**
    290 		 * save buffer when we need to save the messages
    291 		 */
    292 		sbuf : [],
    293 		/**
    294 		 * length of save buffer
    295 		 */
    296 		sbufL : 0,
    297 		/**
    298 		 * now logged buffer
    299 		 */
    300 		lbuf : []
    301 	});
    302 	this.set_board(obj);
    303 };
    304
    305
    306
    307 //	class public interface	---------------------------
    308
    309 CeL.application.debug.log
    310 .
    311 /**
    312  * do the log action
    313  * @memberOf	CeL.application.debug.log
    314  * @private
    315  */
    316 do_log = function(id) {
    317 /*	這段應該只在 module namespace 重複定義時才會發生
    318  var I=p[id];
    319  if(!I){
    320   alert('.do_log: not exist: ['+id+']');
    321   return;
    322  }
    323  I=I.instance;
    324 */
    325 	var I = p[id].instance;
    326 	if (I.do_log)
    327 		I.do_log();
    328 };
    329
    330
    331 CeL.application.debug.log
    332 .
    333 /**
    334  * 對各種不同 error object 作應對，獲得可理解的 error message。
    335  * @param	e	error object
    336  * @param	new_line	new_line
    337  * @param	caller	function caller
    338  * @memberOf	CeL.application.debug.log
    339  * @see
    340  * http://msdn.microsoft.com/en-us/library/ms976144.aspx
    341  * The facility code establishes who originated the error. For example, all internal script engine errors generated by the JScript engine have a facility code of "A".
    342  * http://msdn.microsoft.com/en-us/library/ms690088(VS.85).aspx
    343  *
    344  * http://msdn.microsoft.com/en-us/library/t9zk6eay.aspx
    345  * http://msdn.microsoft.com/en-us/library/microsoft.jscript.errorobject.aspx
    346  * Specifies the name of the type of the error.
    347  * Possible values include Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, and URIError.
    348  */
    349 get_error_message = function get_error_message(e, new_line, caller) {
    350 	if (!new_line)
    351 		new_line = _.prototype.save_new_line;
    352
    353 	if (!caller || typeof caller !== 'string'){
    354 		if (typeof caller !== 'function')
    355 			try {
    356 				// TODO: do not use .caller
    357 				caller = get_error_message.caller;
    358 			} catch (e) {
    359 			}
    360
    361 		if (caller === null)
    362 			caller = 'from the top level';
    363 		else if (typeof caller === 'function')
    364 			caller = '@' + (library_namespace.get_function_name(caller) || caller);
    365 		else
    366 			caller = '@' + library_namespace.Class;
    367 	}
    368
    369
    370 	// from popErr()
    371 	//	type
    372 	var T = library_namespace.is_type(e),
    373 	//	message
    374 	m = T === 'Error' ?
    375 			'Error ' + caller + ': '
    376 			//	http://msdn.microsoft.com/en-us/library/cc231198(PROT.10).aspx
    377 			//	<a href="http://msdn.microsoft.com/en-us/library/ms819773.aspx">Winerror.h</a>: error code definitions for the Win32 API functions
    378 			//	(e.number & 0xFFFF): See 錯誤代碼 /錯誤提示碼 <a href="http://msdn.microsoft.com/en-us/library/ms681381%28VS.85%29.aspx">System Error Codes</a>
    379 			//	http://social.msdn.microsoft.com/Search/zh-TW/?Query=%22System+Error+Codes%22+740&AddEnglish=1
    380 			//	http://msdn.microsoft.com/en-us/library/aa394559(VS.85).aspx
    381 			//	net helpmsg (e.number & 0xFFFF)
    382 			+ (e.number & 0xFFFF) + (e.name ? ' [' + e.name + '] ' : ' ')
    383 			+ '(facility code ' + (e.number >> 16 & 0x1FFF) + '): '
    384 			+ new_line
    385 			+ (e.message || '').replace(/\r?\n/g, '<br/>')
    386 			//	.message 為主，.description 是舊的。
    387 			+ (!e.description || e.description === e.message ?
    388 				'' :
    389 				new_line
    390 					+ new_line
    391 					+ ('' + e.description).replace(/\r?\n/g, '<br/>')
    392 			)
    393
    394 		: T === 'DOMException'?
    395 			//	http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-17189187
    396 			'[' + T + '] ' + e.code + ': ' + e.message
    397
    398 		: !e || T === 'string' ? e
    399
    400 		: '[' + T + '] ' + (e.message || e);
    401
    402
    403 	if (library_namespace.is_debug(2) && typeof e === 'object' && e)
    404 		for (T in e)
    405 			try{
    406 				//	Firefox has (new Error).stack
    407 				//	http://eriwen.com/javascript/js-stack-trace/
    408 				m += '<br/> <span class="debug_debug">' + T + '</span>: '
    409 						+ (typeof e[T] === 'string' && T === 'stack' ?
    410 								e[T].replace(/[\r\n]+$/, '').replace(/(@)([a-z\-]+:\/\/.+)(:)(\d+)$/gm, '$1<a href="view-source:$2#$4" target="_blank">$2</a>$3$4').replace(/\n/g, '<br/>- ')
    411 								: typeof e[T] === 'string' && T === 'fileName' ? '<a href="view-source:' + e[T] + '" target="_blank">' + e[T] + '</a>'
    412 								: e[T]);
    413 			}catch (e) {}
    414
    415 	// m += ' (' + arguments.callee.caller + ')';
    416 	return m;
    417 };
    418
    419
    420 CeL.application.debug.log
    421 .
    422 /**
    423  * get node description
    424  *
    425  * @param node
    426  *            HTML node
    427  * @memberOf CeL.application.debug.log
    428  */
    429 node_description = function(node, flag) {
    430 	if (typeof node === 'string')
    431 		node = document.getElementById(node);
    432 	if (!node)
    433 		return;
    434
    435 	var description = '';
    436
    437 	if (node.id)
    438 		description += '#' + node.id;
    439
    440 	if (node.className)
    441 		description += '.' + node.className;
    442
    443 	if (node.tagName)
    444 		description = '<' + node.tagName + description + '>';
    445
    446 	if (!description && node.innerHTML) {
    447 		description = node.innerHTML;
    448 		if (description.length > 40)
    449 			description = description.slice(0, 40);
    450 		description = description.replace(/</g, '<');
    451 	}
    452
    453 	//	TODO: 對 Range object 之類的處理
    454 	//	http://help.dottoro.com/ljxsqnoi.php
    455 	return description || '(null description node: ' + library_namespace.is_type(node) + ')';
    456 };
    457
    458
    459 //預設以訊息框代替
    460 CeL.application.debug.log
    461 .
    462 default_log_target =
    463 	new Function('m',
    464 			(typeof JSalert === 'function' ? 'JSalert'
    465 					: typeof WScript === 'object' ? 'WScript.Echo' : 'alert')
    466 			+ "(typeof m==='object'?'['+m.l+'] '+m.m:m);");
    467
    468
    469 CeL.application.debug.log
    470 .
    471 /**
    472  * get new extend instance
    473  * @param	{String|object HTMLElement} [obj]	message area element or id
    474  * @return	{Array} [ instance of this module, log function, warning function, error function ]
    475  * @example
    476  *
    477  * //	status logger
    478  * var SL=new CeL.application.debug.log('log'),sl=SL[1],warn=SL[2],err=SL[3];
    479  * sl(msg);
    480  * sl(msg,clear);
    481  *
    482  * //	general log
    483  * function_set = new CeL.application.debug.log.extend('panel',{});
    484  * // 1.
    485  * function_set = new CeL.code.log.extend('panel',{});
    486  * logger = function_set[1];
    487  * // 2.
    488  * log_only = (new CeL.code.log.extend('panel',{}))[1];
    489  *
    490  * @_memberOf	CeL.application.debug.log
    491  * @since	2009/8/24 20:15:31
    492  */
    493 extend = function(obj, className_set) {
    494 	//CeL.Log=new CeL.code.log(function(m){var F=typeof JSalert==='function'?JSalert:typeof alert==='function'?alert:WScript.Echo;F(typeof m==='object'?'['+m.l+'] '+m.m:m);});
    495 	/**
    496 	 * new instance
    497 	 * @type	CeL.application.debug.log
    498 	 * @inner
    499 	 * @ignore
    500 	 */
    501 	var o = new _// JSDT:_module_
    502 			(obj || _.default_log_target, className_set);
    503
    504 	// TODO: do not use arguments
    505 	return [ o, function() {
    506 		o.log.apply(o, arguments);
    507 	}, function() {
    508 		o.warn.apply(o, arguments);
    509 	}, function() {
    510 		o.err.apply(o, arguments);
    511 	} ];
    512
    513 };
    514
    515
    516 /*
    517 _.option_open=function(p){
    518
    519 };
    520
    521 _.option_file=function(p){
    522 };
    523
    524 _.option_folder=function(p){
    525 };
    526 */
    527
    528 //	class constructor	---------------------------
    529
    530
    531 CeL.application.debug.log
    532 .prototype = {
    533
    534 //	instance public interface	-------------------
    535
    536 /**
    537  * 當執行寫檔案或任何錯誤發生時之錯誤訊息。<br/>
    538  * while error occurred.. should read only
    539  * @name	CeL.application.debug.log.prototype.error_message
    540  */
    541 error_message : '',
    542
    543 /**
    544  * 超過這長度才 save。<=0 表示 autoflash，非數字則不紀錄。
    545  * @name	CeL.application.debug.log.prototype.save_limit
    546  * @type	Number
    547  */
    548 save_limit : 4000,
    549
    550 /**
    551  * 在 log 結束時執行，相當於 VB 中 DoEvent() 或 。
    552  * @name	CeL.application.debug.log.prototype.do_event
    553  */
    554 do_event : library_namespace.DoNoting || null,
    555
    556
    557 /**
    558  * log 時使用之 tagName, 可用 div / span 等。若不設定會用 document.createTextNode
    559  * @name	CeL.application.debug.log.prototype.log_tag
    560  */
    561 log_tag : 'div',
    562
    563
    564 /**
    565  * boolean or function(message, log level) return save or not
    566  *
    567  * @name CeL.application.debug.log.prototype.save_log
    568  * @type Boolean
    569  */
    570 save_log : false,
    571 /**
    572  * save log to this file path
    573  *
    574  * @name CeL.application.debug.log.prototype.log_file
    575  * @type Boolean
    576  */
    577 log_file : false,
    578 /**
    579  * auto save log. 若未設定，記得在 onunload 時 .save()
    580  *
    581  * @name CeL.application.debug.log.prototype.flush
    582  * @type Boolean
    583  */
    584 flush : false,
    585 /**
    586  * 在 save log 時 add date
    587  *
    588  * @name CeL.application.debug.log.prototype.save_date
    589  * @type Boolean
    590  */
    591 save_date : true,
    592 /**
    593  * 在 save log 時的換行
    594  *
    595  * @name CeL.application.debug.log.prototype.save_new_line
    596  * @type string
    597  */
    598 save_new_line : library_namespace.env.new_line || '\r\n',
    599 /**
    600  * 在 save log 時的 encoding
    601  *
    602  * @name CeL.application.debug.log.prototype.log_encoding
    603  */
    604 log_encoding : -1,//TristateTrue
    605
    606
    607 /**
    608  * 自動捲動
    609  *
    610  * @name CeL.application.debug.log.prototype.auto_scroll
    611  * @type Boolean
    612  */
    613 auto_scroll : true,
    614 /**
    615  * 沒有內容時自動隱藏
    616  *
    617  * @deprecated TODO
    618  * @name CeL.application.debug.log.prototype.auto_hide
    619  * @type Boolean
    620  */
    621 auto_hide : false,
    622
    623 /**
    624  * 等待多久才顯示 log。若為 0 則直接顯示。<br/>
    625  * (WScript 沒有 setTimeout)
    626  * @name	CeL.application.debug.log.prototype.interval
    627  */
    628 interval : typeof setTimeout === 'undefined' ? 0 : 1,
    629
    630 /**
    631  * log function (no delay)
    632  * @name	CeL.application.debug.log.prototype.do_log
    633  */
    634 do_log : function(level) {
    635 	// if(p[this.id].th)clearTimeout(p[this.id].th);
    636
    637 	// reset timeout handle
    638 	p[this.id].th = 0;
    639
    640 	w(this.id);
    641 },
    642
    643 /**
    644  * class instance 預設作 log 之 function
    645  * @param {String} m	message
    646  * @param clean	clean message area
    647  * @param level	log level
    648  * @return
    649  * @name	CeL.application.debug.log.prototype.log
    650  */
    651 log : function(msg, clean, level) {
    652 	var t = this, _p = p[t.id];
    653 	//var msg_head=(arguments.callee.caller+'').match(/function\s([^\(]+)/);if(msg_head)msg_head=msg_head[1]+' ';
    654 	s(msg, t.id, level);
    655
    656 	// window.status = msg;
    657 	if (level)
    658 		msg = new log_data(msg, level);
    659
    660 	if (clean)
    661 		// clean log next time
    662 		_p.clean = 1, _p.buf = [ msg ];
    663 	else
    664 		_p.buf.push(msg);
    665
    666 	if (!t.interval)
    667 		t.do_log();
    668 	else if (!_p.th)
    669 		if (typeof window.setTimeout === 'undefined')
    670 			t.interval = 0, t.do_log();
    671 		else
    672 			// _p.th=setTimeout(cn+'.do_log('+t.id+');',t.interval);
    673 			_p.th = window.setTimeout(function() {
    674 				_.do_log(t.id);
    675 			}, t.interval);
    676
    677 	if (t.do_event)
    678 		t.do_event();
    679 },
    680
    681 /*
    682 TODO:
    683 other methods: INFO,DEBUG,WARNING,ERROR,FATAL,UNKNOWN
    684 */
    685
    686 /**
    687  * save message
    688  * @name	CeL.application.debug.log.prototype.save
    689  */
    690 save : function() {
    691 	s('', this.id, 1/* force */);
    692 },
    693
    694 //	** important ** 這邊不能作 object 之 initialization，否則因為 object 只會 copy reference，因此 new 時東西會一樣。initialization 得在 _() 中作！
    695 //className_set:{},
    696
    697 /**
    698  * log a warning
    699  * @name	CeL.application.debug.log.prototype.warn
    700  */
    701 warn : function(m, clean) {
    702 	this.log(m, clean, 'warn');
    703 },
    704
    705 /**
    706  * deal with error message
    707  * @name	CeL.application.debug.log.prototype.err
    708  */
    709 err : function err(e, clean) {
    710 	var caller = '';
    711 	try {
    712 		// TODO: do not use .caller
    713 		caller = '' + err.caller;
    714 		if (caller.indexOf('.err.apply(') !== -1)
    715 			// ** 判斷 call from _.extend. 應該避免!
    716 			caller = caller.caller;
    717 	} catch (e) {
    718 		// TODO: handle exception
    719 	}
    720
    721 	this.log(_.get_error_message(e, this.save_new_line,
    722 			caller), clean, 'err');
    723 },
    724
    725
    726 /**
    727  * 設定寫入到哪<br/>set log board for each instance (document object)
    728  * @name	CeL.application.debug.log.prototype.set_board
    729  */
    730 set_board : function(o) {
    731 	var _t = this, _p = p[_t.id];
    732 	if (o)
    733 		if (typeof o === 'function')
    734 			_p.do_function = o;
    735
    736 		else {
    737 			if (typeof o !== 'object'
    738 				&& typeof document === 'object')
    739 				o = document.getElementById(o);
    740 			if (o
    741 					// TODO
    742 					// && library_namespace.is_HTML_obj(o)
    743 				) {
    744 				_p.board = o;
    745 				if (_t = _t.className_set.panel)
    746 					o.className += _t;
    747 				delete _p.do_function;
    748 			}
    749 		}
    750
    751 	return _p.board;
    752 },
    753
    754 /**
    755  * 獲取當前 buffer 中的 log
    756  * @name	CeL.application.debug.log.prototype.get_log
    757  */
    758 get_log : function() {
    759 	return p[this.id].lbuf;
    760 },
    761
    762 /**
    763  * show/hide log board
    764  * @name	CeL.application.debug.log.prototype.toggle
    765  */
    766 toggle : function(s) {
    767 	var _s = p[this.id].board.style;
    768 	if (_s) {
    769 		if (typeof s === 'undefined')
    770 			s = _s.display === 'none';
    771 		return _s.display = s ? 'block' : 'none';
    772 	}
    773 },
    774
    775 /**
    776  * clear log board
    777  * @name	CeL.application.debug.log.prototype.clear_board
    778  */
    779 clear_board : function(b) {
    780 	b.innerHTML = '';
    781 },
    782
    783 /**
    784  * 清除全部訊息 clear message
    785  * @name	CeL.application.debug.log.prototype.clear
    786  */
    787 clear : function() {
    788 	var _p = p[this.id];
    789 	if (_p.board)
    790 		this.clear_board(_p.board);
    791 	_p.lbuf = [];
    792 }
    793
    794 };
    795
    796 /**
    797  * 不 extend 的 member.
    798  * '*': 完全不 extend.
    799  * this: 連 module 本身都不 extend 到 library name-space 下.
    800  * @ignore
    801  */
    802 CeL.application.debug.log
    803 .no_extend = 'this,do_log,extend';
    804
    805 return (
    806 	CeL.application.debug.log
    807 );
    808 };
    809
    810 //	===================================================
    811
    812
    813 //	為 modele log 所作的初始化工作
    814
    815 /**
    816  * modele namespace
    817  * @type	CeL.application.debug.log
    818  * @inner
    819  * @ignore
    820  */
    821 var ns = CeL.setup_module(module_name, code_for_including);
    822
    823 //WScript.Echo(n.extend);
    824
    825 //code_for_including[generateCode.dLK]='*var Debug={log:code_for_including()};';
    826
    827 CeL.include_module_resource('log.css', module_name);
    828
    829 //	為本 library 用
    830 if (!CeL.Log) {
    831 	var o = ns.extend(), i,
    832 		l = {
    833 			/*
    834 			 * WHITE SMILING FACE (U+263A).
    835 			 * http://decodeunicode.org/en/u+263a
    836 			 * http://wiki.livedoor.jp/qvarie/
    837 			 */
    838 			'log' : '☺',
    839 			/*
    840 			 * U+26A1 HIGH VOLTAGE SIGN
    841 			 */
    842 			'em' : '⚡',
    843 			/*
    844 			 * WARNING SIGN (U+26A0).
    845 			 */
    846 			'warn' : '⚠',
    847 			/*
    848 			 * U+2620 SKULL AND CROSSBONES
    849 			 */
    850 			'err' : '☠',
    851 			/*
    852 			 * U+2689 BLACK CIRCLE WITH TWO WHITE DOTS
    853 			 */
    854 			'debug' : '⚉'
    855 		},
    856 		t = '<img class="debug_icon" src="' + CeL.get_module_path(module_name, '') + 'icon/';
    857
    858 	// override CeL.log
    859 	CeL.Log = o[0];
    860 	CeL.Log.className_set.em = 'debug_em';
    861 	CeL.Log.className_set.debug = 'debug_debug';
    862
    863 	for(i in l)
    864 		CeL.Log.message_prefix[i] = t + i + '.png" alt="[' + l[i]
    865 			+ ']" title="' + l[i] + ' ' + i + '"/> ';
    866
    867
    868 	l = CeL.log && CeL.log.buffer;
    869
    870 	CeL.log = o[1];
    871 	CeL.warn = o[2];
    872 	CeL.err = o[3];
    873 	CeL.em = function(msg, clean) {
    874 		CeL.Log.log.call(CeL.Log, msg, clean, 'em');
    875 	};
    876 	CeL.debug = function(msg, level, caller, clean) {
    877 		//alert(CeL.is_debug() + ',' + l + '(' + (l === undefined) + '),' + msg);
    878 		if (CeL.is_debug(level)){
    879 			if(!caller)
    880 				try {
    881 					// TODO: do not use arguments
    882 					caller = CeL.get_function_name(arguments.callee.caller);
    883 				} catch (e) {
    884 				}
    885
    886 			CeL.Log.log.call(
    887 					CeL.Log,
    888 					caller ?
    889 							'<span class="debug_caller">'
    890 							+ caller//(caller.charAt(0) === '.' ? CeL.Class + caller : caller)
    891 							+ '</span>: ' + msg
    892 						: msg
    893 					, clean, 'debug'
    894 			);
    895 		}
    896 	};
    897
    898 	if (l)
    899 		for (i in l)
    900 			CeL.debug('(before loading ' + module_name + ') ' + l[i]);
    901 }
    902
    903 })();
    904
    905