      1 ﻿
      2 /*
      3 	本檔案為自動生成，請勿編輯！
      4 	This file is auto created from _structure\structure.js, base.js, module.js, initialization.js
      5 		by tool: build main script.
      6 */
      7
      8
      9 //<![CDATA[
     10
     11
     12 /**
     13  * @name	JavaScript framework: CeL base loader
     14  * @fileoverview
     15  * Colorless echo JavaScript kit/library base loader.
     16  * 本檔案包含了呼叫其他 library 需要用到的 function，以及常用 base functions。<br/>
     17  * A JavaScript module framework that is simple to use.<br/>
     18  * 本計畫希望能建立一個能簡單上手的 JavaScript 模組架構。
     19  * <br/>
     20  * 2002-, kanashimi <kanasimi@gmail.com>.<br/>
     21  * <br/>
     22  * This file is in tab wide of 4 chars, documentation with JsDoc Toolkit (<a href="http://code.google.com/p/jsdoc-toolkit/wiki/TagReference">tags</a>).<br/>
     23  * <br/>
     24  * <br/>Please visit <a href="http://lyrics.meicho.com.tw/program/">Colorless echo program room</a> for more informations.
     25  * @since	自 function.js 0.2 改寫
     26  * @since	JavaScript 1.2
     27  * @since	2010/1/9 00:01:52 建立
     28  * @author	kanasimi@gmail.com
     29  * @version	$Id: ce.js,v 0.2 2009/11/26 18:37:11 kanashimi Exp $
     30  */
     31
     32
     33 /*
     34 引用：參照
     35 function addCode
     36
     37 CeL.module
     38
     39
     40 駝峰式大小寫命名規則 CamelCase → embedded_underscore/Snake case
     41
     42
     43 單一JS引用：
     44 //	[function.js]_iF
     45 function _iF(){}_iF.p='HKCU\\Software\\Colorless echo\\function.js.path';if(typeof WScript=="object")try{eval(getU((new ActiveXObject("WScript.Shell")).RegRead(_iF.p)));}catch(e){}
     46 function getU(p,enc){var o;try{o=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){o=new XMLHttpRequest();}if(o)with(o){open('GET',p,false);if(enc&&o.overrideMimeType)overrideMimeType('text/xml;charset='+enc);send(null);return responseText;}}
     47 //	[function.js]End
     48
     49
     50 初始化：參照
     51 initialization of function.js
     52
     53 http://www.w3school.com.cn/html5/html5_script.asp
     54 <script type="text/javascript" async="true" src="path/to/function.js"></script>
     55 <script type="application/javascript;version=1.7" async="true" src="path/to/function.js"></script>
     56
     57 JSDoc:
     58 	http://code.google.com/p/jsdoc-toolkit/w/list
     59 	http://jsdoc.sourceforge.net/
     60
     61 Javadoc:
     62 	http://java.sun.com/j2se/javadoc/writingdoccomments/
     63
     64 VSdoc:
     65 	JScript IntelliSense in Visual Studio
     66 	http://weblogs.asp.net/bleroy/archive/2007/04/23/the-format-for-javascript-doc-comments.aspx
     67 	http://blogs.msdn.com/b/webdevtools/archive/2008/11/07/hotfix-to-enable-vsdoc-js-intellisense-doc-files-is-now-available.aspx
     68 	Create JScript XML Code Comments
     69 	http://msdn.microsoft.com/zh-tw/library/bb514138.aspx
     70 	http://blog.miniasp.com/post/2010/04/Visual-Studio-2010-jQuery-Development-Tips.aspx
     71
     72 */
     73
     74
     75
     76 /*
     77 TODO
     78
     79 本 library 大量使用了 arguments.callee，但這與 ECMAScript design principles 不甚相符，需要避免。
     80 	http://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript
     81 	http://wiki.ecmascript.org/doku.php?id=es3.1:design_principles
     82
     83
     84 reset environment (__defineSetter__, __defineGetter__, ..)
     85 in case of
     86 	<a href="http://haacked.com/archive/2009/06/25/json-hijacking.aspx" accessdate="2009/12/2 0:7">JSON Hijacking</a>,
     87 	<a href="http://blog.miniasp.com/post/2009/11/JavaScript-JSON-Hijacking.aspx" accessdate="2009/12/2 0:18">在 Web 2.0 時代必須重視 JavaScript/JSON Hijacking 攻擊</a>,
     88 	etc.
     89 */
     90
     91
     92 //try{
     93
     94
     95
     96
     97
     98
     99 /*
    100 TODO
    101 將 module_name 改成 arguments
    102 http://threecups.org/?p=129
    103
    104 listen language change event
    105 play board
    106
    107 use <a href="http://prototyp.ical.ly/index.php/2007/03/01/javascript-design-patterns-1-the-singleton/" accessdate="2010/4/25 0:23" title="prototyp.ical.ly  &raquo; Javascript Design Patterns - 1. The Singleton">Singleton pattern</a>,
    108 Module 模式或單例模式（<a href="http://zh.wikipedia.org/wiki/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F" accessdate="2010/4/25 0:25" title="单例模式">Singleton</a>）<a href="http://www.comsharp.com/GetKnowledge/zh-CN/TeamBlogTimothyPage_K950.aspx" accessdate="2010/4/25 0:24" title="那些相见恨晚的 JavaScript 技巧 - 基于 COMSHARP CMS">為 Douglas Crockford 所推崇</a>，並被大量應用在 Yahoo User Interface Library YUI。
    109
    110 http://wiki.forum.nokia.com/index.php/JavaScript_Performance_Best_Practices
    111 http://ioio.name/core-javascript-pitfalls.html
    112
    113 CommonJS
    114 http://www.heliximitate.cn/studyblog/archives/tag/commonjs
    115
    116 */
    117
    118
    119 /*
    120 TODO
    121
    122
    123
    124 //module
    125
    126 //typeof CeL_id === 'string' && typeof this[CeL_id] === 'function' &&
    127 typeof CeL === 'function' && CeL.setup_module({
    128 name:[module_name],
    129 require:[function_name,module_name],
    130
    131 code:function(CeL){
    132
    133 var private_value=1;
    134
    135 function module_function_1(arg) {
    136 	;
    137 }
    138 module_function_1.required='';
    139
    140
    141 function module_class_1(arg) {
    142 	;
    143 }
    144
    145 function get_value(){
    146 	return private_value;
    147 }
    148
    149 module_class_1.prototype.print=function(){};
    150 module_class_1.print=function(){};
    151
    152
    153 return {module_function_1,module_class_1};
    154
    155 }
    156
    157 });
    158
    159 2011/7/31 21:18:01
    160
    161
    162
    163
    164 */
    165
    166 //void(
    167 //typeof CeL !== 'function' &&
    168 (
    169 /*
    170  * We can redefine native values only for undefined.<br/>
    171  * http://weblogs.asp.net/bleroy/archive/2006/08/02/Define-undefined.aspx<br/>
    172  * <br/>
    173  * Will speed up references to undefined, and allows redefining its name. (from jQuery)<br/>
    174  * <br/>
    175  * 用在比較或是 return undefined<br/>
    176  * 在舊的 browser 中，undefined 可能不存在。
    177  */
    178 function (undefined) {
    179
    180 /*
    181  * ECMA-262 5th edition, ECMAScript 5 strict mode
    182  * http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
    183  * http://davidflanagan.com/Talks/es5/slides.html
    184  * http://kangax.github.com/es5-compat-table/
    185  */
    186 'use strict';
    187
    188
    189 //if(typeof global !== 'function') throw new Error('No global object specified!');
    190
    191
    192 var
    193 	library_name = 'CeL'
    194
    195 	/**
    196 	 * default debug level
    197 	 * @type	{Integer}
    198 	 * @ignore
    199 	 */
    200 	, debug = 0
    201
    202 	/**
    203 	 * library version
    204 	 * @type	{String}
    205 	 * @ignore
    206 	 */
    207 	, version = '2011.08.04'
    208
    209 	//,window
    210
    211 	, old_namespace
    212
    213 	//	library base name-space
    214 	, _
    215
    216 	//, _base_function_to_extend
    217
    218 	, function_name_pattern
    219 	;
    220
    221
    222 //		members of library	-----------------------------------------------
    223 ;
    224
    225
    226 /**
    227  * Global Scope object<br/>
    228  * 於 CeL.eval_code 使用
    229  * @ignore
    230  * @see
    231  * <a href="http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript" accessdate="2011/8/6 10:7">How to get the Global Object in JavaScript? - Stack Overflow</a>
    232  */
    233 var global = Function('return this')();	//	isWeb()?window:this;
    234
    235 old_namespace = global && global[library_name];
    236
    237
    238 /*
    239 var _Global=(function(){return this;})();
    240 _Global.JustANumber=2;	//	var _GlobalPrototype=_Global.constructor.prototype;_GlobalPrototype.JustANumber=2;
    241 if(typeof _Global=='undefined')_Global=this;
    242 for(i in _Global)alert(i);
    243 */
    244
    245 //	若已經定義過，跳過。因為已有對 conflict 的對策，因此跳過。
    246 //if(global[library_name] !== undefined) return;
    247
    248
    249 /**
    250  * Will speed up references to DOM: window, and allows redefining its name. (from jQuery)
    251  * @ignore
    252  */
    253 //window = this;
    254
    255
    256 /**
    257  * 本 JavaScript framework 的框架基本宣告<br/>
    258  * base name-space declaration of JavaScript library framework
    259  * @example
    260  * //	load library
    261  * <script type="text/javascript" src="../ce.js"></script>
    262  * //	預防 initialization 到一半彈出警告視窗，所以設大一點。
    263  * CeL.log.max_length = 20;
    264  * //	set debug
    265  * CeL.set_debug();
    266  *
    267  * //	判別是否已經 load 過
    268  * if(typeof CeL !== 'function' || CeL.Class !== 'CeL')
    269  * 	;	//	CeL has not been loaded
    270  * @name	CeL
    271  * @class	Colorless echo JavaScript kit/library: base name-space declaration
    272  */
    273 function _() {
    274 	//	function CeL: library root
    275 	//	declaration for debug
    276 	//this.global = arguments[0] || arguments.callee.ce_doc;
    277 	return new (this.init.apply(global, arguments));
    278 };
    279
    280
    281 //	name-space 歸屬設定
    282
    283 /**
    284  * Map over main name-space in case of overwrite (from jQuery)
    285  * @ignore
    286  */
    287 global[library_name] = _;
    288
    289 CeL
    290 .
    291 get_old_namespace = function(){
    292 	return old_namespace;
    293 };
    294
    295 CeL
    296 .
    297 recover_namespace = function(){
    298 	if (old_namespace === undefined)
    299 		delete global[library_name];
    300 	else
    301 		global[library_name] = old_namespace;
    302 	return _;
    303 };
    304
    305 if (typeof _.prototype !== 'object')
    306 	CeL
    307 	.
    308 	/**
    309 	 * framework main prototype definition
    310 	 * for JSDT: 有 prototype 才會將之當作 Class
    311 	 */
    312 	prototype = {
    313 	};
    314
    315
    316 CeL
    317 .
    318 /**
    319  * JavaScript library framework main class name.
    320  * @see	<a href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf">ECMA-262</a>: Object.Class: A string value indicating the kind of this object.
    321  * @constant
    322  */
    323 Class = library_name;
    324
    325
    326
    327
    328 CeL
    329 .
    330 /**
    331  * 本 library 專用之 evaluate()。
    332  *
    333  * 若在 function 中 eval 以獲得 local variable，在舊 browser 中須加 var。
    334  * e.g., 'var local_variable=' + ..
    335  * 不加 var 在舊 browser 中會變成 global 變數。
    336  * @param code	script code to evaluate
    337  * @returns	value that evaluate process returned
    338  * @see	window.eval === window.parent.eval
    339  * http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript
    340  */
    341 eval_code = function eval_code(code) {
    342 	/*
    343 		JSC eval() takes an optional second argument which can be 'unsafe'.
    344 		Mozilla/SpiderMonkey eval() takes an optional second argument which is the scope object for new symbols.
    345
    346 		use window.execScript(code,"JavaScript") in IE: window.execScript() 將直接使用全局上下文環境，因此，execScript(Str)中的字符串Str可以影響全局變量。——也包括聲明全局變量、函數以及對象構造器。
    347 	*/
    348 	//this.debug(global.eval, 2);
    349 	//this.debug(global && global.eval && global.eval !== arguments.callee);
    350 	return global && global.eval && global.eval !== eval_code ? global.eval.call(global, code) : eval(code);
    351 };
    352
    353
    354 CeL
    355 .
    356 /**
    357  * evaluate @ Global scope.
    358  * By the ECMA-262, new Function() will 'Pass in the Global Environment as the Scope parameter.'
    359  * copy from jQuery core.js
    360  * @param code	script code to evaluate
    361  * @returns	value that evaluate process returned
    362  * @see
    363  * <a href="http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context" accessdate="2011/8/6 8:56">Eval JavaScript in a global context | Java.net</a>
    364  * use execScript on Internet Explorer
    365  */
    366 global_eval = new Function('code', 'return '
    367 		+ (global.execScript ? 'global.execScript('
    368 		: global.eval ? 'global.eval.call(global,'
    369 		: window && window.eval ? 'window.eval.call(window,'
    370 		: 'eval.call(null,')
    371 		+ 'code);');
    372
    373
    374
    375 CeL
    376 .
    377 /**
    378  * simple evaluates to get value of specified variable identifier name.
    379  * 不使用 eval().
    380  * @param {String} variable_name	variable identifier name. e.g., /[a-z\d$_]+(.[a-z\d_]+)+/i
    381  * @param {Object|Function} [name_space]	initialize name-space. default: global
    382  * @returns	value of specified variable identifier name
    383  * @since	2010/1/1 18:11:40
    384  * @note
    385  * 'namespace' 是 JScript.NET 的保留字
    386  *
    387  * 在兩個子層(a.b.c)下，這樣作效率較差 @User agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.29 Safari/533.4:
    388  * function(v){try{return(new Function('return('+v+')'))();}catch(e){}}
    389  */
    390 get_variable = function(variable_name, name_space) {
    391 	//this.debug('get value of [' + variable_name + ']');
    392 	if (typeof variable_name !== 'string' || !variable_name)
    393 		return variable_name;
    394
    395 	var i = 0,
    396 	//	TODO: 可處理 e.g., obj1  . obj2 [ ' obj3.4 * \[ ' ] [''] . obj5 [ " obj6 \" \' \] . " ]
    397 	//	or detect obj1 .. obj2
    398 	s = variable_name.split('.'),
    399 	l = s.length,
    400 	v = name_space ||
    401 		//this.env.global
    402 		global
    403 		;
    404 	//this.debug('global.' + this.Class + ' = ' + this.env.global[this.Class]);
    405
    406 	try {
    407 		while (i < l)
    408 			if (v)
    409 				// this.debug('to [' + s[i] + ']: ' + v[s[i]]),
    410 				v = v[s[i++]];
    411 			else
    412 				throw 1;
    413 	} catch (e) {
    414 		s[i - 1] = '<em>' + s[i - 1] + '</em><span class="debug_weaken">';
    415 		//alert(this.log.buffer.length+','+this.log.max_length+'\n'+this.debug);
    416 		this.debug('Cannot get [<span title="' + variable_name + '">' + s.join('.') + '</span></span>]!', 2, 'get_variable');
    417 		return;
    418 	}
    419
    420 	return v;
    421 };
    422
    423
    424
    425
    426 CeL
    427 .
    428 /**
    429  * 取得執行 script 之 path, 在 .hta 中取代 WScript.ScriptFullName。
    430  * @returns	{String}	執行 script 之 path
    431  * @returns	''	unknown environment
    432  */
    433 get_script_full_name = function() {
    434 	//	在 IE8, IE9 中，get_object_type.call(WScript) 為 '[object Object]' !!
    435 	return typeof WScript === 'object' && (!this.is_Object(WScript) || String(WScript) === 'Windows Script Host')
    436 				&& WScript.ScriptFullName
    437 		|| typeof location === 'object' && location === window.location && unescape(location.pathname)
    438 		|| '';
    439 };
    440
    441 CeL
    442 .
    443 /**
    444  * 取得執行 script 之名稱
    445  * @returns	{String} 執行 script 之 名稱
    446  * @returns	''	unknown environment
    447  */
    448 get_script_name = function() {
    449 	var n, i, j;
    450
    451 	//	在 IE8, IE9 中，get_object_type.call(WScript) 為 '[object Object]' !!
    452 	if (typeof WScript === 'object'
    453 		&& (!this.is_Object(WScript) || String(WScript) === 'Windows Script Host')) {
    454 		n = WScript.ScriptName;
    455 		i = n.lastIndexOf('.');
    456 		return i == -1 ? n : n.slice(0, i);
    457 	}
    458
    459 	if (typeof location === 'object' && location === window.location) {
    460 		n = unescape(location.pathname), j = n.lastIndexOf('.');
    461 		if (!(i = n.lastIndexOf('\\') + 1))
    462 			//	location.pathname 在 .hta 中會回傳 '\' 形式的 path
    463 			i = n.lastIndexOf('/') + 1;
    464 		return i < j ? n.slice(i, j) : n.slice(i);
    465 	}
    466
    467 	return typeof document === 'object' && document === window.document ? document.title : '';
    468 };
    469
    470
    471
    472
    473 /*
    474 測試各 type:
    475
    476 undefined:
    477 變數值存在且變數 'undefined' 存在時: variable === undefined
    478 否則: typeof(variable) === 'undefined'
    479
    480 number, boolean, string:
    481 typeof(variable) === '~'
    482
    483 ** NaN
    484 ** int/float
    485
    486 object:
    487 null
    488
    489 不同frame中的Array擁有不同的constructor
    490 */
    491 /**
    492  * A cache to the function we use to get the type of specified value.<br/>
    493  * Get the [[Class]] property of this object.<br/>
    494  * 不使用 Object.toString() 是怕被 overridden
    495  * @type	{Function}
    496  * @inner
    497  */
    498 var get_object_type = Object.prototype.toString;
    499
    500 CeL
    501 .
    502 /**
    503  * 判斷為何種 type。主要用在 Error, DOMException 等 native object 之判別。
    504  * @param	value	variable or class instance to test
    505  * @param	{String} [want_type]	type to compare: number, string, boolean, undefined, object, function
    506  * @param	{Boolean} [get_Class]	get the class name of a class(function) instance.
    507  * @returns	{Boolean}	The type is matched.
    508  * @returns	{String}	The type of value
    509  * @returns	{undefined}	error occurred
    510  * @example
    511  * CeL.is_type(value_to_test, 'Array');
    512  * @since	2009/12/14 19:50:14
    513  * @see
    514  * <a href="http://lifesinger.org/blog/2009/02/javascript-type-check-2/" accessdate="2009/12/6 19:10">JavaScript类型检测小结（下） - 岁月如歌</a><br/>
    515  * <a href="http://thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/" accessdate="2009/12/6 19:10">Perfection kills » `instanceof` considered harmful (or how to write a robust `isArray`)</a>
    516  */
    517 is_type = function(value, want_type, get_Class) {
    518 	var type;
    519 	if (want_type && (type = typeof want_type) !== 'string')
    520 		want_type = type;
    521
    522 	type = value === null ? String(value) : typeof value;
    523
    524 	if (get_Class)
    525 		try {
    526 			if(type === 'function' && value.Class)
    527 				//	get the class name of a class
    528 				//	若 value 為 function 時，測試其本身之 Class。
    529 				type = value.Class;
    530 			else if (type === 'function' || type === 'object')
    531 				if (('constructor' in value) && (get_Class = value.constructor).Class)
    532 					// get the class name of a class instance
    533 					// 若 value 為 function 且無 Class，或為 object 時，測試其 constructor 之 Class。
    534 					type = get_Class.Class;
    535 				else if (get_Class = this.get_function_name(get_Class))
    536 					// get Class by function name
    537 					type = get_Class;
    538 		} catch (e) {
    539 			this.err(this.Class + '.is_type: Fault to get ths class name of value!');
    540 		}
    541
    542 	if (type !== 'object')
    543 		//	type maybe 'unknown' or 'date'!
    544 		return want_type ? type === want_type.toLowerCase() : type;
    545
    546 	try {
    547 		get_Class = get_object_type.call(value);
    548 	} catch (e) {
    549 		this.err(this.Class + '.is_type: Fault to get object type of value!');
    550 		get_Class = '';
    551 	}
    552
    553 	if (want_type)
    554 		return get_Class === (want_type.charAt(0) === '[' ? want_type
    555 				: '[object ' + want_type + ']');
    556
    557 	if (want_type = get_Class.match(
    558 					/^\[object ([^\]]+)\]$/))
    559 		return want_type[1];
    560
    561 	return type;
    562 };
    563
    564
    565 CeL
    566 .
    567 /**
    568  * get a type test function
    569  * @param	{String} want_type	object type to compare
    570  * @param	{String} [toString_reference]	a reference name to Object.prototype.toString
    571  * @returns	{Function}	type test function
    572  * @since	2009/12/20 08:38:26
    573  * @example
    574  * // 大量驗證時，推薦另外在本身 scope 中造出捷徑：
    575  * this.OtS = Object.prototype.toString;
    576  * var is_Array = CeL.object_tester('Array', 'OtS');
    577  * // test
    578  * if(is_Array(value))
    579  * 	//	it's really a native Array
    580  * 	;
    581  */
    582 object_tester = function(want_type, toString_reference) {
    583 	var t = '[object ' + want_type + ']';
    584
    585 /*
    586 	return new Function('v', 'return "' + t + '"==='
    587 				+ (toString_reference ||
    588 						//	在 Google Chrome 中 'Object.prototype.toString' 可以與其 reference 同速度，但其他的 reference 會快些。
    589 						'Object.prototype.toString'
    590 						//'get_object_type'
    591 						)
    592 				+ '.call(v);');
    593 */
    594
    595 	return typeof toString_reference === 'string'
    596 		&& toString_reference ?
    597 			new Function('v', 'return "' + t
    598 				+ '"===' + toString_reference + '.call(v);')
    599
    600 			//	slow@Chrome
    601 			: function(v) { return t === get_object_type.call(v); };
    602 			//	faster@Chrome
    603 			//: new Function('v', 'return "' + t + '"===Object.prototype.toString.call(v);');
    604
    605 };
    606
    607 CeL
    608 .
    609 /**
    610  * Test if the value is a native Array.
    611  * @param	v	value to test
    612  * @returns	{Boolean}	the value is a native Array.
    613  * @since	2009/12/20 08:38:26
    614  */
    615 is_Array =
    616 	// _.object_tester('Array');
    617 	function(v) {
    618 		// instanceof 比 Object.prototype.toString 快
    619 		return v instanceof Array
    620 				|| get_object_type.call(v) === '[object Array]';
    621 	};
    622
    623 CeL
    624 .
    625 /**
    626  * Test if the value is a native Object.
    627  * TODO:
    628  * test null
    629  * @param	v	value to test
    630  * @returns	{Boolean}	the value is a native Object.
    631  * @since	2009/12/20 08:38:26
    632  */
    633 is_Object =
    634 	//	Object.prototype.toString.call(undefined) === '[object Object]' @ MSIE 6.0
    635 	get_object_type.call(undefined) === '[object Object]'?
    636 	function(v) {
    637 		return typeof v !== 'undefined'
    638 				&& get_object_type.call(v) === '[object Object]';
    639 	}
    640 	:
    641 	//_.object_tester('Object');
    642 	function(v) {
    643 		//	非如此不得與 jQuery 平起平坐…
    644 		return get_object_type.call(v) === '[object Object]';
    645 	};
    646
    647 CeL
    648 .
    649 /**
    650  * Test if the value is a native Function.
    651  * @param	v	value to test
    652  * @returns	{Boolean}	the value is a native Function.
    653  * @since	2009/12/20 08:38:26
    654  */
    655 is_Function =
    656 	//_.object_tester('Function');
    657 	function(v) {
    658 		//	typeof 比 Object.prototype.toString 快，不過得注意有些 native object 可能 type 是 'function'，但不具有 function 特性。
    659 		return get_object_type.call(v) === '[object Function]';
    660
    661 		//	須注意，在 firefox 3 中，typeof [object HTMLObjectElement] 之外的 HTMLElement 皆 === 'function'，
    662 		//	因此光用 typeof() === 'function' 而執行下去會得出 [XPCWrappedNative_NoHelper] Component is not available
    663 		//return typeof v === 'function' || get_object_type.call(v) === '[object Function]';
    664 	};
    665
    666
    667 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    668
    669
    670 CeL
    671 .
    672 /**
    673  * 取得/設定環境變數 enumeration<br/>
    674  * （雖然不喜歡另開 name-space，但以 2009 當下的 JsDoc Toolkit 來說，似乎沒辦法創造 enumeration。）
    675  * @class	環境變數 (environment variables) 與程式會用到的 library 相關變數 / configuration。
    676  * @param {String} name	環境變數名稱
    677  * @param value	環境變數之值
    678  * @returns	舊環境變數之值
    679  * @memberOf	CeL
    680  */
    681 env = function env(name, value) {
    682 	if (!name)
    683 		//return undefined;
    684 		return;
    685
    686 	var _s = env, v = _s[name];
    687
    688 	if (arguments.length > 1) _s[name] = value;
    689 	//if (typeof value !== 'undefined') _s[name] = value;
    690
    691 	return isNaN(v) ? String(v) : v;
    692 };
    693
    694
    695 CeL
    696 .
    697 /**
    698  * Setup environment variables
    699  * @param	{String} [OS_type]	type of OS
    700  * @param	{Boolean} [reset]	reset the environment variables
    701  * @returns	{Object}	environment variables set
    702  */
    703 initial_env = function(OS_type, reset){
    704 	if (reset)
    705 		this.env = {};
    706
    707 	var OS, env = this.env;
    708
    709 	/**
    710 	 * default extension of script file.
    711 	 * 設定成 '.' 時由 CeL.get_script_base_path 設定
    712 	 * @type	String
    713 	 * @see
    714 	 * <a href="http://soswitcher.blogspot.com/2009/05/blogger-host-javascript-file-for-free.html" accessdate="2010/3/11 23:30">Blogger - Host Javascript File for Free - Blogger,Javascript - Blogger Blog by Switcher</a>
    715 	 * @name	CeL.env.script_extension
    716 	 */
    717 	env.script_extension = typeof WScript === 'undefined' ? '.' : '.js';//'.txt'
    718
    719 	/**
    720 	 * library main file base name
    721 	 * @name	CeL.env.main_script_name
    722 	 * @type	String
    723 	 */
    724 	env.main_script_name = 'ce';
    725
    726 	/**
    727 	 * library main file name<br/>
    728 	 * full path: {@link CeL.env.registry_path} + {@link CeL.env.main_script}
    729 	 * @example:
    730 	 * CeL.log('full path: ['+CeL.env.registry_path+CeL.env.main_script+']');
    731 	 * @name	CeL.env.main_script
    732 	 * @type	String
    733 	 */
    734 	env.main_script = env.main_script_name + env.script_extension;
    735
    736 	/**
    737 	 * module 中的這 member 定義了哪些 member 不被 extend
    738 	 * @name	CeL.env.not_to_extend_keyword
    739 	 * @type	String
    740 	 */
    741 	env.not_to_extend_keyword = 'no_extend';
    742
    743 	/**
    744 	 * 本 library source 檔案使用之 encoding<br/>
    745 	 * 不使用會產生語法錯誤
    746 	 * @name	CeL.env.source_encoding
    747 	 * @type	String
    748 	 */
    749 	env.source_encoding = 'UTF-16';
    750
    751 	/**
    752 	 * default global object.
    753 	 * 有可能為 undefined!
    754 	 * @name	CeL.env.global
    755 	 * @type	Object
    756 	 */
    757 	env.global = global;
    758
    759 	/**
    760 	 * creator group / 組織名稱 organization name
    761 	 * @name	CeL.env.organization
    762 	 * @type	String
    763 	 */
    764 	env.organization = 'Colorless echo';
    765
    766 	/**
    767 	 * 在 registry 中存放 library 資料的 base path
    768 	 * @name	CeL.env.registry_base
    769 	 * @type	String
    770 	 */
    771 	env.registry_base = 'HKCU\\Software\\' + env.organization + '\\' + this.Class
    772 				+ '\\';
    773 	/**
    774 	 * 在 registry 中存放 library 在 File System 中的 base path 的 key name
    775 	 * @name	CeL.env.registry_base
    776 	 * @type	String
    777 	 */
    778 	env.registry_path_key_name = env.registry_base + 'path';
    779 	//if(typeof WScript === 'object')
    780 	try {
    781 		//WScript.Echo(env.registry_path_key_name);
    782
    783 		/**
    784 		 * 存放在 registry 中的 path，通常指的是 library 在 File System 中的 base path
    785 		 * @name	CeL.env.registry_path
    786 		 * @type	String
    787 		 */
    788 		env.registry_path = (WScript.CreateObject("WScript.Shell"))
    789 			.RegRead(env.registry_path_key_name)
    790 			// 去除 filename
    791 			//.replace(/[^\\\/]+$/, '')
    792 			;
    793 		//this.debug(env.registry_path);
    794 	} catch (e) {
    795 		// this.warn(e.message);
    796 	}
    797
    798
    799 	//條件式編譯(条件コンパイル) for version>=4, 用 /*@ and @*/ to 判別
    800 	/*@cc_on
    801 	@if(@_PowerPC||@_mac)
    802 	 OS='Mac';
    803 	@else
    804 	 @if(@_win32||@_win64||@_win16)
    805 	  OS='DOS';
    806 	 @else
    807 	  OS='unix';	//	unknown
    808 	 @end
    809 	@end@*/
    810
    811 	/**
    812 	 * 本次執行所在 OS 平台
    813 	 * @name	CeL.env.OS
    814 	 * @type	String
    815 	 */
    816 	env.OS = OS = typeof OS_type === 'string' ? OS_type
    817 			// 假如未設定則取預設值
    818 			: (OS || 'unix');
    819
    820 	/**
    821 	 * 文件預設 new line
    822 	 * @name	CeL.env.new_line
    823 	 * @type	String
    824 	 */
    825 	env.new_line=		OS == 'unix' ? '\n' : OS == 'Mac' ? '\r' : '\r\n';	//	in VB: vbCrLf
    826 	/**
    827 	 * file system 預設 path separator<br/>
    828 	 * platform-dependent path separator character, 決定目錄(directory)分隔
    829 	 * @name	CeL.env.path_separator
    830 	 * @type	String
    831 	 */
    832 	env.path_separator	=	OS == 'unix' ? '/' : '\\';
    833 	/**
    834 	 * 預設 module name separator
    835 	 * @name	CeL.env.module_name_separator
    836 	 * @type	String
    837 	 */
    838 	env.module_name_separator = '.';
    839 	/**
    840 	 * path_separator in 通用(regular)運算式
    841 	 * @name	CeL.env.path_separator_RegExp
    842 	 * @type	RegExp
    843 	 */
    844 	env.path_separator_RegExp = this.to_RegExp_pattern ? this
    845 			.to_RegExp_pattern(env.path_separator)
    846 			: (env.path_separator === '\\' ? '\\' : '') + env.path_separator;
    847 	/**
    848 	 * 預設語系
    849 	 * 0x404:中文-台灣,0x0411:日文-日本
    850 	 * @name	CeL.env.locale
    851 	 * @see	<a href="http://msdn.microsoft.com/zh-tw/library/system.globalization.cultureinfo(VS.80).aspx">CultureInfo 類別</a>
    852 	 * @type	Number
    853 	 */
    854 	env.locale = 0x404;
    855
    856 	/**
    857 	 * script name
    858 	 * @name	CeL.env.script_name
    859 	 * @type	String
    860 	 */
    861 	env.script_name = this.get_script_name();
    862 	/**
    863 	 * base path of script.
    864 	 * TODO
    865 	 * 以 reg 代替
    866 	 * @name	CeL.env.script_base_path
    867 	 * @type	String
    868 	 */
    869 	env.script_base_path = this.get_script_full_name()
    870 		// 去除 filename
    871 		.replace(/[^\\\/]+$/, '');
    872
    873 	/**
    874 	 * Legal identifier name in RegExp.
    875 	 * 這 pattern 會佔去兩個筆紀錄: first letter, and least.
    876 	 * .replace(/_/ [g],'for first letter')
    877 	 * .replace(/\\d/,'for least')
    878 	 * 這邊列出的只是合法 identifier 的*子集*，且未去除 reserved words!
    879 	 * 請注意實際判別須加入 ^..$
    880 	 *
    881 	 * 不用 \d 而用 0-9 是因為 \d 還包括了 MATHEMATICAL BOLD DIGIT。
    882 	 * <a href="http://blog.est.im/archives/3229" accessdate="2010/11/16 20:6">基于正则的URL匹配安全性考虑</a>
    883 	 * @name	CeL.env.identifier_RegExp
    884 	 * @see
    885 	 * ECMA-262	7.6 Identifier Names and Identifiers
    886 	 * @type	RegExp
    887 	 */
    888 	env.identifier_RegExp = /([a-zA-Z$_]|\\u[0-9a-fA-F]{4})([a-zA-Z$_0-9]+|\\u[0-9a-fA-F]{4}){0,63}/;
    889
    890 	/**
    891 	 * Legal identifier name in String from env.identifier_RegExp.
    892 	 * @name	CeL.env.identifier_String
    893 	 */
    894 	env.identifier_String = env.identifier_RegExp.source;
    895
    896 	return env;
    897 };
    898
    899
    900 CeL
    901 .
    902 //	TODO
    903 get_identifier_RegExp = function(pattern, flag, add_for_first_letter, add_for_all_letter) {
    904 	var s = this.env.identifier_String;
    905 	if (add_for_first_letter)
    906 		s = s.replace(/_/g, add_for_first_letter);
    907 	if (add_for_all_letter)
    908 		s = s.replace(/0-9/g, add_for_all_letter);
    909
    910 	return new RegExp(
    911 			(get_object_type.call(pattern) === '[object RegExp]' ? pattern.source : pattern)
    912 				.replace(/$identifier/g, s), flag || '');
    913 };
    914
    915
    916 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    917
    918
    919 CeL
    920 .
    921 /**
    922  * Tell if it's now debugging.
    923  * @param {Integer} [debug_level]	if it's now in this debug level.
    924  * @returns	{Boolean}	It's now in specified debug level.
    925  * @returns	{Number}	It's now in what debug level (Integer).
    926  */
    927 is_debug = function(debug_level){
    928 	return typeof debug_level === 'undefined' ? debug
    929 				: debug >= debug_level;
    930 };
    931
    932 CeL
    933 .
    934 /**
    935  * Set debugging level
    936  * @param {Integer} [debug_level]	The debugging level to set.
    937  * @type	Integer
    938  * @returns	{Number} debugging level now
    939  */
    940 set_debug = function (debug_level) {
    941 	if (!isNaN(debug_level))
    942 		debug = debug_level;
    943
    944 	else if (typeof debug_level === 'undefined' && !debug)
    945 		debug = 1;
    946
    947 	return debug;
    948 };
    949
    950
    951 /*
    952 CeL.extend(function f_name(){}, object || string, initial arguments);
    953 CeL.extend({name:function(){},.. }, object || string);
    954 CeL.extend([function1,function12,..], object || string);
    955
    956 set .name
    957 */
    958
    959
    960
    961
    962
    963
    964
    965 CeL
    966 .
    967 /**
    968  * Get the hash key of text.
    969  * @param {String} text	text to test
    970  * @returns	{String}	hash key
    971  */
    972 _get_hash_key = function(text) {
    973 	//text = String(text);
    974 	//text = '' + text;
    975 	var l = text.length, take = 30, from = .3;
    976 	from = Math.floor(l * from);
    977 	//this.log(from + '~' + l + ': ' + (l - from < take ? text : text.substr(from, take)));
    978 	return l - from < take ? text : text.substr(from, take);
    979 };
    980
    981
    982 //	for JScript<=5
    983 try {
    984 	function_name_pattern = new RegExp('^function[\\s\\n]+(\\w+)[\\s\\n]*\\(');
    985 } catch (e) {
    986 	function_name_pattern = function emulate_function_name(fs) {
    987 		fs = String(fs);
    988 		var l = 'function ', r, s;
    989
    990 		if (fs.indexOf(l) === 0) {
    991 			l = l.length;
    992 			s = {
    993 					' ' : 1,
    994 					'\n' : 1,
    995 					'\r' : 1,
    996 					'\t' : 1
    997 			};
    998 			while (fs.charAt(l) in s)
    999 				l++;
    1000 			r = fs.indexOf('(', l);
    1001 			while (fs.charAt(--r) in s)
    1002 				;
    1003
    1004 			return [ , fs.slice(l, r + 1) ];
    1005 		}
    1006 	};
    1007 	if (typeof RegExp != 'object')
    1008 		eval('RegExp = function(){};');
    1009 }
    1010
    1011 CeL
    1012 .
    1013 /**
    1014  * 獲得函數名
    1015  * @param {Function} fr	function reference
    1016  * @param {String} ns	name-space
    1017  * @param {Boolean} force_load	force reload this name-space
    1018  * @returns
    1019  * @see
    1020  * 可能的話請改用 {@link CeL.native.parse_function}(F).funcName
    1021  * @since	2010/1/7 22:10:27
    1022  */
    1023 get_function_name = function(fr, ns, force_load) {
    1024 	var _s = _.get_function_name,
    1025 	//	初始化變數 'm'
    1026 	m = 0, ft, b, load, k, i;
    1027 	if (!fr)
    1028 		try{
    1029 			fr = _s.caller;
    1030 		}catch (e) {
    1031 			// TODO: handle exception
    1032 		}
    1033
    1034 	//	get function text (函數的解譯文字)
    1035 	//	不用 insteadof 是怕傳入奇怪的東西，例如 {string} script code
    1036 	m = typeof fr;
    1037 	if (m === 'function') {
    1038 		//	勿更改傳入之 argument
    1039 		/*
    1040 		if ('toString' in fr) {
    1041 			m = fr.toString;
    1042 			delete fr.toString;
    1043 		}
    1044 		ft = String(fr);
    1045 		if (m)
    1046 			fr.toString = m;
    1047 		*/
    1048 		//	TODO: cache Function.prototype.toString
    1049 		ft = Function.prototype.toString.call(fr);
    1050 	} else if(m === 'string')
    1051 		// typeof fr === 'string'
    1052 		ft = fr;
    1053 	else
    1054 		return '';
    1055
    1056 	//	以函數的解譯文字獲得函數名
    1057 	if (m = function_name_pattern instanceof RegExp ?
    1058 			//	包含引數:	+ '(' + (f ? m[2] : '') + ')';
    1059 			((m = ft.match(function_name_pattern)) && m[1] || 0)
    1060 			: function_name_pattern instanceof Function ?
    1061 				function_name_pattern(ft)
    1062 				: 0){
    1063 		//this.debug('matched ' + m, 1, this.Class + '.get_function_name');
    1064 		return m;
    1065 	}
    1066 	//	無法從 function code 本身得到 name 之資訊。
    1067
    1068 	//	查詢是否是已註冊之 function
    1069 	if (b = _s.b)
    1070 		load = _s.ns;
    1071 	else
    1072 		_s.b = b = {}, _s.ns = load = {};
    1073
    1074 	if (!ns)
    1075 		ns = this;
    1076
    1077 	//	cache functions
    1078 	if ((typeof ns === 'function' || this.is_Object(ns)) && ns.Class
    1079 					&& (force_load || !load[ns.Class])) {
    1080 		for (i in ns)
    1081 			if (typeof ns[i] === 'function'){
    1082 				k = this._get_hash_key(String(ns[i]));
    1083 				m = ns.Class + this.env.module_name_separator + i;
    1084 				//this.debug(m + ': ' + k + (', ' + ns[i]).slice(0, 200));
    1085 				if(!(m in load)){
    1086 					load[m] = 1;
    1087 					if (!b[k])
    1088 						b[k] = [];
    1089 					b[k].push( [ m, ns[i] ]);
    1090 				}
    1091 			}
    1092 		load[ns.Class] = 1;
    1093 	}
    1094
    1095 	//	將函數與 cache 比對以獲得函數名
    1096 	if (m = b[this._get_hash_key(ft)])
    1097 		for (i = 0; i < m.length; i++) {
    1098 			b= m[i][1];
    1099 			if (// typeof fr === 'function' &&
    1100 					fr === b)
    1101 				return m[i][0];
    1102 			if (ft === String(b))
    1103 				return m[i];
    1104 		}
    1105 };
    1106
    1107
    1108
    1109
    1110
    1111
    1112
    1113 CeL
    1114 .
    1115 null_function = function() {};
    1116
    1117
    1118 //	Initialization
    1119
    1120 //	temporary decoration in case we call for nothing and raise error
    1121 _.debug = _.err = _.warn = _.log = function(m) {
    1122 	/*
    1123 	 * 請注意:
    1124 	 * _.log.buffer === this.log.buffer !== log.buffer
    1125 	 * 在 WScript 中 需要用 _.log，其他則可用 log。
    1126 	 * 因此應該將所有類似的值指定給雙方，並注意非[常數]的情況。
    1127 	 */
    1128 	var _s = this.log;
    1129 	//_s.function_to_call.apply(null,arguments);
    1130 	//_s.function_to_call.apply(global, arguments);
    1131
    1132 	_s.buffer.push(m);
    1133
    1134 	if (!_s.max_length)
    1135 		_s.max_length = 0;
    1136
    1137 	if (debug && _s.buffer.length > _s.max_length)
    1138 		_s.function_to_call.call(global, _s.buffer.join('\n\n')),
    1139 		_s.buffer = [];
    1140 };
    1141
    1142
    1143 /*
    1144  * test:
    1145  * var k=function l(){alert(l.m);};k.m=1;alert(l.m+','+k.m);k();
    1146  *
    1147  * JScript 中
    1148  * k();
    1149  * 為 undefined, 其他會把 "l." 代換成 "k."？
    1150  *
    1151  * @inner
    1152  */
    1153 //_.debug.buffer = _.err.buffer = _.warn.buffer =
    1154 _.log.buffer = [];
    1155
    1156
    1157 //_.debug.max_length = _.err.max_length = _.warn.max_length =
    1158 _.log.max_length = 0;
    1159
    1160
    1161 var max_log_length = 1000;
    1162 //_.debug.function_to_call = _.err.function_to_call = _.warn.function_to_call =
    1163 _.log.function_to_call =
    1164 	typeof JSalert === 'function' ? JSalert :
    1165 	typeof WScript === 'object' ? function(m){m=String(m);if(m.length>2*max_log_length)m=m.slice(0,max_log_length)+'\n\n..\n\n'+m.slice(-max_log_length);WScript.Echo(m);} :
    1166 	typeof alert === 'object' || typeof alert === 'function' ? function(m){m=String(m);if(m.length>2*max_log_length)m=m.slice(0,max_log_length)+'\n\n..\n\n'+m.slice(-max_log_length);alert(m);} :
    1167 	_.null_function;
    1168
    1169
    1170 _.initial_env();
    1171
    1172
    1173 /*
    1174 var test_obj = _(2, 'test: Initialization');
    1175
    1176 test_obj.test_print('OK!');
    1177 */
    1178 ;
    1179
    1180
    1181 }
    1182 )(
    1183 	//	In strict mode, this inside globe functions is undefined.
    1184 	//	https://developer.mozilla.org/en/JavaScript/Strict_mode
    1185 	//this	// || typeof window === 'undefined' || window
    1186 )
    1187 //)	//	void(
    1188 ;
    1189
    1190
    1191
    1192 //==========================================================================================================================================================//
    1193
    1194
    1195
    1196
    1197
    1198
    1199 /*
    1200 TODO:
    1201
    1202 瘦身
    1203
    1204 use -> using because of 'use' is a keyword of JScript.
    1205
    1206 等呼叫時才 initialization
    1207
    1208
    1209 http://headjs.com/#theory
    1210 Head JS :: The only script in your HEAD
    1211
    1212
    1213 do not use eval.
    1214 以其他方法取代 eval 的使用。
    1215
    1216 http://msdn.microsoft.com/en-us/library/2b36h1wa(VS.71).aspx
    1217 The arguments object is not available when running in fast mode, the default for JScript .NET. To compile a program from the command line that uses the arguments object, you must turn off the fast option by using /fast-. It is not safe to turn off the fast option in ASP.NET because of threading issues.
    1218
    1219
    1220 Multiversion Support
    1221 http://requirejs.org/docs/api.html
    1222
    1223 */
    1224
    1225
    1226 typeof CeL === 'function' &&
    1227 (function (_) {
    1228
    1229 'use strict';
    1230
    1231
    1232 //var _// JSDT:_module_
    1233 //= this;
    1234
    1235
    1236 CeL
    1237 .
    1238 /**
    1239  * 延展物件 (learned from jQuery):
    1240  * 將 from_name_space 下的 variable_set 延展/覆蓋到 name_space。
    1241  * @since	2009/11/25 21:17:44
    1242  * @param	variable_set	variable set
    1243  * @param	{Object|Function} name_space	extend to what name-space
    1244  * @param	{Object|Function} from_name_space	When inputing function names, we need a base name-space to search these functions.
    1245  * @returns	library names-pace
    1246  * @see
    1247  * <a href="http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/03/01/jquery-extend.aspx" accessdate="2009/11/17 1:24" title="jQuery.extend的用法 - 黑暗執行緒">jQuery.extend的用法</a>,
    1248  * <a href="http://www.cnblogs.com/rubylouvre/archive/2009/11/21/1607072.html" accessdate="2010/1/1 1:40">jQuery源码学习笔记三 - Ruby's Louvre - 博客园</a>
    1249  */
    1250 extend = function extend(variable_set, name_space, from_name_space) {
    1251 	var _s = extend, i, l;
    1252
    1253 	if(typeof name_space === 'undefined' || name_space === null)
    1254 		//	如果沒有指定擴展的對象，則擴展到 library 自身
    1255 		name_space = _s.default_target;
    1256
    1257 	if (typeof from_name_space === 'undefined')
    1258 		from_name_space = _s.default_target;
    1259 	else if (variable_set === null && _.is_Function(from_name_space))
    1260 		variable_set = from_name_space;
    1261
    1262 	if (typeof variable_set === 'function') {
    1263 		if (_.parse_function) {
    1264 		} else {
    1265 			_.warn('Warning: Please include ' + _.Class + '.parse_function() first!');
    1266 		}
    1267
    1268 	} else if (typeof variable_set === 'string') {
    1269 		if (!from_name_space)
    1270 			from_name_space = _;
    1271
    1272 		if(name_space === from_name_space)
    1273 			;
    1274 		else if(variable_set in from_name_space){
    1275 			//_.debug('extend (' + (typeof variable_set) + ') ' + variable_set + '\n=' + from_name_space[variable_set] + '\n\nto:\n' + name_space);
    1276 			name_space[variable_set] = from_name_space[variable_set];
    1277 		}else
    1278 			try{
    1279 				name_space[variable_set] = _.get_variable(variable_set);
    1280 				//_.debug(variable_set + ' = ' + name_space[variable_set]);
    1281 			}catch(e){
    1282 				_.warn(_.Class + '.extend:\n' + e.message);
    1283 			}
    1284
    1285 	} else if (_.is_Array(variable_set)
    1286 						&& !_.is_Array(name_space)) {
    1287 		for (i = 0, l = variable_set.length; i < l; i++) {
    1288 			_s(variable_set[i], name_space, from_name_space);
    1289 		}
    1290
    1291 	} else if (_.is_Object(variable_set)
    1292 			//|| _.is_Function(variable_set)
    1293 			) {
    1294 		for (i in variable_set) {
    1295 			if (from_name_space)
    1296 				name_space[i] = from_name_space[variable_set[i] || i];
    1297 			else
    1298 				name_space[i] = variable_set[i];
    1299 		}
    1300 	}
    1301
    1302 	return _;
    1303 };
    1304
    1305 //_.extend.default_target = _;
    1306
    1307
    1308 CeL
    1309 .
    1310 /**
    1311  * workaround.
    1312  * 把 name_space 下的 function_name (name_space[function_name]) 換成 new_function。
    1313  * for Lazy Function Definition Pattern.
    1314  * 惰性求值（Lazy Evaluation），又稱懶惰求值、懶漢求值
    1315  * @example
    1316  * library_namespace.replace_function(_, 'to_SI_prefix', to_SI_prefix);
    1317  * @param name_space	in which name-space
    1318  * @param {String} function_name	name_space.function_name
    1319  * @param {Function} new_function	replace to what function
    1320  * @returns	new_function
    1321  * @see
    1322  * http://realazy.org/blog/2007/08/16/lazy-function-definition-pattern/,
    1323  * http://peter.michaux.ca/article/3556
    1324  */
    1325 replace_function = function(name_space, function_name, new_function) {
    1326 	if(!name_space)
    1327 		return;//name_space = this;
    1328
    1329 	var old_function = name_space[function_name], type = typeof new_function;
    1330
    1331 	//	TODO: RegExp
    1332 	if (type === 'bool' || type === 'string' || type === 'number')
    1333 		new_function = new Function('return'
    1334 				//	對 String 只是做簡單處理，勢必得再加強。
    1335 				+ (type === 'string' ? '"' + type.replace(/\\/g, '\\').replace(/"/g, '\"').replace(/\n/g, '\\n')
    1336 						+ '"' : ' '+type));
    1337
    1338 	name_space[function_name] = new_function;
    1339 	//	search for other extends
    1340 	if (_[function_name] === old_function)
    1341 		_[function_name] = new_function;
    1342
    1343 	return new_function.apply(name_space, arguments);
    1344 };
    1345
    1346
    1347 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    1348
    1349 /**
    1350  * XMLHttpRequest object type cache.
    1351  * {Number} 0: no XMLHttpRequest, 1: new XMLHttpRequest_type(), 2: new ActiveXObject('Microsoft.XMLHTTP').
    1352  * @inner
    1353  * @ignore
    1354  */
    1355 var XMLHttpRequest_type = 0;
    1356 try{
    1357 	if(new XMLHttpRequest())
    1358 		XMLHttpRequest_type = 1;
    1359 	else
    1360 		throw 1;
    1361 }catch(e){
    1362 	try{
    1363 		if(new ActiveXObject('Microsoft.XMLHTTP'))
    1364 			XMLHttpRequest_type = 2;
    1365 	}catch(e){
    1366 	}
    1367 }
    1368
    1369 var is_Opera = typeof navigator === 'object'
    1370 	&& navigator.appName === 'Opera';
    1371
    1372 CeL
    1373 .
    1374 /**
    1375  * Get file resource by {@link XMLHttpRequest}<br/>
    1376  * 依序載入 resource，用於 include JavaScript 檔之類需求時，取得檔案內容之輕量級函數。<br/>
    1377  * 除 Ajax，本函數亦可用在 CScript 執行中。
    1378  * @example
    1379  * //	get contents of [path/to/file]:
    1380  * var file_contents = CeL.get_file('path/to/file');
    1381  * @param	{String} path	URI / full path. <em style="text-decoration:line-through;">不能用相對path！</em>
    1382  * @param	{String} [encoding]	file encoding
    1383  * @returns	{String} data	content of path
    1384  * @returns	{undefined}	when error occurred: no Ajax function, ..
    1385  * @throws	uncaught exception @ Firefox: 0x80520012 (NS_ERROR_FILE_NOT_FOUND), <a href="http://www.w3.org/TR/2007/WD-XMLHttpRequest-20070227/#exceptions">NETWORK_ERR</a> exception
    1386  * @throws	'Access to restricted URI denied' 當 access 到上一層目錄時 @ Firefox
    1387  * @see
    1388  * <a href=http://blog.joycode.com/saucer/archive/2006/10/03/84572.aspx">Cross Site AJAX</a>,
    1389  * <a href="http://domscripting.com/blog/display/91">Cross-domain Ajax</a>,
    1390  * <a href="http://forums.mozillazine.org/viewtopic.php?f=25&t=737645" accessdate="2010/1/1 19:37">FF3 issue with iFrames and XSLT standards</a>,
    1391  * <a href="http://kb.mozillazine.org/Security.fileuri.strict_origin_policy" accessdate="2010/1/1 19:38">Security.fileuri.strict origin policy - MozillaZine Knowledge Base</a>
    1392  * Chrome: <a href="http://code.google.com/p/chromium/issues/detail?id=37586" title="between builds 39339 (good) and 39344 (bad)">NETWORK_ERR: XMLHttpRequest Exception 101</a>
    1393  */
    1394 get_file = XMLHttpRequest_type ? function(path, encoding) {
    1395 	//with(typeof window.XMLHttpRequest=='undefined'?new ActiveXObject('Microsoft.XMLHTTP'):new XMLHttpRequest()){
    1396
    1397 	//_.debug('XMLHttpRequest type: ' + XMLHttpRequest_type, 1, 'get_file');
    1398
    1399 	var _s = _.get_file,
    1400 	data,
    1401 	type = 'GET',
    1402 	/**
    1403 	 * XMLHttpRequest object.
    1404 	 * Can't cache this object.
    1405 	 * @inner
    1406 	 * @ignore
    1407 	 */
    1408 	o = XMLHttpRequest_type === 1 ?
    1409 			new XMLHttpRequest()
    1410 			: new ActiveXObject('Microsoft.XMLHTTP');
    1411
    1412 	//	4096: URL 長度限制，與瀏覽器有關。
    1413 	if (typeof path === 'string' && path.length > 4096
    1414 			&& (data = path.match(/^([^?]{6,200})\?(.+)$/)))
    1415 		path = data[1], data = data[2], type = 'PUT';
    1416 	else
    1417 		data = null;
    1418
    1419 	o.open(type, path, false);
    1420
    1421 	if (encoding && o.overrideMimeType)
    1422 		/*
    1423 		 * old: o.overrideMimeType('text/xml;charset='+encoding);
    1424 		 * 但這樣會被當作 XML 解析，產生語法錯誤。
    1425 		 */
    1426 		o.overrideMimeType('application/json;charset=' + encoding);
    1427
    1428 	try {
    1429 		//	http://www.w3.org/TR/2007/WD-XMLHttpRequest-20070227/#dfn-send
    1430 		//	Invoking send() without the data argument must give the same result as if it was invoked with null as argument.
    1431 		o.send(data);
    1432 		delete _s.error;
    1433
    1434 	} catch (e) {
    1435 		//	Chome: XMLHttpRequest cannot load file:///X:/*.js. Cross origin requests are only supported for HTTP.
    1436 		//	Opera 11.50: 不會 throw，但是 .responseText === ''。
    1437 		//	Apple Safari 3.0.3 may throw NETWORK_ERR: XMLHttpRequest Exception 101
    1438 		_s.error = e;
    1439
    1440 		//_.warn(_.Class + '.get_file: Loading [' + path + '] failed: ' + e);
    1441 		//_.err(e);
    1442 		//_.debug('Loading [' + path + '] failed.');
    1443
    1444 		//e.object = o;	//	[XPCWrappedNative_NoHelper] Cannot modify properties of a WrappedNative @ firefox
    1445
    1446 		if (typeof location === 'object'
    1447 						&& (o = path.match(/:(\/\/)?([^\/]+)/))
    1448 						&& o[2] !== location.hostname) {
    1449 			_.warn('get_file: 所要求檔案之 domain [' + o[2]
    1450 						+ '] 與所處之 domain [' + location.hostname + '] 不同!<br/>\n您可能需要嘗試使用 '
    1451 						+ _.Class + '.include_resource()!');
    1452 			throw new Error('get_file: Different domain!');
    1453 		}
    1454
    1455 		o = _.require_netscape_privilege(e, [_s, arguments]);
    1456 		//_.debug('require_netscape_privilege return [' + typeof (o) + ('] ' + o).slice(0, 200) + ' ' + (e === o ? '=' : '!') + '== ' + 'error (' + e + ')');
    1457 		if (e === o)
    1458 			throw e;
    1459
    1460 		return o;
    1461 	}
    1462
    1463 	//	workaround for Opera: Opera 11.50: 不會 throw，但是 .responseText === ''。
    1464 	if (o.responseText === '' && is_Opera)
    1465 		throw new Error('get_file: Nothing get @ Opera');
    1466
    1467 	//	當在 local 時，成功的話 status === 0。失敗的話，除 IE 外，status 亦總是 0。
    1468 	//	status was introduced in Windows Internet Explorer 7.	http://msdn.microsoft.com/en-us/library/ms534650%28VS.85%29.aspx
    1469 	//	因此，在 local 失敗時，僅 IE 可由 status 探測，其他得由 responseText 判別。
    1470 	//_.debug('Get [' + path + '], status: [' + o.status + '] ' + o.statusText);
    1471
    1472 	return Math.floor(o.status / 100) > 3 ? [ o.status, o.responseText ] : o.responseText;
    1473 }
    1474 : function() {
    1475 	//	No XMLHttpRequest object.
    1476
    1477 	throw new Error('get_file: This browser does not support XMLHttpRequest.');
    1478 	//	firefox: This function must return a result of type any.
    1479 	//return undefined;
    1480 };
    1481
    1482
    1483 CeL
    1484 .
    1485 /**
    1486  * Ask privilege in mozilla projects: Firefox 2, 3.
    1487  * get_file() 遇到需要提高權限時使用。
    1488  * enablePrivilege 似乎只能在執行的 function 本身或 caller 呼叫才有效果，跳出函數即無效，不能 cache，因此提供 callback。
    1489  * 就算按下「記住此決定」，重開瀏覽器後需要再重新授權。
    1490  * @param {String|Error} privilege	privilege that asked 或因權限不足導致的 Error
    1491  * @param {Function|Array} callback|[callback,arguments]	Run this callback if getting the privilege. If it's not a function but a number(經過幾層/loop層數), detect if there's a loop or run the caller.
    1492  * @returns	OK / the return of callback
    1493  * @throws	error
    1494  * @since	2010/1/2 00:40:42
    1495  */
    1496 require_netscape_privilege = function require_netscape_privilege(privilege, callback) {
    1497 	var _s = require_netscape_privilege, f, i,
    1498 	/**
    1499 	 * raise error.
    1500 	 * error 有很多種，所以僅以 'object' 判定。
    1501 	 * @inner
    1502 	 * @ignore
    1503 	 */
    1504 	re = function(m) {
    1505 		//_.debug('Error: ' + m);
    1506 		throw privilege && typeof privilege === 'object' ?
    1507 			//	Error object
    1508 			privilege :
    1509 			//	new Error (message)
    1510 			new Error(m);
    1511 	};
    1512
    1513 	if (!_s.enabled)
    1514 		re('Privilege requiring disabled.');
    1515
    1516 	//	test loop
    1517 	//	得小心使用: 指定錯可能造成 loop!
    1518 	if (!isNaN(callback) && callback > 0 && callback < 32) {
    1519 		try{
    1520 			//	@Firefox 4: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
    1521 			for (f = _s, i = 0; i < callback; i++)
    1522 				if (f = f.caller)
    1523 					//	TODO: do not use arguments
    1524 					f = f.arguments.callee;
    1525
    1526 			if (f === _s)
    1527 				// It's looped
    1528 				re('Privilege requiring looped.');
    1529
    1530 			callback = 1;
    1531
    1532 		}catch (e) {
    1533 			// TODO: handle exception
    1534 		}
    1535
    1536 	}
    1537
    1538 	f = _s.enablePrivilege;
    1539 	//_.debug('enablePrivilege: ' + f);
    1540 	if (!f && !(_s.enablePrivilege = f =
    1541 					_.get_variable('netscape.security.PrivilegeManager.enablePrivilege')))
    1542 		//	更改設定，預防白忙。
    1543 		_s.enabled = false,
    1544 		re('No enablePrivilege get.');
    1545
    1546 	if (_.is_type(privilege, 'DOMException')
    1547 					&& privilege.code === 1012)
    1548 		//	http://jck11.pixnet.net/blog/post/11630232
    1549 		//	Mozilla的安全機制是透過PrivilegeManager來管理，透過PrivilegeManager的enablePrivilege()函式來開啟這項設定。
    1550 		//	須在open()之前呼叫enablePrivilege()開啟UniversalBrowserRead權限。
    1551
    1552 		//	http://code.google.com/p/ubiquity-xforms/wiki/CrossDomainSubmissionDeployment
    1553 		//	Or: In the URL type "about:config", get to "signed.applets.codebase_principal_support" and change its value to true.
    1554
    1555 		//	由任何網站或視窗讀取私密性資料
    1556 		privilege = 'UniversalBrowserRead';
    1557
    1558 	else if (!privilege || typeof privilege !== 'string')
    1559 		re('Unknown privilege.');
    1560
    1561 	//_.debug('privilege: ' + privilege);
    1562 	try {
    1563 		//_.log(_.Class + '.require_netscape_privilege: Asking privilege [' + privilege + ']..');
    1564 		f(privilege);
    1565 	} catch (e) {
    1566 		if (privilege !== 'UniversalBrowserRead' || !_.is_local())
    1567 			_.warn(_.Class + '.require_netscape_privilege: User denied privilege [' + privilege + '].');
    1568 		throw e;
    1569 	}
    1570
    1571 	//_.debug('OK. Get [' + privilege + ']');
    1572
    1573
    1574 	if (callback === 1) {
    1575 		//_.debug('再執行一次 caller..');
    1576 		try{
    1577 			callback = _s.caller;
    1578 		}catch (e) {
    1579 			// TODO: handle exception
    1580 		}
    1581 		return callback.apply(_, callback.arguments);
    1582
    1583 /*		i = callback.apply(_, callback.arguments);
    1584 		_.debug(('return ' + i).slice(0, 200));
    1585 		return i;
    1586 */
    1587 	} else if (_.is_Function(callback))
    1588 		// 已審查過，為 function
    1589 		return callback();
    1590 	else if (_.is_Array(callback))
    1591 		return callback[0].apply(_, callback[1]);
    1592 };
    1593
    1594 CeL
    1595 .
    1596 /**
    1597  * 當需要要求權限時，是否執行。（這樣可能彈出對話框）
    1598  * Firefox 5 之後，就算要求了，對 local 也沒用，甚至會 hang 住掛掉，因此取消了。
    1599  * @type	Boolean
    1600  */
    1601 require_netscape_privilege.enabled = false;
    1602
    1603
    1604 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    1605
    1606
    1607 CeL
    1608 .
    1609 /**
    1610  * 得知 script file 之相對 base path
    1611  * @param	{String} JSFN	script file name
    1612  * @returns	{String} relative base path
    1613  * @example
    1614  * <script type="text/javascript" src="../baseFunc.js"></script>
    1615  * //	引數為本.js檔名。若是更改.js檔名，亦需要同步更動此值！
    1616  * var basePath=get_script_base_path('baseFunc.js');
    1617  * perl: use File::Basename;
    1618  */
    1619 get_script_base_path = function(JSFN){
    1620 	//alert(JSFN);
    1621 	if(!JSFN)
    1622 		return (typeof location === 'object' ?
    1623 				// location.pathname
    1624 				location.href
    1625 				: typeof WScript === 'object' ? WScript.ScriptFullName
    1626 				//	用在把檔案拉到此檔上時不方便
    1627 				//: typeof WshShell === 'object' ? WshShell.CurrentDirectory
    1628 				: '').replace(/[^\/\\]+$/, '');
    1629
    1630 	//	We don't use is_Object or so.
    1631 	//	通常會傳入的，都是已經驗證過的值，不會出現需要特殊認證的情況。
    1632 	//	因此精確繁複的驗證只用在可能輸入奇怪引數的情況。
    1633 	if (typeof document !== 'object')
    1634 			return '';
    1635
    1636 	//	form dojo: d.config.baseUrl = src.substring(0, m.index);
    1637 	var i = 0, o = document.getElementsByTagName('script'), l = o.length, j, b, I;
    1638
    1639 	for (; i < l; i++)
    1640 		try {
    1641 			//	o[i].src 多是 full path, o[i].getAttribute('src') 僅取得其值，因此可能是相對的。
    1642 			j = o[i].getAttribute ? o[i].getAttribute('src') : o[i].src;
    1643 			I = j.lastIndexOf(JSFN);
    1644 			//alert(j + ',' + JSFN + ',' + I);
    1645 			if (I !== -1){
    1646 				//	TODO: dirty hack
    1647 				if (_.env.script_extension === '.') {
    1648 					b = j.slice(I + JSFN.length);
    1649 					if (b === 'js' || b === 'txt')
    1650 						_.env.script_extension += b,
    1651 						_.env.main_script += b;
    1652 					else{
    1653 						b = '';
    1654 						//	遇到奇怪的 extension
    1655 						continue;
    1656 					}
    1657 				}
    1658 				//	TODO: test 是否以 JSFN 作為結尾
    1659 				b = j.slice(0, I);
    1660 			}
    1661 		} catch (e) {
    1662 		}
    1663
    1664 	//_.log()
    1665
    1666 	//	b || './'
    1667 	return b || '';
    1668 };
    1669
    1670
    1671 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    1672
    1673
    1674 CeL
    1675 .
    1676 /**
    1677  * test 是否符合 module pattern.
    1678  * TODO: improve
    1679  * @param {String} test_string	string to test
    1680  * @returns	{Boolean}	是否符合 module pattern
    1681  */
    1682 is_module_pattern = function(test_string){
    1683 	var r = _.env.module_identifier_RegExp;
    1684 	if (!r) {
    1685 		//	initial module_identifier_RegExp
    1686 		r = _.env.identifier_RegExp.source;
    1687 		r = _.env.module_identifier_RegExp = new RegExp('^' + r
    1688 				+ '(\\.' + r + ')*$');
    1689 	}
    1690
    1691 	return r.test(test_string);
    1692 };
    1693
    1694
    1695 CeL
    1696 .
    1697 /**
    1698  * test function.request 的項目是否為 module.
    1699  * TODO
    1700  * 現在還有很大問題!
    1701  * @param {String} resource_string	resource to test
    1702  * @returns	{Boolean}	resource 是否為 module (true: is module, false: is URL?)
    1703  */
    1704 request_item_maybe_module = function(resource_string) {
    1705 	return resource_string.charAt(0) === '.'
    1706 		|| resource_string.charAt(0) === '/'
    1707 			|| resource_string.indexOf(':') !== -1
    1708 			// || resource_string.indexOf('%')!==-1
    1709 			|| /\.(js|css)$/i.test(resource_string) ? false :
    1710 				/\.$/.test(resource_string)
    1711 				|| _.is_module_pattern(resource_string);
    1712 };
    1713
    1714
    1715 var library_base_path;
    1716 CeL
    1717 .
    1718 /**
    1719  * get the path of specified module.
    1720  * @example
    1721  * //	存放 data 的 path
    1722  * path = library_namespace.get_module_path(this, '');
    1723  *
    1724  * @param {String} module_name	module name
    1725  * @param	{String} file_name	取得在同一目錄下檔名為 file_name 之 path。若填入 '' 可取得 parent 目錄。
    1726  * @returns	{String} module path
    1727  */
    1728 get_module_path = function(module_name, file_name){
    1729 	module_name = get_module_name(module_name);
    1730 	var m;
    1731 	if (!module_name || !(m = _.split_module_name(module_name)))
    1732 		return module_name;
    1733
    1734 	//_.debug('load [' + module_name + ']', 1, 'get_module_path');
    1735 	var module_path = library_base_path
    1736 	|| (library_base_path =
    1737 			_.env.registry_path
    1738 			|| _.get_script_base_path(_.env.main_script)
    1739 			|| _.get_script_base_path()
    1740 		);
    1741 	//_.debug('library_base_path: ' + library_base_path, 1, 'get_module_path');
    1742
    1743 	module_path += m.join(/\//.test(module_path)?'/':'\\') + _.env.script_extension;
    1744 	//_.debug('module_path: ' + module_path, 1, 'get_module_path');
    1745
    1746 	if (typeof file_name !== 'undefined')
    1747 		module_path = module_path.replace(/[^\/]+$/, file_name);
    1748 	else if (_.getFP)
    1749 		module_path = _.getFP(module_path, 1);
    1750
    1751 	//_.debug(module_name + ': return [' + module_path + ']', 1, 'get_module_path');
    1752
    1753 	return module_path;
    1754 };
    1755
    1756
    1757 /*
    1758 sample to test:
    1759
    1760 ./a/b
    1761 ./a/b/
    1762 ../a/b
    1763 ../a/b/
    1764 a/../b		./b
    1765 a/./b		a/b
    1766 /../a/b		/a/b
    1767 /./a/b		/a/b
    1768 /a/./b		/a/b
    1769 /a/../b		/b
    1770 /a/../../../b	/b
    1771 /a/b/..		/a
    1772 /a/b/../	/a/
    1773 a/b/..		a
    1774 a/b/../		a/
    1775 a/..		.
    1776 ./a/b/../../../a.b/../c	../c
    1777 ../../../a.b/../c	../../../c
    1778
    1779 */
    1780
    1781 //	2009/11/23 22:12:5
    1782 if(0)
    1783 CeL
    1784 .
    1785 deprecated_simplify_path = function(path){
    1786 	if(typeof path === 'string'){
    1787 		//	去除前後空白
    1788 		path = path.replace(/\s+$|^\s+/,'').replace(/\/\/+/g,'/');
    1789
    1790 		var p, is_absolute = '/' === path.charAt(0);
    1791
    1792 		while( path !== (p=path.replace(/\/\.(\/|$)/g,function($0,$1){return $1;})) )
    1793 			path = p;
    1794 		_.debug('1. '+p);
    1795
    1796 		while (path !== (p = path.replace(
    1797 				/\/([^\/]+)\/\.\.(\/|$)/g, function($0, $1, $2) {
    1798 					alert( [ $0, $1, $2 ].join('\n'));
    1799 					return $1 === '..' ? $0 : $2;
    1800 				})))
    1801 			path = p;
    1802 		_.debug('2. '+p);
    1803
    1804 		if(is_absolute)
    1805 			path = path.replace(/^(\/\.\.)+/g,'');
    1806 		else
    1807 			path = path.replace(/^(\.\/)+/g,'');
    1808 		_.debug('3. '+p);
    1809
    1810 		if(!path)
    1811 			path = '.';
    1812 	}
    1813
    1814 	return path;
    1815 };
    1816
    1817 CeL
    1818 .
    1819 /**
    1820  * 轉化所有 /., /.., //
    1821  * @since	2009/11/23 22:32:52
    1822  * @param {String} path	欲轉化之 path
    1823  * @returns	{String} path
    1824  */
    1825 simplify_path = function(path){
    1826 	if(typeof path === 'string'){
    1827 		var i, j, l, is_absolute, head;
    1828
    1829 		path = path
    1830 			.replace(/^[\w\d\-]+:\/\//,function($0){head = $0; return '';})
    1831 			//	去除前後空白
    1832 			//.replace(/\s+$|^\s+/g,'')
    1833 			//.replace(/\/\/+/g,'/')
    1834 			.split('/');
    1835
    1836 		i = 0;
    1837 		l = path.length;
    1838 		is_absolute = !path[0];
    1839
    1840 		for(;i<l;i++){
    1841 			if(path[i] === '.')
    1842 				path[i] = '';
    1843
    1844 			else if(path[i] === '..'){
    1845 				j=i;
    1846 				while(j>0)
    1847 					if(path[--j] && path[j]!='..'){
    1848 						path[i] = path[j] = '';	//	相消
    1849 						break;
    1850 					}
    1851 			}
    1852 		}
    1853
    1854 		if(!is_absolute && !path[0])
    1855 			path[0] = '.';
    1856
    1857 		path = path.join('/')
    1858 			.replace(/\/\/+/g,'/')
    1859 			.replace(is_absolute? /^(\/\.\.)+/g: /^(\.\/)+/g,'')
    1860 			;
    1861
    1862 		if(!path)
    1863 			path = '.';
    1864
    1865 		if(head)
    1866 			path = head + path;
    1867 	}
    1868
    1869 	return path;
    1870 };
    1871
    1872
    1873
    1874 /**
    1875  * 載入 module 時執行 extend 工作
    1876  * @param module
    1877  * @param extend_to
    1878  * @param {Function} callback
    1879  * @returns
    1880  * @inner
    1881  * @ignore
    1882  */
    1883 var extend_module_member = function(module, extend_to, callback) {
    1884 	var i, l;
    1885
    1886 	//typeof name_space !== 'undefined' && _.debug(name_space);
    1887 	//	處理 extend to what name-space
    1888 	if (!extend_to && extend_to !== false
    1889 			//	若是在 .setup_module 中的話，可以探測得到 name_space？（忘了）
    1890 			//|| typeof name_space !== 'function'
    1891 			|| !_.is_Object(extend_to))
    1892 		//	預設會 extend 到 library 本身下
    1893 		extend_to = _;
    1894
    1895 	if (extend_to && (i = _.get_module(module))) {
    1896 		var ns = i, kw = _.env.not_to_extend_keyword, no_extend = {};
    1897 		//_.debug('load [' + module + ']:\nextend\n' + ns);
    1898
    1899 		if (kw in ns) {
    1900 			l = ns[kw];
    1901 			if (typeof l === 'string' && l.indexOf(',') > 0)
    1902 				l = l.split(',');
    1903
    1904 			if (typeof l === 'string') {
    1905 				no_extend[l] = 1;
    1906 			} else if (_.is_Array(l)) {
    1907 				for (i = 0; i < l.length; i++)
    1908 					// WScript.Echo('no_extend '+l[i]),
    1909 					no_extend[l[i]] = 1;
    1910 			} else if (_.is_Object(l)) {
    1911 				no_extend = l;
    1912 			}
    1913
    1914 			no_extend[kw] = 1;
    1915 		}
    1916
    1917 		//	'*': 完全不 extend
    1918 		if (!no_extend['*']) {
    1919 			no_extend.Class = 1;
    1920 			//	this: 連 module 本身都不 extend 到 library name-space 下
    1921 			var no_self = 'this' in no_extend;
    1922 			if(no_self)
    1923 				delete no_extend['this'];
    1924
    1925 			l = [];
    1926 			for (i in ns)
    1927 				if (!(i in no_extend))
    1928 					l.push(i);
    1929
    1930 			//_.debug('load [' + module + ']:\nextend\n' + l + '\n\nto:\n' + (extend_to.Class || extend_to));
    1931 			_.extend(l, extend_to, ns);
    1932
    1933 			/*
    1934 			 * extend module itself.
    1935 			 * e.g., .net.web -> .web
    1936 			 */
    1937 			if (!no_self && (i = _.split_module_name(module))
    1938 							&& (i = i.pop()) && !(i in _))
    1939 						_[i] = ns;
    1940 		}
    1941
    1942 	}
    1943
    1944
    1945 	try {
    1946 		i = _.is_Function(callback) && callback(undefined, module);
    1947 	} catch (e) {
    1948 	}
    1949 	return i;
    1950 };
    1951
    1952
    1953
    1954
    1955 CeL
    1956 .
    1957 /**
    1958  * 不使用 eval 的方法，get the module namespace of specific module name.
    1959  * @param	{String} module_name	module name
    1960  * @returns	null	some error occurred
    1961  * @returns	namespace of specific module name
    1962  */
    1963 get_module = function(module_name) {
    1964 	module_name = _.split_module_name.call(_, module_name);
    1965
    1966 	//	TODO: test module_name.length
    1967 	if(!module_name)
    1968 		return null;
    1969
    1970 	var i = 0, l = module_name.length, name_space = _;
    1971 	//	一層一層 call name-space
    1972 	while (i < l)
    1973 		try {
    1974 			name_space = name_space[module_name[i++]];
    1975 		} catch (e) {
    1976 			return null;
    1977 		}
    1978
    1979 	return name_space;
    1980 };
    1981
    1982
    1983
    1984
    1985 CeL
    1986 .
    1987 /**
    1988  * 載入 module。
    1989  * <p>
    1990  * 本函數會預先準備好下層 module 定義時的環境，但請盡量先 call 上層 name-space
    1991  * 再定義下層的，否則可能會出現問題，如 memory leak 等。
    1992  * </p>
    1993  *
    1994  * @param {String}
    1995  *            [module_name]
    1996  *            <p>
    1997  *            module name to register: 本 module 之 name(id)
    1998  *            </p>
    1999  * @param {Function}
    2000  *            code_for_including
    2001  *            <p>
    2002  *            若欲 include 整個 module 時，需囊括之 code。
    2003  *            </p>
    2004  *            code_for_including(
    2005  *            		{Function} library_namespace:	namespace of library,
    2006  *            		load_arguments:	呼叫時之 argument(s)
    2007  *            )
    2008  * @returns null
    2009  *          <p>
    2010  *          invalid module
    2011  *          </p>
    2012  * @returns {Object}
    2013  *          <p>
    2014  *          下層 module 之 name-space
    2015  *          </p>
    2016  * @returns undefined
    2017  *          <p>
    2018  *          something error, e.g., 未成功 load，code_for_including
    2019  *          return null, ..
    2020  *          </p>
    2021  */
    2022 setup_module = function(module_name, code_for_including, parent_module_name) {
    2023 	// adapt arguments
    2024 	var i, l, name_space, allow_inherit,
    2025 	/**
    2026 	 * translate {String} code_for_including to function
    2027 	 */
    2028 	name = function() {
    2029 		//	null module constructor
    2030 		if (!code_for_including)
    2031 			code_for_including = function() {
    2032 				return function() {};
    2033 			};
    2034
    2035 		else if (typeof code_for_including === 'string')
    2036 			code_for_including =
    2037 				// (new Function(code_for_including)).bind(CeL)
    2038 				new Function(code_for_including);
    2039 	};
    2040
    2041 	if (typeof module_name === 'string') {
    2042 		name();
    2043 		if (_.is_Function(code_for_including)
    2044 				|| _.is_Object(code_for_including))
    2045 			code_for_including.module_name = module_name;
    2046
    2047 	} else {
    2048 		code_for_including = module_name;
    2049 		// TODO: 不設定時會從呼叫時之 path (directory + file name) 取得
    2050 	}
    2051
    2052 	if (_.is_Object(code_for_including)) {
    2053 		name_space = code_for_including;
    2054 		code_for_including = name_space.code;
    2055 		delete name_space.code;
    2056 		name();
    2057
    2058 		_.extend(name_space, code_for_including);
    2059
    2060 	} else
    2061 		name();
    2062
    2063 	if (!module_name && !(module_name = code_for_including.module_name)) {
    2064 		_.err('The module name is not specified!');
    2065 		_.debug(code_for_including);
    2066 		return null;
    2067 	}
    2068
    2069 	//	sub module
    2070 	if (_.is_Object(l = code_for_including.sub_module)) {
    2071 		name_space = module_name + _.env.module_name_separator;
    2072 		for (i in l)
    2073 			_.setup_module(name_space + i, l[i], module_name);
    2074 	}
    2075
    2076 	//_.debug('prepare to setup module [' + module_name + ']', 1, 'setup_module');
    2077
    2078 	/**
    2079 	 * 測試 dependency list 是不是皆已 loaded。
    2080 	 * 會合併 parent module 之 request。
    2081 	 * <dl>
    2082 	 * <dt>依 (module name-space).require 設定 dependency list</dt>
    2083 	 * <dd>(module name-space).require_module = module name[]</dd>
    2084 	 * <dd>(module name-space).require_variable = {variable_name: full_name_with_module_name}</dd>
    2085 	 * <dd>(module name-space).require_URL = URL[]</dd>
    2086 	 * </dl>
    2087 	 * TODO:
    2088 	 * 就算輸入 module path 亦可自動判別出為 module 而非普通 resource。
    2089 	 */
    2090 	var require = _.parse_require(code_for_including.require, code_for_including.require_separator, parent_module_name && module_require_chain[parent_module_name]), URL_to_load, module_to_load;
    2091 	if (_.is_Object(require)) {
    2092 		_.extend( {
    2093 			require_module : 'module_to_load',
    2094 			require_variable : 'variable',
    2095 			require_URL : 'URL_to_load'
    2096 		}, code_for_including, require);
    2097
    2098 		if (_.is_Array(require.module_to_load)
    2099 				&& require.module_to_load.length)
    2100 			module_to_load = require.module_to_load;
    2101
    2102 		if (_.is_Array(require.URL_to_load)
    2103 				&& require.URL_to_load.length)
    2104 			URL_to_load = require.URL_to_load;
    2105 	}
    2106
    2107
    2108 	if (module_to_load || URL_to_load) {
    2109
    2110 		//_.debug('module [' + (typeof module_name === 'string' ? module_name: undefined) + '] need to load:\n' + module_to_load, 1, 'setup_module');
    2111
    2112 		//	check 登錄
    2113 		if (module_name in module_require_chain) {
    2114 			//	可能是循環參照(circular dependencies)，還是執行 module code_for_including
    2115 			//	若本身已經在需求名單中則放行，避免相互需要造成堆疊空間不足(Out of stack space)或 Stack overflow。
    2116 			_.warn('Skip to load dependencies [' + module_to_load + '] of module [' + module_name + '] because the module is already in the require chain.\nmodule 正在需求鏈中。也許是循環參照(circular dependencies)？');
    2117
    2118 		}else{
    2119
    2120 			//	登錄: module_name 正在 call。若由其他 module call 的，那就登錄此 parent module。
    2121 			module_require_chain[parent_module_name || module_name] = require;
    2122
    2123 			// include required modules
    2124 			if (module_to_load && _.use(module_to_load)) {
    2125 				//	若有未載入之 dependencies，則不載入 module。
    2126 				if(!_.is_local() || _.is_debug(2))
    2127 					_.warn(_.Class + '.setup_module: Module [' + module_name + '] fault to load dependencies [' + module_to_load + ']. You have to load it later.');
    2128
    2129 				//	throw and wait .include_resource() to call callback(path, module_name)
    2130 				//	為了預防後面還有 code 而繼續執行下去，所以採用 throw 而非 return。
    2131 				throw new Error(_.Class + '.setup_module: Module [' + module_name + '] 無法以 Ajax load required module!\nrequired module list: ['+module_to_load+']');
    2132 			}
    2133
    2134 			if (URL_to_load) {
    2135 				// 嘗試直接載入
    2136 				for (i in URL_to_load)
    2137 					try {
    2138 						if (l = _.get_file(i = URL_to_load[i]))
    2139 							_.eval_code(l);
    2140 						else
    2141 							throw 1;
    2142 					} catch (e) {
    2143 						_ .err('module [' + (typeof module_name === 'string' ? module_name : undefined) + '] load URL [' + i
    2144 								+ '] error. You have to load it later.');
    2145 						// return and wait .include_resource() to call callback(path, module_name)
    2146 						throw new Error(_.Class + '.setup_module: module [' + module_name + '] 無法以 Ajax load required URL [' + i + ']!');
    2147 					}
    2148 			}
    2149
    2150 		}
    2151
    2152 	}
    2153 	// else	所有需求皆已在 queue 中，因此最後總**有機會（不包括發生錯誤的情況！）**會被 load，故 skip。
    2154
    2155
    2156 	var module_name_list = _.split_module_name(module_name);
    2157 	if (!module_name_list) {
    2158 		_.err('Illegal module name: [' + module_name + ']!');
    2159 		_.debug(code_for_including);
    2160
    2161 		//	執行完清除載入中之登錄
    2162 		if(module_name in module_require_chain)
    2163 			delete module_require_chain[module_name];
    2164
    2165 		return null;
    2166 	}
    2167
    2168 	//	若皆載入: 準備執行 module code_for_including
    2169 	//	一層一層準備好、預定義 name-space
    2170 	for (i = 0, l = module_name_list.length - 1, name_space = _; i < l; i++) {
    2171 		if (!name_space[name = module_name_list[i]])
    2172 			/**
    2173 			 * <code>
    2174 			 * _.debug('預先定義 module [' + _.to_module_name(module_name.slice(0, i + 1)) + ']'),
    2175 			 * </code>
    2176 			 */
    2177 			name_space[name] = new Function(
    2178 					'//	null constructor for module ' +
    2179 					_.to_module_name(module_name_list.slice(0, i + 1)));
    2180 		name_space = name_space[name];
    2181 	}
    2182 	//	name_space 這時是 module 的 parent module。
    2183
    2184 	if (
    2185 			// 尚未被定義或宣告過
    2186 			!name_space[name = module_name_list[l]] ||
    2187 			// 可能是之前簡單定義過，例如被上面處理過。這時重新定義，並把原先的 member 搬過來。
    2188 			!name_space[name].Class) {
    2189
    2190 		// 保留原先的 name-space，for 重新定義
    2191 		l = name_space[name];
    2192
    2193 		// extend code, 起始 name-space
    2194 		try {
    2195 			/**
    2196 			 * 真正執行 module code.
    2197 			 * <code>
    2198 			 * _.debug('including code of [' + _.to_module_name(module_name) + ']..'),
    2199 			 * </code>
    2200 			 * TODO: code_for_including(_, load_arguments)
    2201 			 */
    2202 			i = code_for_including.call(code_for_including, _);
    2203 			i.prototype.constructor = i;
    2204 			if('allow_inherit' in i){
    2205 				allow_inherit = i.allow_inherit;
    2206 				delete i.allow_inherit;
    2207 			}
    2208 			//code_for_including.toString = function() { return '[class_template ' + name + ']'; };
    2209 			//i.toString = function() { return '[class ' + name + ']'; };
    2210 		} catch (e) {
    2211 			_.err(_.Class + '.setup_module: load module ['
    2212 					+ _.to_module_name(module_name) + '] error!\n' + e.message);
    2213 			i = undefined;
    2214 		}
    2215
    2216 		if (i === undefined)
    2217 			//	error?
    2218 			return;
    2219
    2220 		name_space = name_space[name] = i;
    2221
    2222 		// 把原先的 member 搬過來
    2223 		if (l) {
    2224 			delete l.Class;
    2225 			//	may use: _.extend()
    2226 			for (i in l)
    2227 				name_space[i] = l[i];
    2228 		}
    2229 		name_space.Class = _.to_module_name(module_name);
    2230 	}
    2231
    2232 /*
    2233 	l=[];
    2234 	for(i in name_space)
    2235 		l.push(i);
    2236 	WScript.Echo('Get members:\n'+l.join(', '));
    2237 */
    2238
    2239 	//	執行完清除載入中之登錄
    2240 	if(module_name in module_require_chain)
    2241 		delete module_require_chain[module_name];
    2242
    2243 	set_loaded(name_space.Class, code_for_including, allow_inherit);
    2244
    2245 	//_.debug('module [' + module_name + '] 設定 OK.', 1, 'setup_module');
    2246
    2247 	return name_space;
    2248 };
    2249
    2250
    2251
    2252 CeL
    2253 .
    2254 /**
    2255  * 是否 cache code。
    2256  * 若不是要重構 code 則不需要。
    2257  * undefined: 依照預設
    2258  * Boolean: 明確設定，但如此即無法繼承。
    2259  * @type	Boolean, undefined
    2260  */
    2261 cache_code = /*_.is_debug() || */ undefined;
    2262
    2263 /**
    2264  * cache 已經 include 之函式或 class。
    2265  * loaded_module[module_name] =
    2266  * 		undefined: 尚未載入。
    2267  * 		{Boolean} true	已經載入，但未 cache code。
    2268  * 		{Function} code	已經載入，這是 cache 了的 code。
    2269  * @inner
    2270  * @ignore
    2271  * @type Object
    2272  */
    2273 var loaded_module = {
    2274 };
    2275
    2276
    2277 /**
    2278  * 紀錄 **正在 load** 之 module 所需之 dependency list。
    2279  * module_require_chain[module_name] = [未載入之 dependency list by .parse_require()] requesting now.
    2280  *
    2281  * ** 這一項僅在 .setup_module() 發現 dependency list 尚未載入完時，預防循環 request 而用。
    2282  * @inner
    2283  * @ignore
    2284  * @type Object
    2285  */
    2286 var module_require_chain = {
    2287 };
    2288
    2289
    2290
    2291 CeL
    2292 .
    2293 /**
    2294  * 將輸入的 string 分割成各 module 單元。<br/>
    2295  * need environment_adapter()<br/>
    2296  * ** 並沒有對 module 做完善的審核!
    2297  * @param {String} module_name	module name
    2298  * @returns	{Array}	module unit array
    2299  */
    2300 split_module_name = function(module_name) {
    2301 	//_.debug('[' + module_name + ']→[' + module_name.replace(/\.\.+|\\\\+|\/\/+/g, '.').split(/\.|\\|\/|::/) + ']');
    2302 	if (typeof module_name === 'string')
    2303 		module_name = module_name
    2304 			//.replace(/\.\.+|\\\\+|\/\/+/g, '.')
    2305 			.replace(/[\\\/]/g, '.')
    2306 			.split(/[.\\\/]|::/);
    2307
    2308 	if (_.is_Array(module_name) && module_name.length) {
    2309 		//	去除 library name
    2310 		if (module_name.length > 1 && _.Class === module_name[0])
    2311 			module_name.shift();
    2312 		return module_name;
    2313 	} else
    2314 		return null;
    2315 };
    2316
    2317
    2318 /**
    2319  * 取得建構 code 之 module name。不以 library name 起始。
    2320  * // get_module_name()
    2321  * code_for_including.module_name === 'module_name';
    2322  * // _.to_module_name()
    2323  * library_name.module_parent.module_child.Class === 'library_name.module_parent.module_child' === 'library_name.module_name';
    2324  * TODO:
    2325  * 有效率的整合 get_module_name() 與 _.to_module_name()
    2326  * @param code_for_including
    2327  * @returns {String} module name
    2328  */
    2329 var get_module_name = function(code_for_including) {
    2330 	//_.debug('module_name: ' + (_.is_Function(code_for_including) && code_for_including.module_name ? code_for_including.module_name : code_for_including), 1, 'get_module_name');
    2331 	//_.debug('Class: ' + (_.is_Function(code_for_including) && code_for_including.Class ? code_for_including.Class : code_for_including), 1, 'get_module_name');
    2332
    2333 	return _.is_Function(code_for_including) && code_for_including.module_name ?
    2334 			code_for_including.module_name
    2335 			: code_for_including;
    2336 };
    2337
    2338
    2339 CeL
    2340 .
    2341 /**
    2342  * 取得 module 之 name。以 library name 起始。
    2343  * @returns {String} module name start with library name
    2344  */
    2345 to_module_name = function(module, separator) {
    2346 	if (_.is_Function(module))
    2347 		module = module.Class;
    2348 	else if (module === _.env.main_script_name)
    2349 		module = _.Class;
    2350
    2351 	if (typeof module === 'string')
    2352 		module = _.split_module_name(module);
    2353
    2354 	var name = '';
    2355 	if (_.is_Array(module)) {
    2356 		if (typeof separator !== 'string')
    2357 			separator = _.env.module_name_separator;
    2358 		if (module[0] !== _.Class)
    2359 			name = _.Class + separator;
    2360 		name += module.join(separator);
    2361 	}
    2362
    2363 	return name;
    2364 };
    2365
    2366
    2367
    2368 //TODO
    2369 CeL
    2370 .
    2371 get_require = function(func) {
    2372 	if (_.is_Function(func) || _.is_Object(func))
    2373 		return func.require;
    2374
    2375 	if (_.is_Function(func = loaded_module[_.to_module_name(func)]))
    2376 		return func.require_module;
    2377 };
    2378
    2379 //TODO
    2380 CeL
    2381 .
    2382 unload_module = function(module, g){
    2383 	///	<returns>error</returns>
    2384 	if(_.is_debug())
    2385 		throw new Error('UNDO');
    2386
    2387 };
    2388
    2389
    2390 CeL
    2391 .
    2392 /**
    2393  * 判斷 module 是否存在，
    2394  * TODO
    2395  * 以及是否破損。
    2396  * @param	{String} module_name	module name
    2397  * @param	{Array} module_name	module name list
    2398  * @returns	{Boolean} 所指定 module 是否全部存在以及良好。
    2399  */
    2400 is_loaded = function(module_name) {
    2401 	if (_.is_Array(module_name)) {
    2402 		for ( var i = 0, l = module_name.length; i < l; i++)
    2403 			if (!loaded_module[_.to_module_name(module_name[i])])
    2404 				return false;
    2405 		return true;
    2406 	}
    2407
    2408 	// var _s = arguments.callee;
    2409 	//_.debug('test ' + _.to_module_name(module_name));
    2410
    2411 	/*
    2412 	var code = loaded_module[_.to_module_name(module_name)], sub_module, prefix;
    2413 	if (_.is_Function(code) && (sub_module = code.sub_module)) {
    2414 		sub_module = sub_module.split('|');
    2415 		prefix = module_name + _.env.module_name_separator;
    2416 		for ( var i = 0, l = module_name.length; i < l; i++){
    2417 			_.debug('check [' + prefix + sub_module[i] + ']', 1, 'is_loaded');
    2418 			if (!_.is_loaded(prefix + sub_module[i]))
    2419 				return false;
    2420 		}
    2421 		return true;
    2422 	}
    2423 	*/
    2424
    2425 	return !!loaded_module[_.to_module_name(module_name)];
    2426 };
    2427
    2428
    2429
    2430 /**
    2431  * 設定登記 module 已載入。
    2432  * @inner
    2433  * @private
    2434  */
    2435 var set_loaded = function(module_name, code_for_including,
    2436 		cache_code) {
    2437 	// _.debug(_.to_module_name(module_name));
    2438 	loaded_module[_.to_module_name(module_name)] = (_.cache_code === undefined
    2439 			&& cache_code || _.cache_code)
    2440 			&& code_for_including || true;
    2441 };
    2442
    2443
    2444
    2445
    2446
    2447 function get_include_resource(split) {
    2448 	if (typeof document !== 'object' || !document.getElementsByTagName)
    2449 		//	document!=='object': 誤在非 HTML 環境執行，卻要求 HTML 環境下的 resource？
    2450 		//if(typeof document==='object')_.warn(_.Class + ".include_resource: Can't load [" + path + "]!");
    2451 		return;
    2452
    2453 	var i, nodes = document.getElementsByTagName('script'), h, hn, count = 0, p, l;
    2454 	if (split)
    2455 		h = {
    2456 			script : {},
    2457 			css : {}
    2458 		},
    2459 		hn = h.script;
    2460 	else
    2461 		hn = h = {};
    2462
    2463 	l = nodes.length;
    2464 	for (i = 0; i < l; i++)
    2465 		if (p = _.simplify_path(nodes[i].src))
    2466 			hn[p] = 1, count++;
    2467
    2468 	nodes = document.getElementsByTagName('link');
    2469 	if (split)
    2470 		hn = l.css;
    2471
    2472 	l = nodes.length;
    2473 	for (i = 0; i < l; i++)
    2474 		if (p = _.simplify_path(nodes[i].href))
    2475 			hn[p] = 1, count++;
    2476
    2477 	return [ h, count ];
    2478 };
    2479
    2480 /**
    2481  * 已經 include_resource 了哪些 JavaScript 檔（存有其路徑）.
    2482  * included_path[path] =
    2483  * 		undefined: 尚未載入。
    2484  * 		true	已經載入。
    2485  *
    2486  * TODO:
    2487  * included_path[index] = [time stamp, path],
    2488  * @inner
    2489  * @ignore
    2490  * @type Object
    2491  */
    2492 var included_path;
    2493
    2494 function included_path_init(){
    2495 	var s = get_include_resource();
    2496 	if(s)
    2497 		included_path = s[0];
    2498 	return included_path || {};
    2499 }
    2500
    2501
    2502 CeL
    2503 .
    2504 is_included = function(path) {
    2505 	return !!(included_path || included_path_init())[path];
    2506 };
    2507
    2508 var set_included = function(path, timeout_id) {
    2509 	(included_path || included_path_init())[path] = timeout_id;
    2510 },
    2511
    2512 get_included = function(path) {
    2513 	return (included_path || included_path_init())[path];
    2514 };
    2515
    2516
    2517
    2518 CeL
    2519 .
    2520 /**
    2521  * include resource of module.
    2522  * @example
    2523  * //	外部程式使用時，通常用在 include 相對於 library 本身路徑固定的檔案。
    2524  * //	例如 file_name 改成相對於 library 本身來說的路徑。
    2525  * CeL.include_module_resource('../../game/game.css');
    2526  *
    2527  * library_namespace.include_module_resource('select_input.css', this);
    2528  *
    2529  * @param {String} file_name	與 module 位於相同目錄下的 resource file name
    2530  * @param {String} [module_name]	呼叫的 module name。未提供則設成 library base path，此時 file_name 為相對於 library 本身路徑的檔案。
    2531  * @returns
    2532  * @since	2010/1/1-2 13:58:09
    2533  */
    2534 include_module_resource = function(file_name, module_name) {
    2535 	//var m = _.split_module_name.call(_, module_name);
    2536 	//if (m)m[m.length - 1] = file_name;
    2537 	return _.include_resource.call(_,
    2538 			_.get_module_path(get_module_name(module_name) || _.Class, file_name));
    2539 };
    2540
    2541
    2542
    2543 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    2544
    2545
    2546 CeL
    2547 .
    2548 /**
    2549  * Include specified module.<br/>
    2550  *
    2551  * 會先嘗試以依序載入(asynchronous)的方式取得 module。
    2552  * 無法以 Ajax 載入時，若未設定 callback，會回傳錯誤。若設定 callback，會以同步(synchronous)的方式載入 module，於載入完成執行 callback。
    2553  * 		若因為 browser 安全性設定而無法取得則會回傳 -1，表示將以同步的方式載入 module。因為 module 尚未載入，在此階段尚無法判別此 module 所需之 dependency list。此 list 會被作為引數傳入 callback。
    2554  *
    2555  * 注意：以下的 code 中，CeL.warn 不一定會被執行（可能會、可能不會），因為執行時 log 可能尚未被 include。<br/>
    2556  * 此時應該改用 CeL.set_run('application.log', callback);<br/>
    2557  * code in head/script/:
    2558  * <code>
    2559  * CeL.use('code.log');
    2560  * CeL.warn('WARNING message');
    2561  * </code>
    2562  * **	在指定 callback 時 name_space 無效！
    2563  * **	預設會 extend 到 library 本身之下！
    2564  * @param	{String} module	module name
    2565  * @param	{Function} [callback]	callback function | [callback, 進度改變時之 function (TODO)]
    2566  * @param	{Object|Boolean} [extend_to]	extend to which name-space<br/>
    2567  * 		false:	just load, don't extend to library name-space<br/>
    2568  * 		this:	extend to global<br/>
    2569  * 		object:	extend to specified name-space that you can use [name_space]._func_ to run it<br/>
    2570  * 		(others, including undefined):	extend to root of this library. e.g., call CeL._function_name_ and we can get the specified function.
    2571  * @returns	{Error}
    2572  * @returns	-1	will execute callback after load, 不代表 load module 了!
    2573  * @returns	{undefined}	no error, OK
    2574  * @example
    2575  * CeL.use('code.log', function(){..});
    2576  * CeL.use(['code.log', 'code.debug']);
    2577  * @note
    2578  * 'use' 是 JScript.NET 的保留字.
    2579  */
    2580 use = function requires(module, callback, extend_to, force){
    2581 	var _s = requires, i, l, module_path;
    2582
    2583 	//_.debug('load [' + module + ']');
    2584 	if (!module)
    2585 		return;
    2586
    2587 	/*
    2588 	if (arguments.length > 3) {
    2589 		l = arguments.length;
    2590 		name_space = arguments[--l];
    2591 		callback = arguments[--l];
    2592 		--l;
    2593 		for (i = 0; i < l; i++)
    2594 			_s.call(_, arguments[i], callback, name_space);
    2595 		return;
    2596 	}
    2597 	*/
    2598
    2599 	if (_.is_Array(module)) {
    2600 		var error;
    2601 		for (i = 0, l = module.length; i < l; i++)
    2602 			if (error = _s.call(_, module[i], 0, extend_to))
    2603 				return error;
    2604 		try {
    2605 			i = _.is_Function(callback) && callback(undefined, module);
    2606 		} catch (e) {
    2607 		}
    2608 		return i;
    2609 	}
    2610
    2611 	if (!force && _.is_loaded(module)
    2612 			|| !(module_path = _.get_module_path(module))) {
    2613 		try {
    2614 			i = _.is_Function(callback)
    2615 			&& callback(undefined, module);
    2616 		} catch (e) {
    2617 		}
    2618 		return i;
    2619 	}
    2620
    2621 	//_.debug('load [' + module + ']:\ntry to load [' + module_path + ']');
    2622
    2623 	//	including code
    2624 	try {
    2625 		try{
    2626 			// _.debug('load ['+module_path+']');
    2627 			// _.debug('load ['+module_path+']:\n'+_.get_file(module_path, _.env.source_encoding));
    2628 			//WScript.Echo(_.eval);
    2629 			if (i = _.get_file(module_path, _.env.source_encoding))
    2630 				//	eval @ global. 這邊可能會出現 security 問題。
    2631 				//	TODO: 以其他方法取代 eval 的使用。
    2632 				_.eval_code(i);
    2633 			else
    2634 				_.warn('Get no result from [' + module_path + ']! Some error occurred?');
    2635 			i = 0;
    2636 		} catch (e) {
    2637 			i = e;
    2638 		}
    2639
    2640 		if (!i)
    2641 			return extend_module_member(module, extend_to, callback);
    2642
    2643 		//	依序載入失敗
    2644 		if (callback && typeof window !== 'undefined') {
    2645 			//	不能直接用 .get_file()，得採用其他方法的狀況。但只在有 callback 時才 include，否則當下 block 的都沒執行，可能出亂子。
    2646 			//	** 較新之 browser 通常需要使用 callback 的方法，不能使用 "CeL.use('module');_do_some_thing_;"!!
    2647 			// TODO: 在指定 callback 時使 name_space 依然有效。
    2648 			_.include_resource(module_path, {
    2649 				module : module,
    2650 				callback : function(){
    2651 					extend_module_member(module, extend_to, callback);
    2652 				},
    2653 				start : new Date(),
    2654 				timeout : 80,
    2655 				global : _
    2656 			},
    2657 			//	正在 call(循環參照?)則強制 include
    2658 			module in module_require_chain);
    2659 			//	TODO: 一次指定多個 module 時可以知道進度，全部 load 完才 callback()。
    2660 			//	此時 callback=[callback, 進度改變時之 function]
    2661 			//	return 進度 Object
    2662 			return -1;
    2663 		}
    2664 		throw i;
    2665
    2666 	} catch (e) {
    2667 		//_.err(e);
    2668
    2669 		// http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html
    2670 		// http://reference.sitepoint.com/javascript/DOMException
    2671 		if (_.is_type(e, 'DOMException') && e.code === 1012) {
    2672 			if(!_.is_local() || _.is_debug(2))
    2673 				_.err(_.Class
    2674 					+ '.use:\n'
    2675 					+ e.message + '\n'
    2676 					+ module_path
    2677 					+ '\n\n程式可能呼叫了一個'
    2678 					+ (_.is_local() ? '不存在的，\n或是繞經上層目錄'
    2679 								: 'cross domain')
    2680 								+ '的檔案？\n\n請嘗試使用相對路徑，\n或加入  callback: '
    2681 								+ _.Class
    2682 								+ '.use(module, callback function, name_space)');
    2683 		} else if (_.is_type(e, 'Error') && (e.number & 0xFFFF) == 5
    2684 				|| _.is_type(e, 'XPCWrappedNative_NoHelper')
    2685 						&& ('' + e.message).indexOf('NS_ERROR_FILE_NOT_FOUND') !== -1) {
    2686 			_.err(_.Class + '.use: 檔案可能不存在或存取被拒？\n[' + module_path + ']' +
    2687 					(_.get_error_message
    2688 							? ('<br/>' + _.get_error_message(e))
    2689 							: '\n' + e.message
    2690 					)
    2691 				);
    2692 		} else if(!_.is_local() || _.is_debug(2))
    2693 			_.err(_.Class + '.use: Cannot load [<a href="' + module_path + '">' + module + '</a>]!'
    2694 					+ (_.get_error_message
    2695 							? ('<br/>' + _.get_error_message(e) + '<br/>')
    2696 							: '\n[' + (e.constructor) + '] ' + (e.number ? (e.number & 0xFFFF) : e.code) + ': ' + e.message + '\n'
    2697 					)
    2698 					+ '抱歉！在載入其他網頁時發生錯誤，有些功能可能失常。\n重新讀取(reload)，或是過段時間再嘗試或許可以解決問題。');
    2699 		//_.log('Cannot load [' + module + ']!', _.log.ERROR, e);
    2700
    2701 		return e;
    2702 	}
    2703
    2704 };
    2705
    2706
    2707 CeL
    2708 .
    2709 is_local = function() {
    2710 	return typeof window !== 'object'
    2711 		|| typeof location !== 'object'
    2712 			|| window.location !== location
    2713 			|| location.protocol === 'file:';
    2714 };
    2715
    2716 /*
    2717 bad: sometimes doesn't work. e.g. Google Maps API in IE
    2718 push inside window.onload:
    2719 window.onload=function(){
    2720 include_resource(p);
    2721 setTimeout('init();',2000);
    2722 };
    2723
    2724 way 3:	ref. dojo.provide();, dojo.require();
    2725 document.write('<script type="text/javascript" src="'+encodeURI(p)+'"><\/script>');
    2726
    2727 TODO:
    2728 encode
    2729
    2730 */
    2731 ;
    2732
    2733 CeL
    2734 .
    2735 /**
    2736  * Including other JavaScript/CSS files synchronously.
    2737  *
    2738  * TODO:
    2739  * timeout for giving up
    2740  * use document.createElementNS()
    2741  * http://headjs.com/#theory
    2742  *
    2743  * @param {String} resource path
    2744  * @param {Function|Object} callback
    2745  * 		use_write ? test function{return } : callback function(path)
    2746  * 		/	{callback: callback function(path, module), module: module name, global: global object when run callback}
    2747  * @param {Boolean} [use_write]	use document.write() instead of insert a element to <head>
    2748  * @param {Number} [type]	1: is a .css file, others: script
    2749  */
    2750 include_resource = function include_resource(path, callback, force, timeout, type, use_write) {
    2751 	var _s = _.include_resource, s, t, h;
    2752
    2753 	if (_.is_Array(path)) {
    2754 		for (s = 0, t = path.length; s < t; s++)
    2755 			_s(path[s], callback, use_write, type);
    2756 		return;
    2757 	}
    2758
    2759 	if (_.is_Object(force) && arguments.length === 3) {
    2760 		timeout = force.timeout;
    2761 		type = force.type;
    2762 		use_write = force.use_write;
    2763 		force = force.force;
    2764 	}
    2765
    2766 	if(!force && _.is_included(path)){
    2767 		//	已經載入完成
    2768 		_.is_Function(callback) && _s.wait_to_call(callback, path);
    2769 		return;
    2770 	}
    2771 	set_included(path);
    2772
    2773 	//_.debug('Including [' + path + '].', 1, 'include_resource');
    2774 	if (typeof type === 'undefined')
    2775 		type = /\.css$/i.test(path) ? 1 : 0;
    2776
    2777 	t = 'text/' + (type === 1 ? 'css' : 'javascript');
    2778 /*@cc_on
    2779 //use_write=1;	//	old old IE hack
    2780 @*/
    2781 	if (!use_write)
    2782 		try {
    2783 			// Dynamic Loading / lazy loading
    2784 			// http://code.google.com/apis/ajax/documentation/#Dynamic
    2785 			//	http://en.wikipedia.org/wiki/Futures_and_promises
    2786 			s = document.createElement(type === 1 ? 'link' : 'script');
    2787 			s.type = t;
    2788 			if (type === 1)
    2789 				s.href = path,
    2790 				// s.media = 'all',//'print'
    2791 				s.rel = 'stylesheet';
    2792 			else
    2793 				//	TODO: see jquery-1.4a2.js: globalEval
    2794 				//	if (is_code) s.text = path;
    2795 				//s.setAttribute('src', path);
    2796 				s.src = path,
    2797 				s.async = true;
    2798
    2799 			s.width = s.height = 0;
    2800
    2801 			//	http://wiki.forum.nokia.com/index.php/JavaScript_Performance_Best_Practices
    2802 			//	** onload 在 local 好像無效
    2803 			var done = false;
    2804 			s.onload = s.onreadstatechange = function(e) {
    2805 				var r;
    2806 				//_.debug('Loading [' + path + '] .. ' + this.readyState);
    2807 				//	navigator.platform === 'PLAYSTATION 3' 時僅用 'complete'? from requireJS
    2808 				if (!done && (!(r = this.readyState /* 'readyState' in this ? this.readyState : e.type !== 'load' */) || r === 'loaded' || r === 'complete')) {
    2809 					done = true;
    2810 					//_.debug('[' + (this.src || s.href) + '] loaded.');
    2811
    2812 					//this.onload = this.onreadystatechange = null;
    2813 					try{
    2814 						delete this.onload;
    2815 					}catch (e) {
    2816 						//	error on IE5–7: Error: Object doesn't support this action
    2817 						this.onload = null;
    2818 					}
    2819 					try{
    2820 						delete this.onreadystatechange;
    2821 					}catch (e) {
    2822 						//	error on IE5–7: Error: Object doesn't support this action
    2823 						this.onreadystatechange = null;
    2824 					}
    2825
    2826 					//	callback 完自動移除 .js。隨即移除會無效。 .css 移除會失效。
    2827 					setTimeout(function() {
    2828 						if (type !== 1)
    2829 							h.removeChild(s);
    2830 						h = s = null;
    2831 					}, 1);
    2832
    2833 					//	css 無 timeout 功能。
    2834 					var tid = get_included(path);
    2835 					if (tid) {
    2836 						clearTimeout(tid);
    2837 						set_included(path, 0);
    2838 					}
    2839
    2840 					if(callback)
    2841 						_s.wait_to_call(callback, path);
    2842
    2843 				}
    2844 			};
    2845
    2846 			//	HTML5: document.head === document.getElementsByTagName('head')[0]
    2847 			h = document.head || document.getElementsByTagName('head')[0]
    2848 				|| (document.body.parentNode || document.body).appendChild(document.createElement('head'));
    2849
    2850 			h.appendChild(s);
    2851 			//h.parentNode.insertBefore(s, h);
    2852
    2853 			//_.debug('HTML:\n' + document.getElementsByTagName('html')[0].innerHTML);
    2854 			/*
    2855 			 * from jquery-1.4a2.js:
    2856 			 * Use insertBefore instead of appendChild to circumvent an IE6 bug
    2857 			 *  when using globalEval and a base node is found.
    2858 			 * This arises when a base node is used (#2709).
    2859 			 * @see
    2860 			 * http://github.com/jquery/jquery/commit/d44c5025c42645a6e2b6e664b689669c3752b236
    2861 			 * 不過這會有問題: 後加的 CSS file 優先權會比較高。因此，可以的話還是用 appendChild。
    2862 			 */
    2863 			//h.insertBefore(s, h.firstChild);
    2864
    2865 			//	css 無 timeout 功能。
    2866 			if (type !== 1)
    2867 				set_included(path, setTimeout(function() {
    2868 					_.warn('include_resource: Loading failed (timeout ' + timeout + ' ms): [' + path + ']');
    2869 					// 自動移除 .js。
    2870 					h.removeChild(s);
    2871 					h = s = null;
    2872
    2873 					if(callback)
    2874 						_s.wait_to_call(callback, path, true);
    2875 				}, timeout || (timeout = _.is_local() ? 2000 : 8000)));
    2876
    2877 			return s;
    2878
    2879 		} catch (e) {
    2880 		}
    2881
    2882 	//_.debug('Writing code for [' + path + '].');
    2883 	//	直接寫入，若非正在 load 頁面時使用會出問題!
    2884 	if (use_write
    2885 			|| typeof use_write === 'undefined' // && TODO: 正在 load 頁面
    2886 			)
    2887 		document.write(type === 1 ?
    2888 				'<link type="' + t + '" rel="stylesheet" href="' + path + '"><\/link>'
    2889 				: '<script type="' + t + '" src="' + path
    2890 					// language="JScript"
    2891 					+ '"><\/script>');
    2892
    2893 	//	若是到這邊還沒 load，會造成問題。
    2894 	//set_included(path);
    2895
    2896 	if (callback)
    2897 		_s.wait_to_call(callback, path);
    2898 };
    2899
    2900
    2901 CeL
    2902 .
    2903 /**
    2904  * 準備 callback
    2905  * @inner
    2906  * @private
    2907  * @ignore
    2908  */
    2909 include_resource.wait_to_call = function(callback, path, failed) {
    2910 	//alert('include_resource.wait_to_call:\n' + _.to_module_name(callback.module));
    2911
    2912 	if (_.is_Function(callback))
    2913 		//	不是 module，僅僅為指定 function 的話，直接等一下再看看。
    2914 		//	TODO: 等太久時 error handle
    2915 		setTimeout(function() {
    2916 			callback(path, undefined, failed);
    2917 		}, 200);
    2918
    2919 	else if (_.is_Object(callback) && callback.global)
    2920 		//	是 module。
    2921 		if (callback.global.is_loaded(callback.module)
    2922 							|| (new Date() - callback.start) > callback.timeout) {
    2923 			//	依 callback 的類型處理 callback
    2924 			if(_.is_Function(callback.callback))
    2925 				//	直接執行
    2926 				callback.callback(path, callback.module, failed);
    2927
    2928 			else if (typeof callback.callback === 'string')
    2929 				//	load 另一個 module
    2930 				_.use(callback.callback);
    2931 			// TODO
    2932 			// else..
    2933
    2934 		} else {
    2935 			/**
    2936 			 * 還沒載入完成，所以再等一下。 the function it self, not 'this'.
    2937 			 * @inner
    2938 			 * @ignore
    2939 			 */
    2940 			var _s = _.include_resource.wait_to_call, _t = this, _a = arguments;
    2941 			setTimeout(function() {
    2942 				_s.apply(_t, _a);
    2943 			}, 50);
    2944 		}
    2945 };
    2946
    2947 //if (_.is_Function(include_resource))
    2948 //	_.extend(null, include_resource, _.include_resource);
    2949
    2950
    2951
    2952 /*
    2953
    2954 CeL.set_run(running sequence: [commands]|[required sequence])
    2955 	[commands]/動作串
    2956 		[],
    2957 		function_to_run
    2958 			[optional] {object} function_to_run.config
    2959 			執行次序：
    2960 			[optional: run_first, on load required] function_to_run.run_first = function(is prepared?): [bool] time (ms) to re-check
    2961 			[optional] function_to_run.require = [require sequence]
    2962 			[optional: prepared, before trigger] function_to_run.before_load = function()
    2963 			[optional] waiting for function_to_run.trigger =
    2964 				觸發時機/trigger action time
    2965 				[string] action name | number = 0
    2966 				onload: 'load' (default), {number} timeout (ms)
    2967 			function_to_run.send_argument = (default: auto detect)
    2968 			function_to_run = function() event handler
    2969 			TODO: after_load
    2970
    2971 	[required sequence]/前置條件/先備條件/prerequisite/necessary
    2972 		{string} library module name to import, {string} file path(image/JavaScript files/CSS), {number} timeout (ms)
    2973
    2974 		.charAt(0)==='.' || .charAt(0)==='/' || .indexOf(':')!==-1
    2975 			//|| .indexOf('%')!==-1
    2976 			|| /\.(js|css)$/i	→URL
    2977
    2978 		i=env.identifier_RegExp.source;
    2979 		env.module_identifier_RegExp=new RegExp('^'+i+'(\\.'+i+')*$');	→module
    2980
    2981 		else→URL
    2982
    2983 		∴'path1.sub1.sub2'→'./path1.sub1.sub2'
    2984
    2985
    2986
    2987 CeL.set_run.error=function(message){
    2988 	;
    2989 };
    2990 CeL.set_run.load={resource:status};
    2991
    2992 CeL.use('module_name');
    2993 CeL.load('resource path');
    2994
    2995
    2996 2011/6/22 17:43:50,2011/7/31 00:11:52
    2997
    2998
    2999
    3000
    3001
    3002
    3003
    3004 .set_run(running sequence)
    3005
    3006
    3007 //	同步 loading set: 可同時 load 的 {String|Function} module/path/function
    3008 synchronous_group = {
    3009 	//check: {Function},
    3010
    3011 	//	.to_run 會先執行，而後 delete
    3012 	to_run[]: [{Function} function],
    3013 	//	to load
    3014 	to_load_path{}: [{String} path],
    3015 	//	有幾個 resources 需要 load
    3016 	path_count: integer count of to_load_path,
    3017 	to_load_module{}: [{String} module],
    3018 	module_count: integer count of to_load_module,
    3019
    3020 	//	可能闕如: 下一組
    3021 	next_group: next synchronous_group{},
    3022
    3023 	//	可能闕如: timeout 用
    3024 	start_time: integer,
    3025 	//	已設定之 timeout (ms)
    3026 	timeout: integer,
    3027
    3028 	//	可能闕如: 臨時新增用，是為了預防有 call C，但 dependency 為 A→B→C 的情況。重複使用 queue 但不檢查 require 可能造成 B 與 C 被放在同一 synchronous_group。
    3029 	require: {}
    3030 };
    3031
    3032
    3033
    3034
    3035 臨時/後續/後來新增:
    3036
    3037 原先	［C,E]
    3038 發現B→C	[B,E]→[C]
    3039 發現D→E	[B,D]→[E]→[C]
    3040 發現A→B	[A,D]→[B]→[E]→[C]
    3041
    3042 2011/8/8 00:07:06
    3043
    3044
    3045
    3046 */
    3047
    3048 CeL
    3049 .
    3050 /**
    3051  * control/setup source codes to run.
    3052  * 基本上使用同步(synchronous)的方式，除非所需資源已經載入，或是有辦法以 {@link XMLHttpRequest} 取得資源。
    3053  *
    3054  * @example
    3055  * sr = CeL.set_run;
    3056  * sr('module_name', function(){
    3057  * 	// ...
    3058  * });
    3059  *
    3060  * TODO:
    3061  * sr('module_name', function(){
    3062  * 	CeL.import('module_name', {module_function_1:0});
    3063  *
    3064  * 	CeL.module_function_1('11') === module_function_1('11');
    3065  *
    3066  * 	var instance=new CeL.module_name.module_class_1;
    3067  * 	instance.print(112);
    3068  * });
    3069  *
    3070  *
    3071  * @param	running sequence: list of
    3072  * 		{Function} function to run/欲執行之 function → change .to_run
    3073  * 		| {Integer} timeout (ms): 僅能保證上次 function 執行至此次 function 一定會等超過這段時間 → change .start_time, .timeout
    3074  * 		| {String} library module name to import → change .to_load_module, .module_count
    3075  * 		| {String} URL/file path (image/JavaScript files/CSS) → change .to_load_path, .path_count
    3076  * 		| {Array} 另一組同時 loading set: [{String|Function|Integer}, ..] → 拆開全部當作同時 loading
    3077  * 		| TODO: {Object}	loading with additional config
    3078  *
    3079  * @since 2011/8/4 22:31:47
    3080  */
    3081 set_run = function() {
    3082 	//_.debug('process ' + arguments.length + ' items.', 2, '.set_run');
    3083 	if (arguments.length > 0)
    3084 		//Array.prototype.slice.call(arguments)
    3085 		check_run(arguments, 0);
    3086 };
    3087
    3088
    3089 /**
    3090  * main process.
    3091  *
    3092  * @param {Arguments} work_queue
    3093  *            sequence of set_run.arguments. 不修改 work_queue===set_run.arguments，直接以 work_queue_index 為開始值。
    3094  * @param {Integer} work_queue_index
    3095  *            index of work queue
    3096  * @param {Object}
    3097  *            [synchronous_group] 正在 running 的 set.
    3098  *
    3099  * @since 2011/8/4 22:31:47
    3100  * 2011/8/8 23:27:15, –2011/8/11 18:29:51	rewrite
    3101  */
    3102 function check_run(work_queue, work_queue_index, synchronous_group) {
    3103
    3104 	var work_queue_length = work_queue.length, work_set;
    3105 	// 沒有累積的 synchronous_group 時，才繼續處理指定的工作。否則先處理之。
    3106 	if (!synchronous_group) {
    3107
    3108 		while (!(work_set = work_queue[work_queue_index++])) {
    3109 			if (work_queue_index >= work_queue_length)
    3110 				_.debug('處理完畢: [' + work_queue_length + '] [' + Array.prototype.slice.call(work_queue) + ']', 2, 'check_run');
    3111 				return;
    3112 		}
    3113
    3114 		var to_run = [], to_load_path = {}, path_count = 0, to_load_module = {}, module_count = 0, timeout = 0,
    3115 		/**
    3116 		 * 增加項目至當前的 synchronous_group.
    3117 		 */
    3118 		add_item = function(item) {
    3119 			// TODO
    3120 			// {Object} loading with additional config
    3121
    3122 			if (_.is_Array(item)) {
    3123 				// {Array} 另一組同時 loading set: [{String|Function|Integer}, ..] →
    3124 				// 拆開全部當作同時 loading
    3125 				for ( var i in item)
    3126 					add_item(item[i]);
    3127
    3128 			} else if (_.is_Function(item)) {
    3129 				// {Function} function to run → to_run
    3130 				if (!item.require){
    3131 					//	TODO
    3132 					// check if the function require something first.
    3133 					to_run.push(item);
    3134 				} else
    3135 					to_run.push(item);
    3136
    3137 			} else if (typeof item === 'string') {
    3138 				if (_.request_item_maybe_module(item)){
    3139 					//	TODO: 若是已 cached 則跳過。
    3140 					//_.debug('treat resource [' + item + '] as module ' + module_count, 2, 'check_run');
    3141 					if (!(item in to_load_module) && !_.is_loaded(item))
    3142 						to_load_module[item] = 0, module_count++;
    3143 				} else if (!(item in to_load_path) && !_.is_included(item))
    3144 					//_.debug('treat resource [' + item + '] as URL ' + path_count, 2, 'check_run');
    3145 					to_load_path[item] = 0, path_count++;
    3146
    3147 			} else if ((item = Math.floor(item)) > timeout) {
    3148 				// {Integer} timeout
    3149 				timeout = item;
    3150
    3151 			} else {
    3152 				// 其他都將被忽略!
    3153 				_.warn('check_run: Unknown item: [' + item + ']');
    3154 			}
    3155 		};
    3156
    3157 		// add item to synchronous_group
    3158 		add_item(work_set);
    3159
    3160 		// 初始化 initialization synchronous_group
    3161 		synchronous_group = {};
    3162
    3163 		if (timeout)
    3164 			// 設定好時間
    3165 			synchronous_group.start_time = new Date(),
    3166 			synchronous_group.timeout = timeout;
    3167 		if (to_run.length)
    3168 			synchronous_group.to_run = to_run;
    3169 		if (path_count)
    3170 			synchronous_group.path_count = path_count,
    3171 			synchronous_group.to_load_path = to_load_path;
    3172 		if (module_count)
    3173 			synchronous_group.module_count = module_count,
    3174 			synchronous_group.to_load_module = to_load_module;
    3175
    3176 		//_.debug(module_count + '個同步載入 resource 設定完畢。', 2, 'check_run');
    3177 	}
    3178
    3179
    3180 	//_.debug('開始處理當前的 synchronous_group, work_queue ' + work_queue_index + '/' + work_queue_length, 2, 'check_run');
    3181
    3182 	var s, index,
    3183
    3184 /*
    3185
    3186 臨時/後續/後來新增:
    3187 如果 check 發現 _path_ dependencies 尚未 load，則把 dependencies 加入 to_load_path|to_load_module，去除 (to_load_path|to_load_module)[_path_]，
    3188 新增一 synchronous_group， next_group.(to_load_path|to_load_module) = _path_ 並設置 synchronous_group.require{} = dependencies
    3189
    3190 原先	［C,E]
    3191 發現B→C	[B,E]→[C]
    3192 發現D→E	[B,D]→[E]→[C]
    3193 發現A→B	[A,D]→[B]→[E]→[C]
    3194
    3195 */
    3196 	/**
    3197 	 * 臨時/後續新增項目至當前的 synchronous_group.
    3198 	 * callback 用.
    3199 	 */
    3200 	afterwards_add = function(item, item_is_path) {
    3201
    3202 		var
    3203 		require = _.is_Function(item) ?
    3204 			_.parse_require(item.require, item.require_separator) :
    3205 			/** module */
    3206 			module_require_chain[item],
    3207
    3208 		to_load_path = require.URL_to_load,
    3209 		to_load_module = require.module_to_load;
    3210
    3211 		if (!to_load_path && !to_load_module)
    3212 			return 1;
    3213
    3214
    3215 		var i, changed = false, s, n;
    3216
    3217 		//	把 dependencies: URL 加入 synchronous_group
    3218 		if (to_load_path) {
    3219 			//	synchronous_group 可能並沒有 .path_count
    3220 			if (isNaN(synchronous_group.path_count))
    3221 				s = synchronous_group.to_load_path = {},
    3222 				synchronous_group.path_count = 0;
    3223 			else
    3224 				s = synchronous_group.to_load_path;
    3225
    3226 			for (i in to_load_path)
    3227 				if (i = to_load_path[i]){
    3228 					_.debug('URL load dependency: [' + i + ']→[' + item + ']', 2, 'check_run.afterwards_add');
    3229 					if(i in s)
    3230 						//	假如是同一批的 M1, M2 都需要 P0，則跑到 M2 時 P0 不需要設定第二次，但需要把 M2 移到下一批次。
    3231 						if ((n = synchronous_group.next_group) && !(item in n.to_load_path))
    3232 							n.to_load_path[item] = 0,
    3233 							n.path_count++;
    3234 						else {
    3235 							if (_.is_debug() && (!n || _.is_debug(2)))
    3236 								_.warn('check_run.afterwards_add: 無法把 URL [' + item + '] 移到下一批次: 下一批次' + (n ? '不存在' : '已有此 URL') + '!');
    3237 						}
    3238 					else
    3239 						//	因為是指向 Object，因此不需要再設定 synchronous_group.to_load_path。為防節外生枝，直接改 .path_count，不 cache。
    3240 						s[i] = 0, synchronous_group.path_count++, changed = true, load_URL(i);
    3241 				}
    3242
    3243 			//show_set('after afterwards_add URL dependency changed');
    3244 		}
    3245
    3246 		//	把 dependencies: module 加入 synchronous_group
    3247 		if(to_load_module){
    3248 			//	synchronous_group 可能並沒有 .module_count
    3249 			if (isNaN(synchronous_group.module_count))
    3250 				s = synchronous_group.to_load_module = {},
    3251 				synchronous_group.module_count = 0;
    3252 			else
    3253 				//	s: 當前欲載入之 module
    3254 				s = synchronous_group.to_load_module;
    3255
    3256 			for (i in to_load_module)
    3257 				if (i = to_load_module[i]){
    3258 					_.debug('module load dependency: [' + i + ']→[' + item + ']', 2, 'check_run.afterwards_add');
    3259 					if (i in s)
    3260 						// 假如是同一批的 M1, M2 都需要 M0，則跑到 M2 時 M0 不需要設定第二次，但需要把 M2 移到下一批次。
    3261 						if ((n = synchronous_group.next_group) && !(item in n.to_load_module))
    3262 							n.to_load_module[item] = 0,
    3263 							n.module_count++;
    3264 						else {
    3265 							if (_.is_debug() && (!n || _.is_debug(2)))
    3266 								_.warn('check_run.afterwards_add: 無法把 module [' + item + '] 移到下一批次: 下一批次' + (n ? '已有此 module' : '不存在') + '!');
    3267 						}
    3268 					else
    3269 						//	因為是指向 Object，因此不需要再設定 synchronous_group.to_load_module。為防節外生枝，直接改 .module_count，不 cache。
    3270 						s[i] = 0, synchronous_group.module_count++, changed = true, load_module(i);
    3271 				}
    3272
    3273 			//show_set('after afterwards_add module dependency changed');
    3274 		}
    3275
    3276 		if (changed && item) {
    3277 			//show_set('準備將 [' + item + '] 從 synchronous_group 搬到 next_group');
    3278
    3279 			if (s = synchronous_group.next_group)
    3280 				s = {
    3281 					next_group : s
    3282 				};
    3283 			else {
    3284 				s = {};
    3285 				if ('timeout' in synchronous_group)
    3286 					_.extend( {
    3287 						timeout : 0,
    3288 						start_time : 0
    3289 					}, s, synchronous_group);
    3290 			}
    3291 			synchronous_group.next_group = s;
    3292
    3293 			if (item_is_path) {
    3294 				(s.to_load_path = {})[item] = 0;
    3295 				s.path_count = 1;
    3296 			} else if (typeof item === 'string') {
    3297 				(s.to_load_module = {})[item] = 0;
    3298 				s.module_count = 1;
    3299 			} else if (_.is_Function(item)) {
    3300 				(s.to_run = []).push(item);
    3301 			}
    3302 			//else warn();
    3303
    3304 			//show_set('已將 [' + item + '] 從 synchronous_group 搬到 next_group');
    3305 		} else
    3306 			return 2;
    3307
    3308 	},
    3309
    3310 	//	debug 用
    3311 	//TODO: Object.keys(obj)
    3312 	//	https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
    3313 	get_Object_key = function(o) {
    3314 		if (_.is_Array(o))
    3315 			return o;
    3316 		//if (!_.is_Object(o)) return;
    3317 		var i, l = [];
    3318 		for(i in o)
    3319 			l.push(i);
    3320 		return l;
    3321 	},
    3322
    3323 	//	debug 用
    3324 	show_set = function(from) {
    3325 		if(_.is_debug(2)){
    3326 			var ptr = synchronous_group, s_data = [ '預計先後載入同步載入組: ' + (from || '') ], d;
    3327 			do {
    3328 				d = ptr.to_load_module ? get_Object_key(ptr.to_load_module) : 0;
    3329 				s_data.push(
    3330 						d?
    3331 								'[' + (ptr.module_count === d.length ? ptr.module_count : '<em>登記 ' + ptr.module_count + ' != 實際 ' + d.length + '</em>') + '] '
    3332 										+ d.join(' <span style="color:#f00">|</span> ')
    3333 								: '<span style="color:#888">(none: 此同步載入組無預計載入之 module)</span>'
    3334 						);
    3335 			} while (ptr = ptr.next_group);
    3336 			_.debug(s_data.join('<br/>'), 1, 'check_run.show_set');
    3337 		}
    3338 	},
    3339
    3340 	//check module_require_chain{module_name}
    3341 	/**
    3342 	 * 載入間執行之 function.
    3343 	 * 有未載入之 dependencies，僅能從 callback 傳入此 module 所需之 dependency list 來處置。
    3344 	 * TODO: 確認若是load錯誤時，會不會跳過 check_loading 不執行。
    3345 	 */
    3346 	check_loading,
    3347 	load_module, load_URL,
    3348 	move_to_next_group = false;
    3349
    3350 	//	synchronous_group.to_run: 若要處理 .to_run 的 require，則 check_loading() 還是需要設定。
    3351 	if (work_queue_index < work_queue_length || synchronous_group.to_run)
    3352 	check_loading = function(path, module_name) {
    3353 		//_.debug((module_name ? 'module [' + module_name  + ']/all ' + synchronous_group.module_count : path ? 'path [' + path + ']/all ' + synchronous_group.path_count : '沒有尚未 load 的 resource') + (synchronous_group.timeout ? ', timeout ' + synchronous_group.timeout : ''), 1, 'check_run.check_loading');
    3354 		//show_set('check_loading start');
    3355
    3356 		if(module_name){
    3357
    3358 			//	is module
    3359 			delete synchronous_group.to_load_module[module_name];
    3360 			synchronous_group.module_count--;
    3361
    3362 			if (!_.is_loaded(module_name))
    3363 				if (module_require_chain[module_name])
    3364 					afterwards_add(module_name);
    3365 				else
    3366 					//	若有不存在的 module，因為會以 .include_resource 載入，在 MSIE 中會 throw。
    3367 					//	可以由判別 browser 改善此體驗。
    3368 					_.err('check_run.check_loading: Cannot load module [' + module_name + ']!');
    3369
    3370 		} else if (path) {
    3371
    3372 			//	is path, 無法判別是否成功 included。
    3373 			delete synchronous_group.to_load_path[path];
    3374 			synchronous_group.path_count--;
    3375
    3376 		}
    3377
    3378 		//	可能因為循環參照(circular dependencies)，這邊的 module 之前已經 load 過，因此需要再作 check。
    3379 		//	.. pass
    3380 		;
    3381
    3382 		if (!synchronous_group.module_count
    3383 					&& !synchronous_group.path_count){
    3384 			var timeout = synchronous_group.timeout
    3385 						- (new Date() - synchronous_group.start_time);
    3386 			synchronous_group = synchronous_group.next_group;
    3387 			move_to_next_group = true;
    3388
    3389 			//_.debug('Move to next synchronous load group. 本同步載入組已全部載入，' + (synchronous_group ? '進入下一同步載入組。' : work_queue_index < work_queue.length ? '繼續下一組指定的工作 [' + work_queue_index + '/' + work_queue.length + ']。' : '本次指定的 ' + work_queue_index + ' 項工作已全部執行完成。') + (timeout > 4 ? 'timeout ' + timeout + ' 超過 4ms，設定 timeout。' : ''), 1, 'check_run.check_loading');
    3390 			if (timeout > 4)
    3391 				// TODO: setTimeout 可能不存在!
    3392 				setTimeout(function() {
    3393 					check_run(work_queue, work_queue_index,
    3394 							synchronous_group);
    3395 				}, timeout);
    3396 			else
    3397 				check_run(work_queue, work_queue_index,
    3398 						synchronous_group);
    3399 			//_.debug('設定完畢', 1, 'check_run.check_loading');
    3400 		}
    3401 	},
    3402
    3403 	load_module = function(module_name) {
    3404 		//_.debug('[' + module_name + ']', 1, 'check_run.load_module');
    3405 		// .use 會先試試 .get_file()
    3406 		_.use(module_name, check_loading);
    3407 	},
    3408
    3409 	load_URL = function(URL, encoding) {
    3410 		// 準備載入 resource. ** 在已經 loaded 的情況下有可能直接就執行完 return!
    3411 		//_.debug('[' + URL + ']', 1, 'check_run.load_URL');
    3412 		if (/\.js$/i.test(URL))
    3413 			try{
    3414 				// 對 .js 先試試 .get_file()
    3415 				var t = _.get_file(URL, encoding);
    3416 				//_.debug('Get [' + t + ']', 2, 'check_run.load_URL');
    3417 				if (t)
    3418 					//	eval @ global. 這邊可能會出現 security 問題。
    3419 					//	TODO: 以其他方法取代 eval 的使用。
    3420 					_.eval_code(t);
    3421
    3422 				check_loading(URL);
    3423 				return;
    3424
    3425 			}catch (e) {
    3426 				//_.err(e);
    3427 			}
    3428
    3429 		//_.debug('需要作同步 loading resource [' + URL + ']', 1, 'check_run.load_URL');
    3430 		_.include_resource(URL, check_loading);
    3431 	};
    3432
    3433 	// 把能處理的 .to_run function 先執行處理，而後早點 delete 以釋放空間。
    3434 	if(s = synchronous_group.to_run){
    3435 		for (index in s)
    3436 			try {
    3437 				// 已經過鑑別，這邊的都是 Function
    3438 				s[index]();
    3439
    3440 			} catch (e) {
    3441 				_.err('check_run: ' + e.message);
    3442 				_.debug('<code>'
    3443 						+ ('' + s[index]).replace(/\n/g, '<br />')
    3444 						+ '</code>');
    3445 			}
    3446 		//_.debug('把能處理的 function 先處理完了，刪除synchronous_group.to_run 的資料。', 2);
    3447 		delete synchronous_group.to_run;
    3448 	}
    3449
    3450
    3451 	if(s = synchronous_group.to_load_module)
    3452 		for (index in s)
    3453 			load_module(index);
    3454
    3455 	if(move_to_next_group)
    3456 		//	在上一個 load_module() 呼叫 check_loading() 時，可能因為 synchronous_group = synchronous_group.next_group 使得 synchronous_group 已轉換到下一 synchronous load group。
    3457 		return;
    3458
    3459 	if(s = synchronous_group.to_load_path)
    3460 		for (index in s)
    3461 			load_URL(index);
    3462
    3463
    3464 	if (!move_to_next_group && check_loading && !synchronous_group.module_count
    3465 			&& !synchronous_group.path_count){
    3466 		//_.debug('[' + work_queue_index + '/' + work_queue_length + '] 沒有尚未 load 的 resource (例如只輸入 timeout 或每個 resource 皆 loaded)，手動執行 check_loading。', 1, 'check_run');
    3467 		check_loading();
    3468 	}
    3469
    3470 	// 開始蟄伏, waiting for callback
    3471 }
    3472
    3473
    3474
    3475 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    3476
    3477
    3478
    3479 CeL
    3480 .
    3481 /**
    3482  * module 中模擬 inherit 時使用。
    3483  *
    3484  * TODO:
    3485  * 同步載入功能
    3486  * @param {String} parent_module_name	欲繼承的 module_name
    3487  * @param initial_arguments	繼承時的 initial arguments
    3488  * @returns
    3489  * @see
    3490  * <a href="http://fillano.blog.ithome.com.tw/post/257/17355" accessdate="2010/1/1 0:6">Fillano's Learning Notes | 物件導向Javascript - 實作繼承的效果</a>,
    3491  * <a href="http://www.crockford.com/javascript/inheritance.html" accessdate="2010/1/1 0:6">Classical Inheritance in JavaScript</a>
    3492  */
    3493 inherit = function(parent_module_name, initial_arguments) {
    3494 	if(!_.cache_code && _.cache_code !== undefined)
    3495 		_.debug('inherit: cache code did not setted but try to inherit module!');
    3496
    3497 	var code_for_including = loaded_module[_.to_module_name(parent_module_name)];
    3498 	try {
    3499 		if (_.is_Function(code_for_including))
    3500 			return code_for_including.call(code_for_including, _, initial_arguments);
    3501
    3502 		_.err('inherit: [' + parent_module_name + '] did not catched!');
    3503 	} catch (e) {
    3504 		_.err('inherit: running of [' + parent_module_name + '] error!');
    3505 		return e;
    3506 	}
    3507 };
    3508
    3509
    3510
    3511
    3512 CeL
    3513 .
    3514 /**
    3515  * 解析 dependency list 以獲得所需之 module/path/variable name..
    3516  *
    3517  * @param {Array|String}
    3518  *            dependency_list
    3519  *            <p>
    3520  *            list of dependency function/module/variable required. module 須以
    3521  *            CeL.env.module_name_separator ('.') 結尾。若輸入 String，則以 separator 或 '|' 分割。
    3522  *            </p>
    3523  * @returns {Object} result { variable: {variable_name: full_name}, module:
    3524  *          {module name: loaded or not}, module_to_load: [], URL: {}}
    3525  * @returns {Number} error_no
    3526  * @since 2011/8/6 22:10:57
    3527  */
    3528 parse_require = function(dependency_list, separator, base_require) {
    3529
    3530 	if(!dependency_list)
    3531 		//	is_Object(undefined) === true!
    3532 		return 0;
    3533
    3534 	if (typeof dependency_list === 'string')
    3535 		dependency_list = dependency_list.split(separator || '|');
    3536 	else if (!_.is_Array(dependency_list) || !_.is_Object(dependency_list))
    3537 		return 1;
    3538
    3539 	var i, module, module_name_separator = _.env.module_name_separator,
    3540 	/**
    3541 	 * variable name under module
    3542 	 */
    3543 	var_name,
    3544 	/**
    3545 	 * 解析出要 extend 到 'this' 下的 variables。
    3546 	 * variable_hash[variable name] = 所在 module name.
    3547 	 */
    3548 	//variable_hash = {},
    3549 	/**
    3550 	 * 解析出要 extend 到 'this' 下的 variables。
    3551 	 * variable_full_name[variable name] = variable full name.
    3552 	 */
    3553 	variable_full_name,
    3554 	/**
    3555 	 * 解析出的 URL paths.
    3556 	 * URL_hash[URL] = loaded or not;
    3557 	 */
    3558 	URL_hash,
    3559 	/**
    3560 	 * 解析出需要 load 的 URL paths.
    3561 	 */
    3562 	URL_to_load,
    3563 	/**
    3564 	 * dependency_list 中指定的 module。
    3565 	 * module_hash[module name] = loaded or not
    3566 	 */
    3567 	module_hash,
    3568 	/**
    3569 	 * 已 load 的 module。
    3570 	 */
    3571 	//module_loaded = [],
    3572 	/**
    3573 	 * 要 load 的 module。
    3574 	 */
    3575 	module_to_load;
    3576
    3577 	if (_.is_Object(base_require)) {
    3578 		variable_full_name = base_require.variable,
    3579 		URL_hash = base_require.URL,
    3580 		URL_to_load = base_require.URL_to_load,
    3581 		module_hash = base_require.module,
    3582 		module_to_load = base_require.module_to_load;
    3583
    3584 		//variable_hash = {};
    3585 	} else {
    3586 		variable_full_name = {},
    3587 		URL_hash = {},
    3588 		URL_to_load = [],
    3589 		module_hash = {},
    3590 		module_to_load = [];
    3591 	}
    3592
    3593 	//	解析 dependency_list，將所須 functions/modules 置於 variable_hash/module_hash 中。
    3594 	for (i in dependency_list)
    3595 		if (_.request_item_maybe_module(i = dependency_list[i])
    3596 				&& (module = _.split_module_name(i))) {
    3597
    3598 			// 類似 'data.split_String_to_Object' 的形式，為 function。
    3599 			// 類似 'data.' 的形式，為 module。
    3600 			if (var_name = module.pop())
    3601 				variable_full_name[var_name] = (
    3602 					//variable_hash[var_name] =
    3603 					 _.to_module_name(module))
    3604 						+ module_name_separator + var_name;
    3605 			//_.debug('load module [' + _.to_module_name(module) + ']' + (var_name ? '.' + var_name : ''));
    3606
    3607 			//_.debug('test module ['+module.join(module_name_separator)+']: '+_.get_variable(module.join(module_name_separator),_));
    3608
    3609 			//	不用 _.to_module_name，因為會加油添醋。
    3610 			module = module.join(module_name_separator);
    3611
    3612 			//	確定是否還沒載入，必須 load。還沒載入則放在 module_to_load[] 中。
    3613 			if (!(module in module_hash)) {
    3614 				if (!(module_hash[module] = _.is_loaded(module)))
    3615 					//_.debug('module [' + module + '] need to load first.'),
    3616 					module_to_load.push(module);
    3617 			}
    3618
    3619 		} else if (!(i in URL_hash) && !(URL_hash[i] = _.is_included(i)))
    3620 			URL_to_load.push(i);
    3621
    3622
    3623 	return {
    3624 		//require : dependency_list,
    3625 		variable : variable_full_name,
    3626
    3627 		module : module_hash,
    3628 		//module_loaded : module_loaded,
    3629 		module_to_load : module_to_load,
    3630
    3631 		URL : URL_hash,
    3632 		URL_to_load : URL_to_load
    3633 	};
    3634 };
    3635
    3636
    3637 /*
    3638 //這得要直接貼在標的 scope 內才有用。
    3639 var no_strict_variable_use = (function() {
    3640 	var v, i = 0;
    3641 	try {
    3642 		// find a undefined var_name
    3643 		for (;;)
    3644 			eval(v = 'tmp_' + i++);
    3645 	} catch (i) {
    3646 	}
    3647
    3648 	eval('var ' + v + '=1;');
    3649
    3650 	try {
    3651 		//	OK 表示在 eval 中可以設定 var.
    3652 		//	若是 'use strict'; 則不可在 eval() 中置 var.
    3653 		return eval(v);
    3654 	} catch (i) {
    3655 	}
    3656 })();
    3657 */
    3658
    3659 //	http://closure-compiler.appspot.com/
    3660 //	這得要直接貼在標的 scope 內才有用。
    3661 //var no_strict_variable_use=function(){var a,b=9;try{for(;;)eval(a="t_"+b++)}catch(c){}eval("var "+a+"=1;");try{return eval(a)}catch(d){}}();
    3662
    3663 CeL
    3664 .
    3665 /**
    3666  * module 中需要 include function/module/variable 時設定 local variables 使用。<br/>
    3667  * 本函數將把所需 function include 至當前 namespace 下。
    3668  *
    3669  * TODO: 輸入 function name 即可
    3670  *
    3671  * @example
    3672  *
    3673  * //	requires (inside module)
    3674  * //	事先定義 @ 'use strict';
    3675  * var split_String_to_Object;
    3676  * //	之所以需要使用 eval 是因為要 extend 至當前 namespace 下。
    3677  * //	若無法 load CeL.data，將會 throw
    3678  * eval(library_namespace.use_function(this, 'data.split_String_to_Object'));
    3679  * //	use it
    3680  * split_String_to_Object();
    3681  *
    3682  * //	不用 eval 的方法 1: function 預設都會 extend 至當前 library_namespace 下。
    3683  * library_namespace.use_function(this, 'data.split_String_to_Object');
    3684  * library_namespace.use_function(this, 'data.split_String_to_Object', false);
    3685  * //	若無法 load CeL.data，將會 throw
    3686  * //	use it
    3687  * library_namespace.split_String_to_Object();
    3688  *
    3689  * //	不用 eval 的方法 2: 設定 extend_to
    3690  * var o={};
    3691  * //	若無法 load CeL.data，將會 throw
    3692  * library_namespace.use_function(this, 'data.split_String_to_Object', o);
    3693  * //	use it
    3694  * o.split_String_to_Object();
    3695  *
    3696  * @param	{Function|Object} name_space	module name-space
    3697  * @param	{Array|String} dependency_list	list of dependency function/module/variable required. module 須以 '.' 結尾。若輸入 String，則以 ',' 分割。
    3698  * @param	{Function|Object} [extend_to]	若設定將把 variable extend 至 extend_to
    3699  *
    3700  * @returns	{Number} error code
    3701  * 		1: can't parse dependency_list
    3702  *
    3703  * @throws	{Error}	有些 module 尚未載入。
    3704  *
    3705  * @since	2009/12/26 02:36:31
    3706  * 2009/12/31 22:21:23	add 類似 'data.' 的形式，為 module。
    3707  * 2010/6/14 22:58:18	避免相互 require
    3708  */
    3709 use_function = function(name_space, extend_to, optional_use, no_strict) {
    3710
    3711 	var module_name = get_module_name(name_space);
    3712
    3713 	//_.debug('load function [' + dependency_list + ']' + (typeof module_name === 'string' && module_name ? ' from [' + module_name + ']' : ''));
    3714
    3715 	var variable_name, value, eval_code = [],
    3716 	/**
    3717 	 * 要 extend 到 name_space 下的 variables。
    3718 	 * variable_hash[variable name] = variable full name, 包括所在 module name.
    3719 	 */
    3720 	variable_hash = name_space.require_variable;
    3721
    3722 	no_strict = no_strict && !extend_to ? [] : false;
    3723
    3724 	//	設定 required variables
    3725 	for (variable_name in variable_hash)
    3726 		if ((value = _.get_variable(variable_hash[variable_name])) !== undefined) {
    3727 			//_.debug('指定 [' + variable_name + ']: ' + value));
    3728 			if (extend_to)
    3729 				extend_to[variable_name] = value;
    3730 			else {
    3731 				no_strict && no_strict.push(variable_name);
    3732
    3733 				eval_code.push('try{' + variable_name + '=' +
    3734 						//	預防有保留字，所以用 bracket notation。例如 Chrome 中會出現 'Unexpected token native'。
    3735 						//	Dot Notation and Square Bracket Notation in JavaScript	http://www.dev-archive.net/articles/js-dot-notation/
    3736 						variable_hash[variable_name].replace(/\.([a-z\d_]+)/gi, '["$1"]') + ';}catch(e){}');
    3737 			}
    3738
    3739 		} else {
    3740 			// 可能因為循環參照(circular dependencies)，事實上 required 並未 loaded。
    3741 			if(!(module_name in module_require_chain) || _.is_debug(2))
    3742 				_.err(_.Class + '.use_function: load [' + variable_hash[variable_name] + '] @ ['
    3743 						+ _.to_module_name(module_name) + '] error: The module is not included or defined? You have to load they all later.');
    3744
    3745 			if (extend_to) {
    3746 				extend_to[variable_name] = function() {
    3747 					try {
    3748 						//	稍後求值，僅對 function 有效。
    3749 						return _.get_variable(variable_hash[variable_name]);
    3750 					} catch (e) {
    3751 					}
    3752 				};
    3753 			} else {
    3754 				no_strict && no_strict.push(variable_name);
    3755
    3756 				//	稍後求值，僅對 function 有效。
    3757 				eval_code.push(variable_name + '=function(){try{return ' + variable_name + '='
    3758 						+ variable_hash[variable_name].replace(/\.([a-z\d_]+)/gi, '["$1"]')
    3759 						+ ';}catch(e){}};');
    3760 			}
    3761
    3762
    3763 			// delete it if doesn't exists
    3764 			//delete variable_hash[variable_name];
    3765 		}
    3766
    3767 	//	應注意 module_name 為保留字之類的情況，會掛在這邊 return 後的 eval。
    3768 	return extend_to
    3769 		|| (no_strict ? 'var ' + no_strict.join(',') + ';' : '') + eval_code.join('');
    3770 };
    3771
    3772
    3773
    3774 //----------------------------------------------------------------------------------------------------------------------------------------------------------//
    3775
    3776
    3777 /**
    3778  * 為一些比較舊的版本或不同瀏覽器而做調適。
    3779  * @since	2010/1/14 17:58:31
    3780  * @inner
    3781  * @private
    3782  * @ignore
    3783  */
    3784 function environment_adapter() {
    3785 	/*
    3786 	 * workaround:
    3787 	 * 理論上 '.'.split(/\./).length 應該是 2，但 IE 5–8 中卻為 0!
    3788 	 * 用 .split('.') 倒是 OK.
    3789 	 * TODO:
    3790 	 * 應該增加可以管控與回復的手段，預防有時需要回到原有行為。
    3791 	 * @since	2010/1/1 19:03:40
    3792 	 */
    3793 	if ('.'.split(/\./).length === 0)
    3794 		(function() {
    3795 			var _String_split = String.prototype.split,
    3796 				is_Regexp = _.object_tester('RegExp');
    3797 			String.prototype.split = function(r) {
    3798 				return is_Regexp(r) ?
    3799 						_String_split.call(this.valueOf().replace(
    3800 								r.global ? r :
    3801 									// TODO: 少了 multiline
    3802 									new RegExp(r.source, r.ignoreCase ? 'ig' : 'g'),
    3803 							'\0'), '\0') :
    3804 						_String_split.call(this, r);
    3805 			};
    3806 		})();
    3807 }
    3808
    3809 environment_adapter();
    3810
    3811 }
    3812 //	不用 apply()，因為比較舊的瀏覽器沒有 apply()。
    3813 )(CeL);
    3814
    3815
    3816
    3817
    3818 //===========================================================================================================================================================//
    3819
    3820
    3821
    3822
    3823 //args=args.concat(['turnCode.js']);
    3824
    3825 //	不作 initialization
    3826 //CeL.no_initialization = 0;
    3827
    3828 if (typeof CeL === 'function' && CeL.env.script_name === CeL.env.main_script_name
    3829 		&& !CeL.no_initialization)
    3830 	try {
    3831 		(function() {
    3832 			// WScript.Echo(CeL.env.script_name);
    3833 			// CeL.debug(CeL.env.script_name);
    3834
    3835
    3836 			//	將 path 寫入 registry
    3837 			CeL.use('application.OS.Windows');
    3838 			CeL.use('application.OS.Windows.registry');
    3839 			// CeL.debug(CeL.reg);
    3840 			//WScript.Echo(CeL.reg);
    3841
    3842 			var path_key_name = CeL.env.registry_path_key_name,
    3843 			//	此時 script 即為 main_script
    3844 			library_base_path = CeL.env.script_base_path,
    3845 			path_in_registry = CeL.reg.getValue(path_key_name) || '(null)';
    3846 			//WScript.Echo('registry:\n' + path_in_registry + '\npath now:\n' + library_base_path);
    3847 			if (path_in_registry !== library_base_path) {
    3848 				WScript.Echo('Change the base path of [' + CeL.Class + '] from:\n'
    3849 						+ path_in_registry + '\n to\n' + library_base_path
    3850 						+ '\n\nkey name:\n' + path_key_name);
    3851 				CeL.reg.setValue.cid = 1;
    3852 				CeL.reg.setValue(path_key_name, library_base_path, 0, 0, 1);
    3853 				CeL.reg.setValue(CeL.env.registry_base + 'main_script',
    3854 						library_base_path + CeL.env.script_name, 0, 0, 1);
    3855 				CeL.reg.setValue.cid = 0;
    3856 			}
    3857
    3858
    3859 			//	TODO
    3860 			//	拖曳檔案到本檔案上面時之處置。
    3861 			if (
    3862 					// args instanceof Array
    3863 					typeof args === 'object') {
    3864 				// getEnvironment();
    3865 				// alert('Get arguments ['+args.length+']\n'+args.join('\n'));
    3866 				if (args.length) {
    3867 					var i = 0, p, enc, f, backupDir = dBasePath('kanashimi\\www\\cgi-bin\\program\\log\\');
    3868 					if (!fso.FolderExists(backupDir))
    3869 						try {
    3870 							fso.CreateFolder(backupDir);
    3871 						} catch (e) {
    3872 							backupDir = dBasePath('kanashimi\\www\\cgi-bin\\game\\log\\');
    3873 						}
    3874 						if (!fso.FolderExists(backupDir))
    3875 							try {
    3876 								fso.CreateFolder(backupDir);
    3877 							} catch (e) {
    3878 								if (2 === alert('無法建立備份資料夾[' + backupDir
    3879 										+ ']！\n接下來的操作將不會備份！', 0, 0, 1 + 48))
    3880 									WScript.Quit();
    3881 								backupDir = '';
    3882 							}
    3883 							// addCode.report=true; // 是否加入報告
    3884 							for (; i < args.length; i++)
    3885 								if ((f = dealShortcut(args[i], 1))
    3886 										.match(/\.(js|vbs|hta|s?html?|txt|wsf|pac)$/i)
    3887 										&& isFile(f)) {
    3888 									p = alert(
    3889 											'是否以預設編碼['
    3890 											+ ((enc = autodetectEncode(f)) == simpleFileDformat ? '內定語系('
    3891 													+ simpleFileDformat + ')'
    3892 													: enc) + ']處理下面檔案？\n' + f,
    3893 													0, 0, 3 + 32);
    3894 									if (p === 2)
    3895 										break;
    3896 									else if (p === 6) {
    3897 										if (backupDir)
    3898 											fso.CopyFile(f, backupDir + getFN(f), true);
    3899 										addCode(f);
    3900 									}
    3901 								}
    3902 				} else if (1 === alert('We will generate a reduced ['
    3903 						+ CeL.env.script_name + ']\n  to [' + CeL.env.script_name
    3904 						+ '.reduced.js].\nBut it takes several time.', 0, 0,
    3905 						1 + 32))
    3906 					reduceScript(0, CeL.env.script_name + '.reduced.js');
    3907 			}// else window.onload=init;
    3908
    3909 			// CeL._iF=undefined;
    3910 		})();
    3911 	} catch (e) {
    3912 		// TODO: handle exception
    3913 	}
    3914
    3915
    3916
    3917 /*
    3918
    3919 //test WinShell	http://msdn.microsoft.com/en-us/library/bb787810(VS.85).aspx
    3920 if (0) {
    3921 alert(WinShell.Windows().Item(0).FullName);
    3922
    3923 var i, cmd, t = '', objFolder = WinShell.NameSpace(0xa), objFolderItem = objFolder
    3924 		.Items().Item(), colVerbs = objFolderItem.Verbs(); // 假如出意外，objFolder==null
    3925 for (i = 0; i < colVerbs.Count; i++) {
    3926 	t += colVerbs.Item(i) + '\n';
    3927 	if (('' + colVerbs.Item(i)).indexOf('&R') != -1)
    3928 		cmd = colVerbs.Item(i);
    3929 }
    3930 objFolderItem.InvokeVerb('' + cmd);
    3931 alert('Commands:\n' + t);
    3932
    3933 // objShell.NameSpace(FolderFrom).CopyHere(FolderTo,0); // copy folder
    3934 // objFolderItem=objShell.NameSpace(FolderFrom).ParseName("clock.avi");objFolderItem.Items().Item().InvokeVerb([動作]);
    3935 // objShell.NameSpace(FolderFromPath).Items.Item(mName).InvokeVerb();
    3936
    3937 // Sets or gets the date and time that a file was last modified.
    3938 // http://msdn.microsoft.com/en-us/library/bb787825(VS.85).aspx
    3939 // objFolderItem.ModifyDate = "01/01/1900 6:05:00 PM";
    3940 // objShell.NameSpace("C:\Temp").ParseName("Test.Txt").ModifyDate =
    3941 // DateAdd("d", -1, Now()) CDate("19 October 2007")
    3942
    3943 // Touch displays or sets the created, access, and modified times of one or
    3944 // more files. http://www.stevemiller.net/apps/
    3945 }
    3946
    3947 //測試可寫入的字元:0-128,最好用1-127，因為許多編輯器會將\0轉成' '，\128又不確定
    3948 if (0) {
    3949 var t = '', f = 'try.js', i = 0;
    3950 for (; i < 128; i++)
    3951 	t += String.fromCharCode(i);
    3952 if (simpleWrite(f, t))
    3953 	alert('Write error!\n有此local無法相容的字元?');
    3954 else if (simpleRead(f) != t)
    3955 	alert('內容不同!');
    3956 else if (simpleWrite(f, dQuote(t) + ';'))
    3957 	alert('Write error 2!\n有此local無法相容的字元?');
    3958 else if (eval(simpleRead(f)) != t)
    3959 	alert('eval內容不同!');
    3960 else
    3961 	alert('OK!');
    3962 }
    3963
    3964 */
    3965
    3966
    3967
    3968
    3969
    3970 //}catch(e){WScript.Echo('There are some error in function.js!\n'+e.message);throw e;}
    3971
    3972
    3973
    3974 //CeL.use('code.log');
    3975 //CeL.warn('test_print: ' + CeL.code.log.Class);
    3976
    3977
    3978 //]]>
    3979
    3980